diff --git a/.buildkite/custom-tests.json b/.buildkite/custom-tests.json index bfd20306..c3033b94 100644 --- a/.buildkite/custom-tests.json +++ b/.buildkite/custom-tests.json @@ -6,7 +6,8 @@ "platform": [ "x86_64", "aarch64", - "riscv64" + "riscv64", + "s390x" ] }, { diff --git a/.platform b/.platform index b1b16842..b283ca6a 100644 --- a/.platform +++ b/.platform @@ -1,4 +1,4 @@ x86_64 aarch64 riscv64 - +s390x diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e6787ab..74b24f6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Upcoming Release # v0.5.0 +## Added +- [[#97]](https://github.com/rust-vmm/seccompiler/pull/97): Added big-endian + support and S390X as first big-endian system. ## Added - [[#72]](https://github.com/rust-vmm/seccompiler/pull/72): Introduce RISC-V diff --git a/Cargo.toml b/Cargo.toml index 7bd697a4..f3acdc29 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,3 +16,6 @@ json = ["serde", "serde_json"] libc = "^0.2.153" serde = { version = "^1.0.27", features = ["derive"], optional = true} serde_json = {version = "^1.0.9", optional = true} + +[dev-dependencies] +errno = "0.3.14" diff --git a/README.md b/README.md index 937c4659..0f4ff66b 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ Supported host architectures: - Little-endian x86_64 - Little-endian aarch64 - Little-endian riscv64 +- Big-endian s390x (*Experimental*) ## Short seccomp tutorial diff --git a/coverage_config_x86_64.json b/coverage_config_x86_64.json index 8afc04f7..e7cfbd78 100644 --- a/coverage_config_x86_64.json +++ b/coverage_config_x86_64.json @@ -1,5 +1,5 @@ { - "coverage_score": 96.7, + "coverage_score": 97.50, "exclude_path": "tests/integration_tests.rs,tests/json.rs", "crate_features": "json" } diff --git a/src/backend/bpf.rs b/src/backend/bpf.rs index 6a102a93..7b8bc5ae 100644 --- a/src/backend/bpf.rs +++ b/src/backend/bpf.rs @@ -128,6 +128,11 @@ pub const AUDIT_ARCH_AARCH64: u32 = 183 | 0x8000_0000 | 0x4000_0000; // `#define AUDIT_ARCH_RISCV64 (EM_RISCV|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)` pub const AUDIT_ARCH_RISCV64: u32 = 243 | 0x8000_0000 | 0x4000_0000; +// Architecture identifier for s390x BE. +// Defined as: +// #define AUDIT_ARCH_S390X (EM_S390|__AUDIT_ARCH_64BIT) +pub const AUDIT_ARCH_S390X: u32 = 22 | 0x8000_0000; + /// BPF instruction structure definition. // See /usr/include/linux/filter.h . // We cannot use the `libc::sock_filter` definition since it doesn't implement `Debug` and diff --git a/src/backend/condition.rs b/src/backend/condition.rs index fa999242..b2e26334 100644 --- a/src/backend/condition.rs +++ b/src/backend/condition.rs @@ -75,12 +75,17 @@ impl SeccompCondition { // Extracts offsets of most significant and least significant halves of argument. // Addition cannot overflow because it's at most `arg_offset` + 4 = 68. - (arg_offset + SECCOMP_DATA_ARG_SIZE / 2, arg_offset) + #[cfg(target_endian = "little")] + return (arg_offset + SECCOMP_DATA_ARG_SIZE / 2, arg_offset); + + #[cfg(target_endian = "big")] + return (arg_offset, arg_offset + SECCOMP_DATA_ARG_SIZE / 2); } /// Splits the `value` field into 32 bit chunks /// /// Returns the most significant and least significant halves of the `value`. + /// shifts are endianness independent fn split_value(&self) -> (u32, u32) { ((self.value >> 32) as u32, self.value as u32) } @@ -315,6 +320,8 @@ mod tests { fn test_get_data_offsets() { let cond = SeccompCondition::new(1, SeccompCmpArgLen::Qword, SeccompCmpOp::Eq, 60).unwrap(); let (msb_offset, lsb_offset) = cond.get_data_offsets(); + + #[cfg(target_endian = "little")] assert_eq!( (msb_offset, lsb_offset), ( @@ -323,6 +330,15 @@ mod tests { ) ); + #[cfg(target_endian = "big")] + assert_eq!( + (msb_offset, lsb_offset), + ( + SECCOMP_DATA_ARGS_OFFSET + SECCOMP_DATA_ARG_SIZE, + SECCOMP_DATA_ARGS_OFFSET + SECCOMP_DATA_ARG_SIZE + 4 + ) + ); + let data = libc::seccomp_data { nr: 0, arch: 0, diff --git a/src/backend/filter.rs b/src/backend/filter.rs index e7757a0a..1d435df8 100644 --- a/src/backend/filter.rs +++ b/src/backend/filter.rs @@ -346,6 +346,11 @@ mod tests { // Compares translated filter with hardcoded BPF program. let filter = create_test_bpf_filter(ArgLen::Dword); + #[cfg(target_endian = "little")] + let offset = 0; + #[cfg(target_endian = "big")] + let offset = 4; + let mut instructions = Vec::new(); instructions.extend(build_arch_validation_sequence(ARCH.try_into().unwrap())); instructions.extend(vec![ @@ -353,28 +358,28 @@ mod tests { bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 1, 0, 1), bpf_stmt(BPF_JMP | BPF_JA, 1), bpf_stmt(BPF_JMP | BPF_JA, 6), - bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 32), + bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 32 + offset), bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 10, 3, 0), - bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 32), + bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 32 + offset), bpf_jump(BPF_JMP | BPF_JGT | BPF_K, 14, 1, 0), bpf_stmt(BPF_RET, 0x7fff_0000), bpf_stmt(BPF_JMP | BPF_JA, 1), bpf_stmt(BPF_JMP | BPF_JA, 6), - bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 32), + bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 32 + offset), bpf_jump(BPF_JMP | BPF_JGE | BPF_K, 30, 3, 0), - bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 32), + bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 32 + offset), bpf_jump(BPF_JMP | BPF_JGT | BPF_K, 20, 0, 1), bpf_stmt(BPF_RET, 0x7fff_0000), bpf_stmt(BPF_JMP | BPF_JA, 1), bpf_stmt(BPF_JMP | BPF_JA, 4), - bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 32), + bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 32 + offset), bpf_jump(BPF_JMP | BPF_JGE | BPF_K, 42, 0, 1), bpf_stmt(BPF_RET, 0x7fff_0000), bpf_stmt(BPF_RET, 0x0003_0000), bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 9, 0, 1), bpf_stmt(BPF_JMP | BPF_JA, 1), bpf_stmt(BPF_JMP | BPF_JA, 5), - bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 24), + bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 24 + offset), bpf_stmt(BPF_ALU | BPF_AND | BPF_K, 0b100), bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 36 & 0b100, 0, 1), bpf_stmt(BPF_RET, 0x7fff_0000), @@ -394,7 +399,12 @@ mod tests { #[test] fn test_filter_bpf_output_qword() { - let filter = create_test_bpf_filter(ArgLen::Qword); + let filter: SeccompFilter = create_test_bpf_filter(ArgLen::Qword); + + #[cfg(target_endian = "little")] + let (msb_offset, lsb_offset) = (4, 0); + #[cfg(target_endian = "big")] + let (msb_offset, lsb_offset) = (0, 4); let mut instructions = Vec::new(); instructions.extend(build_arch_validation_sequence(ARCH.try_into().unwrap())); @@ -403,45 +413,45 @@ mod tests { bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 1, 0, 1), bpf_stmt(BPF_JMP | BPF_JA, 1), bpf_stmt(BPF_JMP | BPF_JA, 11), - bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 36), + bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 32 + msb_offset), bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, 2), - bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 32), + bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 32 + lsb_offset), bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 10, 6, 0), - bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 36), + bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 32 + msb_offset), bpf_jump(BPF_JMP | BPF_JGT | BPF_K, 0, 4, 0), bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, 2), - bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 32), + bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 32 + lsb_offset), bpf_jump(BPF_JMP | BPF_JGT | BPF_K, 14, 1, 0), bpf_stmt(BPF_RET, 0x7fff_0000), bpf_stmt(BPF_JMP | BPF_JA, 1), bpf_stmt(BPF_JMP | BPF_JA, 12), - bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 36), + bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 32 + msb_offset), bpf_jump(BPF_JMP | BPF_JGT | BPF_K, 0, 9, 0), bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, 2), - bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 32), + bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 32 + lsb_offset), bpf_jump(BPF_JMP | BPF_JGE | BPF_K, 30, 6, 0), - bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 36), + bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 32 + msb_offset), bpf_jump(BPF_JMP | BPF_JGT | BPF_K, 0, 3, 0), bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, 3), - bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 32), + bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 32 + lsb_offset), bpf_jump(BPF_JMP | BPF_JGT | BPF_K, 20, 0, 1), bpf_stmt(BPF_RET, 0x7fff_0000), bpf_stmt(BPF_JMP | BPF_JA, 1), bpf_stmt(BPF_JMP | BPF_JA, 7), - bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 36), + bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 32 + msb_offset), bpf_jump(BPF_JMP | BPF_JGT | BPF_K, 0, 3, 0), bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, 3), - bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 32), + bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 32 + lsb_offset), bpf_jump(BPF_JMP | BPF_JGE | BPF_K, 42, 0, 1), bpf_stmt(BPF_RET, 0x7fff_0000), bpf_stmt(BPF_RET, 0x0003_0000), bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 9, 0, 1), bpf_stmt(BPF_JMP | BPF_JA, 1), bpf_stmt(BPF_JMP | BPF_JA, 8), - bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 28), + bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 24 + msb_offset), bpf_stmt(BPF_ALU | BPF_AND | BPF_K, 0), bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, 4), - bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 24), + bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 24 + lsb_offset), bpf_stmt(BPF_ALU | BPF_AND | BPF_K, 0b100), bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 36 & 0b100, 0, 1), bpf_stmt(BPF_RET, 0x7fff_0000), diff --git a/src/backend/mod.rs b/src/backend/mod.rs index e5730ce7..10d26848 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -25,7 +25,10 @@ use libc::{ SECCOMP_RET_KILL_THREAD, SECCOMP_RET_LOG, SECCOMP_RET_TRACE, SECCOMP_RET_TRAP, }; -use bpf::{ARG_NUMBER_MAX, AUDIT_ARCH_AARCH64, AUDIT_ARCH_RISCV64, AUDIT_ARCH_X86_64, BPF_MAX_LEN}; +use bpf::{ + ARG_NUMBER_MAX, AUDIT_ARCH_AARCH64, AUDIT_ARCH_RISCV64, AUDIT_ARCH_S390X, AUDIT_ARCH_X86_64, + BPF_MAX_LEN, +}; pub use bpf::{sock_filter, BpfProgram, BpfProgramRef}; @@ -85,6 +88,8 @@ pub enum TargetArch { aarch64, /// riscv64 arch riscv64, + /// s390x arch + s390x, } impl TargetArch { @@ -94,6 +99,7 @@ impl TargetArch { TargetArch::x86_64 => AUDIT_ARCH_X86_64, TargetArch::aarch64 => AUDIT_ARCH_AARCH64, TargetArch::riscv64 => AUDIT_ARCH_RISCV64, + TargetArch::s390x => AUDIT_ARCH_S390X, } } } @@ -105,6 +111,7 @@ impl TryFrom<&str> for TargetArch { "x86_64" => Ok(TargetArch::x86_64), "aarch64" => Ok(TargetArch::aarch64), "riscv64" => Ok(TargetArch::riscv64), + "s390x" => Ok(TargetArch::s390x), _ => Err(Error::InvalidTargetArch(input.to_string())), } } diff --git a/src/backend/rule.rs b/src/backend/rule.rs index b87e62a0..ecbbbd35 100644 --- a/src/backend/rule.rs +++ b/src/backend/rule.rs @@ -165,8 +165,12 @@ mod tests { ]) .unwrap(); + #[cfg(target_endian = "little")] let (msb_offset, lsb_offset) = { (4, 0) }; + #[cfg(target_endian = "big")] + let (msb_offset, lsb_offset) = { (0, 4) }; + // Builds hardcoded BPF instructions. let instructions = vec![ bpf_stmt(BPF_JMP | BPF_JA, 1), // Start evaluating the rule. @@ -203,8 +207,12 @@ mod tests { conditions.push(Cond::new(0, ArgLen::Qword, Eq, 0).unwrap()); let rule = SeccompRule::new(conditions).unwrap(); + #[cfg(target_endian = "little")] let (msb_offset, lsb_offset) = { (4, 0) }; + #[cfg(target_endian = "big")] + let (msb_offset, lsb_offset) = { (0, 4) }; + // Builds hardcoded BPF instructions. let mut instructions = vec![ bpf_stmt(BPF_JMP | BPF_JA, 1), // Start evaluating the rule. diff --git a/src/lib.rs b/src/lib.rs index a0d12237..f61c08a8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,6 @@ // Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause #![deny(missing_docs)] -#![cfg(target_endian = "little")] //! Provides easy-to-use Linux seccomp-bpf jailing. //! //! Seccomp is a Linux kernel security feature which enables a tight control over what kernel-level @@ -35,6 +34,7 @@ //! - Little-endian x86_64 //! - Little-endian aarch64 //! - Little-endian riscv64 +//! - Big-endian s390x //! //! # Terminology //! diff --git a/src/syscall_table/mod.rs b/src/syscall_table/mod.rs index f47fc3ca..389f9199 100644 --- a/src/syscall_table/mod.rs +++ b/src/syscall_table/mod.rs @@ -3,6 +3,7 @@ mod aarch64; mod riscv64; +mod s390x; mod x86_64; use crate::backend::TargetArch; @@ -21,6 +22,7 @@ impl SyscallTable { TargetArch::aarch64 => aarch64::make_syscall_table(), TargetArch::x86_64 => x86_64::make_syscall_table(), TargetArch::riscv64 => riscv64::make_syscall_table(), + TargetArch::s390x => s390x::make_syscall_table(), }, } } @@ -42,14 +44,17 @@ mod tests { let instance_x86_64 = SyscallTable::new(TargetArch::x86_64); let instance_aarch64 = SyscallTable::new(TargetArch::aarch64); let instance_riscv64 = SyscallTable::new(TargetArch::riscv64); + let instance_s390x = SyscallTable::new(TargetArch::s390x); assert_eq!(instance_x86_64.get_syscall_nr("close").unwrap(), 3); assert_eq!(instance_aarch64.get_syscall_nr("close").unwrap(), 57); assert_eq!(instance_riscv64.get_syscall_nr("close").unwrap(), 57); + assert_eq!(instance_s390x.get_syscall_nr("close").unwrap(), 6); // invalid syscall name assert!(instance_x86_64.get_syscall_nr("nosyscall").is_none()); assert!(instance_aarch64.get_syscall_nr("nosyscall").is_none()); assert!(instance_riscv64.get_syscall_nr("nosyscall").is_none()); + assert!(instance_s390x.get_syscall_nr("nosyscall").is_none()); } } diff --git a/src/syscall_table/s390x.rs b/src/syscall_table/s390x.rs new file mode 100644 index 00000000..9e21a442 --- /dev/null +++ b/src/syscall_table/s390x.rs @@ -0,0 +1,397 @@ +// Copyright 2026 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause + +// This file is auto-generated by `tools/generate_syscall_tables`. +// Do NOT manually edit! +// Generated on: Wed Mar 11 13:17:40 UTC 2026 +// Kernel version: 6.12 + +use std::collections::HashMap; + +pub(crate) fn make_syscall_table() -> HashMap<&'static str, i64> { + vec![ + ("accept4", 364), + ("access", 33), + ("acct", 51), + ("add_key", 278), + ("adjtimex", 124), + ("afs_syscall", 137), + ("alarm", 27), + ("bdflush", 134), + ("bind", 361), + ("bpf", 351), + ("brk", 45), + ("cachestat", 451), + ("capget", 184), + ("capset", 185), + ("chdir", 12), + ("chmod", 15), + ("chown", 212), + ("chroot", 61), + ("clock_adjtime", 337), + ("clock_getres", 261), + ("clock_gettime", 260), + ("clock_nanosleep", 262), + ("clock_settime", 259), + ("clone", 120), + ("clone3", 435), + ("close", 6), + ("close_range", 436), + ("connect", 362), + ("copy_file_range", 375), + ("creat", 8), + ("create_module", 127), + ("delete_module", 129), + ("dup", 41), + ("dup2", 63), + ("dup3", 326), + ("epoll_create", 249), + ("epoll_create1", 327), + ("epoll_ctl", 250), + ("epoll_pwait", 312), + ("epoll_pwait2", 441), + ("epoll_wait", 251), + ("eventfd", 318), + ("eventfd2", 323), + ("execve", 11), + ("execveat", 354), + ("exit", 1), + ("exit_group", 248), + ("faccessat", 300), + ("faccessat2", 439), + ("fadvise64", 253), + ("fallocate", 314), + ("fanotify_init", 332), + ("fanotify_mark", 333), + ("fchdir", 133), + ("fchmod", 94), + ("fchmodat", 299), + ("fchmodat2", 452), + ("fchown", 207), + ("fchownat", 291), + ("fcntl", 55), + ("fdatasync", 148), + ("fgetxattr", 229), + ("finit_module", 344), + ("flistxattr", 232), + ("flock", 143), + ("fork", 2), + ("fremovexattr", 235), + ("fsconfig", 431), + ("fsetxattr", 226), + ("fsmount", 432), + ("fsopen", 430), + ("fspick", 433), + ("fstat", 108), + ("fstatfs", 100), + ("fstatfs64", 266), + ("fsync", 118), + ("ftruncate", 93), + ("futex", 238), + ("futex_requeue", 456), + ("futex_wait", 455), + ("futex_waitv", 449), + ("futex_wake", 454), + ("futimesat", 292), + ("getcpu", 311), + ("getcwd", 183), + ("getdents", 141), + ("getdents64", 220), + ("getegid", 202), + ("geteuid", 201), + ("getgid", 200), + ("getgroups", 205), + ("getitimer", 105), + ("get_kernel_syms", 130), + ("get_mempolicy", 269), + ("getpeername", 368), + ("getpgid", 132), + ("getpgrp", 65), + ("getpid", 20), + ("getpmsg", 188), + ("getppid", 64), + ("getpriority", 96), + ("getrandom", 349), + ("getresgid", 211), + ("getresuid", 209), + ("getrlimit", 191), + ("get_robust_list", 305), + ("getrusage", 77), + ("getsid", 147), + ("getsockname", 367), + ("getsockopt", 365), + ("gettid", 236), + ("gettimeofday", 78), + ("getuid", 199), + ("getxattr", 227), + ("idle", 112), + ("init_module", 128), + ("inotify_add_watch", 285), + ("inotify_init", 284), + ("inotify_init1", 324), + ("inotify_rm_watch", 286), + ("io_cancel", 247), + ("ioctl", 54), + ("io_destroy", 244), + ("io_getevents", 245), + ("io_pgetevents", 382), + ("ioprio_get", 283), + ("ioprio_set", 282), + ("io_setup", 243), + ("io_submit", 246), + ("io_uring_enter", 426), + ("io_uring_register", 427), + ("io_uring_setup", 425), + ("ipc", 117), + ("kcmp", 343), + ("kexec_file_load", 381), + ("kexec_load", 277), + ("keyctl", 280), + ("kill", 37), + ("landlock_add_rule", 445), + ("landlock_create_ruleset", 444), + ("landlock_restrict_self", 446), + ("lchown", 198), + ("lgetxattr", 228), + ("link", 9), + ("linkat", 296), + ("listen", 363), + ("listmount", 458), + ("listxattr", 230), + ("llistxattr", 231), + ("lookup_dcookie", 110), + ("lremovexattr", 234), + ("lseek", 19), + ("lsetxattr", 225), + ("lsm_get_self_attr", 459), + ("lsm_list_modules", 461), + ("lsm_set_self_attr", 460), + ("lstat", 107), + ("madvise", 219), + ("map_shadow_stack", 453), + ("mbind", 268), + ("membarrier", 356), + ("memfd_create", 350), + ("memfd_secret", 447), + ("migrate_pages", 287), + ("mincore", 218), + ("mkdir", 39), + ("mkdirat", 289), + ("mknod", 14), + ("mknodat", 290), + ("mlock", 150), + ("mlock2", 374), + ("mlockall", 152), + ("mmap", 90), + ("mount", 21), + ("mount_setattr", 442), + ("move_mount", 429), + ("move_pages", 310), + ("mprotect", 125), + ("mq_getsetattr", 276), + ("mq_notify", 275), + ("mq_open", 271), + ("mq_timedreceive", 274), + ("mq_timedsend", 273), + ("mq_unlink", 272), + ("mremap", 163), + ("mseal", 462), + ("msgctl", 402), + ("msgget", 399), + ("msgrcv", 401), + ("msgsnd", 400), + ("msync", 144), + ("munlock", 151), + ("munlockall", 153), + ("munmap", 91), + ("name_to_handle_at", 335), + ("nanosleep", 162), + ("newfstatat", 293), + ("nfsservctl", 169), + ("nice", 34), + ("open", 5), + ("openat", 288), + ("openat2", 437), + ("open_by_handle_at", 336), + ("open_tree", 428), + ("pause", 29), + ("perf_event_open", 331), + ("personality", 136), + ("pidfd_getfd", 438), + ("pidfd_open", 434), + ("pidfd_send_signal", 424), + ("pipe", 42), + ("pipe2", 325), + ("pivot_root", 217), + ("pkey_alloc", 385), + ("pkey_free", 386), + ("pkey_mprotect", 384), + ("poll", 168), + ("ppoll", 302), + ("prctl", 172), + ("pread64", 180), + ("preadv", 328), + ("preadv2", 376), + ("prlimit64", 334), + ("process_madvise", 440), + ("process_mrelease", 448), + ("process_vm_readv", 340), + ("process_vm_writev", 341), + ("pselect6", 301), + ("ptrace", 26), + ("putpmsg", 189), + ("pwrite64", 181), + ("pwritev", 329), + ("pwritev2", 377), + ("query_module", 167), + ("quotactl", 131), + ("quotactl_fd", 443), + ("read", 3), + ("readahead", 222), + ("readdir", 89), + ("readlink", 85), + ("readlinkat", 298), + ("readv", 145), + ("reboot", 88), + ("recvfrom", 371), + ("recvmmsg", 357), + ("recvmsg", 372), + ("remap_file_pages", 267), + ("removexattr", 233), + ("rename", 38), + ("renameat", 295), + ("renameat2", 347), + ("request_key", 279), + ("restart_syscall", 7), + ("rmdir", 40), + ("rseq", 383), + ("rt_sigaction", 174), + ("rt_sigpending", 176), + ("rt_sigprocmask", 175), + ("rt_sigqueueinfo", 178), + ("rt_sigreturn", 173), + ("rt_sigsuspend", 179), + ("rt_sigtimedwait", 177), + ("rt_tgsigqueueinfo", 330), + ("s390_guarded_storage", 378), + ("s390_pci_mmio_read", 353), + ("s390_pci_mmio_write", 352), + ("s390_runtime_instr", 342), + ("s390_sthyi", 380), + ("sched_getaffinity", 240), + ("sched_getattr", 346), + ("sched_getparam", 155), + ("sched_get_priority_max", 159), + ("sched_get_priority_min", 160), + ("sched_getscheduler", 157), + ("sched_rr_get_interval", 161), + ("sched_setaffinity", 239), + ("sched_setattr", 345), + ("sched_setparam", 154), + ("sched_setscheduler", 156), + ("sched_yield", 158), + ("seccomp", 348), + ("select", 142), + ("semctl", 394), + ("semget", 393), + ("semtimedop", 392), + ("sendfile", 187), + ("sendmmsg", 358), + ("sendmsg", 370), + ("sendto", 369), + ("setdomainname", 121), + ("setfsgid", 216), + ("setfsuid", 215), + ("setgid", 214), + ("setgroups", 206), + ("sethostname", 74), + ("setitimer", 104), + ("set_mempolicy", 270), + ("set_mempolicy_home_node", 450), + ("setns", 339), + ("setpgid", 57), + ("setpriority", 97), + ("setregid", 204), + ("setresgid", 210), + ("setresuid", 208), + ("setreuid", 203), + ("setrlimit", 75), + ("set_robust_list", 304), + ("setsid", 66), + ("setsockopt", 366), + ("set_tid_address", 252), + ("settimeofday", 79), + ("setuid", 213), + ("setxattr", 224), + ("shmat", 397), + ("shmctl", 396), + ("shmdt", 398), + ("shmget", 395), + ("shutdown", 373), + ("sigaction", 67), + ("sigaltstack", 186), + ("signal", 48), + ("signalfd", 316), + ("signalfd4", 322), + ("sigpending", 73), + ("sigprocmask", 126), + ("sigreturn", 119), + ("sigsuspend", 72), + ("socket", 359), + ("socketcall", 102), + ("socketpair", 360), + ("splice", 306), + ("stat", 106), + ("statfs", 99), + ("statfs64", 265), + ("statmount", 457), + ("statx", 379), + ("swapoff", 115), + ("swapon", 87), + ("symlink", 83), + ("symlinkat", 297), + ("sync", 36), + ("sync_file_range", 307), + ("syncfs", 338), + ("_sysctl", 149), + ("sysfs", 135), + ("sysinfo", 116), + ("syslog", 103), + ("tee", 308), + ("tgkill", 241), + ("timer_create", 254), + ("timer_delete", 258), + ("timerfd", 317), + ("timerfd_create", 319), + ("timerfd_gettime", 321), + ("timerfd_settime", 320), + ("timer_getoverrun", 257), + ("timer_gettime", 256), + ("timer_settime", 255), + ("times", 43), + ("tkill", 237), + ("truncate", 92), + ("umask", 60), + ("umount", 22), + ("umount2", 52), + ("uname", 122), + ("unlink", 10), + ("unlinkat", 294), + ("unshare", 303), + ("uselib", 86), + ("userfaultfd", 355), + ("ustat", 62), + ("utime", 30), + ("utimensat", 315), + ("utimes", 313), + ("vfork", 190), + ("vhangup", 111), + ("vmsplice", 309), + ("wait4", 114), + ("waitid", 281), + ("write", 4), + ("writev", 146), + ] + .into_iter() + .collect() +} diff --git a/tests/multi_thread.rs b/tests/multi_thread.rs index d741bfc2..83244431 100644 --- a/tests/multi_thread.rs +++ b/tests/multi_thread.rs @@ -34,6 +34,7 @@ fn check_getpid_fails() { /// Test seccomp's TSYNC functionality, which syncs the current filter to all threads in the /// process. fn test_tsync() { + errno::set_errno(errno::Errno(0)); // These channels will block on send until the receiver has called recv. let (setup_tx, setup_rx) = sync_channel::<()>(0); let (finish_tx, finish_rx) = sync_channel::<()>(0); @@ -52,6 +53,7 @@ fn test_tsync() { // create two threads, one which applies the filter to all threads and another which tries // to call getpid. let seccomp_thread = thread::spawn(move || { + errno::set_errno(errno::Errno(0)); let rules = vec![(libc::SYS_getpid, vec![])]; let rule_map: BTreeMap> = rules.into_iter().collect(); @@ -81,6 +83,7 @@ fn test_tsync() { }); let test_thread = thread::spawn(move || { + errno::set_errno(errno::Errno(0)); // wait until seccomp setup is done setup_rx.recv().unwrap(); diff --git a/tools/generate_syscall_tables.sh b/tools/generate_syscall_tables.sh index ce1bd307..597f5f21 100755 --- a/tools/generate_syscall_tables.sh +++ b/tools/generate_syscall_tables.sh @@ -20,10 +20,12 @@ test_mode=0 PATH_TO_X86_TABLE="$ROOT_DIR/src/syscall_table/x86_64.rs" PATH_TO_AARCH64_TABLE="$ROOT_DIR/src/syscall_table/aarch64.rs" PATH_TO_RISCV64_TABLE="$ROOT_DIR/src/syscall_table/riscv64.rs" +PATH_TO_S390X_TABLE="$ROOT_DIR/src/syscall_table/s390x.rs" PATH_TO_X86_TEST_TABLE="$ROOT_DIR/src/syscall_table/test_x86_64.rs" PATH_TO_AARCH64_TEST_TABLE="$ROOT_DIR/src/syscall_table/test_aarch64.rs" PATH_TO_RISCV64_TEST_TABLE="$ROOT_DIR/src/syscall_table/test_riscv64.rs" +PATH_TO_S390X_TEST_TABLE="$ROOT_DIR/src/syscall_table/test_s390x.rs" install_header() { make -C "$KERNEL_DIR/linux" ARCH="$1" INSTALL_HDR_PATH="$1-headers" headers_install &>/dev/null @@ -48,6 +50,8 @@ write_rust_syscall_table() { syscall_list=$(generate_syscall_list arm64) elif [ "$platform" == "riscv64" ]; then syscall_list=$(generate_syscall_list riscv) + elif [ "$platform" == "s390x" ]; then + syscall_list=$(generate_syscall_list s390) else die "Invalid platform" fi @@ -128,6 +132,9 @@ run_validation() { elif [[ $arch == "riscv64" ]]; then path_to_table=$PATH_TO_RISCV64_TABLE path_to_test_table=$PATH_TO_RISCV64_TEST_TABLE + elif [[ $arch == "s390x" ]]; then + path_to_table=$PATH_TO_S390X_TABLE + path_to_test_table=$PATH_TO_S390X_TEST_TABLE else die "Invalid platform" fi @@ -190,6 +197,7 @@ cleanup () { rm -rf $PATH_TO_X86_TEST_TABLE rm -rf $PATH_TO_AARCH64_TEST_TABLE rm -rf $PATH_TO_RISCV64_TEST_TABLE + rm -rf $PATH_TO_S390X_TEST_TABLE fi } @@ -235,6 +243,16 @@ test() { validate_kernel_version "$kernel_version_riscv64" run_validation "riscv64" "$kernel_version_riscv64" + + # Run the validation for s390x. + echo "Validating table for s390x..." + + kernel_version_s390x=$(cat $PATH_TO_S390X_TABLE | \ + awk -F '// Kernel version:' '{print $2}' | xargs) + + validate_kernel_version "$kernel_version_s390x" + + run_validation "s390x" "$kernel_version_s390x" } main() { @@ -262,6 +280,11 @@ main() { echo "Generating table for riscv64..." write_rust_syscall_table \ "$kernel_version" "riscv64" "$PATH_TO_RISCV64_TABLE" + + # generate syscall table for s390 + echo "Generating table for s390x..." + write_rust_syscall_table \ + "$kernel_version" "s390x" "$PATH_TO_S390X_TABLE" fi }