Skip to content

Commit b2131ff

Browse files
committed
Dlopen apparmor
1 parent 6293973 commit b2131ff

File tree

2 files changed

+38
-8
lines changed

2 files changed

+38
-8
lines changed

src/apparmor.rs

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
use std::ffi::CString;
2-
use std::{fs, io};
1+
use std::ffi::{c_char, c_int, CStr, CString};
2+
use std::{fs, io, mem};
33

44
use crate::cutils::cerr;
55

@@ -21,13 +21,43 @@ fn apparmor_is_enabled() -> io::Result<bool> {
2121
}
2222
}
2323

24-
#[link(name = "apparmor")]
25-
extern "C" {
26-
pub fn aa_change_onexec(profile: *const libc::c_char) -> libc::c_int;
27-
}
28-
2924
/// Switch the apparmor profile to the given profile on the next exec call
3025
fn apparmor_prepare_exec(new_profile: &str) -> io::Result<()> {
26+
// SAFETY: Always safe to call
27+
unsafe { libc::dlerror() }; // Clear any existing error
28+
29+
// SAFETY: Loading a known safe dylib. LD_LIBRARY_PATH is ignored because we are setuid.
30+
let handle = unsafe { libc::dlopen(c"libapparmor.so.1".as_ptr(), libc::RTLD_NOW) };
31+
if handle.is_null() {
32+
// SAFETY: In case of an error, dlerror returns a valid C string.
33+
return Err(io::Error::new(io::ErrorKind::NotFound, unsafe {
34+
CStr::from_ptr(libc::dlerror())
35+
.to_string_lossy()
36+
.into_owned()
37+
}));
38+
}
39+
40+
// SAFETY: dlsym will either return a function pointer of the right signature or NULL.
41+
// Option<fn()> is guaranteed to represent a NULL value as None and any other value as Some.
42+
let aa_change_onexec: Option<unsafe extern "C" fn(*const c_char) -> c_int> =
43+
unsafe { mem::transmute(libc::dlsym(handle, c"aa_change_onexec".as_ptr())) };
44+
let Some(aa_change_onexec) = aa_change_onexec else {
45+
// SAFETY: Always safe to call
46+
let err = unsafe { libc::dlerror() };
47+
if err.is_null() {
48+
// There was no error in dlsym, but the symbol itself was defined as NULL pointer.
49+
// This is still an error for us, but dlerror will not return any error.
50+
return Err(io::Error::new(
51+
io::ErrorKind::Other,
52+
"aa_change_onexec symbol is a NULL pointer",
53+
));
54+
}
55+
// SAFETY: In case of an error, dlerror returns a valid C string.
56+
return Err(io::Error::new(io::ErrorKind::NotFound, unsafe {
57+
CStr::from_ptr(err).to_string_lossy().into_owned()
58+
}));
59+
};
60+
3161
let new_profile_cstr = CString::new(new_profile)?;
3262
// SAFETY: new_profile_cstr provided by CString ensures a valid ptr
3363
cerr(unsafe { aa_change_onexec(new_profile_cstr.as_ptr()) })?;

test-framework/sudo-test/src/ours.linux.Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
FROM rust:1-slim-bookworm
22
RUN apt-get update && \
3-
apt-get install -y --no-install-recommends apparmor libpam0g-dev libapparmor-dev procps sshpass rsyslog ca-certificates tzdata
3+
apt-get install -y --no-install-recommends apparmor libpam0g-dev libapparmor1 procps sshpass rsyslog ca-certificates tzdata
44
# cache the crates.io index in the image for faster local testing
55
RUN cargo search sudo
66
WORKDIR /usr/src/sudo

0 commit comments

Comments
 (0)