Rust library for building and running BPF/eBPF modules

Overview

RedBPF

LICENSE element

A Rust eBPF toolchain.

Overview

The redbpf project is a collection of tools and libraries to build eBPF programs using Rust. It includes:

  • redbpf - a user space library that can be used to load eBPF programs

  • redbpf-probes - an idiomatic Rust API to write eBPF programs that can be loaded by the linux kernel

  • redbpf-macros - companion crate to redbpf-probes which provides convenient procedural macros useful when writing eBPF programs

  • cargo-bpf - a cargo subcommand for creating, building and debugging eBPF programs

Requirements

In order to use redbpf you need LLVM 11 and the headers for the kernel you want to target.

Linux kernel

The minimum kernel version supported is 4.19. Kernel headers are discovered automatically, or you can use the KERNEL_SOURCE environment variable to point to a specific location. Building against a linux source tree is supported as long as you run make prepare first.

Installing dependencies on Debian based distributions

On Debian, Ubuntu and derivatives you can install the dependencies running:

sudo apt-get -y install build-essential zlib1g-dev \
		llvm-11-dev libclang-11-dev linux-headers-$(uname -r)

If your distribution doesn't have LLVM 11, you can add the official LLVM APT repository to your sources.list.

Installing dependencies on RPM based distributions

First ensure that your distro includes LLVM 11:

yum info llvm-devel | grep Version
Version      : 11.0.0

If you don't have vesion 11, you can get it from the Fedora 33 repository.

Then install the dependencies running:

yum install clang llvm-devel zlib-devel kernel-devel

Getting started

The easiest way to get started is using cargo-bpf, see the documentation for more info.

redbpf-tools is a cargo-bpf generated crate that includes simple examples you can use to understand how to structure your programs.

Finally the foniod project includes more concrete examples of redbpf programs.

Building from source

After cloning the repository run:

git submodule sync
git submodule update --init

Install the dependencies as documented above, then run cargo build as usual.

License

