fixup and add tests (known broken)

pull/916/head
Addison Crump 7 months ago
parent fd44c9cec2
commit f3ab297357
No known key found for this signature in database
GPG Key ID: D495C2DF24C779B2

@ -33,6 +33,14 @@ unsafe impl<T> FromBtfArgument for *const T {
} }
} }
unsafe impl<T> FromBtfArgument for *mut T {
unsafe fn from_argument(ctx: *const c_void, n: usize) -> *mut T {
// BTF arguments are exposed as an array of `usize` where `usize` can
// either be treated as a pointer or a primitive type
*(ctx as *const usize).add(n) as _
}
}
/// Helper macro to implement [`FromBtfArgument`] for a primitive type. /// Helper macro to implement [`FromBtfArgument`] for a primitive type.
macro_rules! unsafe_impl_from_btf_argument { macro_rules! unsafe_impl_from_btf_argument {
($type:ident) => { ($type:ident) => {

@ -143,7 +143,7 @@ const fn build_def<V>(ty: u32, flags: u32, pin: PinningType) -> bpf_map_def {
type_: ty, type_: ty,
key_size: mem::size_of::<c_int>() as u32, key_size: mem::size_of::<c_int>() as u32,
value_size: mem::size_of::<V>() as u32, value_size: mem::size_of::<V>() as u32,
max_entries: 0, max_entries: 1,
map_flags: flags, map_flags: flags,
id: 0, id: 0,
pinning: pin as u32, pinning: pin as u32,

@ -51,7 +51,7 @@ impl LsmContext {
/// ///
/// [1]: https://elixir.bootlin.com/linux/latest/source/include/linux/lsm_hook_defs.h /// [1]: https://elixir.bootlin.com/linux/latest/source/include/linux/lsm_hook_defs.h
pub unsafe fn arg<T: FromBtfArgument>(&self, n: usize) -> T { pub unsafe fn arg<T: FromBtfArgument>(&self, n: usize) -> T {
T::from_argument(self.ctx as *const _, n) T::from_argument(self.ctx, n)
} }
} }

@ -1,10 +1,46 @@
//! The purpose of this test is to identify if we can prevent a tmpfile from being linked to by
//! storing information in inode storage.
#![no_std] #![no_std]
#![no_main] #![no_main]
use aya_ebpf::{macros::map, maps::inode_storage::InodeStorage}; use aya_ebpf::{
bindings::BPF_F_NO_PREALLOC,
cty::c_void,
macros::{lsm, map},
maps::inode_storage::InodeStorage,
programs::LsmContext,
};
use aya_log_ebpf::warn;
#[map] #[map]
static INODE_STORE: InodeStorage<usize> = InodeStorage::new(0); static TMP_INODE_STORE: InodeStorage<usize> = InodeStorage::new(BPF_F_NO_PREALLOC);
#[lsm(hook = "inode_post_create_tmpfile")]
pub fn inode_post_create_tmpfile(ctx: LsmContext) -> i32 {
unsafe { try_inode_post_create_tmpfile(ctx) }.unwrap_or_else(|ret| ret)
}
unsafe fn try_inode_post_create_tmpfile(ctx: LsmContext) -> Result<i32, i32> {
let tmpfile: *mut c_void = ctx.arg(1);
if TMP_INODE_STORE.get_or_insert_ptr(tmpfile, &0).is_none() {
warn!(&ctx, "Couldn't add information that we deleted a tmp node!");
}
Ok(0)
}
#[lsm(hook = "inode_link")]
pub fn inode_link(ctx: LsmContext) -> i32 {
unsafe { try_inode_link(ctx) }.unwrap_or_else(|ret| ret)
}
unsafe fn try_inode_link(ctx: LsmContext) -> Result<i32, i32> {
let maybe_tmpfile: *mut c_void = ctx.arg(0);
if TMP_INODE_STORE.get(maybe_tmpfile).is_some() {
return Err(130);
}
Ok(0)
}
#[cfg(not(test))] #[cfg(not(test))]
#[panic_handler] #[panic_handler]

@ -12,6 +12,8 @@ pub const TEXT_64_64_RELOC: &[u8] =
pub const LOG: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/log")); pub const LOG: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/log"));
pub const MAP_TEST: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/map_test")); pub const MAP_TEST: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/map_test"));
pub const INODE_STORAGE_TEST: &[u8] =
include_bytes_aligned!(concat!(env!("OUT_DIR"), "/inode_storage"));
pub const NAME_TEST: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/name_test")); pub const NAME_TEST: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/name_test"));
pub const PASS: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/pass")); pub const PASS: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/pass"));
pub const TEST: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/test")); pub const TEST: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/test"));

@ -1,6 +1,7 @@
mod bpf_probe_read; mod bpf_probe_read;
mod btf_relocations; mod btf_relocations;
mod elf; mod elf;
mod inode_storage;
mod load; mod load;
mod log; mod log;
mod rbpf; mod rbpf;

@ -0,0 +1,49 @@
use std::{
error::Error,
fs::OpenOptions,
os::{fd::IntoRawFd, unix::fs::OpenOptionsExt},
};
use aya::{programs::Lsm, Ebpf};
use aya_obj::btf::Btf;
use libc::{linkat, AT_EMPTY_PATH, AT_FDCWD, O_TMPFILE};
use crate::INODE_STORAGE_TEST;
#[test]
fn no_link_to_tmp() -> Result<(), Box<dyn Error>> {
let mut bpf = Ebpf::load(INODE_STORAGE_TEST)?;
let btf = Btf::from_sys_fs()?;
let rename: &mut Lsm = bpf
.program_mut("inode_post_create_tmpfile")
.unwrap()
.try_into()?;
rename.load("inode_post_create_tmpfile", &btf)?;
rename.attach()?;
let link: &mut Lsm = bpf.program_mut("inode_link").unwrap().try_into()?;
link.load("inode_link", &btf)?;
link.attach()?;
// create a temporary file
let tmpfile = OpenOptions::new()
.custom_flags(O_TMPFILE)
.create_new(true)
.open("/tmp/")?;
let fd = tmpfile.into_raw_fd();
let res = unsafe {
linkat(
fd,
c"".as_ptr(),
AT_FDCWD,
c"/tmp/blah".as_ptr(),
AT_EMPTY_PATH,
)
};
assert_eq!(130, res);
Ok(())
}
Loading…
Cancel
Save