Skip to content

Commit

Permalink
aya: Raise the RLIMIT_MEMLOCK warning only if failed to create a map
Browse files Browse the repository at this point in the history
Also, mention that setting the RLIMIT_MEMLOCK to a higher value is an
option.

Signed-off-by: Michal Rostecki <vadorovsky@gmail.com>
  • Loading branch information
vadorovsky committed Jul 8, 2022
1 parent a7fa938 commit 3d592d0
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 39 deletions.
46 changes: 44 additions & 2 deletions aya/src/maps/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,20 +35,23 @@
use std::{
convert::TryFrom,
ffi::CString,
io,
fmt, io,
marker::PhantomData,
mem,
ops::Deref,
os::unix::{io::RawFd, prelude::AsRawFd},
path::Path,
ptr,
};

use libc::{getrlimit, rlimit, RLIMIT_MEMLOCK, RLIM_INFINITY};
use log::warn;
use thiserror::Error;

use crate::{
generated::bpf_map_type,
obj,
sys::{bpf_create_map, bpf_get_object, bpf_map_get_next_key, bpf_pin_object},
sys::{bpf_create_map, bpf_get_object, bpf_map_get_next_key, bpf_pin_object, kernel_version},
util::nr_cpus,
Pod,
};
Expand Down Expand Up @@ -222,6 +225,40 @@ impl AsRawFd for MapFd {
}
}

#[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)
}
}
}

/// Raises a warning about rlimit. Should be used only if creating a map was not
/// successful.
fn maybe_warn_rlimit() {
let mut limit = std::mem::MaybeUninit::<rlimit>::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 either to RLIM_INFINITY or to a higher value sufficient \
for size of your maps",
limit
);
}
}

/// A generic handle to a BPF map.
///
/// You should never need to use this unless you're implementing a new map type.
Expand All @@ -243,6 +280,11 @@ impl Map {
let c_name = CString::new(name).map_err(|_| MapError::InvalidName { name: name.into() })?;

let fd = bpf_create_map(&c_name, &self.obj.def).map_err(|(code, io_error)| {
let k_ver = kernel_version().unwrap();
if k_ver < (5, 11, 0) {
maybe_warn_rlimit();
}

MapError::CreateError {
name: name.into(),
code,
Expand Down
39 changes: 2 additions & 37 deletions aya/src/programs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,11 @@ pub mod uprobe;
mod utils;
pub mod xdp;

use libc::{getrlimit, rlimit, ENOSPC, RLIMIT_MEMLOCK, RLIM_INFINITY};
use log::warn;
use libc::ENOSPC;
use std::{
convert::TryFrom,
ffi::CString,
fmt, io,
io,
os::unix::io::{AsRawFd, RawFd},
path::Path,
};
Expand Down Expand Up @@ -215,20 +214,6 @@ 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);
Expand Down Expand Up @@ -487,22 +472,6 @@ fn unload_program<T: Link>(data: &mut ProgramData<T>) -> Result<(), ProgramError
Ok(())
}

fn check_rlimit() {
let mut limit = std::mem::MaybeUninit::<rlimit>::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<T: Link>(
prog_type: bpf_prog_type,
data: &mut ProgramData<T>,
Expand Down Expand Up @@ -533,10 +502,6 @@ fn load_program<T: Link>(
}
_ => (*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();

Expand Down

0 comments on commit 3d592d0

Please sign in to comment.