This repository contains code from other software in the following directories, licensed under their own particular licenses:

  • bpf-sys/libelf/*: GPL2 + LGPL3
  • bpf-sys/bcc/*: Apache2, public domain
  • include/bpf_helpers.h LGPL2 + BSD-2
  • include/bpf_helper_defs.h: LGPL2 + BSD-2
  • bpf-sys/libbpf: LGPL2 + BSD-2

Where '+' means they are dual licensed.

RedBPF and its components, unless otherwise stated, are licensed under either of

at your option.

Contribution

This project is for everyone. We ask that our users and contributors take a few minutes to review our code of conduct.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

For further advice on getting started, please consult the Contributor's Guide. Please note that all contributions MUST contain a Developer Certificate of Origin sign-off line.

Comments
  • bpf tc can't load by tc or cargo bpf load

    bpf tc can't load by tc or cargo bpf load

    I'm using Archlinux

    Linux sherlockholo-pc 5.14.14-arch1-1 #1 SMP PREEMPT Wed, 20 Oct 2021 21:35:18 +0000 x86_64 GNU/Linux

    I try this codes

    #![no_std]
    #![no_main]
    
    use redbpf_probes::tc::prelude::*;
    // use redbpf_probes::xdp::prelude::*;
    
    program!(0xFFFFFFFE, "GPL");
    
    #[tc_action]
    fn test(skb: SkBuff) -> TcActionResult {
        Ok(TcAction::Ok)
    }
    

    and build with cargo bpf build

    When I try to load it by sudo tc filter add ingress bpf da obj target/bpf/programs/learn_bpf/learn_bpf.elf sec tc_action/test

    it reports

    Error fetching program/map! Unable to load program

    also I try to use cargo-bpf, sudo -E cargo bpf load -i lo target/bpf/programs/learn_bpf/learn_bpf.elf, it just stuck without any output.

    How should I do to load the bpf tc program?

    opened by Sherlock-Holo 24
  • TcHashMap can't set

    TcHashMap can't set

    #![no_std]
    #![no_main]
    
    use core::mem::{size_of, transmute};
    
    use cty::c_void;
    use redbpf_macros::map;
    use redbpf_probes::tc::prelude::*;
    
    program!(0xFFFFFFFE, "GPL");
    
    #[map(link_section = "redirect_map")]
    static mut REDIRECT_MAP: TcHashMap<__be16, u16> =
        TcHashMap::with_max_entries(1024, TcMapPinning::GlobalNamespace);
    
    #[tc_action]
    fn test(skb: SkBuff) -> TcActionResult {
        let mut n: __be16 = 1;
        n = n.to_be();
    
        unsafe {
            REDIRECT_MAP.set(&n, &1);
        }
    
        Ok(TcAction::Ok)
    }
    

    when compile this codes and load by tc, it reports

    Prog section 'tc_action/test' rejected: Permission denied (13)!
     - Type:         3
     - Instructions: 12 (0 over limit)
     - License:      GPL
    
    Verifier analysis:
    
    0: (b7) r1 = 256
    1: (6b) *(u16 *)(r10 -2) = r1
    2: (bf) r2 = r10
    3: (07) r2 += -2
    4: (18) r1 = 0x0
    6: (18) r3 = 0x0
    8: (b7) r4 = 0
    9: (85) call bpf_map_update_elem#2
    R1 type=inv expected=map_ptr
    processed 8 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0
    
    Error fetching program/map!
    Unable to load program
    

    it seems when uses the bpf_map_update_elem, the pointer is incorrect? but I don't know what's wrong in https://github.com/foniod/redbpf/blob/a9b98c2f9dfa1481a93d46560b0e11deec800865/redbpf-probes/src/tc/maps.rs#L172

    opened by Sherlock-Holo 22
  • Unknown func bpf_skb_load_bytes

    Unknown func bpf_skb_load_bytes

    Hello,

    I first followed the tutorial to get started with redbpf which worked very nicely. I then used the tutorial template and changed it to hook into the kernel function __dev_queue_xmit to read properties of network packets being transmitted. Compilation works without errors but the program panicks when trying to load the probe program. In the probe program, I use the struct SkBuff from redbpf_probes::socket::SkBuff, which internally calls bpf_skb_load_bytes. When running it, it panicks with the error "unknown func bpf_skb_load_bytes":

         Running `target/debug/redbpf-tutorial`
    Nov 14 16:52:30.587 ERROR redbpf: error loading BPF program `__dev_queue_xmit' with bpf_load_program_xattr. ret=-1 os error=Invalid argument (os error 22): 0: (bf) r6 = r1
    1: (b7) r8 = 0
    2: (63) *(u32 *)(r10 -24) = r8
    last_idx 2 first_idx 0
    regs=100 stack=0 before 1: (b7) r8 = 0
    3: (7b) *(u64 *)(r10 -32) = r8
    4: (7b) *(u64 *)(r10 -40) = r8
    5: (7b) *(u64 *)(r10 -48) = r8
    6: (7b) *(u64 *)(r10 -56) = r8
    7: (7b) *(u64 *)(r10 -64) = r8
    8: (7b) *(u64 *)(r10 -72) = r8
    9: (7b) *(u64 *)(r10 -80) = r8
    10: (7b) *(u64 *)(r10 -88) = r8
    11: (7b) *(u64 *)(r10 -96) = r8
    12: (7b) *(u64 *)(r10 -104) = r8
    13: (7b) *(u64 *)(r10 -112) = r8
    14: (7b) *(u64 *)(r10 -120) = r8
    15: (7b) *(u64 *)(r10 -128) = r8
    16: (7b) *(u64 *)(r10 -136) = r8
    17: (7b) *(u64 *)(r10 -144) = r8
    18: (79) r7 = *(u64 *)(r6 +112)
    19: (85) call bpf_ktime_get_ns#5
    20: (7b) *(u64 *)(r10 -160) = r0
    21: (85) call bpf_get_current_pid_tgid#14
    22: (7b) *(u64 *)(r10 -152) = r0
    23: (7b) *(u64 *)(r10 -8) = r8
    24: (7b) *(u64 *)(r10 -16) = r8
    25: (bf) r1 = r10
    26: (07) r1 += -16
    27: (b7) r2 = 16
    28: (85) call bpf_get_current_comm#16
    last_idx 28 first_idx 22
    regs=4 stack=0 before 27: (b7) r2 = 16
    29: (79) r1 = *(u64 *)(r10 -8)
    30: (7b) *(u64 *)(r10 -128) = r1
    31: (79) r1 = *(u64 *)(r10 -16)
    32: (7b) *(u64 *)(r10 -136) = r1
    33: (bf) r3 = r10
    34: (07) r3 += -16
    35: (bf) r1 = r7
    36: (b7) r2 = 0
    37: (b7) r4 = 4
    38: (85) call bpf_skb_load_bytes#26
    unknown func bpf_skb_load_bytes#26
    processed 39 insns (limit 1000000) max_states_per_insn 0 total_states 1 peak_states 1 mark_read 1
    
    thread 'main' panicked at 'error on Loader::load: LoadError("__dev_queue_xmit", BPF)', src/main.rs:22:49
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace`
    
    

    I am not quite sure what the issue is here, I'd really appreciate any help!

    This is my system info:

    rustc 1.56.1
    llvm 13.0.0-3
    Kernel: Linux 5.10.78-1-lts
    
    opened by undvikar 20
  • Can't install with Amazon Linux 2 due to LLVM issue

    Can't install with Amazon Linux 2 due to LLVM issue

    I tried to set up a development env in Docker with RedBPF, using:

    FROM amazonlinux:2
    RUN curl https://sh.rustup.rs -sSf | \
            sh -s -- -y --default-toolchain stable && \
            PATH="/root/.cargo/bin:$PATH" rustup install stable
    RUN yum -y install clang-10.0.0 \
        llvm-10.0.0 \
        llvm-libs-10.0.0 \
        llvm-devel-10.0.0 \
        llvm-static-10.0.0 \
        kernel \
        kernel-devel \
        elfutils-libelf-devel \
        ca-certificates 
    RUN PATH="/root/.cargo/bin:$PATH" cargo install cargo-bpf
    ENV PATH $PATH:/root/.cargo/bin
    WORKDIR /tmp
    

    When I do a docker build this fails with:

    ...
    error: No suitable version of LLVM was found system-wide or pointed
           to by LLVM_SYS_100_PREFIX.
    
           Consider using `llvmenv` to compile an appropriate copy of LLVM, and
           refer to the llvm-sys documentation for more information.
    
           llvm-sys: https://crates.io/crates/llvm-sys
           llvmenv: https://crates.io/crates/llvmenv
       --> /root/.cargo/registry/src/github.com-1ecc6299db9ec823/llvm-sys-100.2.0/src/lib.rs:483:1
        |
    483 | / std::compile_error!(concat!(
    484 | |       "No suitable version of LLVM was found system-wide or pointed
    485 | |        to by LLVM_SYS_", env!("CARGO_PKG_VERSION_MAJOR"), "_PREFIX.
    486 | |
    ...   |
    490 | |        llvm-sys: https://crates.io/crates/llvm-sys
    491 | |        llvmenv: https://crates.io/crates/llvmenv"));
        | |____________________________________________________^
    
    error: aborting due to previous error
    
    error: could not compile `llvm-sys`.
    
    To learn more, run the command again with --verbose.
    warning: build failed, waiting for other jobs to finish...
    error: failed to compile `cargo-bpf v1.1.2`, intermediate artifacts can be found at `/tmp/cargo-installKGJVzw`
    

    Any idea what I'm doing wrong? I thought I got all the deps? 8-}

    Great project, BTW!

    wontfix 
    opened by mhausenblas 17
  • Segmentation fault in simple ebpf program

    Segmentation fault in simple ebpf program

    Running a program based on https://github.com/foniod/redbpf/blob/main/examples/example-probes/src/tcp_lifetime/main.rs with code:

    // This program can be executed by
    // # cargo run --example tcp-lifetime [interface]
    #![no_std]
    #![no_main]
    use core::mem::{self, MaybeUninit};
    use memoffset::offset_of;
    
    use redbpf_probes::socket_filter::prelude::*;
    
    use monitor::usage::{SocketAddr,message};
    
    #[map(link_section = "maps/perf_events")]
    static mut perf_events: PerfMap<message> = PerfMap::with_max_entries(1024);
    #[map(link_section = "maps/usage")]
    static mut usage: HashMap<u32, u32> = HashMap::with_max_entries(4096);
    
    #[map(link_section = "maps/time")]
    static mut time: HashMap<u32, u64> = HashMap::with_max_entries(4096);
    
    program!(0xFFFFFFFE, "GPL");
    #[socket_filter]
    fn measure_tcp_lifetime(skb: SkBuff) -> SkBuffResult {
        let eth_len = mem::size_of::<ethhdr>();
        let eth_proto = skb.load::<__be16>(offset_of!(ethhdr, h_proto))? as u32;
        if eth_proto != ETH_P_IP {
            return Ok(SkBuffAction::Ignore);
        }
    
        let ip_proto = skb.load::<__u8>(eth_len + offset_of!(iphdr, protocol))? as u32;
        if ip_proto != IPPROTO_TCP {
            return Ok(SkBuffAction::Ignore);
        }
    
        Ok(SkBuffAction::Ignore)
    }
    ´´´
    
    Gives a segmentation fault, however, used to work about a month ago don't know if it started to happen due to rust updates or redBPF updates.
    Thanks in Advance.
    opened by sebastiaoamaro 14
  • cargo bpf build block_http error: could not compile `redbpf-probes`.

    cargo bpf build block_http error: could not compile `redbpf-probes`.

    Centos7 3.10.0-1062.4.1.el7.x86_64 rust 1.39 clang version 9.0.0 (tags/RELEASE_900/final)

    cargo bpf build block_http Compiling redbpf-probes v0.9.6 error[E0588]: packed type cannot transitively contain a [repr(align)] type --> /home/alphapo/rust/hello-bpf/target/release/build/redbpf-probes-fcf682ba7259472e/out/gen_helpers.rs:977:1 | 977 | / pub struct desc_struct { 978 | | pub __bindgen_anon_1: desc_struct__bindgen_ty_1, 979 | | } | |_^

    error[E0587]: type has conflicting packed and align representation hints --> /home/alphapo/rust/hello-bpf/target/release/build/redbpf-probes-fcf682ba7259472e/out/gen_helpers.rs:5432:1 | 5432 | / pub struct xsave_struct { 5433 | | pub i387: i387_fxsave_struct, 5434 | | pub xsave_hdr: xsave_hdr_struct, 5435 | | pub ymmh: ymmh_struct, ... | 5439 | | pub __bindgen_padding_0: [u8; 48usize], 5440 | | } | |_^

    error: aborting due to 2 previous errors

    error: could not compile redbpf-probes.

    To learn more, run the command again with --verbose. error: failed to compile the `block_http' program

    opened by juaby 12
  • Loader.rs error

    Loader.rs error "Permission denied"

    Hi, again I am running a Kubernetes deployment with multiple pods (17), where one of them injects rust programs in the rest of them, these rust programs run eBPF stuff specifically a part where they load an eBPF program, however, 6 of them load the eBPF program without an issue and the rest of them give the following error:

    "thread 'async-std/runtime' panicked at 'called Result::unwrap() on an Err value: IO(Os { code: 1, kind: PermissionDenied, message: "Operation not permitted" })', redbpf/redbpf/src/load/loader.rs:51:67"

    After looking into the code I saw this was the line: let map = PerfMap::bind(m, -1, *cpuid, 16, -1, 0).unwrap();

    Bind is described here: https://github.com/foniod/redbpf/blob/c7f4b6811a2527ed033ec42aa34fe1d8cb4d97d4/redbpf/src/perf.rs#L274 The map section of the eBPF program (same for all Pods) loaded looks like this:

    #[map(link_section = "maps")]
    static mut perf_events: PerfMap<message> = PerfMap::with_max_entries(1024);
    #[map(link_section = "maps")]
    static mut usage: HashMap<u32, u32> = HashMap::with_max_entries(4096);
    
    #[map(link_section = "maps")]
    static mut time: HashMap<u32, u64> = HashMap::with_max_entries(4096);
    

    As a side note, this works completely fine in Docker, working in Docker, and the fact that 6 of them work makes this extremely confusing for me. Does anyone have any idea why this might happen or a way to continue debugging? Thanks in advance.

    opened by sebastiaoamaro 10
  • Multi distro build test

    Multi distro build test

    I come up with this PR when I ran into the build failure of #131. Because I tried building RedBPF only under my Pop OS, I could not recognize the build failures derived from other distros.

    And also by Dockerfile-alpine-20210212 this PR suggests the solution of #130.

    opened by rhdxmr 10
  • When are socket filters removed?

    When are socket filters removed?

    Hello everyone, I am running a program similar to this https://github.com/foniod/redbpf/blob/main/examples/example-userspace/examples/tcp-lifetime.rs I have a quick question, when are these socket filters removed? Or is there a certain way to remove them? (Didn't know where I could ask this, without creating an issue sorry if it is not supposed to be here) Thanks in advance.

    opened by sebastiaoamaro 9
  • HashMap Pinning for global maps

    HashMap Pinning for global maps

    Hello,

    As I am doing a tc program the creation of the map is not shared between user space and kernel space because we launch it with tc commands such as:

    tc qdisc add dev lo clsact
    
    sudo tc filter add dev lo ingress \
      bpf da obj target/bpf/programs/limit/limit.elf sec tc_action/limit
    

    So in order to share the file descriptor of the map created by this we need to do a global map in order to put it a global namespace so I can get it in other ebpf programs.

    To do that I see that I can modify the 'pinning' in the map options :

    /* This example has a pinning of PIN_OBJECT_NS, so it's private and
    * thus shared among various program sections within the object.
    *
    * A setting of PIN_GLOBAL_NS would place it into a global namespace,
    * so that it can be shared among different object files. A setting
    * of PIN_NONE (= 0) means no sharing, so each tc invocation a new map
    * instance is being created.
    */
    

    https://git.kernel.org/pub/scm/network/iproute2/iproute2-next.git/tree/examples/bpf/bpf_shared.c

    I saw in the documentation the implementation of Hash table map the High level API for BPF_MAP_TYPE_HASH maps

    impl<K, V> HashMap<K, V> {
        /// Creates a map with the specified maximum number of elements.
        pub const fn with_max_entries(max_entries: u32) -> Self {
            Self {
                def: bpf_map_def {
                    type_: bpf_map_type_BPF_MAP_TYPE_HASH,
                    key_size: mem::size_of::<K>() as u32,
                    value_size: mem::size_of::<V>() as u32,
                    max_entries,
                    map_flags: 0,
                },
                _k: PhantomData,
                _v: PhantomData,
            }
        }
    

    And in C they have the pinning options :

    struct bpf_elf_map {
        u32 type;
        u32 size_key;
        u32 size_value;
        u32 max_elem;
        u32 flags;
        u32 id;
        __u32 pinning;
    };
    
    

    Is it possible to choose the pinning value or there is pinning default value ? Can I retrieve the map fd with other solutions for the tc_action program ?

    Thank you

    opened by Dunateo 9
  • Soundness issues

    Soundness issues

    I was reading the post at https://blog.redsift.com/labs/writing-bpf-code-in-rust/ and started playing around with it. While debugging I glanced at the source code for Data::read here:

    https://github.com/redsift/redbpf/blob/master/redbpf-probes/src/xdp.rs#L236

        pub fn read<T>(&self) -> Option<T> {
            unsafe {
                let len = mem::size_of::<T>();
                if self.base.add(len) as *const u8 > (*self.ctx).data_end as *const u8 {
                    return None;
                }
                Some((self.base as *const T).read_unaligned())
            }
        }
    

    This function is not sound for all values of T and should at least be marked unsafe. Right beneath that is the MapData type which appears to be equally unsound and at the very least should have the payload method marked unsafe.

    These are just the first pieces of code I glanced at when trying to figure out what the http trace example in the blog post is doing, it is far from an exhaustive scan of the redbpf code base.

    Would you welcome changes that mark those API's unsafe?

    opened by ggriffiniii 9
  • Error Loading BPF program

    Error Loading BPF program

    Hi, I am trying to load this BPF program, however, I get the error: thread 'tokio-runtime-worker' panicked at 'error loading BPF program: LoadError("measure_tcp_lifetime", BPF)', In RedBPF as far as I am aware tracks to this block https://github.com/foniod/redbpf/blob/55331987dc31a26feb192e4a668bf9bfc336e1e0/redbpf/src/lib.rs#L727 This is the code in the program

    #![no_std]
    #![no_main]
    use core::mem::{self, MaybeUninit};
    use memoffset::offset_of;
    
    use redbpf_probes::socket_filter::prelude::*;
    
    use monitor::usage::{SocketAddr,message};
    
    //map to hold perf_events
    #[map(link_section = "maps")]
    static mut perf_events: PerfMap<message> = PerfMap::with_max_entries(512);
    
    //map to hold the bytes sent
    #[map(link_section = "maps")]
    static mut usage: HashMap<u32, u128> = HashMap::with_max_entries(4096);
    
    //map to hold time that has passed
    #[map(link_section = "maps")]
    static mut time: HashMap<u32, u64> = HashMap::with_max_entries(4096);
    
    program!(0xFFFFFFFE, "GPL");
    #[socket_filter]
    fn measure_tcp_lifetime(skb: SkBuff) -> SkBuffResult {
        let eth_len = mem::size_of::<ethhdr>();
        let eth_proto = skb.load::<__be16>(offset_of!(ethhdr, h_proto))? as u32;
        if eth_proto != ETH_P_IP {
            return Ok(SkBuffAction::Ignore);
        }
    
        let ip_proto = skb.load::<__u8>(eth_len + offset_of!(iphdr, protocol))? as u32;
        if ip_proto != IPPROTO_TCP {
            return Ok(SkBuffAction::Ignore);
        }
    
        let mut ip_hdr = unsafe { MaybeUninit::<iphdr>::zeroed().assume_init() };
        ip_hdr._bitfield_1 = __BindgenBitfieldUnit::new([skb.load::<u8>(eth_len)?]);
        if ip_hdr.version() != 4 {
            return Ok(SkBuffAction::Ignore);
        }
        //Retrieve IPs from skbuff
        let ihl = ip_hdr.ihl() as usize;
        let dst = SocketAddr::new(
            skb.load::<__be32>(eth_len + offset_of!(iphdr, daddr))?,
            skb.load::<__be16>(eth_len + ihl * 4 + offset_of!(tcphdr, dest))?,
        );
        //We send new values every 25 milli seconds for a given ip, via perf_events
        unsafe{
            //retrieve size of packet
            let len:u128 = ((*skb.skb).len).into();
            let currenttime = bpf_ktime_get_ns();
            match time.get(&dst.addr){
                None=>{
                    time.set(&dst.addr,&currenttime);
                },
                Some(oldtime)=>{
                    if currenttime-oldtime > 25000000{
                    //if currenttime-oldtime > 0{
                        match usage.get(&dst.addr){
                            None => usage.set(&dst.addr,&len),
                            Some(value) =>{
                                let newvalue:u128 = value + len;
                                usage.set(&dst.addr,&newvalue);
                                perf_events.insert(skb.skb as *mut __sk_buff,&message {dst:dst.addr,bytes:newvalue,}, );
                                time.set(&dst.addr,&currenttime);
                            }
                        }   
                    }else{
                        match usage.get(&dst.addr){
                            None => usage.set(&dst.addr,&len),
                            Some(value) =>{
                                let newvalue:u128 = value + len;
                                usage.set(&dst.addr,&newvalue);
                            }
                        }
                    }
                }
            }
        }
    
        Ok(SkBuffAction::Ignore)
    }
    

    I previously managed to get this program correctly loaded when I used u32 instead of u128, however, I need to change it now. Is there anything related to u128 that the kernel does not allow? Thank you in advance.

    opened by sebastiaoamaro 0
  • Runtime random error due to bad assert in crate zero?

    Runtime random error due to bad assert in crate zero?

    I got a strange error while testing the tutorial, related to the assert that checks for the alignment in the read_array function of the zero crate used by redbpf:

    pub fn read_array<T: Pod>(input: &[u8]) -> &[T] {
        let t_size = mem::size_of::<T>();
        assert!(t_size > 0, "Can't read arrays of zero-sized types");
        assert!(input.len() % t_size == 0);
        let addr = input.as_ptr() as usize;
        assert!(addr & (mem::align_of::<T>() - 1) == 0); // We speak of this assert that checks the alignment
    
        unsafe { read_array_unsafe(input) }
    }
    

    The error happens randomly, for example while commenting out the code that attach the probe to do_sys_openat2.

    I think redbpf was not affected until recently, as they pushed it a few days ago to crate.io (as explained here).

    A quick fix would be to call read_array_unsafe instead of read_array (same with all read occurrences, if any).

    But I'm not sure I understand why this assert fails.

    opened by dlescos 1
  • sym_offset calculation in attach uprobe fails to account to address differences

    sym_offset calculation in attach uprobe fails to account to address differences

    BPF probes want the offset of a symbol in the object file. In shared object and executable files, at least, the current logic seems to return the virtual address of the symbol as opposed to the offset in the object file.

    The st_value for a goblin::elf:sym::Sym with st_info of STT_FUNC (2) refers to the virtual memory address. In order to compute the offset, one needs to find the offset by translating it to be relative to the address of the section containing the symbol and then adding the offset of the section in the file.

    The offending code is:

    https://github.com/foniod/redbpf/blob/55331987dc31a26feb192e4a668bf9bfc336e1e0/redbpf/src/lib.rs#L965

    In some cases, the address of the symbol is its offset, but certainly not in all cases.

    See: https://github.com/iovisor/bpftrace/issues/1763#issuecomment-1238935968

    opened by ajwerner 1
  • ParseError(Reloc) on master

    ParseError(Reloc) on master

    I'm trying to run this program, which is compiled with clang:

    #include <linux/bpf.h>
    #define SEC(NAME) __attribute__((section(NAME), used))
    
    SEC("tracepoint/syscalls/sys_enter_execve")
    int bpf_prog(void *ctx) {
      char msg[] = "Hello, BPF World!\n";
      bpf_trace_printk(msg, sizeof(msg));
    
      return 0;
    }
    
    char _license[] SEC("license") = "GFPL";
    

    On version = "2.3.0" it seems to work, but tracepoints_mut() is not present and I think I need that to make the program do something. Loader::load() returns an Ok.

    On master it complains about this: ParseError(Reloc).

    I'm new to this so any advice is welcomed. Perhaps I should not load programs compiled from c with clang with this library.

    opened by JosuGZ 0
  • Minor release with tracepoints ?

    Minor release with tracepoints ?

    Hello,

    Thank you for your great work, this library is awesome. I am wondering whether you plan to do a minor release with tracepoints implemented because v2.3.0 does not ?

    Cheers,

    opened by qjerome 0
Releases(v2.3.0)
  • v2.3.0(Jan 9, 2022)

    Prevent some UB in probes

    While compiling BPF programs, raise an error if both two conditions are satisfied

    1. alignment of a value of a BPF map is greater than 8 bytes
    2. a BPF program calls get or get_mut method of the BPF map

    Creating misaligned references by itself causes undefined behavior in Rust language. The Linux kernel does not keep the alignment of value other than 8 byte alignment. Calling get or get_mut method of BPF maps creates references of values stored at BPF maps. Thus, calling get or get_mut creates misaligned references if the alignment of the value is greater than 8 bytes.

    RedBPF prevents this situation.

    Support ARM64(aarch64) architecture

    Build tests for ARM64 architecture are prepared and they are executed to check new commits are compiled correctly on both ARM64 and X86_64.

    Support DevMap for XDP BPF programs

    DevMap can be used when redirecting packets to another interface in XDP.

    Support BTF for tc utility

    Now BPF programs for tc can make use of BPF helpers that requires BTF. For example, bpf_spin_lock helper function.

    Bump up bindgen to 0.59.2

    Now fields of which name is try in C can be converted to Rust language. Some of the Linux kernel structures contain fields of which name is try.

    Add some safe wrappers of BPF helpers that never fail

    Update BPF program template

    Contributors

    Thank you very much for your contribution.

    • @ihciah
    • @kriomant
    • @rhdxmr
    • @rsdy
    Source code(tar.gz)
    Source code(zip)
  • v2.2.0(Nov 17, 2021)

    Here are the added features of v2.2.0 since the last release (v2.1.0)

    Remove .text section from ELF relocatable file

    The ELF relocatable files compiled by cargo-bpf had contained .text section. This section is totally ignored by RedBPF runtime but it is bothersome when users try loading the ELF relocatable file with tc utility. Because tc rejects loading the ELF object file if the file has .text section.

    Now .text section does not exist in the ELF relocatable file. So users who try using tc_action don't need to strip the .text section in person.

    • PR #224

    Add PerCPuHashMap, LruHashMap and LruPerCpuHashMap

    They are implemented both for BPF probes and userspace API in the redbpf_probes::maps and in the redbpf.

    • PR #215

    Add redbpf::SkLookup

    This structure can be used to attach BPF program for socket lookup to specific network namespace.

    Note that it is implemented only in the redbpf crate for userspace API. The API for BPF probes is not supported yet. It is expected that probes API will be added later.

    • PR #216

    Add redbpf::XDP::detach_xdp method

    Now users can detach XDP BPF probes programmatically.

    • PR #211

    Update the tutorial

    Some users had struggled with RedBPF because they had not enough background of RedBPF. So some information that they should know before they were in trouble, was updated into the tutorial.

    Please let me know what part of RedBPF bothers you. I'll answer your question and keep update the documentation.

    • PR #217

    Support the Linux kernel v5.15

    Since the Linux kernel v5.15, the vmlinux includes struct bpf_timer. Before v2.2.0, RedBPF failed to generate right rust bindings of Linux kernel v5.15 with vmlinux.

    • PR #223

    Use docs.rs

    Packages uploaded to crates.io starts to give documentation URL of docs.rs. docs.rs is regular place to serve crates' documentation.

    • PR #225

    Contributors

    Thank you for showing your interest in RedBPF and contributing to it. I was delighted to collaborate with you.

    @eero-thia @raftario @rhdxmr @rsdy

    Source code(tar.gz)
    Source code(zip)
  • v2.1.0(Oct 29, 2021)

    • Add BPF iterator for task struct
    • Allow unsafe function as BPF programs
    • Support recovering original function parameters in retprobe
    • Allow defining multiple maps in maps section
    • Support LLVM 13 to allow rust >= 1.56
    • Fix for generating documentation in docs.rs
    • Recompile redbpf-probes when KERNEL_SOURCE, KERNEL_VERSION and REDBPF_VMLINUX environments variables are changed

    Contributors

    @p-e-w @rhdxmr @rsdy

    Source code(tar.gz)
    Source code(zip)
  • v2.0.2(Sep 25, 2021)

  • v2.0.1(Aug 29, 2021)

  • v2.0.0(Aug 24, 2021)

    The foniod community edition

    This release marks our departure from the original home of the project, Red Sift. After the donation of redBPF and ingraind to the Cloud Native Computing Foundation, the two projects are now maintained by the foniod community. As part of the CNCF, we are independent self-governed project, with no corporate affiliation.

    Since April, development is also not sponsored by the orignal developer, Red Sift. We would like to thank everybody who supported and advocated for the transition, and those who continue to support the project with their time and effort to make this release possible.

    foniod is named after fonio, an ancient grain. foniod marks a continuity with ingraind, the previous name. Very importantly, fonio was chosen just because it ends with IO.

    Our new logo was kindly made by the CNCF's designer team.

    Most of the code in this release is the work of Junyeong Jeong (@rhdxmr), and reviewed by Peter Parkanyi (@rsdy).

    If you're keen to get involved, please reach us on matrix, or take a peek at our subreddit.

    Now, let's move on to the meat of this release, and all the goods that are in it!

    Support vmlinux for BTF information

    In the past, the running Linux kernel's headers were necessary to generate Rust bindings for the kernel structs that BPF programs use.

    With the new support for BTF, if build machines have a usable vmlinux kernel image, redBPF can generate Rust bindings from it and then BPF programs can be compiled without access to the source.

    The required behaviour can be set using environment variables. If redBPF users do not set any environment variables during compilation, redBPF will first tries to find the kernel sources. If it fails, it will try to find the vmlinux image.

    If REDBPF_VMLINUX is set, then redBPF tries compiling only with vmlinux.

    If either KERNEL_SOURCE or KERNEL_VERSION variables are set, redBPF will use the path or version for generating bindings.

    Refer to the documentation of redbpf-probes/lib.rs for more information.

    Support BTF for BPF maps

    redBPF can now parse a .BTF section in a relocatable ELF file to load BPF maps with BTF enabled. Users can now dump BPF map as JSON format when they use bpftool map dump command.

    Pin maps with Map::pin

    pin, unpin and from_pin_file methods were added to redbpf::Map. A BPF map can be pinned to a given file path under the BPF filesystem by calling Map::pin. It can then be unpinned by calling Map::unpin or by removing the file directly. Normally BPF filesystem is mounted at /sys/fs/bpf.

    See sharemap example to learn how to use map pinning features.

    Use LLVM 12

    redBPF uses LLVM 12 as default. LLVM 11 can be used instead with enabling llvm11 and disabling default-features in Cargo.toml.

    Add SockMap

    A sockmap supports the redirection of packets to another socket.

    #[stream_parser] can be used to define a stream parser and #[stream_verdict] is for a stream verdict.

    See the echo example to learn how to use sockmap.

    Add Array and PerCpuArray

    Array is a kind of BPF map that can contain a fixed length of elements. PerCpuArray is the same except that it is allocated with per-CPU memory in the kernel so users do not need to worry about data races.

    See the biolatpcts example to learn how to use PerCpuArray

    Load a maps section created by libbpf

    If a relocatable ELF file contains a maps, redBPF will assume that multiple maps are defined in that section. This is the structure libbpf generates, and it helps with interoperability between the libraries.

    Introduce ModuleBuilder

    Using redbpf::Module::parse to parse a relocatable ELF file will load maps and programs. Now with the addition of redbpf::ModuleBuilder, redBPF allows splitting the parsing and loading as separate steps, so users can manipulate maps or programs before loading them.

    See the sharemap2 example to learn how to use ModuleBuilder.

    Modify kprobe/uprobe detachable

    redbpf::KProbe::detach_kprobe and redbpf::UProbe::detach_uprobe methods were added. kprobe/uprobe can be repeatedly attached and detached.

    Fix TcAction variants

    TcAction is updated. The variants were outdated because they referred to the old manpage.

    Add TcHashMap

    BPF program loaded by tc utility can handle BPF map using redbpf_probes::tc::maps::TcHashMap. Corresponding userspace programs that rely on redBPF can also communicate with the maps by loading them with Map::from_pin_file. See tc-map-share example to learn how to do that.

    Check EUID

    Examples require root privileges and it checks euid is zero, not uid.

    Remove BCC dependency

    redBPF had depended on BCC and libbpf. But BCC dependency is removed.

    Support NixOS

    redBPF can be used in NixOS

    Support Alpine Linux

    redBPF can be used in Alpine Linux

    Upgrade Tokio to 1.0

    redBPF depends on Tokio v1

    Upgrade libbpf

    redBPF now depends on the latest libbpf

    Comply DCO

    Contributors of redbpf must conform to Developer Certificate Origin for their commits to be accepted. So contributors should append Signed-off-by to commit messages.

    Add more examples

    To aid users to understand how to use redBPF, several examples are added.

    Use tracing crate

    redBPF now utilizes tracing crate to record debug or error logs. redBPF users can subscribe log messages using tracing_subscriber crate.

    See any examples of example-userspace to learn how to subscribe to log messages of redBPF.

    Contributors

    Contribution stats after v1.3.0

    • @rhdxmr Junyeong Jeong
    • @Escapingbug Anciety
    • @belltoy belltoy
    • @jvns Julia Evans
    • @kbknapp Kevin K
    • @lwintermelon lwintermelon
    • @p-e-w Philipp Emanuel Weidmann
    • @rsdy Peter Parkanyi
    Source code(tar.gz)
    Source code(zip)
  • v2.0.0-rc3(Aug 15, 2021)

  • v2.0.0-rc2(Aug 13, 2021)

  • v2.0.0-rc1(Aug 9, 2021)

  • v1.3.0(Dec 7, 2020)

    This is a pretty exciting release with some long overdue improvements. First off, better handling of relocations in the loader make writing idiomatic programs a lot easier, thanks to the work of @alessandrod. To make development faster, there's also an awesome patchset by @kbknapp that speeds up the build.

    On top of that, the TC/libbpf compatibility improved in this release, so you can manually add multiple maps to the same ELF section using an improved API, thanks to @kbknapp. Improved examples are also added to the repo through the work of @rhdxmr

    Contributors: @alessandrod @kbknapp @rhdxmr @shun159

    Thanks to everyone who contributed to this release! Happy hacking!

    Source code(tar.gz)
    Source code(zip)
  • v1.2.0(Oct 28, 2020)

    1.2.0 is a significant release, with many improvements regarding build stability, and some new features!

    Probably the most important feature is support for LLVM11 through libllvm, which allows us to target and track Rust LLVM versions in a more flexible way, and actually support the latest stable compilers. There's also support for using RedBPF-based programs in TC, and BPF Stack Traces.

    Contributors: @alessandrod @aquarhead @digikata @neallred @quininer @rsdy

    Many thanks to everyone who contributed to this release!

    Source code(tar.gz)
    Source code(zip)
  • v1.1.2(Sep 16, 2020)

    This release includes a bug fix for a bad interaction between Red Hat kernel macros and cargo-bpf's accessor generation logic. The fix ensures that there's always at most one accessor generated based on macros. In addition, RedBPF now uses the latest bindgen version across all crates.

    This release includes new packages for cargo-bpf, bpf-sys, and redbpf.

    Source code(tar.gz)
    Source code(zip)
  • v1.1.1(Aug 25, 2020)

    This release contains a single patch that includes an improved way of detecting kernel version during build, making it also work on Debian.

    Only bpf-sys and cargo-bpf 1.1.1 have been published, other crates are unaffected.

    Source code(tar.gz)
    Source code(zip)
  • v1.1.0(Aug 22, 2020)

    This release updates the build scripts so RedBPF projects now compile on kernels 5.7 and newer.

    In addition, a new kernel_version cfg variable is available for probe code that allows conditional compilation for different versions. Currently, kernel_version will take up the major and minor versions of Linux (e.g "5.4", "5.7") or "5.7" for kernels newer than "5.7". This allows customizing probe code based on features supported by the kernel and gracefully degrade capabilities.

    This release includes new versions of cargo-bpf, bpf-sys, redbpf, redbpf-macros, and redbpf-probes.

    Re-tagging this release to include the version bump in redbpf-probes and redbpf-macros.

    Source code(tar.gz)
    Source code(zip)
  • v1.0.0(Apr 1, 2020)

    This has been a long time coming, and as of 1.0.0 onwards we commit to following semver rules in releases. This will make the lives of everyone easier, and finally allows us to build applications on stable APIs.

    New release notes after 1.0 will also list the API changes, and generally be more diligent about the features that have arrived.

    Compared to the latest 0.9 release, in 1.0 we cleaned up a few APIs, and brought uprobe support to RedBPF.

    There's also an official website that hosts the documentation: https://ingraind.org

    Source code(tar.gz)
    Source code(zip)
  • v0.9.13(Mar 4, 2020)

    This release focused on improving the documentation around the project, and add better examples using RedBPF without ingraind.

    Another big addition is the redbpf_tools collection of example programs that use RedBPF. See iotop and knock.

    Additionally, all docs are now under https://ingraind.org/api.

    Additional changes:

    • Improve reliability of loop unrolling
    • Expose a high-level, typesafe Map/HashMap API
    • Add use redbpf_probes::xdp::prelude::* as a best practice to start probes. Also works for kprobe, and socket_filter to make imports easier
    • rename redpbf_probes::xdp::Result to redbpf_probes::xdp::XdpResult
    • rename redbpf::LoadError to redbpf::Error
    Source code(tar.gz)
    Source code(zip)
  • v0.9.10(Feb 11, 2020)

    This release changed quite a few APIs and fixed unsoundness issues.

    • Add support for socket filters
    • Improved binding management
    • Add support for panic!() macro
    • Rework XDP accessors so we don't require a copy
    • Fix ARM64 builds
    • Fix unsoundness issues
    Source code(tar.gz)
    Source code(zip)
  • v0.9.7(Dec 20, 2019)

    This release changes the license to allow companies to adapt RedBPF more easily.

    Other changes improve API improvements across the board, and added support for better Kprobe handling.

    Source code(tar.gz)
    Source code(zip)
  • v0.9.0(Oct 31, 2019)

    This release adds experimental support for eBPF probes written completely in Rust.

    Notably missing is thorough documentation at this stage, which will be added on the 0.9 branch as we stabilise 1.0.

    Source code(tar.gz)
    Source code(zip)
  • v0.3.3(Sep 3, 2019)

    This is change is backwards compatible on x86_64, therefore this is just a maintenance release. 0.3.3 add support for building on arm64 on kernels <5.0.

    Source code(tar.gz)
    Source code(zip)
  • v0.3.2(Aug 19, 2019)

  • v0.3.1(Aug 9, 2019)

  • v0.3(Aug 9, 2019)

    • Makes bpf-sys build against upstream libbpf
    • Makes bpf-sys run bindgen from build.rs
    • Support using kernel tree from $KERNEL_SOURCE or /lib/modules/$KERNEL_VERSION/build. $KERNEL_VERSION defaults to uname -r.
    • Makes loading bpf programs work on Ubuntu/Debian by setting the correct kernel version as reported in /proc/version_signature.
    Source code(tar.gz)
    Source code(zip)
  • v0.2.0(Feb 14, 2019)

Owner
foniod
foniod -- a Rust-based eBPF agent
foniod
A simple scanner that loops through ips and checks if a minecraft server is running on port 25565

scanolotl Scanolotl is a simple scanner that loops through ips and checks if a minecraft server is running on port 25565. Scanolotl can also preform a

JustFr33z 3 Jul 28, 2022
Checks whether the process is running as root/sudo/admin permission in Windows and Unix systems

Is_sudo Checks if program is running as sudo in unix systems, or using admin permission in windows. Usage use is_sudo::check; use is_sudo::RunningAs;

Spark 2 Aug 12, 2022
A library for building tools to determine if vulnerabilities are reachable in a code base.

Overview Vuln Reach is a library for developing tools that determine if a given vulnerability is reachable. Provided to the open source community by P

Phylum 3 May 5, 2023
Secure transport for running MPC protocols backed by Signal

MPC over Signal Overview This library provides a high-level interface for connecting to Signal Server and using it to exchange messages with other con

[ZenGo X] 42 Jan 4, 2023
Xori is an automation-ready disassembly and static analysis library for PE32, 32+ and shellcode

Xori - Custom disassembly framework Xori is an automation-ready disassembly and static analysis library that consumes shellcode or PE binaries and pro

ENDGAME 712 Nov 28, 2022
Advanced Fuzzing Library - Slot your Fuzzer together in Rust! Scales across cores and machines. For Windows, Android, MacOS, Linux, no_std, ...

LibAFL, the fuzzer library. Advanced Fuzzing Library - Slot your own fuzzers together and extend their features using Rust. LibAFL is written and main

Advanced Fuzzing League ++ 1.2k Jan 6, 2023
Mundane is a Rust cryptography library backed by BoringSSL that is difficult to misuse, ergonomic, and performant (in that order).

Mundane Mundane is a Rust cryptography library backed by BoringSSL that is difficult to misuse, ergonomic, and performant (in that order). Issues and

Google 1.1k Jan 3, 2023
Linux anti-debugging and anti-analysis rust library

DebugOff Library Linux anti-analysis Rust library The goal of this library is to make both static and dynamic (debugging) analysis more difficult. The

null 65 Jan 7, 2023
A rust library for sharing and updating arbitrary slices between threads, optimized for wait-free reads

atomicslice A Rust library for thread-safe shared slices that are just about as fast as possible to read while also being writable. Overview Use Atomi

Tim Straubinger 5 Dec 6, 2023
unfuck is a utility and library for deobfuscating obfuscated Python 2.7 bytecode

unfuck is a utility and library for deobfuscating obfuscated Python 2.7 bytecode. It is essentially a reimplementation of the Python VM with taint tracking.

Lander Brandt 171 Dec 14, 2022
CVEs for the Rust standard library

Rust CVE Preface This is a list of CVEs for unsound APIs in the Rust standard library. These bugs break Rust's memory safety guarantee and lead to sec

Yechan Bae 26 Dec 4, 2022
Rust library for developing safe canisters.

IC Kit This library provides an alternative to ic-cdk that can help developers write canisters and unit test them in their Rust code. Install Add this

Psychedelic 26 Nov 28, 2022
QuickCheck bug hunting in Rust standard library data structures

BugHunt, Rust This project is aiming to provide "stateful" QuickCheck models for Rust's standard library. That is, we build up a random list of operat

Brian L. Troutwine 161 Dec 15, 2022
A simple rust library for working with ZIP archives

rust-zip A simple rust library to read and write Zip archives, which is also my pet project for learning Rust. At the moment you can list the files in

Jorge Gorbe Moya 11 Aug 6, 2022
An attempt to rewrite lite-client for TON Blockchain in Rust using ton-labs-adnl library.

An attempt to rewrite lite-client for TON Blockchain in Rust using ton-labs-adnl library.

TonStack 4 Nov 9, 2022
A new shellcode injection technique. Given as C++ header, standalone Rust program or library.

FunctionStomping Description This is a brand-new technique for shellcode injection to evade AVs and EDRs. This technique is inspired by Module Stompin

Ido Veltzman 608 Jan 4, 2023
Extended precision integer Rust library. Provides signed/unsigned integer 256 to 2048.

Extended precision integer Rust library. Provides signed/unsigned integer 256 to 2048.

Mohanson 4 Jul 28, 2022
An R interface to Rust's h3o library

h3o h3o is a system-dependency free package to interact with the H3 Geospatial Indexing system by Uber. h3o utilizes the Rust library h3o with is a pu

Josiah Parry 5 Mar 27, 2023
Kepler is a vulnerability database and lookup store and API currently utilising National Vulnerability Database and NPM Advisories as data sources

Kepler — Kepler is a vulnerability database and lookup store and API currently utilising National Vulnerability Database and NPM Advisories as data so

Exein.io 101 Nov 12, 2022