From 024def8da6573e1a3e2a38e703c8a43497043bce Mon Sep 17 00:00:00 2001
From: Quentin JEROME <qjerome@users.noreply.github.com>
Date: Tue, 10 Oct 2023 17:54:47 +0200
Subject: [PATCH] repro issue #808

Signed-off-by: Quentin JEROME <qjerome@users.noreply.github.com>
---
 test/integration-ebpf/Cargo.toml              |  4 ++
 .../src/repro/.cargo/config.toml              |  6 +++
 .../src/repro/log_str_random.rs               | 47 +++++++++++++++++++
 test/integration-test/src/lib.rs              |  1 +
 test/integration-test/src/tests/load.rs       | 16 +++++++
 5 files changed, 74 insertions(+)
 create mode 100644 test/integration-ebpf/src/repro/.cargo/config.toml
 create mode 100644 test/integration-ebpf/src/repro/log_str_random.rs

diff --git a/test/integration-ebpf/Cargo.toml b/test/integration-ebpf/Cargo.toml
index d471acf3..b7443f3f 100644
--- a/test/integration-ebpf/Cargo.toml
+++ b/test/integration-ebpf/Cargo.toml
@@ -55,3 +55,7 @@ path = "src/xdp_sec.rs"
 [[bin]]
 name = "ring_buf"
 path = "src/ring_buf.rs"
+
+[[bin]]
+name = "log_str_random"
+path = "src/repro/log_str_random.rs"
diff --git a/test/integration-ebpf/src/repro/.cargo/config.toml b/test/integration-ebpf/src/repro/.cargo/config.toml
new file mode 100644
index 00000000..ce974823
--- /dev/null
+++ b/test/integration-ebpf/src/repro/.cargo/config.toml
@@ -0,0 +1,6 @@
+# the bug needs debug info so that it triggers
+[profile.release]
+debug = true
+
+[profile.dev]
+debug = true
diff --git a/test/integration-ebpf/src/repro/log_str_random.rs b/test/integration-ebpf/src/repro/log_str_random.rs
new file mode 100644
index 00000000..44d816be
--- /dev/null
+++ b/test/integration-ebpf/src/repro/log_str_random.rs
@@ -0,0 +1,47 @@
+// this file aims at reproducing the bug reported here: https://github.com/aya-rs/aya/issues/808
+#![no_std]
+#![no_main]
+
+use aya_bpf::{helpers::bpf_get_prandom_u32, macros::kprobe, programs::ProbeContext};
+use aya_log_ebpf::error;
+
+#[repr(C)]
+enum Error {
+    Foo,
+    Bar,
+}
+
+impl Error {
+    const fn into_str(self) -> &'static str {
+        match self {
+            Self::Foo => "foo",
+            Self::Bar => "bar",
+        }
+    }
+}
+
+#[kprobe]
+pub fn log_str_random(ctx: ProbeContext) -> u32 {
+    match try_log_str_random(ctx) {
+        Ok(ret) => ret,
+        Err(ret) => ret,
+    }
+}
+
+fn try_log_str_random(ctx: ProbeContext) -> Result<u32, u32> {
+    let err = {
+        if unsafe { bpf_get_prandom_u32() } % 2 == 0 {
+            Error::Bar
+        } else {
+            Error::Foo
+        }
+    };
+    error!(&ctx, "{}", err.into_str());
+    Ok(0)
+}
+
+#[cfg(not(test))]
+#[panic_handler]
+fn panic(_info: &core::panic::PanicInfo) -> ! {
+    loop {}
+}
diff --git a/test/integration-test/src/lib.rs b/test/integration-test/src/lib.rs
index d4708033..f805f240 100644
--- a/test/integration-test/src/lib.rs
+++ b/test/integration-test/src/lib.rs
@@ -22,6 +22,7 @@ pub const BPF_PROBE_READ: &[u8] =
 pub const REDIRECT: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/redirect"));
 pub const XDP_SEC: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/xdp_sec"));
 pub const RING_BUF: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/ring_buf"));
+pub const LOG_STR_RAND: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/log_str_random"));
 
 #[cfg(test)]
 mod tests;
diff --git a/test/integration-test/src/tests/load.rs b/test/integration-test/src/tests/load.rs
index 685867e9..1380c9fc 100644
--- a/test/integration-test/src/tests/load.rs
+++ b/test/integration-test/src/tests/load.rs
@@ -607,3 +607,19 @@ fn pin_lifecycle_uprobe() {
     // Make sure the function isn't optimized out.
     uprobe_function();
 }
+
+#[test]
+fn log_str_random() {
+    // userland code to reproduce bug reported here: https://github.com/aya-rs/aya/issues/808
+    // To reproduce the bug, eBPF code needs to be built with a custom
+    // bpf-linker from the feature/fix-di branch. Additionally, eBPF program
+    // needs to be built with debug information.
+    let mut bpf = Bpf::load(crate::LOG_STR_RAND).unwrap();
+    let prog: &mut KProbe = bpf
+        .program_mut("log_str_random")
+        .unwrap()
+        .try_into()
+        .unwrap();
+    prog.load().unwrap();
+    prog.attach("schedule", 0).unwrap();
+}