diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index b2f3fe7a..4ca4031b 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -64,11 +64,12 @@ pub mod uprobe; mod utils; pub mod xdp; -use libc::ENOSPC; +use libc::{getrlimit, rlimit, ENOSPC, RLIMIT_MEMLOCK, RLIM_INFINITY}; +use log::warn; use std::{ convert::TryFrom, ffi::CString, - io, + fmt, io, os::unix::io::{AsRawFd, RawFd}, path::Path, }; @@ -214,6 +215,20 @@ pub enum ProgramError { }, } +#[derive(PartialEq, Eq, PartialOrd, Ord)] +struct RlimitSize(u64); +impl fmt::Display for RlimitSize { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if self.0 < 1024 { + write!(f, "{} bytes", self.0) + } else if self.0 < 1024 * 1024 { + write!(f, "{} KiB", self.0 / 1024) + } else { + write!(f, "{} MiB", self.0 / 1024 / 1024) + } + } +} + /// A [`Program`] file descriptor. #[derive(Copy, Clone)] pub struct ProgramFd(RawFd); @@ -472,6 +487,22 @@ fn unload_program(data: &mut ProgramData) -> Result<(), ProgramError Ok(()) } +fn check_rlimit() { + let mut limit = std::mem::MaybeUninit::::uninit(); + let ret = unsafe { getrlimit(RLIMIT_MEMLOCK, limit.as_mut_ptr()) }; + if ret == 0 { + let limit = unsafe { limit.assume_init() }; + let limit: RlimitSize = RlimitSize(limit.rlim_cur); + if limit.0 == RLIM_INFINITY { + return; + } + warn!( + "RLIMIT_MEMLOCK value is {}, not RLIM_INFNITY; if experiencing problems with creating maps, try raising RMILIT_MEMLOCK to RLIM_INFINITY", + limit + ); + } +} + fn load_program( prog_type: bpf_prog_type, data: &mut ProgramData, @@ -502,6 +533,10 @@ fn load_program( } _ => (*kernel_version).into(), }; + let version_5_11 = (5 << 16) + (11 << 8); + if target_kernel_version < version_5_11 { + check_rlimit(); + } let mut logger = VerifierLog::new();