aya-log: properly hint log level to verifier

The log level implementation in b36cbc3eb8
was incomplete as the verifier could reject programs which exceeded
their instruction limits within logging statements. This commit
addresses this issue by making the log level static variable immutable
(s.t. the compiler puts it in a read-only section) and adds an
additional test which the verifier will reject as an infinite loop iff
it is unable to detect that the static variable would otherwise allow
the logging.
reviewable/pr1337/r2
Addison Crump 6 days ago committed by Tamir Duberstein
parent b36cbc3eb8
commit f6606473af
No known key found for this signature in database

@ -39,12 +39,11 @@ pub mod macro_support {
///
/// Userspace may patch this symbol before load via `EbpfLoader::set_global`.
#[unsafe(no_mangle)]
pub static mut AYA_LOG_LEVEL: u8 = 0xff;
pub static AYA_LOG_LEVEL: u8 = 0xff;
/// Returns `true` if the provided level is enabled according to [`AYA_LOG_LEVEL`].
#[inline(always)]
pub fn level_enabled(level: Level) -> bool {
#[expect(static_mut_refs)]
let current_level = unsafe { core::ptr::read_volatile(&AYA_LOG_LEVEL) };
level as u8 <= current_level
}

@ -1,7 +1,10 @@
#![no_std]
#![no_main]
use core::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use core::{
hint::black_box,
net::{IpAddr, Ipv4Addr, Ipv6Addr},
};
use aya_ebpf::{macros::uprobe, programs::ProbeContext};
use aya_log_ebpf::{debug, error, info, trace, warn};
@ -83,3 +86,12 @@ pub fn test_log(ctx: ProbeContext) {
debug!(&ctx, "{:x}", no_copy.consume());
}
}
#[uprobe]
pub fn test_log_omission(ctx: ProbeContext) {
debug!(
&ctx,
"This is the last u32: {}",
black_box(0u32..).last().unwrap_or(u32::MAX)
);
}

@ -224,3 +224,40 @@ fn log_level_only_error_warn() {
assert_eq!(records.next(), None);
}
#[test_log::test]
fn log_level_prevents_verif_fail() {
let level = aya_log::Level::Warn as u8;
let mut bpf = EbpfLoader::new()
.set_global(aya_log::LEVEL, &level, true /* must_exist */)
.load(crate::LOG)
.unwrap();
let mut captured_logs = Vec::new();
let logger = TestingLogger {
log: Mutex::new(|record: &Record| {
captured_logs.push(CapturedLog {
body: format!("{}", record.args()).into(),
level: record.level(),
target: record.target().to_string().into(),
});
}),
};
let mut logger = EbpfLogger::init_with_logger(&mut bpf, &logger).unwrap();
let prog: &mut UProbe = bpf
.program_mut("test_log_omission")
.unwrap()
.try_into()
.unwrap();
prog.load().unwrap();
prog.attach("trigger_ebpf_program", "/proc/self/exe", None, None)
.unwrap();
trigger_ebpf_program();
logger.flush();
let mut records = captured_logs.iter();
assert_eq!(records.next(), None);
}

Loading…
Cancel
Save