From 929c067362b12826f324bcff525e59717f6bd349 Mon Sep 17 00:00:00 2001 From: Mikhail Trishchenkov Date: Mon, 7 Feb 2022 22:25:20 +0700 Subject: [PATCH 1/5] Use libbpf-sys Signed-off-by: Mikhail Trishchenkov --- README.md | 7 -- bpf-sys/Cargo.toml | 1 + bpf-sys/build.rs | 85 ------------------------ bpf-sys/src/lib.rs | 12 ---- bpf-sys/src/perf_reader.rs | 13 ---- bpf-sys/src/type_gen.rs | 24 ++++--- cargo-bpf/Cargo.toml | 3 +- redbpf-probes/Cargo.toml | 1 + redbpf/Cargo.toml | 1 + redbpf/src/btf.rs | 4 +- redbpf/src/lib.rs | 128 ++++++++++++++++++------------------- redbpf/src/xdp.rs | 10 +-- 12 files changed, 92 insertions(+), 197 deletions(-) delete mode 100644 bpf-sys/src/perf_reader.rs diff --git a/README.md b/README.md index 50fc9ea0..d9cb6a1d 100644 --- a/README.md +++ b/README.md @@ -269,13 +269,6 @@ It describes build tests of RedBPF that run inside docker containers. # License -This repository contains code from other software in the following -directories, licensed under their own particular licenses: - - * `bpf-sys/libbpf`: LGPL2 + BSD-2 - -Where '+' means they are dual licensed. - RedBPF and its components, unless otherwise stated, are licensed under either of * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or diff --git a/bpf-sys/Cargo.toml b/bpf-sys/Cargo.toml index 21a53da1..8526b05e 100644 --- a/bpf-sys/Cargo.toml +++ b/bpf-sys/Cargo.toml @@ -16,6 +16,7 @@ zero = "0.1" libc = "0.2" regex = { version = "1.5" } glob = "0.3.0" +libbpf-sys = "0.6.1-2" [build-dependencies] cc = "1.0" diff --git a/bpf-sys/build.rs b/bpf-sys/build.rs index d6e31261..9e8705a0 100644 --- a/bpf-sys/build.rs +++ b/bpf-sys/build.rs @@ -5,90 +5,5 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -#![deny(clippy::all)] -use std::env; -use std::path::PathBuf; -use std::process::Command; - -pub mod uname { - include!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/uname.rs")); -} - -pub mod headers { - include!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/headers.rs")); -} - -fn rerun_if_changed_dir(dir: &str) { - println!("cargo:rerun-if-changed={}/", dir); - for ext in &["c", "h", "bash", "map", "md", "rst", "sh", "template"] { - glob::glob(&format!("./{}/**/*.{}", dir, ext)) - .expect("Failed to glob for source files from build.rs") - .filter_map(|e| e.ok()) - .for_each(|path| println!("cargo:rerun-if-changed={}", path.to_string_lossy())); - } -} - fn main() { - println!( - "cargo:rustc-link-search=native={}", - env::var("OUT_DIR").unwrap() - ); - println!("cargo:rustc-link-lib=static=bpf"); - println!("cargo:rustc-link-lib=elf"); - println!("cargo:rustc-link-lib=z"); - - rerun_if_changed_dir("libbpf"); - println!("cargo:rerun-if-changed=bpfsys-musl.h"); - println!("cargo:rerun-if-changed=libbpf_xdp.h"); - - let out_dir = env::var("OUT_DIR").unwrap(); - let out_path = PathBuf::from(out_dir); - - // -fPIE is passed because Fedora 35 requires it. Other distros like Ubuntu - // 21.04, Alpine 3.14 also works fine with it - if !Command::new("make") - .args(format!("-C libbpf/src BUILD_STATIC_ONLY=1 OBJDIR={out_dir}/libbpf DESTDIR={out_dir} INCLUDEDIR= LIBDIR= UAPIDIR=", out_dir=env::var("OUT_DIR").unwrap()).split(" ")) - .arg("CFLAGS=-g -O2 -Werror -Wall -fPIC") - .arg("install") - .status() - .expect("error on executing `make` command for building `libbpf` static library") - .success() { - panic!("failed to build `libbpf` static library"); - } - let bindings = bindgen::Builder::default() - .header("libbpf_xdp.h") - .header("libbpf/src/bpf.h") - .header("libbpf/src/libbpf.h") - .header("libbpf/include/uapi/linux/btf.h") - .header("libbpf/src/btf.h") - .clang_arg("-Ilibbpf/src") - .clang_arg("-Ilibbpf/include/uapi") - .clang_arg("-Ilibbpf/include") - // blacklist `bpf_map_def` to avoid conflict with libbpf_map_def.rs - .blocklist_type("bpf_map_def") - .generate() - .expect("Unable to generate bindings"); - bindings - .write_to_file(out_path.join("libbpf_bindings.rs")) - .expect("Couldn't write bindings!"); - let bindings = bindgen::Builder::default() - .header("libbpf/src/libbpf.h") - .clang_arg("-Ilibbpf/include/uapi") - .clang_arg("-Ilibbpf/include") - .allowlist_type("bpf_map_def") - .generate() - .expect("Unable to generate bindings"); - bindings - .write_to_file(out_path.join("libbpf_map_def.rs")) - .expect("Couldn't write bindings!"); - let bindings = bindgen::Builder::default() - .header("libbpf/src/bpf.h") - .clang_arg("-Ilibbpf/src") - .clang_arg("-Ilibbpf/include/uapi") - .clang_arg("-Ilibbpf/include") - .generate() - .expect("Unable to generate bindings"); - bindings - .write_to_file(out_path.join("perf_reader_bindings.rs")) - .expect("Couldn't write bindings!"); } diff --git a/bpf-sys/src/lib.rs b/bpf-sys/src/lib.rs index c2de7ea9..c01a0348 100644 --- a/bpf-sys/src/lib.rs +++ b/bpf-sys/src/lib.rs @@ -5,19 +5,7 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -#![allow(non_camel_case_types)] -#![allow(non_upper_case_globals)] -#![allow(non_snake_case)] -#![allow(clippy::all)] - -extern crate zero; pub mod headers; -pub mod perf_reader; pub mod uname; -include!(concat!(env!("OUT_DIR"), "/libbpf_bindings.rs")); -include!(concat!(env!("OUT_DIR"), "/libbpf_map_def.rs")); -unsafe impl ::zero::Pod for bpf_map_def {} -unsafe impl ::zero::Pod for bpf_insn {} - pub mod type_gen; diff --git a/bpf-sys/src/perf_reader.rs b/bpf-sys/src/perf_reader.rs deleted file mode 100644 index 6c702cda..00000000 --- a/bpf-sys/src/perf_reader.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2019 Authors of Red Sift -// -// Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be -// copied, modified, or distributed except according to those terms. - -#![allow(non_camel_case_types)] -#![allow(non_upper_case_globals)] -#![allow(non_snake_case)] -#![allow(clippy::all)] - -include!(concat!(env!("OUT_DIR"), "/perf_reader_bindings.rs")); diff --git a/bpf-sys/src/type_gen.rs b/bpf-sys/src/type_gen.rs index 33fb29d7..096c7daa 100644 --- a/bpf-sys/src/type_gen.rs +++ b/bpf-sys/src/type_gen.rs @@ -18,10 +18,10 @@ syntax. So macro constants can not be generated from vmlinux image. But system. */ -use super::{ +use libbpf_sys::{ btf, btf__free, btf__get_nr_types, btf__name_by_offset, btf__parse_elf, btf__parse_raw, btf__type_by_id, btf_dump, btf_dump__dump_type, btf_dump__free, btf_dump__new, btf_dump_opts, - libbpf_find_kernel_btf, vdprintf, + libbpf_find_kernel_btf, __va_list_tag, }; use libc::{c_char, c_void}; use regex::RegexSet; @@ -36,6 +36,14 @@ use std::path::PathBuf; use std::ptr; pub const ENV_VMLINUX_PATH: &'static str = "REDBPF_VMLINUX"; +extern "C" { + fn vdprintf( + __fd: libc::c_int, + __fmt: *const c_char, + __arg: *mut __va_list_tag + ) -> libc::c_int; +} + // only used for RAII struct RawFdWrapper(RawFd); impl Drop for RawFdWrapper { @@ -194,16 +202,16 @@ impl VmlinuxBtfDump { None }; unsafe { - let dump_opts = { + let mut dump_opts = { let mut uninit = MaybeUninit::::zeroed(); - (*uninit.as_mut_ptr()).ctx = &mut rawfd as *mut _ as *mut _; + (*uninit.as_mut_ptr()).__bindgen_anon_1.ctx = &mut rawfd as *mut _ as *mut _; uninit.assume_init() }; let dumpptr = btf_dump__new( self.btfptr, - ptr::null(), - &dump_opts as *const _, - Some(vdprintf_wrapper), + None, + &mut dump_opts as *const _ as *mut _, + vdprintf_wrapper as *const _, ); if (dumpptr as isize) < 0 { return Err(TypeGenError::DumpError); @@ -250,7 +258,7 @@ impl Drop for VmlinuxBtfDump { unsafe extern "C" fn vdprintf_wrapper( ctx: *mut c_void, format: *const c_char, - va_list: *mut super::__va_list_tag, + va_list: *mut __va_list_tag, ) { let rawfd_wrapper = &*(ctx as *mut RawFdWrapper); vdprintf(rawfd_wrapper.0, format, va_list); diff --git a/cargo-bpf/Cargo.toml b/cargo-bpf/Cargo.toml index bbb268f7..8196d51a 100644 --- a/cargo-bpf/Cargo.toml +++ b/cargo-bpf/Cargo.toml @@ -22,6 +22,7 @@ required-features = ["command-line"] clap = { version = "2.33", optional = true } bindgen = {version = "0.59.2", default-features = false, features = ["runtime"], optional = true} toml_edit = { version = "0.2", optional = true } +libbpf-sys = { version = "0.6.1-2", optional = true } bpf-sys = { version = "2.3.0", path = "../bpf-sys", optional = true } redbpf = { version = "2.3.0", path = "../redbpf", default-features = false, optional = true } futures = { version = "0.3", optional = true } @@ -49,7 +50,7 @@ cfg-if = "1.0.0" [features] default = ["command-line", "llvm-sys"] -bindings = ["bpf-sys", "bindgen", "syn", "quote", "proc-macro2", "tempfile"] +bindings = ["libbpf-sys", "bpf-sys", "bindgen", "syn", "quote", "proc-macro2", "tempfile"] build = ["bindings", "libc", "toml_edit", "redbpf"] docsrs-llvm = ["llvm-sys-130/no-llvm-linking", "llvm-sys-130/disable-alltargets-init"] build-c = [] diff --git a/redbpf-probes/Cargo.toml b/redbpf-probes/Cargo.toml index be2d9823..89bdf42c 100644 --- a/redbpf-probes/Cargo.toml +++ b/redbpf-probes/Cargo.toml @@ -18,6 +18,7 @@ ufmt = { version = "0.1.0", default-features = false } [build-dependencies] cargo-bpf = { version = "2.3.0", path = "../cargo-bpf", default-features = false, features = ["bindings"] } bpf-sys = { version = "2.3.0", path = "../bpf-sys" } +libbpf-sys = "0.6.1-2" syn = {version = "1.0", default-features = false, features = ["parsing", "visit"] } quote = "1.0" glob = "0.3.0" diff --git a/redbpf/Cargo.toml b/redbpf/Cargo.toml index 89ea0bae..0c0a755f 100644 --- a/redbpf/Cargo.toml +++ b/redbpf/Cargo.toml @@ -16,6 +16,7 @@ maintenance = { status = "actively-developed" } [dependencies] bpf-sys = { path = "../bpf-sys", version = "2.3.0" } +libbpf-sys = "0.6.1-2" goblin = "0.4" zero = "0.1" libc = "0.2" diff --git a/redbpf/src/btf.rs b/redbpf/src/btf.rs index 12816ce8..5581a523 100644 --- a/redbpf/src/btf.rs +++ b/redbpf/src/btf.rs @@ -19,7 +19,7 @@ use std::ptr; use std::slice; use tracing::{debug, error, warn}; -use bpf_sys::{ +use libbpf_sys::{ btf_array, btf_enum, btf_header, btf_member, btf_param, btf_type, btf_var, btf_var_secinfo, BTF_INT_BOOL, BTF_INT_CHAR, BTF_INT_SIGNED, BTF_KIND_ARRAY, BTF_KIND_CONST, BTF_KIND_DATASEC, BTF_KIND_ENUM, BTF_KIND_FLOAT, BTF_KIND_FUNC, BTF_KIND_FUNC_PROTO, BTF_KIND_FWD, BTF_KIND_INT, @@ -129,7 +129,7 @@ impl BTF { let log_buf_size = v.capacity() * mem::size_of_val(&v[0]); let fd; unsafe { - fd = bpf_sys::bpf_load_btf( + fd = libbpf_sys::bpf_load_btf( raw_bytes.as_ptr() as *const _, raw_bytes.len() as u32, log_buf as _, diff --git a/redbpf/src/lib.rs b/redbpf/src/lib.rs index c6543e1d..356529a3 100644 --- a/redbpf/src/lib.rs +++ b/redbpf/src/lib.rs @@ -55,14 +55,14 @@ pub mod sys; pub mod xdp; pub use bpf_sys::uname; -use bpf_sys::{ - bpf_attach_type_BPF_SK_LOOKUP, bpf_attach_type_BPF_SK_SKB_STREAM_PARSER, - bpf_attach_type_BPF_SK_SKB_STREAM_VERDICT, bpf_attach_type_BPF_TRACE_ITER, bpf_create_map_attr, +use libbpf_sys::{ + BPF_SK_LOOKUP, BPF_SK_SKB_STREAM_PARSER, + BPF_SK_SKB_STREAM_VERDICT, BPF_TRACE_ITER, bpf_create_map_attr, bpf_create_map_xattr, bpf_insn, bpf_iter_create, bpf_link_create, bpf_load_program_xattr, - bpf_map_def, bpf_map_info, bpf_map_type_BPF_MAP_TYPE_ARRAY, bpf_map_type_BPF_MAP_TYPE_HASH, - bpf_map_type_BPF_MAP_TYPE_LRU_HASH, bpf_map_type_BPF_MAP_TYPE_LRU_PERCPU_HASH, - bpf_map_type_BPF_MAP_TYPE_PERCPU_ARRAY, bpf_map_type_BPF_MAP_TYPE_PERCPU_HASH, - bpf_map_type_BPF_MAP_TYPE_PERF_EVENT_ARRAY, bpf_prog_type, BPF_ANY, + bpf_map_def, bpf_map_info, BPF_MAP_TYPE_ARRAY, BPF_MAP_TYPE_HASH, + BPF_MAP_TYPE_LRU_HASH, BPF_MAP_TYPE_LRU_PERCPU_HASH, + BPF_MAP_TYPE_PERCPU_ARRAY, BPF_MAP_TYPE_PERCPU_HASH, + BPF_MAP_TYPE_PERF_EVENT_ARRAY, bpf_prog_type, BPF_ANY, }; use goblin::elf::{reloc::RelocSection, section_header as hdr, Elf, SectionHeader, Sym}; @@ -256,7 +256,7 @@ pub struct TaskIter { /// ```no_run /// # static SK_LOOKUP: &[u8] = &[]; /// use std::net::TcpListener; -/// use std::os::unix::io::AsRawFd +/// use std::os::unix::io::AsRawFd; /// /// use redbpf::{HashMap, SockMap}; /// use redbpf::load::Loader; @@ -265,11 +265,11 @@ pub struct TaskIter { /// let mut loaded = Loader::load(SK_LOOKUP).unwrap(); /// /// // Pass the listener fd to the BPF program -/// let mut socket = SockMap::new(loaded.map("socket")).unwrap(); +/// let mut socket = SockMap::new(loaded.map("socket").unwrap()).unwrap(); /// socket.set(0, listener.as_raw_fd()); /// /// // Pass our port range to the BPF program -/// let mut ports = HashMap::::new(loaded.map("ports")).unwrap(); +/// let mut ports = HashMap::::new(loaded.map("ports").unwrap()).unwrap(); /// for port in 80..430 { /// ports.set(port, 1); /// } @@ -458,7 +458,7 @@ trait MapIterable { impl Program { #[allow(clippy::unnecessary_wraps)] fn new(kind: &str, name: &str, code: &[u8]) -> Result { - let code = zero::read_array(code).to_vec(); + let code = unsafe { zero::read_array_unsafe(code) }.to_vec(); let name = name.to_string(); let common = ProgramData { @@ -502,7 +502,7 @@ impl Program { } fn with_btf(kind: &str, name: &str, code: &[u8], btf: &BTF) -> Result { - let code = zero::read_array(code).to_vec(); + let code = unsafe { zero::read_array_unsafe(code) }.to_vec(); let name = name.to_string(); let common = ProgramData { @@ -532,14 +532,14 @@ impl Program { match self { KProbe(_) | KRetProbe(_) | UProbe(_) | URetProbe(_) => { - bpf_sys::bpf_prog_type_BPF_PROG_TYPE_KPROBE + libbpf_sys::BPF_PROG_TYPE_KPROBE } - XDP(_) => bpf_sys::bpf_prog_type_BPF_PROG_TYPE_XDP, - SocketFilter(_) => bpf_sys::bpf_prog_type_BPF_PROG_TYPE_SOCKET_FILTER, - TracePoint(_) => bpf_sys::bpf_prog_type_BPF_PROG_TYPE_TRACEPOINT, - StreamParser(_) | StreamVerdict(_) => bpf_sys::bpf_prog_type_BPF_PROG_TYPE_SK_SKB, - TaskIter(_) => bpf_sys::bpf_prog_type_BPF_PROG_TYPE_TRACING, - SkLookup(_) => bpf_sys::bpf_prog_type_BPF_PROG_TYPE_SK_LOOKUP, + XDP(_) => libbpf_sys::BPF_PROG_TYPE_XDP, + SocketFilter(_) => libbpf_sys::BPF_PROG_TYPE_SOCKET_FILTER, + TracePoint(_) => libbpf_sys::BPF_PROG_TYPE_TRACEPOINT, + StreamParser(_) | StreamVerdict(_) => libbpf_sys::BPF_PROG_TYPE_SK_SKB, + TaskIter(_) => libbpf_sys::BPF_PROG_TYPE_TRACING, + SkLookup(_) => libbpf_sys::BPF_PROG_TYPE_SK_LOOKUP, } } @@ -606,7 +606,7 @@ impl Program { let cname = CString::new(self.name().clone())?; let clicense = CString::new(license)?; - let mut attr = unsafe { mem::zeroed::() }; + let mut attr = unsafe { mem::zeroed::() }; attr.prog_type = self.to_prog_type(); attr.name = cname.as_ptr(); @@ -617,11 +617,11 @@ impl Program { match self { Program::TaskIter(bpf_iter) => { - attr.expected_attach_type = bpf_attach_type_BPF_TRACE_ITER; + attr.expected_attach_type = BPF_TRACE_ITER; attr.__bindgen_anon_2.attach_btf_id = bpf_iter.attach_btf_id; } Program::SkLookup(_) => { - attr.expected_attach_type = bpf_attach_type_BPF_SK_LOOKUP; + attr.expected_attach_type = BPF_SK_LOOKUP; attr.__bindgen_anon_1.kern_version = kernel_version; } _ => { @@ -670,7 +670,7 @@ impl Program { let mut buf_vec = vec![0; vec_len]; let log_buffer: MutDataPtr = buf_vec.as_mut_ptr(); let buf_size = buf_vec.capacity() * mem::size_of_val(unsafe { &*log_buffer }); - let fd = unsafe { bpf_sys::bpf_load_program_xattr(&attr, log_buffer, buf_size as u64) }; + let fd = unsafe { libbpf_sys::bpf_load_program_xattr(&attr, log_buffer, buf_size as u64) }; if fd >= 0 { warn!( "bpf_load_program_xattr had failed but it unexpectedly succeeded while reproducing the error" @@ -746,7 +746,7 @@ fn pin_bpf_obj(fd: RawFd, file: impl AsRef) -> Result<()> { fs::create_dir_all(dir)?; unsafe { let cpathname = CString::new(file.to_str().unwrap())?; - if bpf_sys::bpf_obj_pin(fd, cpathname.as_ptr()) != 0 { + if libbpf_sys::bpf_obj_pin(fd, cpathname.as_ptr()) != 0 { error!("error on bpf_obj_pin: {}", io::Error::last_os_error()); Err(Error::IO(io::Error::last_os_error())) } else { @@ -1094,7 +1094,7 @@ unsafe fn attach_xdp(dev_name: &str, progfd: libc::c_int, flags: libc::c_uint) - return Err(Error::IO(io::Error::last_os_error())); } - if bpf_sys::bpf_set_link_xdp_fd(ifindex, progfd, flags) != 0 { + if libbpf_sys::bpf_set_link_xdp_fd(ifindex, progfd, flags) != 0 { return Err(Error::IO(io::Error::last_os_error())); } Ok(()) @@ -1159,7 +1159,7 @@ impl SkLookup { return Err(Error::IO(io::Error::last_os_error())); } - let lfd = bpf_link_create(fd, nfd, bpf_attach_type_BPF_SK_LOOKUP, ptr::null()); + let lfd = bpf_link_create(fd, nfd, BPF_SK_LOOKUP, ptr::null()); if lfd < 0 { libc::close(nfd); return Err(Error::IO(io::Error::last_os_error())); @@ -1693,10 +1693,10 @@ impl RelocationInfo { // the index of the instruction we need to patch if map.section_data { - code[insn_idx].set_src_reg(bpf_sys::BPF_PSEUDO_MAP_VALUE as u8); + code[insn_idx].set_src_reg(libbpf_sys::BPF_PSEUDO_MAP_VALUE as u8); code[insn_idx + 1].imm = code[insn_idx].imm + sym.st_value as i32; } else { - code[insn_idx].set_src_reg(bpf_sys::BPF_PSEUDO_MAP_FD as u8); + code[insn_idx].set_src_reg(libbpf_sys::BPF_PSEUDO_MAP_FD as u8); } code[insn_idx].imm = map.fd; Ok(()) @@ -1714,7 +1714,7 @@ impl RelocationInfo { let insn_idx = (self.offset / std::mem::size_of::() as u64) as usize; let code = &mut prog.data_mut().code; let map = symval_to_maps.get(&sym.st_value).ok_or(Error::Reloc)?; - code[insn_idx].set_src_reg(bpf_sys::BPF_PSEUDO_MAP_FD as u8); + code[insn_idx].set_src_reg(libbpf_sys::BPF_PSEUDO_MAP_FD as u8); code[insn_idx].imm = map.fd; Ok(()) } @@ -1722,7 +1722,7 @@ impl RelocationInfo { impl Map { pub fn load(name: &str, code: &[u8]) -> Result { - let config: bpf_map_def = *zero::read(code); + let config: bpf_map_def = *unsafe { zero::read_unsafe(code) }; Map::with_map_def(name, config, None) } @@ -1730,7 +1730,7 @@ impl Map { let mut map = Map::with_map_def( name, bpf_map_def { - type_: bpf_sys::bpf_map_type_BPF_MAP_TYPE_ARRAY, + type_: libbpf_sys::BPF_MAP_TYPE_ARRAY, key_size: mem::size_of::() as u32, value_size: data.len() as u32, max_entries: 1, @@ -1742,7 +1742,7 @@ impl Map { // for BSS we don't need to copy the data, it's already 0-initialized if name != ".bss" { unsafe { - let ret = bpf_sys::bpf_map_update_elem( + let ret = libbpf_sys::bpf_map_update_elem( map.fd, &mut 0 as *mut _ as *mut _, data.as_ptr() as *mut u8 as *mut _, @@ -1830,7 +1830,7 @@ impl Map { let file = file.as_ref(); let fd = unsafe { let cpathname = CString::new(file.to_str().unwrap())?; - bpf_sys::bpf_obj_get(cpathname.as_ptr()) + libbpf_sys::bpf_obj_get(cpathname.as_ptr()) }; if fd < 0 { error!("error on bpf_obj_get: {}", io::Error::last_os_error()); @@ -1839,7 +1839,7 @@ impl Map { let map_info = unsafe { let mut info = mem::zeroed::(); let mut info_len = mem::size_of_val(&info) as u32; - if bpf_sys::bpf_obj_get_info_by_fd(fd, &mut info as *mut _ as *mut _, &mut info_len) + if libbpf_sys::bpf_obj_get_info_by_fd(fd, &mut info as *mut _ as *mut _, &mut info_len) != 0 { error!( @@ -1972,7 +1972,7 @@ impl<'a> MapBuilder<'a> { name.as_ref(), bytes, if name.starts_with(".rodata") { - bpf_sys::BPF_F_RDONLY_PROG + libbpf_sys::BPF_F_RDONLY_PROG } else { 0 }, @@ -1986,8 +1986,8 @@ impl<'base, K: Clone, V: Clone> HashMap<'base, K, V> { pub fn new(base: &Map) -> Result> { if mem::size_of::() != base.config.key_size as usize || mem::size_of::() != base.config.value_size as usize - || (bpf_map_type_BPF_MAP_TYPE_HASH != base.config.type_ - && bpf_map_type_BPF_MAP_TYPE_PERF_EVENT_ARRAY != base.config.type_) + || (BPF_MAP_TYPE_HASH != base.config.type_ + && BPF_MAP_TYPE_PERF_EVENT_ARRAY != base.config.type_) { error!( "map definitions (map type and key/value size) of base `Map' and @@ -2038,7 +2038,7 @@ impl<'base, K: Clone, V: Clone> LruHashMap<'base, K, V> { pub fn new(base: &Map) -> Result> { if mem::size_of::() != base.config.key_size as usize || mem::size_of::() != base.config.value_size as usize - || bpf_map_type_BPF_MAP_TYPE_LRU_HASH != base.config.type_ + || BPF_MAP_TYPE_LRU_HASH != base.config.type_ { error!( "map definitions (map type and key/value sizes) of base `Map' and `LruHashMap' do not match" @@ -2088,7 +2088,7 @@ impl<'base, K: Clone, V: Clone> PerCpuHashMap<'base, K, V> { pub fn new(base: &Map) -> Result> { if mem::size_of::() != base.config.key_size as usize || mem::size_of::() != base.config.value_size as usize - || bpf_map_type_BPF_MAP_TYPE_PERCPU_HASH != base.config.type_ + || BPF_MAP_TYPE_PERCPU_HASH != base.config.type_ { error!("map definitions (size of key/value and map type) of base `Map' and `PerCpuHashMap' do not match"); return Err(Error::Map); @@ -2150,7 +2150,7 @@ impl<'base, K: Clone, V: Clone> LruPerCpuHashMap<'base, K, V> { pub fn new(base: &Map) -> Result> { if mem::size_of::() != base.config.key_size as usize || mem::size_of::() != base.config.value_size as usize - || bpf_map_type_BPF_MAP_TYPE_LRU_PERCPU_HASH != base.config.type_ + || BPF_MAP_TYPE_LRU_PERCPU_HASH != base.config.type_ { error!("map definitions (size of key/value and map type) of base `Map' and `LruPerCpuHashMap' do not match"); return Err(Error::Map); @@ -2212,7 +2212,7 @@ impl<'base, T: Clone> Array<'base, T> { /// Create `Array` map from `base` pub fn new(base: &Map) -> Result> { if mem::size_of::() != base.config.value_size as usize - || bpf_map_type_BPF_MAP_TYPE_ARRAY != base.config.type_ + || BPF_MAP_TYPE_ARRAY != base.config.type_ { error!( "map definitions (size of value, map type) of base `Map' and @@ -2232,7 +2232,7 @@ impl<'base, T: Clone> Array<'base, T> { /// This method can fail if `index` is out of bound pub fn set(&self, mut index: u32, mut value: T) -> Result<()> { let rv = unsafe { - bpf_sys::bpf_map_update_elem( + libbpf_sys::bpf_map_update_elem( self.base.fd, &mut index as *mut _ as *mut _, &mut value as *mut _ as *mut _, @@ -2253,7 +2253,7 @@ impl<'base, T: Clone> Array<'base, T> { pub fn get(&self, mut index: u32) -> Option { let mut value = MaybeUninit::zeroed(); if unsafe { - bpf_sys::bpf_map_lookup_elem( + libbpf_sys::bpf_map_lookup_elem( self.base.fd, &mut index as *mut _ as *mut _, &mut value as *mut _ as *mut _, @@ -2336,7 +2336,7 @@ impl DerefMut for PerCpuValues { impl<'base, T: Clone> PerCpuArray<'base, T> { pub fn new(base: &Map) -> Result> { if mem::size_of::() != base.config.value_size as usize - || bpf_map_type_BPF_MAP_TYPE_PERCPU_ARRAY != base.config.type_ + || BPF_MAP_TYPE_PERCPU_ARRAY != base.config.type_ { error!( "map definitions (size of value, map type) of base `Map' and @@ -2376,7 +2376,7 @@ impl<'base, T: Clone> PerCpuArray<'base, T> { } } let rv = unsafe { - bpf_sys::bpf_map_update_elem( + libbpf_sys::bpf_map_update_elem( self.base.fd, &mut index as *mut _ as *mut _, &mut ptr as *mut _ as *mut _, @@ -2406,7 +2406,7 @@ impl<'base, T: Clone> PerCpuArray<'base, T> { let mut alloc = vec![0u8; alloc_size]; let ptr = alloc.as_mut_ptr(); if unsafe { - bpf_sys::bpf_map_lookup_elem( + libbpf_sys::bpf_map_lookup_elem( self.base.fd, &mut index as *mut _ as *mut _, ptr as *mut _, @@ -2452,7 +2452,7 @@ impl<'base> ProgramArray<'base> { pub fn get(&self, mut index: u32) -> Result { let mut fd: RawFd = 0; if unsafe { - bpf_sys::bpf_map_lookup_elem( + libbpf_sys::bpf_map_lookup_elem( self.base.fd, &mut index as *mut _ as *mut _, &mut fd as *mut _ as *mut _, @@ -2484,7 +2484,7 @@ impl<'base> ProgramArray<'base> { /// ``` pub fn set(&mut self, mut index: u32, mut fd: RawFd) -> Result<()> { let ret = unsafe { - bpf_sys::bpf_map_update_elem( + libbpf_sys::bpf_map_update_elem( self.base.fd, &mut index as *mut _ as *mut _, &mut fd as *mut _ as *mut _, @@ -2526,7 +2526,7 @@ impl StackTrace<'_> { unsafe { let mut value = MaybeUninit::uninit(); - let ret = bpf_sys::bpf_map_lookup_elem( + let ret = libbpf_sys::bpf_map_lookup_elem( self.base.fd, &mut id as *const _ as *mut _, value.as_mut_ptr() as *mut _, @@ -2542,7 +2542,7 @@ impl StackTrace<'_> { pub fn delete(&mut self, id: i64) -> Result<()> { unsafe { - let ret = bpf_sys::bpf_map_delete_elem(self.base.fd, &id as *const _ as *mut _); + let ret = libbpf_sys::bpf_map_delete_elem(self.base.fd, &id as *const _ as *mut _); if ret == 0 { Ok(()) @@ -2569,10 +2569,10 @@ impl StreamParser { let prog_fd = self.common.fd.unwrap(); let ret = unsafe { - bpf_sys::bpf_prog_attach( + libbpf_sys::bpf_prog_attach( prog_fd, attach_fd, - bpf_attach_type_BPF_SK_SKB_STREAM_PARSER, + BPF_SK_SKB_STREAM_PARSER, 0, ) }; @@ -2600,10 +2600,10 @@ impl StreamVerdict { let prog_fd = self.common.fd.unwrap(); let ret = unsafe { - bpf_sys::bpf_prog_attach( + libbpf_sys::bpf_prog_attach( prog_fd, attach_fd, - bpf_attach_type_BPF_SK_SKB_STREAM_VERDICT, + BPF_SK_SKB_STREAM_VERDICT, 0, ) }; @@ -2622,7 +2622,7 @@ impl<'a> SockMap<'a> { pub fn set(&mut self, mut idx: u32, mut fd: RawFd) -> Result<()> { let ret = unsafe { - bpf_sys::bpf_map_update_elem( + libbpf_sys::bpf_map_update_elem( self.base.fd, &mut idx as *mut _ as *mut _, &mut fd as *mut _ as *mut _, @@ -2638,7 +2638,7 @@ impl<'a> SockMap<'a> { pub fn delete(&mut self, mut idx: u32) -> Result<()> { let ret = - unsafe { bpf_sys::bpf_map_delete_elem(self.base.fd, &mut idx as *mut _ as *mut _) }; + unsafe { libbpf_sys::bpf_map_delete_elem(self.base.fd, &mut idx as *mut _ as *mut _) }; if ret < 0 { Err(Error::Map) } else { @@ -2697,7 +2697,7 @@ impl TaskIter { bpf_link_create( self.common.fd.unwrap(), 0, - bpf_attach_type_BPF_TRACE_ITER, + BPF_TRACE_ITER, ptr::null(), ) }; @@ -2777,7 +2777,7 @@ fn data<'d>(bytes: &'d [u8], shdr: &SectionHeader) -> &'d [u8] { fn bpf_map_set(fd: RawFd, mut key: K, mut value: V) -> Result<()> { if unsafe { - bpf_sys::bpf_map_update_elem( + libbpf_sys::bpf_map_update_elem( fd, &mut key as *mut _ as *mut _, &mut value as *mut _ as *mut _, @@ -2794,7 +2794,7 @@ fn bpf_map_set(fd: RawFd, mut key: K, mut value: V) -> Resul fn bpf_map_get(fd: RawFd, mut key: K) -> Option { let mut value = MaybeUninit::zeroed(); if unsafe { - bpf_sys::bpf_map_lookup_elem( + libbpf_sys::bpf_map_lookup_elem( fd, &mut key as *mut _ as *mut _, &mut value as *mut _ as *mut _, @@ -2807,7 +2807,7 @@ fn bpf_map_get(fd: RawFd, mut key: K) -> Option { } fn bpf_map_delete(fd: RawFd, mut key: K) -> Result<()> { - if unsafe { bpf_sys::bpf_map_delete_elem(fd, &mut key as *mut _ as *mut _) } < 0 { + if unsafe { libbpf_sys::bpf_map_delete_elem(fd, &mut key as *mut _ as *mut _) } < 0 { Err(Error::Map) } else { Ok(()) @@ -2818,7 +2818,7 @@ fn bpf_map_get_next_key(fd: RawFd, key: Option) -> Option { if let Some(mut key) = key { let mut next_key = MaybeUninit::::zeroed(); let ret = unsafe { - bpf_sys::bpf_map_get_next_key( + libbpf_sys::bpf_map_get_next_key( fd, &mut key as *mut _ as *mut _, &mut next_key as *mut _ as *mut _, @@ -2831,7 +2831,7 @@ fn bpf_map_get_next_key(fd: RawFd, key: Option) -> Option { } } else { let mut key = MaybeUninit::::zeroed(); - if unsafe { bpf_sys::bpf_map_get_next_key(fd, ptr::null(), &mut key as *mut _ as *mut _) } + if unsafe { libbpf_sys::bpf_map_get_next_key(fd, ptr::null(), &mut key as *mut _ as *mut _) } < 0 { None @@ -2864,7 +2864,7 @@ fn bpf_percpu_map_set( } } if unsafe { - bpf_sys::bpf_map_update_elem( + libbpf_sys::bpf_map_update_elem( fd, &mut key as *mut _ as *mut _, &mut data as *mut _ as *mut _, @@ -2886,7 +2886,7 @@ fn bpf_percpu_map_get(fd: RawFd, mut key: K) -> Option DevMap<'a> { pub fn new(base: &'a Map) -> Result> { if mem::size_of::() != base.config.key_size as usize || mem::size_of::() != base.config.value_size as usize - || (bpf_map_type_BPF_MAP_TYPE_DEVMAP != base.config.type_) + || (BPF_MAP_TYPE_DEVMAP != base.config.type_) { error!( "map definitions (map type and key/value size) of base `Map' and @@ -92,7 +92,7 @@ impl<'a> DevMap<'a> { pub fn set(&mut self, mut idx: u32, mut interface_index: u32) -> Result<()> { let ret = unsafe { - bpf_sys::bpf_map_update_elem( + libbpf_sys::bpf_map_update_elem( self.base.fd, &mut idx as *mut _ as *mut _ as *mut _, &mut interface_index as *mut _ as *mut _, @@ -108,7 +108,7 @@ impl<'a> DevMap<'a> { pub fn delete(&mut self, mut idx: u32) -> Result<()> { let ret = - unsafe { bpf_sys::bpf_map_delete_elem(self.base.fd, &mut idx as *mut _ as *mut _) }; + unsafe { libbpf_sys::bpf_map_delete_elem(self.base.fd, &mut idx as *mut _ as *mut _) }; if ret < 0 { Err(Error::Map) } else { From 6b47c284fabc7b92c468c488d6c5dc67091cbb4d Mon Sep 17 00:00:00 2001 From: Junyeong Jeong Date: Fri, 18 Feb 2022 00:08:11 +0900 Subject: [PATCH 2/5] Use libbpf binding for btf_dump__new btf_dump__new is passed btf_dump_printf_fn_t that requires va_list. The implementation of va_list differs depending on architectures but libbpf-sys only supports amd64 bindings. The actual type of va_list in x86-64 is struct __va_list_tag. And va_list in aarch64 is [u64; 4usize]. For now It is uncertain that using __va_list_tag in aarch64 is okay. So keep using libbpf bindings only for functions relevant with va_list. Bump up libbpf to v0.6.1 since libbpf-sys uses it. Signed-off-by: Junyeong Jeong --- bpf-sys/bindings.h | 2 ++ bpf-sys/build.rs | 18 +++++++++++++ bpf-sys/libbpf | 2 +- bpf-sys/src/lib.rs | 7 ++++++ bpf-sys/src/type_gen.rs | 56 ++++++++++++++--------------------------- 5 files changed, 47 insertions(+), 38 deletions(-) create mode 100644 bpf-sys/bindings.h diff --git a/bpf-sys/bindings.h b/bpf-sys/bindings.h new file mode 100644 index 00000000..0ec64d04 --- /dev/null +++ b/bpf-sys/bindings.h @@ -0,0 +1,2 @@ +#include +#include diff --git a/bpf-sys/build.rs b/bpf-sys/build.rs index 9e8705a0..e3df01fb 100644 --- a/bpf-sys/build.rs +++ b/bpf-sys/build.rs @@ -4,6 +4,24 @@ // http://apache.org/licenses/LICENSE-2.0> or the MIT license , at your option. This file may not be // copied, modified, or distributed except according to those terms. +use bindgen; +use std::env; +use std::path::PathBuf; fn main() { + let out_dir = env::var("OUT_DIR").unwrap(); + let out_path = PathBuf::from(out_dir); + + let bindings = bindgen::Builder::default() + .header("bindings.h") + .clang_arg("-Ilibbpf/src") + .clang_arg("-Ilibbpf/include/uapi") + .clang_arg("-Ilibbpf/include") + .allowlist_function("btf_dump__new") + .allowlist_function("vdprintf") + .generate() + .expect("Unable to generate bindings"); + bindings + .write_to_file(out_path.join("libbpf_bindings.rs")) + .expect("Couldn't write bindings!"); } diff --git a/bpf-sys/libbpf b/bpf-sys/libbpf index 6e6f18ac..56794b31 160000 --- a/bpf-sys/libbpf +++ b/bpf-sys/libbpf @@ -1 +1 @@ -Subproject commit 6e6f18ac5d811706b6fa5416c07b22f22d972b32 +Subproject commit 56794b31eea0a6245f194b5915e3ed867be144fe diff --git a/bpf-sys/src/lib.rs b/bpf-sys/src/lib.rs index c01a0348..3723b4c4 100644 --- a/bpf-sys/src/lib.rs +++ b/bpf-sys/src/lib.rs @@ -9,3 +9,10 @@ pub mod headers; pub mod uname; pub mod type_gen; + +// FIXME: Remove libbpf_bindings in favor of libbpf-sys +mod libbpf_bindings { + #![allow(non_camel_case_types)] + #![allow(dead_code)] + include!(concat!(env!("OUT_DIR"), "/libbpf_bindings.rs")); +} diff --git a/bpf-sys/src/type_gen.rs b/bpf-sys/src/type_gen.rs index 096c7daa..8a018b1e 100644 --- a/bpf-sys/src/type_gen.rs +++ b/bpf-sys/src/type_gen.rs @@ -18,10 +18,10 @@ syntax. So macro constants can not be generated from vmlinux image. But system. */ +use super::libbpf_bindings; use libbpf_sys::{ btf, btf__free, btf__get_nr_types, btf__name_by_offset, btf__parse_elf, btf__parse_raw, - btf__type_by_id, btf_dump, btf_dump__dump_type, btf_dump__free, btf_dump__new, btf_dump_opts, - libbpf_find_kernel_btf, __va_list_tag, + btf__type_by_id, btf_dump, btf_dump__dump_type, btf_dump__free, libbpf_find_kernel_btf, }; use libc::{c_char, c_void}; use regex::RegexSet; @@ -29,21 +29,13 @@ use std::env; use std::ffi::{CStr, CString}; use std::fs::File; use std::io::{self, Write}; -use std::mem::{self, MaybeUninit}; +use std::mem; use std::os::unix::io::{FromRawFd, IntoRawFd, RawFd}; use std::path::Path; use std::path::PathBuf; use std::ptr; pub const ENV_VMLINUX_PATH: &'static str = "REDBPF_VMLINUX"; -extern "C" { - fn vdprintf( - __fd: libc::c_int, - __fmt: *const c_char, - __arg: *mut __va_list_tag - ) -> libc::c_int; -} - // only used for RAII struct RawFdWrapper(RawFd); impl Drop for RawFdWrapper { @@ -202,21 +194,16 @@ impl VmlinuxBtfDump { None }; unsafe { - let mut dump_opts = { - let mut uninit = MaybeUninit::::zeroed(); - (*uninit.as_mut_ptr()).__bindgen_anon_1.ctx = &mut rawfd as *mut _ as *mut _; - uninit.assume_init() - }; - let dumpptr = btf_dump__new( - self.btfptr, - None, - &mut dump_opts as *const _ as *mut _, - vdprintf_wrapper as *const _, + let dumpptr = libbpf_bindings::btf_dump__new( + self.btfptr as _, + Some(vdprintf_wrapper), + &mut rawfd as *mut _ as *mut _, + ptr::null(), ); if (dumpptr as isize) < 0 { return Err(TypeGenError::DumpError); } - let dumpptr = BtfDumpWrapper(dumpptr); + let dumpptr = BtfDumpWrapper(dumpptr as _); for type_id in 1..=btf__get_nr_types(self.btfptr) { let btftypeptr = btf__type_by_id(self.btfptr, type_id); let nameptr = btf__name_by_offset(self.btfptr, (*btftypeptr).name_off); @@ -253,27 +240,22 @@ impl Drop for VmlinuxBtfDump { } } +// FIXME: remove libbpf_bindings in favor of libbpf-sys // wrapping vdprintf to get rid of return type -#[cfg(not(any(target_arch = "arm", target_arch = "aarch64")))] -unsafe extern "C" fn vdprintf_wrapper( - ctx: *mut c_void, - format: *const c_char, - va_list: *mut __va_list_tag, -) { - let rawfd_wrapper = &*(ctx as *mut RawFdWrapper); - vdprintf(rawfd_wrapper.0, format, va_list); -} - -// wrapping vdprintf to get rid of return type -#[cfg(any(target_arch = "arm", target_arch = "aarch64"))] unsafe extern "C" fn vdprintf_wrapper( ctx: *mut c_void, format: *const c_char, - #[cfg(target_env = "musl")] va_list: super::__isoc_va_list, - #[cfg(not(target_env = "musl"))] va_list: super::__gnuc_va_list, + #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] + #[cfg(target_env = "musl")] + va_list: libbpf_bindings::__isoc_va_list, + #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] + #[cfg(not(target_env = "musl"))] + va_list: libbpf_bindings::__gnuc_va_list, + #[cfg(not(any(target_arch = "arm", target_arch = "aarch64")))] + va_list: *mut libbpf_bindings::__va_list_tag, ) { let rawfd_wrapper = &*(ctx as *mut RawFdWrapper); - vdprintf(rawfd_wrapper.0, format, va_list); + libbpf_bindings::vdprintf(rawfd_wrapper.0, format, va_list); } pub fn get_custom_vmlinux_path() -> Option { From f41b29c1741ddb81f9af304e7364dd7b257296c0 Mon Sep 17 00:00:00 2001 From: Junyeong Jeong Date: Fri, 18 Feb 2022 01:25:41 +0900 Subject: [PATCH 3/5] Generate binding for struct unix_sock for probes Signed-off-by: Junyeong Jeong --- redbpf-probes/build.rs | 2 ++ redbpf-probes/include/redbpf_helpers.h | 1 + 2 files changed, 3 insertions(+) diff --git a/redbpf-probes/build.rs b/redbpf-probes/build.rs index bf73ef4a..6504a575 100644 --- a/redbpf-probes/build.rs +++ b/redbpf-probes/build.rs @@ -83,6 +83,7 @@ fn generate_bindings_kernel_headers() -> Result<()> { "__sk_.*", "sk_.*", "inet_sock", + "unix_sock", "sockaddr", "sockaddr_in", "in_addr", @@ -181,6 +182,7 @@ fn generate_bindings_vmlinux() -> Result<()> { "^__sk_.*", "^sk_.*", "^inet_sock$", + "^unix_sock$", "^sockaddr$", "^sockaddr_in$", "^in_addr$", diff --git a/redbpf-probes/include/redbpf_helpers.h b/redbpf-probes/include/redbpf_helpers.h index c0fd9509..c7e3c13c 100644 --- a/redbpf-probes/include/redbpf_helpers.h +++ b/redbpf-probes/include/redbpf_helpers.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include "xdp.h" #include "bpf_iter.h" From 87fae7c32f9d7a534a8f5732b3f3ca3f91642ffe Mon Sep 17 00:00:00 2001 From: Junyeong Jeong Date: Fri, 18 Feb 2022 23:14:22 +0900 Subject: [PATCH 4/5] libbpf is still used to generate bpf helpers by redbpf-probes Signed-off-by: Junyeong Jeong --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index d9cb6a1d..50fc9ea0 100644 --- a/README.md +++ b/README.md @@ -269,6 +269,13 @@ It describes build tests of RedBPF that run inside docker containers. # License +This repository contains code from other software in the following +directories, licensed under their own particular licenses: + + * `bpf-sys/libbpf`: LGPL2 + BSD-2 + +Where '+' means they are dual licensed. + RedBPF and its components, unless otherwise stated, are licensed under either of * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or From c2b4dcb31dfd55ea1fe95573126ae840085f1bc5 Mon Sep 17 00:00:00 2001 From: Junyeong Jeong Date: Sat, 19 Feb 2022 01:24:42 +0900 Subject: [PATCH 5/5] Fix bug Signed-off-by: Junyeong Jeong --- redbpf/src/lib.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/redbpf/src/lib.rs b/redbpf/src/lib.rs index 38967c9d..b6c481ad 100644 --- a/redbpf/src/lib.rs +++ b/redbpf/src/lib.rs @@ -2369,7 +2369,7 @@ impl<'base, T: Clone> PerCpuArray<'base, T> { let value_size = round_up::(8); let alloc_size = value_size * count; let mut alloc = vec![0u8; alloc_size]; - let mut data = alloc.as_mut_ptr(); + let data = alloc.as_mut_ptr(); for i in 0..count { unsafe { let dst_ptr = data.add(value_size * i) as *mut T; @@ -2857,7 +2857,7 @@ fn bpf_percpu_map_set( let value_size = round_up::(8); let alloc_size = value_size * count; let mut alloc = vec![0u8; alloc_size]; - let mut data = alloc.as_mut_ptr(); + let data = alloc.as_mut_ptr(); for i in 0..count { unsafe { let dst_ptr = data.add(value_size * i) as *mut V; @@ -2866,12 +2866,7 @@ fn bpf_percpu_map_set( } if unsafe { - libbpf_sys::bpf_map_update_elem( - fd, - &mut key as *mut _ as *mut _, - &mut data as *mut _ as *mut _, - 0, - ) + libbpf_sys::bpf_map_update_elem(fd, &mut key as *mut _ as *mut _, data as *mut _, 0) } < 0 { Err(Error::Map)