use seccompiler::{BpfProgram, SeccompAction, SeccompFilter, SeccompRule};
use std::collections::BTreeMap;
use std::io;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SeccompProfile {
Docker,
DockerWithIoUring,
Minimal,
None,
}
pub fn docker_default_filter() -> Result<BpfProgram, io::Error> {
use std::convert::TryInto;
let blocked_syscalls = vec![
"unshare", "setns", "mount", "umount", "umount2", "pivot_root", "chroot", "ptrace", "process_vm_readv", "process_vm_writev", "init_module", "finit_module", "delete_module", "reboot", "kexec_load", "kexec_file_load", "clock_settime", "settimeofday", "clock_adjtime", "adjtimex", "swapon", "swapoff", "add_key", "request_key", "keyctl", "bpf", "perf_event_open", "mbind", "set_mempolicy", "migrate_pages", "move_pages", "quotactl", "setuid", "setgid", "personality", "acct", "lookup_dcookie", "name_to_handle_at", "open_by_handle_at", "userfaultfd", "io_uring_setup", "io_uring_enter", "io_uring_register", ];
let rules: BTreeMap<i64, Vec<SeccompRule>> = blocked_syscalls
.iter()
.filter_map(|name| syscall_number(name).ok().map(|num| (num, vec![])))
.collect();
let target_arch = std::env::consts::ARCH
.try_into()
.map_err(|e| io::Error::other(format!("Unsupported architecture: {:?}", e)))?;
let filter = SeccompFilter::new(
rules,
SeccompAction::Allow, SeccompAction::Errno(libc::EPERM as u32), target_arch,
)
.map_err(|e| io::Error::other(format!("Failed to create seccomp filter: {}", e)))?;
let program: BpfProgram = filter
.try_into()
.map_err(|e| io::Error::other(format!("Failed to compile seccomp filter: {}", e)))?;
Ok(program)
}
pub fn docker_iouring_filter() -> Result<BpfProgram, io::Error> {
use std::convert::TryInto;
let mut blocked_syscalls = vec![
"unshare",
"setns",
"mount",
"umount",
"umount2",
"pivot_root",
"chroot",
"ptrace",
"process_vm_readv",
"process_vm_writev",
"init_module",
"finit_module",
"delete_module",
"reboot",
"kexec_load",
"kexec_file_load",
"clock_settime",
"settimeofday",
"clock_adjtime",
"adjtimex",
"swapon",
"swapoff",
"add_key",
"request_key",
"keyctl",
"bpf",
"perf_event_open",
"mbind",
"set_mempolicy",
"migrate_pages",
"move_pages",
"quotactl",
"setuid",
"setgid",
"personality",
"acct",
"lookup_dcookie",
"name_to_handle_at",
"open_by_handle_at",
"userfaultfd",
];
blocked_syscalls.sort_unstable();
let rules: BTreeMap<i64, Vec<SeccompRule>> = blocked_syscalls
.iter()
.filter_map(|name| syscall_number(name).ok().map(|num| (num, vec![])))
.collect();
let target_arch = std::env::consts::ARCH
.try_into()
.map_err(|e| io::Error::other(format!("Unsupported architecture: {:?}", e)))?;
let filter = SeccompFilter::new(
rules,
SeccompAction::Allow,
SeccompAction::Errno(libc::EPERM as u32),
target_arch,
)
.map_err(|e| io::Error::other(format!("Failed to create io_uring seccomp filter: {}", e)))?;
let program: BpfProgram = filter.try_into().map_err(|e| {
io::Error::other(format!("Failed to compile io_uring seccomp filter: {}", e))
})?;
Ok(program)
}
pub fn minimal_filter() -> Result<BpfProgram, io::Error> {
use std::convert::TryInto;
let allowed_syscalls = vec![
"exit",
"exit_group",
"wait4",
"waitid",
"execve",
"execveat",
"clone",
"fork",
"vfork",
"brk",
"mmap",
"munmap",
"mprotect",
"mremap",
"madvise",
"read",
"write",
"readv",
"writev",
"pread64",
"pwrite64",
"open",
"openat",
"close",
"lseek",
"dup",
"dup2",
"dup3",
"pipe",
"pipe2",
"poll",
"ppoll",
"select",
"pselect6",
"fstat",
"stat",
"lstat",
"newfstatat",
"access",
"faccessat",
"faccessat2",
"readlink",
"readlinkat",
"fcntl",
"ioctl",
"ftruncate",
"truncate",
"rename",
"renameat",
"renameat2",
"unlink",
"unlinkat",
"mkdir",
"mkdirat",
"rmdir",
"chmod",
"fchmod",
"fchmodat",
"chown",
"fchown",
"fchownat",
"symlink",
"symlinkat",
"link",
"linkat",
"getcwd",
"chdir",
"fchdir",
"getdents64",
"getdents",
"rt_sigaction",
"rt_sigprocmask",
"rt_sigreturn",
"sigaltstack",
"kill",
"tgkill",
"clock_gettime",
"clock_getres",
"gettimeofday",
"time",
"nanosleep",
"clock_nanosleep",
"getpid",
"getppid",
"gettid",
"getuid",
"getgid",
"geteuid",
"getegid",
"getgroups",
"getresuid",
"getresgid",
"getrlimit",
"prlimit64",
"arch_prctl",
"set_tid_address",
"set_robust_list",
"get_robust_list",
"prctl",
"rseq",
"getrandom",
"futex",
"socket",
"connect",
"sendto",
"recvfrom",
"sendmsg",
"recvmsg",
"bind",
"listen",
"accept",
"accept4",
"getsockname",
"getpeername",
"getsockopt",
"setsockopt",
"shutdown",
"uname",
"umask",
"sysinfo",
"statfs",
"fstatfs",
];
let rules: BTreeMap<i64, Vec<SeccompRule>> = allowed_syscalls
.iter()
.filter_map(|name| syscall_number(name).ok().map(|num| (num, vec![])))
.collect();
let target_arch = std::env::consts::ARCH
.try_into()
.map_err(|e| io::Error::other(format!("Unsupported architecture: {:?}", e)))?;
let filter = SeccompFilter::new(
rules,
SeccompAction::Errno(libc::EPERM as u32), SeccompAction::Allow, target_arch,
)
.map_err(|e| io::Error::other(format!("Failed to create minimal filter: {}", e)))?;
let program: BpfProgram = filter
.try_into()
.map_err(|e| io::Error::other(format!("Failed to compile minimal filter: {}", e)))?;
Ok(program)
}
pub fn filter_from_oci(config: &crate::oci::OciSeccomp) -> Result<BpfProgram, io::Error> {
use std::convert::TryInto;
fn oci_action_to_seccomp(action: &str) -> Option<SeccompAction> {
match action {
"SCMP_ACT_ALLOW" => Some(SeccompAction::Allow),
"SCMP_ACT_ERRNO" | "SCMP_ACT_ENOSYS" => Some(SeccompAction::Errno(libc::EPERM as u32)),
"SCMP_ACT_KILL" | "SCMP_ACT_KILL_THREAD" => Some(SeccompAction::KillThread),
"SCMP_ACT_KILL_PROCESS" => Some(SeccompAction::KillProcess),
"SCMP_ACT_LOG" => Some(SeccompAction::Log),
"SCMP_ACT_TRAP" => Some(SeccompAction::Trap),
_ => None,
}
}
let default_action = oci_action_to_seccomp(&config.default_action).ok_or_else(|| {
io::Error::other(format!(
"unknown seccomp defaultAction: {}",
config.default_action
))
})?;
let mut rules: BTreeMap<i64, Vec<SeccompRule>> = BTreeMap::new();
for rule in &config.syscalls {
let action = match oci_action_to_seccomp(&rule.action) {
Some(a) => a,
None => continue, };
for name in &rule.names {
if let Ok(num) = syscall_number(name) {
rules.entry(num).or_default();
let _ = action; }
}
}
let mut filtered_rules: BTreeMap<i64, Vec<SeccompRule>> = BTreeMap::new();
let mut match_action: Option<SeccompAction> = None;
for rule in &config.syscalls {
let action = match oci_action_to_seccomp(&rule.action) {
Some(a) => a,
None => continue,
};
if action == default_action {
continue; }
if match_action.is_none() {
match_action = Some(action.clone());
}
for name in &rule.names {
if let Ok(num) = syscall_number(name) {
filtered_rules.entry(num).or_default();
}
}
}
let effective_match = match_action.unwrap_or(SeccompAction::Allow);
let target_arch = std::env::consts::ARCH
.try_into()
.map_err(|e| io::Error::other(format!("Unsupported architecture: {:?}", e)))?;
let filter =
SeccompFilter::new(filtered_rules, default_action, effective_match, target_arch)
.map_err(|e| io::Error::other(format!("Failed to create OCI seccomp filter: {}", e)))?;
filter
.try_into()
.map_err(|e| io::Error::other(format!("Failed to compile OCI seccomp filter: {}", e)))
}
pub fn syscall_number(name: &str) -> Result<i64, io::Error> {
#[cfg(target_arch = "x86_64")]
match name {
"unshare" => Ok(272),
"setns" => Ok(308),
"mount" => Ok(165),
"umount" => Ok(166),
"umount2" => Ok(166),
"pivot_root" => Ok(155),
"chroot" => Ok(161),
"ptrace" => Ok(101),
"process_vm_readv" => Ok(310),
"process_vm_writev" => Ok(311),
"init_module" => Ok(175),
"finit_module" => Ok(313),
"delete_module" => Ok(176),
"reboot" => Ok(169),
"kexec_load" => Ok(246),
"kexec_file_load" => Ok(320),
"clock_settime" => Ok(227),
"settimeofday" => Ok(164),
"clock_adjtime" => Ok(305),
"adjtimex" => Ok(159),
"swapon" => Ok(167),
"swapoff" => Ok(168),
"add_key" => Ok(248),
"request_key" => Ok(249),
"keyctl" => Ok(250),
"bpf" => Ok(321),
"perf_event_open" => Ok(298),
"mbind" => Ok(237),
"set_mempolicy" => Ok(238),
"migrate_pages" => Ok(256),
"move_pages" => Ok(279),
"quotactl" => Ok(179),
"setuid" => Ok(105),
"setgid" => Ok(106),
"personality" => Ok(135),
"acct" => Ok(163),
"lookup_dcookie" => Ok(212),
"name_to_handle_at" => Ok(303),
"open_by_handle_at" => Ok(304),
"userfaultfd" => Ok(323),
"exit" => Ok(60),
"exit_group" => Ok(231),
"wait4" => Ok(61),
"waitid" => Ok(247),
"execve" => Ok(59),
"execveat" => Ok(322),
"clone" => Ok(56),
"fork" => Ok(57),
"vfork" => Ok(58),
"brk" => Ok(12),
"mmap" => Ok(9),
"munmap" => Ok(11),
"mprotect" => Ok(10),
"mremap" => Ok(25),
"madvise" => Ok(28),
"read" => Ok(0),
"write" => Ok(1),
"readv" => Ok(19),
"writev" => Ok(20),
"pread64" => Ok(17),
"pwrite64" => Ok(18),
"open" => Ok(2),
"openat" => Ok(257),
"close" => Ok(3),
"lseek" => Ok(8),
"dup" => Ok(32),
"dup2" => Ok(33),
"dup3" => Ok(292),
"pipe" => Ok(22),
"pipe2" => Ok(293),
"poll" => Ok(7),
"ppoll" => Ok(271),
"select" => Ok(23),
"pselect6" => Ok(270),
"fstat" => Ok(5),
"stat" => Ok(4),
"lstat" => Ok(6),
"newfstatat" => Ok(262),
"access" => Ok(21),
"faccessat" => Ok(269),
"faccessat2" => Ok(439),
"readlink" => Ok(89),
"readlinkat" => Ok(267),
"fcntl" => Ok(72),
"ioctl" => Ok(16),
"ftruncate" => Ok(77),
"truncate" => Ok(76),
"rename" => Ok(82),
"renameat" => Ok(264),
"renameat2" => Ok(316),
"unlink" => Ok(87),
"unlinkat" => Ok(263),
"mkdir" => Ok(83),
"mkdirat" => Ok(258),
"rmdir" => Ok(84),
"chmod" => Ok(90),
"fchmod" => Ok(91),
"fchmodat" => Ok(268),
"chown" => Ok(92),
"fchown" => Ok(93),
"fchownat" => Ok(260),
"symlink" => Ok(88),
"symlinkat" => Ok(266),
"link" => Ok(86),
"linkat" => Ok(265),
"getcwd" => Ok(79),
"chdir" => Ok(80),
"fchdir" => Ok(81),
"getdents64" => Ok(217),
"getdents" => Ok(78),
"rt_sigaction" => Ok(13),
"rt_sigprocmask" => Ok(14),
"rt_sigreturn" => Ok(15),
"sigaltstack" => Ok(131),
"kill" => Ok(62),
"tgkill" => Ok(234),
"clock_gettime" => Ok(228),
"clock_getres" => Ok(229),
"gettimeofday" => Ok(96),
"time" => Ok(201),
"nanosleep" => Ok(35),
"clock_nanosleep" => Ok(230),
"getpid" => Ok(39),
"getppid" => Ok(110),
"gettid" => Ok(186),
"getuid" => Ok(102),
"getgid" => Ok(104),
"geteuid" => Ok(107),
"getegid" => Ok(108),
"getgroups" => Ok(115),
"getresuid" => Ok(118),
"getresgid" => Ok(120),
"getrlimit" => Ok(97),
"prlimit64" => Ok(302),
"arch_prctl" => Ok(158),
"set_tid_address" => Ok(218),
"set_robust_list" => Ok(273),
"get_robust_list" => Ok(274),
"prctl" => Ok(157),
"rseq" => Ok(334),
"getrandom" => Ok(318),
"futex" => Ok(202),
"socket" => Ok(41),
"connect" => Ok(42),
"sendto" => Ok(44),
"recvfrom" => Ok(45),
"sendmsg" => Ok(46),
"recvmsg" => Ok(47),
"bind" => Ok(49),
"listen" => Ok(50),
"accept" => Ok(43),
"accept4" => Ok(288),
"getsockname" => Ok(51),
"getpeername" => Ok(52),
"getsockopt" => Ok(55),
"setsockopt" => Ok(54),
"shutdown" => Ok(48),
"uname" => Ok(63),
"umask" => Ok(95),
"sysinfo" => Ok(99),
"statfs" => Ok(137),
"fstatfs" => Ok(138),
"rt_sigsuspend" => Ok(130),
"rt_sigpending" => Ok(127),
"rt_sigtimedwait" => Ok(128),
"rt_sigqueueinfo" => Ok(129),
"rt_tgsigqueueinfo" => Ok(297),
"signalfd" => Ok(282),
"signalfd4" => Ok(289),
"tkill" => Ok(200),
"pause" => Ok(34),
"setpgid" => Ok(109),
"getpgid" => Ok(121),
"getpgrp" => Ok(111),
"getsid" => Ok(124),
"setsid" => Ok(112),
"setreuid" => Ok(113),
"setresuid" => Ok(117),
"setresgid" => Ok(119),
"setregid" => Ok(114),
"setgroups" => Ok(116),
"setfsgid" => Ok(123),
"setfsuid" => Ok(122),
"setpriority" => Ok(141),
"getpriority" => Ok(140),
"setitimer" => Ok(38),
"getitimer" => Ok(36),
"setrlimit" => Ok(160),
"getrusage" => Ok(98),
"times" => Ok(100),
"alarm" => Ok(37),
"syslog" => Ok(103),
"capget" => Ok(125),
"capset" => Ok(126),
"creat" => Ok(85),
"flock" => Ok(73),
"fsync" => Ok(74),
"fdatasync" => Ok(75),
"mknod" => Ok(133),
"mknodat" => Ok(259),
"lchown" => Ok(94),
"utime" => Ok(132),
"utimes" => Ok(235),
"utimensat" => Ok(280),
"futimesat" => Ok(261),
"readahead" => Ok(187),
"fallocate" => Ok(285),
"copy_file_range" => Ok(326),
"fadvise64" => Ok(221),
"fanotify_mark" => Ok(301),
"sync" => Ok(162),
"syncfs" => Ok(306),
"sync_file_range" => Ok(277),
"statx" => Ok(332),
"getxattr" => Ok(191),
"lgetxattr" => Ok(192),
"fgetxattr" => Ok(193),
"listxattr" => Ok(194),
"llistxattr" => Ok(195),
"removexattr" => Ok(197),
"lremovexattr" => Ok(198),
"fremovexattr" => Ok(199),
"setxattr" => Ok(188),
"lsetxattr" => Ok(189),
"fsetxattr" => Ok(190),
"semget" => Ok(64),
"semop" => Ok(65),
"semctl" => Ok(66),
"semtimedop" => Ok(220),
"msgget" => Ok(68),
"msgsnd" => Ok(69),
"msgrcv" => Ok(70),
"msgctl" => Ok(71),
"shmget" => Ok(29),
"shmat" => Ok(30),
"shmctl" => Ok(31),
"shmdt" => Ok(67),
"mq_open" => Ok(240),
"mq_unlink" => Ok(241),
"mq_timedsend" => Ok(242),
"mq_timedreceive" => Ok(243),
"mq_notify" => Ok(244),
"mq_getsetattr" => Ok(245),
"socketpair" => Ok(53),
"sendfile" => Ok(40),
"sendmmsg" => Ok(307),
"recvmmsg" => Ok(299),
"splice" => Ok(275),
"tee" => Ok(276),
"vmsplice" => Ok(278),
"mincore" => Ok(27),
"msync" => Ok(26),
"mlock" => Ok(149),
"mlock2" => Ok(325),
"mlockall" => Ok(151),
"munlock" => Ok(150),
"munlockall" => Ok(152),
"remap_file_pages" => Ok(216),
"memfd_create" => Ok(319),
"io_setup" => Ok(206),
"io_destroy" => Ok(207),
"io_getevents" => Ok(208),
"io_submit" => Ok(209),
"io_cancel" => Ok(210),
"preadv" => Ok(295),
"pwritev" => Ok(296),
"ioprio_set" => Ok(251),
"ioprio_get" => Ok(252),
"epoll_create" => Ok(213),
"epoll_create1" => Ok(291),
"epoll_ctl" => Ok(233),
"epoll_wait" => Ok(232),
"epoll_pwait" => Ok(281),
"timer_create" => Ok(222),
"timer_settime" => Ok(223),
"timer_gettime" => Ok(224),
"timer_getoverrun" => Ok(225),
"timer_delete" => Ok(226),
"timerfd_create" => Ok(283),
"timerfd_settime" => Ok(286),
"timerfd_gettime" => Ok(287),
"eventfd" => Ok(284),
"eventfd2" => Ok(290),
"inotify_init" => Ok(253),
"inotify_init1" => Ok(294),
"inotify_add_watch" => Ok(254),
"inotify_rm_watch" => Ok(255),
"sched_setparam" => Ok(142),
"sched_getparam" => Ok(143),
"sched_setscheduler" => Ok(144),
"sched_getscheduler" => Ok(145),
"sched_get_priority_max" => Ok(146),
"sched_get_priority_min" => Ok(147),
"sched_rr_get_interval" => Ok(148),
"sched_setaffinity" => Ok(203),
"sched_getaffinity" => Ok(204),
"sched_setattr" => Ok(314),
"sched_getattr" => Ok(315),
"sched_yield" => Ok(24),
"getcpu" => Ok(309),
"get_thread_area" => Ok(211),
"set_thread_area" => Ok(205),
"modify_ldt" => Ok(154),
"seccomp" => Ok(317),
"landlock_create_ruleset" => Ok(444),
"landlock_add_rule" => Ok(445),
"landlock_restrict_self" => Ok(446),
"io_uring_setup" => Ok(425),
"io_uring_enter" => Ok(426),
"io_uring_register" => Ok(427),
"restart_syscall" => Ok(219),
"_llseek" | "_newselect" | "chown32" | "epoll_ctl_old" | "epoll_wait_old"
| "fadvise64_64" | "fchown32" | "fcntl64" | "fstat64" | "fstatat64" | "fstatfs64"
| "ftruncate64" | "getegid32" | "geteuid32" | "getgid32" | "getgroups32"
| "getresgid32" | "getresuid32" | "getuid32" | "ipc" | "lchown32" | "lstat64" | "mmap2"
| "recv" | "send" | "sendfile64" | "setfsgid32" | "setfsuid32" | "setgid32"
| "setgroups32" | "setregid32" | "setresgid32" | "setresuid32" | "setreuid32"
| "setuid32" | "sigreturn" | "socketcall" | "stat64" | "statfs64" | "truncate64"
| "ugetrlimit" | "waitpid" => Err(io::Error::other(format!(
"32-bit compat syscall not available on x86_64: {}",
name
))),
_ => Err(io::Error::other(format!("Unknown syscall: {}", name))),
}
#[cfg(target_arch = "aarch64")]
match name {
"unshare" => Ok(97),
"setns" => Ok(268),
"mount" => Ok(40),
"umount" => Ok(39),
"umount2" => Ok(39),
"pivot_root" => Ok(41),
"chroot" => Ok(51),
"ptrace" => Ok(117),
"process_vm_readv" => Ok(270),
"process_vm_writev" => Ok(271),
"init_module" => Ok(105),
"finit_module" => Ok(273),
"delete_module" => Ok(106),
"reboot" => Ok(142),
"kexec_load" => Ok(104),
"kexec_file_load" => Ok(294),
"clock_settime" => Ok(112),
"settimeofday" => Ok(170),
"clock_adjtime" => Ok(266),
"adjtimex" => Ok(171),
"swapon" => Ok(224),
"swapoff" => Ok(225),
"add_key" => Ok(217),
"request_key" => Ok(218),
"keyctl" => Ok(219),
"bpf" => Ok(280),
"perf_event_open" => Ok(241),
"mbind" => Ok(235),
"set_mempolicy" => Ok(237),
"migrate_pages" => Ok(238),
"move_pages" => Ok(239),
"quotactl" => Ok(60),
"setuid" => Ok(146),
"setgid" => Ok(144),
"personality" => Ok(92),
"acct" => Ok(89),
"lookup_dcookie" => Ok(18),
"name_to_handle_at" => Ok(264),
"open_by_handle_at" => Ok(265),
"userfaultfd" => Ok(282),
"exit" => Ok(93),
"exit_group" => Ok(94),
"wait4" => Ok(260),
"waitid" => Ok(95),
"brk" => Ok(214),
"mmap" => Ok(222),
"munmap" => Ok(215),
"mprotect" => Ok(226),
"mremap" => Ok(216),
"read" => Ok(63),
"write" => Ok(64),
"readv" => Ok(65),
"writev" => Ok(66),
"pread64" => Ok(67),
"pwrite64" => Ok(68),
"openat" => Ok(56),
"close" => Ok(57),
"lseek" => Ok(62),
"fstat" => Ok(80),
"newfstatat" => Ok(79),
"faccessat" => Ok(48),
"getcwd" => Ok(17),
"chdir" => Ok(49),
"fchdir" => Ok(50),
"rt_sigaction" => Ok(134),
"rt_sigprocmask" => Ok(135),
"rt_sigreturn" => Ok(139),
"clock_gettime" => Ok(113),
"gettimeofday" => Ok(169),
"nanosleep" => Ok(101),
"getpid" => Ok(172),
"getuid" => Ok(174),
"getgid" => Ok(176),
"geteuid" => Ok(175),
"getegid" => Ok(177),
"futex" => Ok(98),
"set_robust_list" => Ok(99),
"get_robust_list" => Ok(100),
"io_uring_setup" => Ok(425),
"io_uring_enter" => Ok(426),
"io_uring_register" => Ok(427),
_ => Err(io::Error::other(format!(
"Unknown syscall for aarch64: {}",
name
))),
}
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
{
Err(io::Error::other(format!(
"Unsupported architecture for syscall {}",
name
)))
}
}
pub fn apply_filter(program: &BpfProgram) -> Result<(), io::Error> {
seccompiler::apply_filter(program)
.map_err(|e| io::Error::other(format!("Failed to apply seccomp filter: {}", e)))
}
pub fn apply_filter_no_nnp(program: &BpfProgram) -> Result<(), io::Error> {
let fprog = libc::sock_fprog {
len: program.len() as u16,
filter: program.as_ptr() as *mut libc::sock_filter,
};
let result = unsafe {
libc::prctl(
libc::PR_SET_SECCOMP,
libc::SECCOMP_MODE_FILTER as libc::c_ulong,
&fprog as *const libc::sock_fprog as libc::c_ulong,
0,
0,
)
};
if result != 0 {
Err(io::Error::other(format!(
"Failed to apply seccomp filter (no-nnp): {}",
io::Error::last_os_error()
)))
} else {
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_docker_filter_compiles() {
let result = docker_default_filter();
assert!(result.is_ok(), "Docker filter should compile successfully");
}
#[test]
fn test_minimal_filter_compiles() {
let result = minimal_filter();
assert!(result.is_ok(), "Minimal filter should compile successfully");
}
#[test]
fn test_syscall_numbers_x86_64() {
#[cfg(target_arch = "x86_64")]
{
assert_eq!(syscall_number("read").unwrap(), 0);
assert_eq!(syscall_number("write").unwrap(), 1);
assert_eq!(syscall_number("open").unwrap(), 2);
assert_eq!(syscall_number("close").unwrap(), 3);
assert_eq!(syscall_number("ptrace").unwrap(), 101);
assert_eq!(syscall_number("reboot").unwrap(), 169);
}
}
#[test]
fn test_unknown_syscall() {
let result = syscall_number("nonexistent_syscall_12345");
assert!(result.is_err());
}
#[test]
fn test_seccomp_profile_equality() {
assert_eq!(SeccompProfile::Docker, SeccompProfile::Docker);
assert_eq!(
SeccompProfile::DockerWithIoUring,
SeccompProfile::DockerWithIoUring
);
assert_eq!(SeccompProfile::Minimal, SeccompProfile::Minimal);
assert_eq!(SeccompProfile::None, SeccompProfile::None);
assert_ne!(SeccompProfile::Docker, SeccompProfile::Minimal);
assert_ne!(SeccompProfile::Docker, SeccompProfile::DockerWithIoUring);
}
#[test]
fn test_docker_iouring_filter_compiles() {
let result = docker_iouring_filter();
assert!(
result.is_ok(),
"DockerWithIoUring filter should compile: {:?}",
result.err()
);
}
#[test]
fn test_io_uring_syscall_numbers() {
#[cfg(target_arch = "x86_64")]
{
assert_eq!(syscall_number("io_uring_setup").unwrap(), 425);
assert_eq!(syscall_number("io_uring_enter").unwrap(), 426);
assert_eq!(syscall_number("io_uring_register").unwrap(), 427);
}
#[cfg(target_arch = "aarch64")]
{
assert_eq!(syscall_number("io_uring_setup").unwrap(), 425);
assert_eq!(syscall_number("io_uring_enter").unwrap(), 426);
assert_eq!(syscall_number("io_uring_register").unwrap(), 427);
}
}
#[test]
fn test_docker_filter_blocks_io_uring_syscalls() {
assert!(syscall_number("io_uring_setup").is_ok());
assert!(syscall_number("io_uring_enter").is_ok());
assert!(syscall_number("io_uring_register").is_ok());
}
}