#![allow(unsafe_code)]
use extrasafe::*;
use builtins::SystemIO;
use syscalls::Sysno;
use std::collections::HashMap;
struct IoctlRestricted64(u64);
impl RuleSet for IoctlRestricted64 {
fn simple_rules(&self) -> Vec<Sysno> {
Vec::new()
}
fn conditional_rules(&self) -> HashMap<Sysno, Vec<SeccompRule>> {
let cmp = SeccompArgumentFilter::new64(1, SeccompilerComparator::Eq, self.0);
let rule = SeccompRule::new(Sysno::ioctl)
.and_condition(cmp);
HashMap::from([(Sysno::ioctl, vec![rule])])
}
fn name(&self) -> &'static str {
"ioctl restricted 64"
}
}
struct IoctlRestricted32(u32);
impl RuleSet for IoctlRestricted32 {
fn simple_rules(&self) -> Vec<Sysno> {
Vec::new()
}
fn conditional_rules(&self) -> HashMap<Sysno, Vec<SeccompRule>> {
let cmp = SeccompArgumentFilter::new32(1, SeccompilerComparator::Eq, self.0);
let rule = SeccompRule::new(Sysno::ioctl)
.and_condition(cmp);
HashMap::from([(Sysno::ioctl, vec![rule])])
}
fn name(&self) -> &'static str {
"ioctl restricted 32"
}
}
struct GetUidRestricted;
impl RuleSet for GetUidRestricted {
fn simple_rules(&self) -> Vec<Sysno> {
Vec::new()
}
fn conditional_rules(&self) -> HashMap<Sysno, Vec<SeccompRule>> {
let rule = SeccompRule::new(Sysno::getuid)
.and_condition(seccomp_arg_filter!(arg0 == 10));
HashMap::from([(Sysno::getuid, vec![rule])])
}
fn name(&self) -> &'static str {
"getuid restricted"
}
}
#[test]
fn cmp_arg_syscall_unused_parameter() {
let uid1 = unsafe { libc::getuid() };
assert!(uid1 > 0);
extrasafe::SafetyContext::new()
.enable(SystemIO::nothing()
.allow_stdout()
.allow_stderr()).unwrap()
.enable(GetUidRestricted).unwrap()
.apply_to_current_thread().unwrap();
let uid2 = unsafe { libc::getuid() };
assert!(uid1 != uid2);
}
macro_rules! assert_errno {
($e: expr) => {
let errno = std::io::Error::last_os_error().raw_os_error().unwrap();
assert_eq!(errno, $e);
}
}
#[test]
fn cmp_arg_64bit_ioctl_musl_glibc_diff() {
let value: u64 = 0x8000_0000;
let seccomp_errno = 999;
extrasafe::SafetyContext::new()
.with_errno(seccomp_errno)
.enable(SystemIO::nothing()
.allow_stdout()
.allow_stderr()).unwrap()
.enable(IoctlRestricted64(value)).unwrap()
.apply_to_current_thread().unwrap();
#[cfg(target_env = "gnu")]
{
let ret = unsafe { libc::ioctl(4321, value, 0) };
assert_eq!(ret, -1);
assert_errno!(libc::EBADF);
}
#[cfg(target_env = "musl")]
{
let ret = unsafe { libc::ioctl(4321, value as i32, 0) };
assert_eq!(ret, -1);
assert_errno!(seccomp_errno as i32); }
}
#[test]
fn cmp_arg_32bit_ioctl_musl_glibc_same() {
let value: u32 = 0x8000_0000;
let seccomp_errno = 999;
extrasafe::SafetyContext::new()
.with_errno(seccomp_errno)
.enable(SystemIO::nothing()
.allow_stdout()
.allow_stderr()).unwrap()
.enable(IoctlRestricted32(value)).unwrap()
.apply_to_current_thread().unwrap();
#[cfg(target_env = "gnu")]
let ret = unsafe { libc::ioctl(4321, u64::from(value), 0) };
#[cfg(target_env = "musl")]
let ret = unsafe { libc::ioctl(4321, value as i32, 0) };
assert_eq!(ret, -1);
assert_errno!(libc::EBADF);
}