Browse Source

Merge pull request #1073 from dave-tucker/reloc-bug

fix(aya): BSS Sections must be filled with zeros
Dave Tucker 4 months ago
parent
commit
b2ac9fe85d

+ 13 - 1
aya-obj/src/obj.rs

@@ -5,6 +5,7 @@ use alloc::{
     collections::BTreeMap,
     ffi::CString,
     string::{String, ToString},
+    vec,
     vec::Vec,
 };
 use core::{ffi::CStr, mem, ptr, slice::from_raw_parts_mut, str::FromStr};
@@ -1193,7 +1194,7 @@ fn get_map_field(btf: &Btf, type_id: u32) -> Result<u32, BtfError> {
 // bytes and are relocated based on their section index.
 fn parse_data_map_section(section: &Section) -> Result<Map, ParseError> {
     let (def, data) = match section.kind {
-        EbpfSectionKind::Bss | EbpfSectionKind::Data | EbpfSectionKind::Rodata => {
+        EbpfSectionKind::Data | EbpfSectionKind::Rodata => {
             let def = bpf_map_def {
                 map_type: BPF_MAP_TYPE_ARRAY as u32,
                 key_size: mem::size_of::<u32>() as u32,
@@ -1210,6 +1211,17 @@ fn parse_data_map_section(section: &Section) -> Result<Map, ParseError> {
             };
             (def, section.data.to_vec())
         }
+        EbpfSectionKind::Bss => {
+            let def = bpf_map_def {
+                map_type: BPF_MAP_TYPE_ARRAY as u32,
+                key_size: mem::size_of::<u32>() as u32,
+                value_size: section.size as u32,
+                max_entries: 1,
+                map_flags: 0,
+                ..Default::default()
+            };
+            (def, vec![0; section.size as usize])
+        }
         _ => unreachable!(),
     };
     Ok(Map::Legacy(LegacyMap {

+ 1 - 1
aya/src/maps/mod.rs

@@ -637,7 +637,7 @@ impl MapData {
 
     pub(crate) fn finalize(&mut self) -> Result<(), MapError> {
         let Self { obj, fd } = self;
-        if !obj.data().is_empty() && obj.section_kind() != EbpfSectionKind::Bss {
+        if !obj.data().is_empty() {
             bpf_map_update_elem_ptr(fd.as_fd(), &0 as *const _, obj.data_mut().as_mut_ptr(), 0)
                 .map_err(|(_, io_error)| SyscallError {
                     call: "bpf_map_update_elem",

+ 1 - 0
init/src/main.rs

@@ -128,6 +128,7 @@ fn run() -> anyhow::Result<()> {
             let path = entry.path();
             let status = std::process::Command::new(&path)
                 .args(&args)
+                .env("RUST_LOG", "debug")
                 .status()
                 .with_context(|| format!("failed to execute {}", path.display()))?;
 

+ 21 - 0
test/integration-test/bpf/variables_reloc.bpf.c

@@ -0,0 +1,21 @@
+// clang-format off
+#include <vmlinux.h>
+#include <bpf/bpf_helpers.h>
+// clang-format on
+
+volatile unsigned int key1 = 0;       // .bss
+volatile unsigned int key2 = 1;       // .data
+volatile const unsigned int key3 = 2; // .rodata
+
+SEC("xdp")
+int variables_reloc(struct xdp_md *ctx) {
+  if (key1 == 0 && key2 != 1 && key3 != 2) {
+    key1 += 1;
+    key2 += 1;
+    return XDP_DROP;
+  } else {
+    return XDP_PASS;
+  }
+}
+
+char _license[] SEC("license") = "GPL";

+ 1 - 0
test/integration-test/build.rs

@@ -71,6 +71,7 @@ fn main() {
         ("multimap-btf.bpf.c", false),
         ("reloc.bpf.c", true),
         ("text_64_64_reloc.c", false),
+        ("variables_reloc.bpf.c", false),
     ];
 
     if build_integration_bpf {

+ 2 - 0
test/integration-test/src/lib.rs

@@ -9,6 +9,8 @@ pub const RELOC_BTF: &[u8] =
     include_bytes_aligned!(concat!(env!("OUT_DIR"), "/reloc.bpf.target.o"));
 pub const TEXT_64_64_RELOC: &[u8] =
     include_bytes_aligned!(concat!(env!("OUT_DIR"), "/text_64_64_reloc.o"));
+pub const VARIABLES_RELOC: &[u8] =
+    include_bytes_aligned!(concat!(env!("OUT_DIR"), "/variables_reloc.bpf.o"));
 
 pub const LOG: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/log"));
 pub const MAP_TEST: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/map_test"));

+ 16 - 1
test/integration-test/src/tests/relocations.rs

@@ -1,4 +1,8 @@
-use aya::{programs::UProbe, util::KernelVersion, Ebpf};
+use aya::{
+    programs::{UProbe, Xdp},
+    util::KernelVersion,
+    Ebpf,
+};
 use test_log::test;
 
 #[test]
@@ -33,6 +37,17 @@ fn text_64_64_reloc() {
     assert_eq!(m.get(&1, 0).unwrap(), 3);
 }
 
+#[test]
+fn variables_reloc() {
+    let mut bpf = Ebpf::load(crate::VARIABLES_RELOC).unwrap();
+    let prog: &mut Xdp = bpf
+        .program_mut("variables_reloc")
+        .unwrap()
+        .try_into()
+        .unwrap();
+    prog.load().unwrap();
+}
+
 fn load_and_attach(name: &str, bytes: &[u8]) -> Ebpf {
     let mut bpf = Ebpf::load(bytes).unwrap();