From 5eb336007f43aa6536692acb4fff322620231dde Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Sun, 3 Oct 2021 22:26:59 +0100 Subject: [PATCH] revert_arch_consolidate_all_of_the_multiplexed_syscall_handling REVERTS From f454456e261930d94b3a1a444b6bac75c11c3cb0 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Wed, 4 Aug 2021 11:51:12 -0400 Subject: [PATCH] arch: consolidate all of the multiplexed syscall handling Not only does this reduce the amount of duplicated code significantly, it removes a lot of the "magic" numbers in the code, and it happened to catch some bugs too. Acked-by: Tom Hromatka Signed-off-by: Paul Moore (imported from commit 17cbd2c253ce63e5e9e3cec867ff58efbe8b5fdc) Gbp-Pq: Name revert_arch_consolidate_all_of_the_multiplexed_syscall_handling.patch --- src/arch-aarch64.c | 4 +- src/arch-arm.c | 13 +- src/arch-mips.c | 540 +++++++++++++++++++++++++++++++++++-- src/arch-mips64.c | 16 +- src/arch-mips64n32.c | 12 +- src/arch-parisc.c | 4 +- src/arch-parisc64.c | 4 +- src/arch-ppc.c | 525 +++++++++++++++++++++++++++++++++++- src/arch-ppc64.c | 615 +++++++++++++++++++++++++++++++++++++++++-- src/arch-riscv64.c | 4 +- src/arch-s390.c | 592 ++++++++++++++++++++++++++++++++++++++++- src/arch-s390x.c | 591 ++++++++++++++++++++++++++++++++++++++++- src/arch-x32.c | 14 +- src/arch-x86.c | 592 ++++++++++++++++++++++++++++++++++++++++- src/arch-x86_64.c | 4 +- src/arch.c | 10 +- src/arch.h | 14 +- src/syscalls.c | 529 +------------------------------------ src/syscalls.h | 8 - 19 files changed, 3422 insertions(+), 669 deletions(-) diff --git a/src/arch-aarch64.c b/src/arch-aarch64.c index b2d76c6..188bc6f 100644 --- a/src/arch-aarch64.c +++ b/src/arch-aarch64.c @@ -31,8 +31,8 @@ const struct arch_def arch_def_aarch64 = { .token_bpf = AUDIT_ARCH_AARCH64, .size = ARCH_SIZE_64, .endian = ARCH_ENDIAN_LITTLE, - .syscall_resolve_name_raw = aarch64_syscall_resolve_name, - .syscall_resolve_num_raw = aarch64_syscall_resolve_num, + .syscall_resolve_name = aarch64_syscall_resolve_name, + .syscall_resolve_num = aarch64_syscall_resolve_num, .syscall_rewrite = NULL, .rule_add = NULL, }; diff --git a/src/arch-arm.c b/src/arch-arm.c index 732940e..9c9153a 100644 --- a/src/arch-arm.c +++ b/src/arch-arm.c @@ -39,7 +39,6 @@ /** * Resolve a syscall name to a number - * @param arch the architecture definition * @param name the syscall name * * Resolve the given syscall name to the syscall number using the syscall table. @@ -47,13 +46,12 @@ * numbers; returns __NR_SCMP_ERROR on failure. * */ -int arm_syscall_resolve_name_munge(const struct arch_def *arch, - const char *name) +int arm_syscall_resolve_name_munge(const char *name) { int sys; /* NOTE: we don't want to modify the pseudo-syscall numbers */ - sys = arch->syscall_resolve_name_raw(name); + sys = arm_syscall_resolve_name(name); if (sys == __NR_SCMP_ERROR || sys < 0) return sys; @@ -62,7 +60,6 @@ int arm_syscall_resolve_name_munge(const struct arch_def *arch, /** * Resolve a syscall number to a name - * @param arch the architecture definition * @param num the syscall number * * Resolve the given syscall number to the syscall name using the syscall table. @@ -70,12 +67,12 @@ int arm_syscall_resolve_name_munge(const struct arch_def *arch, * syscall names; returns NULL on failure. * */ -const char *arm_syscall_resolve_num_munge(const struct arch_def *arch, int num) +const char *arm_syscall_resolve_num_munge(int num) { /* NOTE: we don't want to modify the pseudo-syscall numbers */ if (num >= 0) num &= ~__SCMP_NR_BASE; - return arch->syscall_resolve_num_raw(num); + return arm_syscall_resolve_num(num); } const struct arch_def arch_def_arm = { @@ -84,9 +81,7 @@ const struct arch_def arch_def_arm = { .size = ARCH_SIZE_32, .endian = ARCH_ENDIAN_LITTLE, .syscall_resolve_name = arm_syscall_resolve_name_munge, - .syscall_resolve_name_raw = arm_syscall_resolve_name, .syscall_resolve_num = arm_syscall_resolve_num_munge, - .syscall_resolve_num_raw = arm_syscall_resolve_num, .syscall_rewrite = NULL, .rule_add = NULL, }; diff --git a/src/arch-mips.c b/src/arch-mips.c index 2625ddc..1510d82 100644 --- a/src/arch-mips.c +++ b/src/arch-mips.c @@ -30,23 +30,535 @@ #include "arch.h" #include "arch-mips.h" +/* O32 ABI */ +#define __SCMP_NR_BASE 4000 + /* mips syscall numbers */ #define __mips_NR_socketcall 102 #define __mips_NR_ipc 117 +/** + * Resolve a syscall name to a number + * @param name the syscall name + * + * Resolve the given syscall name to the syscall number using the syscall table. + * Returns the syscall number on success, including negative pseudo syscall + * numbers; returns __NR_SCMP_ERROR on failure. + * + */ +int mips_syscall_resolve_name_munge(const char *name) +{ + +#define _ABI_SYSCALL_RES_NAME_CHK(NAME) \ + if (!strcmp(name, #NAME)) return __PNR_##NAME; + + _ABI_SYSCALL_RES_NAME_CHK(socket) + _ABI_SYSCALL_RES_NAME_CHK(bind) + _ABI_SYSCALL_RES_NAME_CHK(connect) + _ABI_SYSCALL_RES_NAME_CHK(listen) + _ABI_SYSCALL_RES_NAME_CHK(accept) + _ABI_SYSCALL_RES_NAME_CHK(getsockname) + _ABI_SYSCALL_RES_NAME_CHK(getpeername) + _ABI_SYSCALL_RES_NAME_CHK(socketpair) + _ABI_SYSCALL_RES_NAME_CHK(send) + _ABI_SYSCALL_RES_NAME_CHK(recv) + _ABI_SYSCALL_RES_NAME_CHK(sendto) + _ABI_SYSCALL_RES_NAME_CHK(recvfrom) + _ABI_SYSCALL_RES_NAME_CHK(shutdown) + _ABI_SYSCALL_RES_NAME_CHK(setsockopt) + _ABI_SYSCALL_RES_NAME_CHK(getsockopt) + _ABI_SYSCALL_RES_NAME_CHK(sendmsg) + _ABI_SYSCALL_RES_NAME_CHK(recvmsg) + _ABI_SYSCALL_RES_NAME_CHK(accept4) + _ABI_SYSCALL_RES_NAME_CHK(recvmmsg) + _ABI_SYSCALL_RES_NAME_CHK(sendmmsg) + _ABI_SYSCALL_RES_NAME_CHK(semop) + _ABI_SYSCALL_RES_NAME_CHK(semget) + _ABI_SYSCALL_RES_NAME_CHK(semctl) + _ABI_SYSCALL_RES_NAME_CHK(semtimedop) + _ABI_SYSCALL_RES_NAME_CHK(msgsnd) + _ABI_SYSCALL_RES_NAME_CHK(msgrcv) + _ABI_SYSCALL_RES_NAME_CHK(msgget) + _ABI_SYSCALL_RES_NAME_CHK(msgctl) + _ABI_SYSCALL_RES_NAME_CHK(shmat) + _ABI_SYSCALL_RES_NAME_CHK(shmdt) + _ABI_SYSCALL_RES_NAME_CHK(shmget) + _ABI_SYSCALL_RES_NAME_CHK(shmctl) + + return mips_syscall_resolve_name(name); +} + +/** + * Resolve a syscall number to a name + * @param num the syscall number + * + * Resolve the given syscall number to the syscall name using the syscall table. + * Returns a pointer to the syscall name string on success, including pseudo + * syscall names; returns NULL on failure. + * + */ +const char *mips_syscall_resolve_num_munge(int num) +{ + +#define _ABI_SYSCALL_RES_NUM_CHK(NAME) \ + if (num == __PNR_##NAME) return #NAME; + + _ABI_SYSCALL_RES_NUM_CHK(socket) + _ABI_SYSCALL_RES_NUM_CHK(bind) + _ABI_SYSCALL_RES_NUM_CHK(connect) + _ABI_SYSCALL_RES_NUM_CHK(listen) + _ABI_SYSCALL_RES_NUM_CHK(accept) + _ABI_SYSCALL_RES_NUM_CHK(getsockname) + _ABI_SYSCALL_RES_NUM_CHK(getpeername) + _ABI_SYSCALL_RES_NUM_CHK(socketpair) + _ABI_SYSCALL_RES_NUM_CHK(send) + _ABI_SYSCALL_RES_NUM_CHK(recv) + _ABI_SYSCALL_RES_NUM_CHK(sendto) + _ABI_SYSCALL_RES_NUM_CHK(recvfrom) + _ABI_SYSCALL_RES_NUM_CHK(shutdown) + _ABI_SYSCALL_RES_NUM_CHK(setsockopt) + _ABI_SYSCALL_RES_NUM_CHK(getsockopt) + _ABI_SYSCALL_RES_NUM_CHK(sendmsg) + _ABI_SYSCALL_RES_NUM_CHK(recvmsg) + _ABI_SYSCALL_RES_NUM_CHK(accept4) + _ABI_SYSCALL_RES_NUM_CHK(recvmmsg) + _ABI_SYSCALL_RES_NUM_CHK(sendmmsg) + _ABI_SYSCALL_RES_NUM_CHK(semop) + _ABI_SYSCALL_RES_NUM_CHK(semget) + _ABI_SYSCALL_RES_NUM_CHK(semctl) + _ABI_SYSCALL_RES_NUM_CHK(semtimedop) + _ABI_SYSCALL_RES_NUM_CHK(msgsnd) + _ABI_SYSCALL_RES_NUM_CHK(msgrcv) + _ABI_SYSCALL_RES_NUM_CHK(msgget) + _ABI_SYSCALL_RES_NUM_CHK(msgctl) + _ABI_SYSCALL_RES_NUM_CHK(shmat) + _ABI_SYSCALL_RES_NUM_CHK(shmdt) + _ABI_SYSCALL_RES_NUM_CHK(shmget) + _ABI_SYSCALL_RES_NUM_CHK(shmctl) + + return mips_syscall_resolve_num(num); +} + +/** + * Check if a syscall is a socket syscall + * @param sys the syscall number + * + * Returns true if the syscall is a socket related syscall, false otherwise. + * + */ +static bool _mips_syscall_socket_test(int sys) +{ + const char *name; + + /* multiplexed pseduo-syscalls */ + if (sys <= -100 && sys >= -120) + return true; + + name = mips_syscall_resolve_num(sys); + if (!name) + return false; + +#define _ABI_SYSCALL_SOCK_CHK(NAME) \ + if (!strcmp(name, #NAME)) return true; + + _ABI_SYSCALL_SOCK_CHK(socket) + _ABI_SYSCALL_SOCK_CHK(bind) + _ABI_SYSCALL_SOCK_CHK(connect) + _ABI_SYSCALL_SOCK_CHK(listen) + _ABI_SYSCALL_SOCK_CHK(accept) + _ABI_SYSCALL_SOCK_CHK(getsockname) + _ABI_SYSCALL_SOCK_CHK(getpeername) + _ABI_SYSCALL_SOCK_CHK(socketpair) + _ABI_SYSCALL_SOCK_CHK(send) + _ABI_SYSCALL_SOCK_CHK(recv) + _ABI_SYSCALL_SOCK_CHK(sendto) + _ABI_SYSCALL_SOCK_CHK(recvfrom) + _ABI_SYSCALL_SOCK_CHK(shutdown) + _ABI_SYSCALL_SOCK_CHK(setsockopt) + _ABI_SYSCALL_SOCK_CHK(getsockopt) + _ABI_SYSCALL_SOCK_CHK(sendmsg) + _ABI_SYSCALL_SOCK_CHK(recvmsg) + _ABI_SYSCALL_SOCK_CHK(accept4) + _ABI_SYSCALL_SOCK_CHK(recvmmsg) + _ABI_SYSCALL_SOCK_CHK(sendmmsg) + + return false; +} + +/** + * Check if a syscall is an ipc syscall + * @param sys the syscall number + * + * Returns true if the syscall is an ipc related syscall, false otherwise. + * + */ +static bool _mips_syscall_ipc_test(int sys) +{ + const char *name; + + /* multiplexed pseduo-syscalls */ + if (sys <= -200 && sys >= -224) + return true; + + name = mips_syscall_resolve_num(sys); + if (!name) + return false; + +#define _ABI_SYSCALL_IPC_CHK(NAME) \ + if (!strcmp(name, #NAME)) return true; + + _ABI_SYSCALL_IPC_CHK(semop) + _ABI_SYSCALL_IPC_CHK(semget) + _ABI_SYSCALL_IPC_CHK(semctl) + _ABI_SYSCALL_IPC_CHK(semtimedop) + _ABI_SYSCALL_IPC_CHK(msgsnd) + _ABI_SYSCALL_IPC_CHK(msgrcv) + _ABI_SYSCALL_IPC_CHK(msgget) + _ABI_SYSCALL_IPC_CHK(msgctl) + _ABI_SYSCALL_IPC_CHK(shmat) + _ABI_SYSCALL_IPC_CHK(shmdt) + _ABI_SYSCALL_IPC_CHK(shmget) + _ABI_SYSCALL_IPC_CHK(shmctl) + + return false; +} + +/** + * Convert a multiplexed pseudo syscall into a direct syscall + * @param syscall the multiplexed pseudo syscall number + * + * Return the related direct syscall number, __NR_SCMP_UNDEF is there is + * no related syscall, or __NR_SCMP_ERROR otherwise. + * + */ +static int _mips_syscall_demux(int syscall) +{ + int sys = __NR_SCMP_UNDEF; + +#define _ABI_SYSCALL_DEMUX_CHK(NAME) \ +case __PNR_##NAME: \ + sys = mips_syscall_resolve_name(#NAME); break; + + switch (syscall) { + _ABI_SYSCALL_DEMUX_CHK(socket) + _ABI_SYSCALL_DEMUX_CHK(bind) + _ABI_SYSCALL_DEMUX_CHK(connect) + _ABI_SYSCALL_DEMUX_CHK(listen) + _ABI_SYSCALL_DEMUX_CHK(accept) + _ABI_SYSCALL_DEMUX_CHK(getsockname) + _ABI_SYSCALL_DEMUX_CHK(getpeername) + _ABI_SYSCALL_DEMUX_CHK(socketpair) + _ABI_SYSCALL_DEMUX_CHK(send) + _ABI_SYSCALL_DEMUX_CHK(recv) + _ABI_SYSCALL_DEMUX_CHK(sendto) + _ABI_SYSCALL_DEMUX_CHK(recvfrom) + _ABI_SYSCALL_DEMUX_CHK(shutdown) + _ABI_SYSCALL_DEMUX_CHK(setsockopt) + _ABI_SYSCALL_DEMUX_CHK(getsockopt) + _ABI_SYSCALL_DEMUX_CHK(sendmsg) + _ABI_SYSCALL_DEMUX_CHK(recvmsg) + _ABI_SYSCALL_DEMUX_CHK(accept4) + _ABI_SYSCALL_DEMUX_CHK(recvmmsg) + _ABI_SYSCALL_DEMUX_CHK(sendmmsg) + _ABI_SYSCALL_DEMUX_CHK(semop) + _ABI_SYSCALL_DEMUX_CHK(semget) + _ABI_SYSCALL_DEMUX_CHK(semctl) + _ABI_SYSCALL_DEMUX_CHK(semtimedop) + _ABI_SYSCALL_DEMUX_CHK(msgsnd) + _ABI_SYSCALL_DEMUX_CHK(msgrcv) + _ABI_SYSCALL_DEMUX_CHK(msgget) + _ABI_SYSCALL_DEMUX_CHK(msgctl) + _ABI_SYSCALL_DEMUX_CHK(shmat) + _ABI_SYSCALL_DEMUX_CHK(shmdt) + _ABI_SYSCALL_DEMUX_CHK(shmget) + _ABI_SYSCALL_DEMUX_CHK(shmctl) + } + + /* this looks odd because the arch resolver returns _ERROR if it can't + * resolve the syscall, but we want to use _UNDEF for that, so we set + * 'sys' to a sentinel value of _UNDEF and if it is error here we know + * the resolve failed to find a match */ + if (sys == __NR_SCMP_UNDEF) + sys = __NR_SCMP_ERROR; + else if (sys == __NR_SCMP_ERROR) + sys = __NR_SCMP_UNDEF; + + return sys; +} + +/** + * Convert a direct syscall into multiplexed pseudo socket syscall + * @param syscall the direct syscall + * + * Return the related multiplexed pseduo syscall number, __NR_SCMP_UNDEF is + * there is no related pseudo syscall, or __NR_SCMP_ERROR otherwise. + * + */ +static int _mips_syscall_mux(int syscall) +{ + const char *sys; + + sys = mips_syscall_resolve_num(syscall); + if (!sys) + return __NR_SCMP_ERROR; + +#define _ABI_SYSCALL_MUX_CHK(NAME) \ + if (!strcmp(sys, #NAME)) return __PNR_##NAME; + + _ABI_SYSCALL_MUX_CHK(socket) + _ABI_SYSCALL_MUX_CHK(bind) + _ABI_SYSCALL_MUX_CHK(connect) + _ABI_SYSCALL_MUX_CHK(listen) + _ABI_SYSCALL_MUX_CHK(accept) + _ABI_SYSCALL_MUX_CHK(getsockname) + _ABI_SYSCALL_MUX_CHK(getpeername) + _ABI_SYSCALL_MUX_CHK(socketpair) + _ABI_SYSCALL_MUX_CHK(send) + _ABI_SYSCALL_MUX_CHK(recv) + _ABI_SYSCALL_MUX_CHK(sendto) + _ABI_SYSCALL_MUX_CHK(recvfrom) + _ABI_SYSCALL_MUX_CHK(shutdown) + _ABI_SYSCALL_MUX_CHK(setsockopt) + _ABI_SYSCALL_MUX_CHK(getsockopt) + _ABI_SYSCALL_MUX_CHK(sendmsg) + _ABI_SYSCALL_MUX_CHK(recvmsg) + _ABI_SYSCALL_MUX_CHK(accept4) + _ABI_SYSCALL_MUX_CHK(recvmmsg) + _ABI_SYSCALL_MUX_CHK(sendmmsg) + _ABI_SYSCALL_MUX_CHK(semop) + _ABI_SYSCALL_MUX_CHK(semget) + _ABI_SYSCALL_MUX_CHK(semctl) + _ABI_SYSCALL_MUX_CHK(semtimedop) + _ABI_SYSCALL_MUX_CHK(msgsnd) + _ABI_SYSCALL_MUX_CHK(msgrcv) + _ABI_SYSCALL_MUX_CHK(msgget) + _ABI_SYSCALL_MUX_CHK(msgctl) + _ABI_SYSCALL_MUX_CHK(shmat) + _ABI_SYSCALL_MUX_CHK(shmdt) + _ABI_SYSCALL_MUX_CHK(shmget) + _ABI_SYSCALL_MUX_CHK(shmctl) + + return __NR_SCMP_ERROR; +} + +/** + * Rewrite a syscall value to match the architecture + * @param syscall the syscall number + * + * Syscalls can vary across different architectures so this function rewrites + * the syscall into the correct value for the specified architecture. Returns + * zero on success, negative values on failure. + * + */ +int mips_syscall_rewrite(int *syscall) +{ + int sys = *syscall; + + if (sys <= -100 && sys >= -120) + *syscall = __mips_NR_socketcall; + else if (sys <= -200 && sys >= -224) + *syscall = __mips_NR_ipc; + else if (sys < 0) + return -EDOM; + + return 0; +} + +/** + * add a new rule to the mips seccomp filter + * @param db the seccomp filter db + * @param rule the filter rule + * + * This function adds a new syscall filter to the seccomp filter db, making any + * necessary adjustments for the mips ABI. Returns zero on success, negative + * values on failure. + * + * It is important to note that in the case of failure the db may be corrupted, + * the caller must use the transaction mechanism if the db integrity is + * important. + * + */ +int mips_rule_add(struct db_filter *db, struct db_api_rule_list *rule) +{ + int rc = 0; + unsigned int iter; + int sys = rule->syscall; + int sys_a, sys_b; + struct db_api_rule_list *rule_a, *rule_b, *rule_dup = NULL; + + if (_mips_syscall_socket_test(sys)) { + /* socket syscalls */ + + /* strict check for the multiplexed socket syscalls */ + for (iter = 0; iter < ARG_COUNT_MAX; iter++) { + if ((rule->args[iter].valid != 0) && (rule->strict)) { + rc = -EINVAL; + goto add_return; + } + } + + /* determine both the muxed and direct syscall numbers */ + if (sys > 0) { + sys_a = _mips_syscall_mux(sys); + if (sys_a == __NR_SCMP_ERROR) { + rc = __NR_SCMP_ERROR; + goto add_return; + } + sys_b = sys; + } else { + sys_a = sys; + sys_b = _mips_syscall_demux(sys); + if (sys_b == __NR_SCMP_ERROR) { + rc = __NR_SCMP_ERROR; + goto add_return; + } + } + + /* use rule_a for the multiplexed syscall and use rule_b for + * the direct wired syscall */ + + if (sys_a == __NR_SCMP_UNDEF) { + rule_a = NULL; + rule_b = rule; + } else if (sys_b == __NR_SCMP_UNDEF) { + rule_a = rule; + rule_b = NULL; + } else { + /* need two rules, dup the first and link together */ + rule_a = rule; + rule_dup = db_rule_dup(rule_a); + rule_b = rule_dup; + if (rule_b == NULL) + goto add_return; + rule_b->prev = rule_a; + rule_b->next = NULL; + rule_a->next = rule_b; + } + + /* multiplexed socket syscalls */ + if (rule_a != NULL) { + rule_a->syscall = __mips_NR_socketcall; + rule_a->args[0].arg = 0; + rule_a->args[0].op = SCMP_CMP_EQ; + rule_a->args[0].mask = DATUM_MAX; + rule_a->args[0].datum = (-sys_a) % 100; + rule_a->args[0].valid = 1; + } + + /* direct wired socket syscalls */ + if (rule_b != NULL) + rule_b->syscall = sys_b; + + /* we should be protected by a transaction checkpoint */ + if (rule_a != NULL) { + rc = db_rule_add(db, rule_a); + if (rc < 0) + goto add_return; + } + if (rule_b != NULL) { + rc = db_rule_add(db, rule_b); + if (rc < 0) + goto add_return; + } + } else if (_mips_syscall_ipc_test(sys)) { + /* ipc syscalls */ + + /* strict check for the multiplexed socket syscalls */ + for (iter = 0; iter < ARG_COUNT_MAX; iter++) { + if ((rule->args[iter].valid != 0) && (rule->strict)) { + rc = -EINVAL; + goto add_return; + } + } + + /* determine both the muxed and direct syscall numbers */ + if (sys > 0) { + sys_a = _mips_syscall_mux(sys); + if (sys_a == __NR_SCMP_ERROR) { + rc = __NR_SCMP_ERROR; + goto add_return; + } + sys_b = sys; + } else { + sys_a = sys; + sys_b = _mips_syscall_demux(sys); + if (sys_b == __NR_SCMP_ERROR) { + rc = __NR_SCMP_ERROR; + goto add_return; + } + } + + /* use rule_a for the multiplexed syscall and use rule_b for + * the direct wired syscall */ + + if (sys_a == __NR_SCMP_UNDEF) { + rule_a = NULL; + rule_b = rule; + } else if (sys_b == __NR_SCMP_UNDEF) { + rule_a = rule; + rule_b = NULL; + } else { + /* need two rules, dup the first and link together */ + rule_a = rule; + rule_dup = db_rule_dup(rule_a); + rule_b = rule_dup; + if (rule_b == NULL) + goto add_return; + rule_b->prev = rule_a; + rule_b->next = NULL; + rule_a->next = rule_b; + } + + /* multiplexed socket syscalls */ + if (rule_a != NULL) { + rule_a->syscall = __mips_NR_ipc; + rule_a->args[0].arg = 0; + rule_a->args[0].op = SCMP_CMP_EQ; + rule_a->args[0].mask = DATUM_MAX; + rule_a->args[0].datum = (-sys_a) % 200; + rule_a->args[0].valid = 1; + } + + /* direct wired socket syscalls */ + if (rule_b != NULL) + rule_b->syscall = sys_b; + + /* we should be protected by a transaction checkpoint */ + if (rule_a != NULL) { + rc = db_rule_add(db, rule_a); + if (rc < 0) + goto add_return; + } + if (rule_b != NULL) { + rc = db_rule_add(db, rule_b); + if (rc < 0) + goto add_return; + } + } else if (sys >= 0) { + /* normal syscall processing */ + rc = db_rule_add(db, rule); + if (rc < 0) + goto add_return; + } else if (rule->strict) { + rc = -EDOM; + goto add_return; + } + +add_return: + if (rule_dup != NULL) + free(rule_dup); + return rc; +} + const struct arch_def arch_def_mips = { .token = SCMP_ARCH_MIPS, .token_bpf = AUDIT_ARCH_MIPS, .size = ARCH_SIZE_32, .endian = ARCH_ENDIAN_BIG, - .sys_socketcall = __mips_NR_socketcall, - .sys_ipc = __mips_NR_ipc, - .syscall_resolve_name = abi_syscall_resolve_name_munge, - .syscall_resolve_name_raw = mips_syscall_resolve_name, - .syscall_resolve_num = abi_syscall_resolve_num_munge, - .syscall_resolve_num_raw = mips_syscall_resolve_num, - .syscall_rewrite = abi_syscall_rewrite, - .rule_add = abi_rule_add, + .syscall_resolve_name = mips_syscall_resolve_name_munge, + .syscall_resolve_num = mips_syscall_resolve_num_munge, + .syscall_rewrite = mips_syscall_rewrite, + .rule_add = mips_rule_add, }; const struct arch_def arch_def_mipsel = { @@ -54,12 +566,8 @@ const struct arch_def arch_def_mipsel = { .token_bpf = AUDIT_ARCH_MIPSEL, .size = ARCH_SIZE_32, .endian = ARCH_ENDIAN_LITTLE, - .sys_socketcall = __mips_NR_socketcall, - .sys_ipc = __mips_NR_ipc, - .syscall_resolve_name = abi_syscall_resolve_name_munge, - .syscall_resolve_name_raw = mips_syscall_resolve_name, - .syscall_resolve_num = abi_syscall_resolve_num_munge, - .syscall_resolve_num_raw = mips_syscall_resolve_num, - .syscall_rewrite = abi_syscall_rewrite, - .rule_add = abi_rule_add, + .syscall_resolve_name = mips_syscall_resolve_name_munge, + .syscall_resolve_num = mips_syscall_resolve_num_munge, + .syscall_rewrite = mips_syscall_rewrite, + .rule_add = mips_rule_add, }; diff --git a/src/arch-mips64.c b/src/arch-mips64.c index d0f72b8..342d0d8 100644 --- a/src/arch-mips64.c +++ b/src/arch-mips64.c @@ -30,7 +30,6 @@ /** * Resolve a syscall name to a number - * @param arch the architecture definition * @param name the syscall name * * Resolve the given syscall name to the syscall number using the syscall table. @@ -38,13 +37,12 @@ * numbers; returns __NR_SCMP_ERROR on failure. * */ -int mips64_syscall_resolve_name_munge(const struct arch_def *arch, - const char *name) +int mips64_syscall_resolve_name_munge(const char *name) { int sys; /* NOTE: we don't want to modify the pseudo-syscall numbers */ - sys = arch->syscall_resolve_name_raw(name); + sys = mips64_syscall_resolve_name(name); if (sys == __NR_SCMP_ERROR || sys < 0) return sys; @@ -53,7 +51,6 @@ int mips64_syscall_resolve_name_munge(const struct arch_def *arch, /** * Resolve a syscall number to a name - * @param arch the architecture definition * @param num the syscall number * * Resolve the given syscall number to the syscall name using the syscall table. @@ -61,13 +58,12 @@ int mips64_syscall_resolve_name_munge(const struct arch_def *arch, * syscall names; returns NULL on failure. * */ -const char *mips64_syscall_resolve_num_munge(const struct arch_def *arch, - int num) +const char *mips64_syscall_resolve_num_munge(int num) { /* NOTE: we don't want to modify the pseudo-syscall numbers */ if (num >= __SCMP_NR_BASE) num -= __SCMP_NR_BASE; - return arch->syscall_resolve_num_raw(num); + return mips64_syscall_resolve_num(num); } const struct arch_def arch_def_mips64 = { @@ -76,9 +72,7 @@ const struct arch_def arch_def_mips64 = { .size = ARCH_SIZE_64, .endian = ARCH_ENDIAN_BIG, .syscall_resolve_name = mips64_syscall_resolve_name_munge, - .syscall_resolve_name_raw = mips64_syscall_resolve_name, .syscall_resolve_num = mips64_syscall_resolve_num_munge, - .syscall_resolve_num_raw = mips64_syscall_resolve_num, .syscall_rewrite = NULL, .rule_add = NULL, }; @@ -89,9 +83,7 @@ const struct arch_def arch_def_mipsel64 = { .size = ARCH_SIZE_64, .endian = ARCH_ENDIAN_LITTLE, .syscall_resolve_name = mips64_syscall_resolve_name_munge, - .syscall_resolve_name_raw = mips64_syscall_resolve_name, .syscall_resolve_num = mips64_syscall_resolve_num_munge, - .syscall_resolve_num_raw = mips64_syscall_resolve_num, .syscall_rewrite = NULL, .rule_add = NULL, }; diff --git a/src/arch-mips64n32.c b/src/arch-mips64n32.c index 532c8f3..098864b 100644 --- a/src/arch-mips64n32.c +++ b/src/arch-mips64n32.c @@ -32,7 +32,6 @@ /** * Resolve a syscall name to a number - * @param arch the architecture definition * @param name the syscall name * * Resolve the given syscall name to the syscall number using the syscall table. @@ -40,8 +39,7 @@ * numbers; returns __NR_SCMP_ERROR on failure. * */ -int mips64n32_syscall_resolve_name_munge(const struct arch_def *arch, - const char *name) +int mips64n32_syscall_resolve_name_munge(const char *name) { int sys; @@ -55,7 +53,6 @@ int mips64n32_syscall_resolve_name_munge(const struct arch_def *arch, /** * Resolve a syscall number to a name - * @param arch the architecture definition * @param num the syscall number * * Resolve the given syscall number to the syscall name using the syscall table. @@ -63,8 +60,7 @@ int mips64n32_syscall_resolve_name_munge(const struct arch_def *arch, * syscall names; returns NULL on failure. * */ -const char *mips64n32_syscall_resolve_num_munge(const struct arch_def *arch, - int num) +const char *mips64n32_syscall_resolve_num_munge(int num) { /* NOTE: we don't want to modify the pseudo-syscall numbers */ if (num >= __SCMP_NR_BASE) @@ -78,9 +74,7 @@ const struct arch_def arch_def_mips64n32 = { .size = ARCH_SIZE_32, .endian = ARCH_ENDIAN_BIG, .syscall_resolve_name = mips64n32_syscall_resolve_name_munge, - .syscall_resolve_name_raw = mips64n32_syscall_resolve_name, .syscall_resolve_num = mips64n32_syscall_resolve_num_munge, - .syscall_resolve_num_raw = mips64n32_syscall_resolve_num, .syscall_rewrite = NULL, .rule_add = NULL, }; @@ -91,9 +85,7 @@ const struct arch_def arch_def_mipsel64n32 = { .size = ARCH_SIZE_32, .endian = ARCH_ENDIAN_LITTLE, .syscall_resolve_name = mips64n32_syscall_resolve_name_munge, - .syscall_resolve_name_raw = mips64n32_syscall_resolve_name, .syscall_resolve_num = mips64n32_syscall_resolve_num_munge, - .syscall_resolve_num_raw = mips64n32_syscall_resolve_num, .syscall_rewrite = NULL, .rule_add = NULL, }; diff --git a/src/arch-parisc.c b/src/arch-parisc.c index 4440a04..f317fed 100644 --- a/src/arch-parisc.c +++ b/src/arch-parisc.c @@ -15,8 +15,8 @@ const struct arch_def arch_def_parisc = { .token_bpf = AUDIT_ARCH_PARISC, .size = ARCH_SIZE_32, .endian = ARCH_ENDIAN_BIG, - .syscall_resolve_name_raw = parisc_syscall_resolve_name, - .syscall_resolve_num_raw = parisc_syscall_resolve_num, + .syscall_resolve_name = parisc_syscall_resolve_name, + .syscall_resolve_num = parisc_syscall_resolve_num, .syscall_rewrite = NULL, .rule_add = NULL, }; diff --git a/src/arch-parisc64.c b/src/arch-parisc64.c index d2d85e6..08e5081 100644 --- a/src/arch-parisc64.c +++ b/src/arch-parisc64.c @@ -15,8 +15,8 @@ const struct arch_def arch_def_parisc64 = { .token_bpf = AUDIT_ARCH_PARISC64, .size = ARCH_SIZE_64, .endian = ARCH_ENDIAN_BIG, - .syscall_resolve_name_raw = parisc64_syscall_resolve_name, - .syscall_resolve_num_raw = parisc64_syscall_resolve_num, + .syscall_resolve_name = parisc64_syscall_resolve_name, + .syscall_resolve_num = parisc64_syscall_resolve_num, .syscall_rewrite = NULL, .rule_add = NULL, }; diff --git a/src/arch-ppc.c b/src/arch-ppc.c index 0c97bf5..035888c 100644 --- a/src/arch-ppc.c +++ b/src/arch-ppc.c @@ -34,17 +34,526 @@ #define __ppc_NR_socketcall 102 #define __ppc_NR_ipc 117 +/** + * Resolve a syscall name to a number + * @param name the syscall name + * + * Resolve the given syscall name to the syscall number using the syscall table. + * Returns the syscall number on success, including negative pseudo syscall + * numbers; returns __NR_SCMP_ERROR on failure. + * + */ +int ppc_syscall_resolve_name_munge(const char *name) +{ + +#define _ABI_SYSCALL_RES_NAME_CHK(NAME) \ + if (!strcmp(name, #NAME)) return __PNR_##NAME; + + _ABI_SYSCALL_RES_NAME_CHK(socket) + _ABI_SYSCALL_RES_NAME_CHK(bind) + _ABI_SYSCALL_RES_NAME_CHK(connect) + _ABI_SYSCALL_RES_NAME_CHK(listen) + _ABI_SYSCALL_RES_NAME_CHK(accept) + _ABI_SYSCALL_RES_NAME_CHK(getsockname) + _ABI_SYSCALL_RES_NAME_CHK(getpeername) + _ABI_SYSCALL_RES_NAME_CHK(socketpair) + _ABI_SYSCALL_RES_NAME_CHK(send) + _ABI_SYSCALL_RES_NAME_CHK(recv) + _ABI_SYSCALL_RES_NAME_CHK(sendto) + _ABI_SYSCALL_RES_NAME_CHK(recvfrom) + _ABI_SYSCALL_RES_NAME_CHK(shutdown) + _ABI_SYSCALL_RES_NAME_CHK(setsockopt) + _ABI_SYSCALL_RES_NAME_CHK(getsockopt) + _ABI_SYSCALL_RES_NAME_CHK(sendmsg) + _ABI_SYSCALL_RES_NAME_CHK(recvmsg) + _ABI_SYSCALL_RES_NAME_CHK(accept4) + _ABI_SYSCALL_RES_NAME_CHK(recvmmsg) + _ABI_SYSCALL_RES_NAME_CHK(sendmmsg) + _ABI_SYSCALL_RES_NAME_CHK(semop) + _ABI_SYSCALL_RES_NAME_CHK(semget) + _ABI_SYSCALL_RES_NAME_CHK(semctl) + _ABI_SYSCALL_RES_NAME_CHK(semtimedop) + _ABI_SYSCALL_RES_NAME_CHK(msgsnd) + _ABI_SYSCALL_RES_NAME_CHK(msgrcv) + _ABI_SYSCALL_RES_NAME_CHK(msgget) + _ABI_SYSCALL_RES_NAME_CHK(msgctl) + _ABI_SYSCALL_RES_NAME_CHK(shmat) + _ABI_SYSCALL_RES_NAME_CHK(shmdt) + _ABI_SYSCALL_RES_NAME_CHK(shmget) + _ABI_SYSCALL_RES_NAME_CHK(shmctl) + + return ppc_syscall_resolve_name(name); +} + +/** + * Resolve a syscall number to a name + * @param num the syscall number + * + * Resolve the given syscall number to the syscall name using the syscall table. + * Returns a pointer to the syscall name string on success, including pseudo + * syscall names; returns NULL on failure. + * + */ +const char *ppc_syscall_resolve_num_munge(int num) +{ + +#define _ABI_SYSCALL_RES_NUM_CHK(NAME) \ + if (num == __PNR_##NAME) return #NAME; + + _ABI_SYSCALL_RES_NUM_CHK(socket) + _ABI_SYSCALL_RES_NUM_CHK(bind) + _ABI_SYSCALL_RES_NUM_CHK(connect) + _ABI_SYSCALL_RES_NUM_CHK(listen) + _ABI_SYSCALL_RES_NUM_CHK(accept) + _ABI_SYSCALL_RES_NUM_CHK(getsockname) + _ABI_SYSCALL_RES_NUM_CHK(getpeername) + _ABI_SYSCALL_RES_NUM_CHK(socketpair) + _ABI_SYSCALL_RES_NUM_CHK(send) + _ABI_SYSCALL_RES_NUM_CHK(recv) + _ABI_SYSCALL_RES_NUM_CHK(sendto) + _ABI_SYSCALL_RES_NUM_CHK(recvfrom) + _ABI_SYSCALL_RES_NUM_CHK(shutdown) + _ABI_SYSCALL_RES_NUM_CHK(setsockopt) + _ABI_SYSCALL_RES_NUM_CHK(getsockopt) + _ABI_SYSCALL_RES_NUM_CHK(sendmsg) + _ABI_SYSCALL_RES_NUM_CHK(recvmsg) + _ABI_SYSCALL_RES_NUM_CHK(accept4) + _ABI_SYSCALL_RES_NUM_CHK(recvmmsg) + _ABI_SYSCALL_RES_NUM_CHK(sendmmsg) + _ABI_SYSCALL_RES_NUM_CHK(semop) + _ABI_SYSCALL_RES_NUM_CHK(semget) + _ABI_SYSCALL_RES_NUM_CHK(semctl) + _ABI_SYSCALL_RES_NUM_CHK(semtimedop) + _ABI_SYSCALL_RES_NUM_CHK(msgsnd) + _ABI_SYSCALL_RES_NUM_CHK(msgrcv) + _ABI_SYSCALL_RES_NUM_CHK(msgget) + _ABI_SYSCALL_RES_NUM_CHK(msgctl) + _ABI_SYSCALL_RES_NUM_CHK(shmat) + _ABI_SYSCALL_RES_NUM_CHK(shmdt) + _ABI_SYSCALL_RES_NUM_CHK(shmget) + _ABI_SYSCALL_RES_NUM_CHK(shmctl) + + return ppc_syscall_resolve_num(num); +} + +/** + * Check if a syscall is a socket syscall + * @param sys the syscall number + * + * Returns true if the syscall is a socket related syscall, false otherwise. + * + */ +static bool _ppc_syscall_socket_test(int sys) +{ + const char *name; + + /* multiplexed pseduo-syscalls */ + if (sys <= -100 && sys >= -120) + return true; + + name = ppc_syscall_resolve_num(sys); + if (!name) + return false; + +#define _ABI_SYSCALL_SOCK_CHK(NAME) \ + if (!strcmp(name, #NAME)) return true; + + _ABI_SYSCALL_SOCK_CHK(socket) + _ABI_SYSCALL_SOCK_CHK(bind) + _ABI_SYSCALL_SOCK_CHK(connect) + _ABI_SYSCALL_SOCK_CHK(listen) + _ABI_SYSCALL_SOCK_CHK(accept) + _ABI_SYSCALL_SOCK_CHK(getsockname) + _ABI_SYSCALL_SOCK_CHK(getpeername) + _ABI_SYSCALL_SOCK_CHK(socketpair) + _ABI_SYSCALL_SOCK_CHK(send) + _ABI_SYSCALL_SOCK_CHK(recv) + _ABI_SYSCALL_SOCK_CHK(sendto) + _ABI_SYSCALL_SOCK_CHK(recvfrom) + _ABI_SYSCALL_SOCK_CHK(shutdown) + _ABI_SYSCALL_SOCK_CHK(setsockopt) + _ABI_SYSCALL_SOCK_CHK(getsockopt) + _ABI_SYSCALL_SOCK_CHK(sendmsg) + _ABI_SYSCALL_SOCK_CHK(recvmsg) + _ABI_SYSCALL_SOCK_CHK(accept4) + _ABI_SYSCALL_SOCK_CHK(recvmmsg) + _ABI_SYSCALL_SOCK_CHK(sendmmsg) + + return false; +} + +/** + * Check if a syscall is an ipc syscall + * @param sys the syscall number + * + * Returns true if the syscall is an ipc related syscall, false otherwise. + * + */ +static bool _ppc_syscall_ipc_test(int sys) +{ + const char *name; + + /* multiplexed pseduo-syscalls */ + if (sys <= -200 && sys >= -224) + return true; + + name = ppc_syscall_resolve_num(sys); + if (!name) + return false; + +#define _ABI_SYSCALL_IPC_CHK(NAME) \ + if (!strcmp(name, #NAME)) return true; + + _ABI_SYSCALL_IPC_CHK(semop) + _ABI_SYSCALL_IPC_CHK(semget) + _ABI_SYSCALL_IPC_CHK(semctl) + _ABI_SYSCALL_IPC_CHK(semtimedop) + _ABI_SYSCALL_IPC_CHK(msgsnd) + _ABI_SYSCALL_IPC_CHK(msgrcv) + _ABI_SYSCALL_IPC_CHK(msgget) + _ABI_SYSCALL_IPC_CHK(msgctl) + _ABI_SYSCALL_IPC_CHK(shmat) + _ABI_SYSCALL_IPC_CHK(shmdt) + _ABI_SYSCALL_IPC_CHK(shmget) + _ABI_SYSCALL_IPC_CHK(shmctl) + + return false; +} + +/** + * Convert a multiplexed pseudo syscall into a direct syscall + * @param syscall the multiplexed pseudo syscall number + * + * Return the related direct syscall number, __NR_SCMP_UNDEF is there is + * no related syscall, or __NR_SCMP_ERROR otherwise. + * + */ +static int _ppc_syscall_demux(int syscall) +{ + int sys = __NR_SCMP_UNDEF; + +#define _ABI_SYSCALL_DEMUX_CHK(NAME) \ +case __PNR_##NAME: \ + sys = ppc_syscall_resolve_name(#NAME); break; + + switch (syscall) { + _ABI_SYSCALL_DEMUX_CHK(socket) + _ABI_SYSCALL_DEMUX_CHK(bind) + _ABI_SYSCALL_DEMUX_CHK(connect) + _ABI_SYSCALL_DEMUX_CHK(listen) + _ABI_SYSCALL_DEMUX_CHK(accept) + _ABI_SYSCALL_DEMUX_CHK(getsockname) + _ABI_SYSCALL_DEMUX_CHK(getpeername) + _ABI_SYSCALL_DEMUX_CHK(socketpair) + _ABI_SYSCALL_DEMUX_CHK(send) + _ABI_SYSCALL_DEMUX_CHK(recv) + _ABI_SYSCALL_DEMUX_CHK(sendto) + _ABI_SYSCALL_DEMUX_CHK(recvfrom) + _ABI_SYSCALL_DEMUX_CHK(shutdown) + _ABI_SYSCALL_DEMUX_CHK(setsockopt) + _ABI_SYSCALL_DEMUX_CHK(getsockopt) + _ABI_SYSCALL_DEMUX_CHK(sendmsg) + _ABI_SYSCALL_DEMUX_CHK(recvmsg) + _ABI_SYSCALL_DEMUX_CHK(accept4) + _ABI_SYSCALL_DEMUX_CHK(recvmmsg) + _ABI_SYSCALL_DEMUX_CHK(sendmmsg) + _ABI_SYSCALL_DEMUX_CHK(semop) + _ABI_SYSCALL_DEMUX_CHK(semget) + _ABI_SYSCALL_DEMUX_CHK(semctl) + _ABI_SYSCALL_DEMUX_CHK(semtimedop) + _ABI_SYSCALL_DEMUX_CHK(msgsnd) + _ABI_SYSCALL_DEMUX_CHK(msgrcv) + _ABI_SYSCALL_DEMUX_CHK(msgget) + _ABI_SYSCALL_DEMUX_CHK(msgctl) + _ABI_SYSCALL_DEMUX_CHK(shmat) + _ABI_SYSCALL_DEMUX_CHK(shmdt) + _ABI_SYSCALL_DEMUX_CHK(shmget) + _ABI_SYSCALL_DEMUX_CHK(shmctl) + } + + /* this looks odd because the arch resolver returns _ERROR if it can't + * resolve the syscall, but we want to use _UNDEF for that, so we set + * 'sys' to a sentinel value of _UNDEF and if it is error here we know + * the resolve failed to find a match */ + if (sys == __NR_SCMP_UNDEF) + sys = __NR_SCMP_ERROR; + else if (sys == __NR_SCMP_ERROR) + sys = __NR_SCMP_UNDEF; + + return sys; +} + +/** + * Convert a direct syscall into multiplexed pseudo socket syscall + * @param syscall the direct syscall + * + * Return the related multiplexed pseduo syscall number, __NR_SCMP_UNDEF is + * there is no related pseudo syscall, or __NR_SCMP_ERROR otherwise. + * + */ +static int _ppc_syscall_mux(int syscall) +{ + const char *sys; + + sys = ppc_syscall_resolve_num(syscall); + if (!sys) + return __NR_SCMP_ERROR; + +#define _ABI_SYSCALL_MUX_CHK(NAME) \ + if (!strcmp(sys, #NAME)) return __PNR_##NAME; + + _ABI_SYSCALL_MUX_CHK(socket) + _ABI_SYSCALL_MUX_CHK(bind) + _ABI_SYSCALL_MUX_CHK(connect) + _ABI_SYSCALL_MUX_CHK(listen) + _ABI_SYSCALL_MUX_CHK(accept) + _ABI_SYSCALL_MUX_CHK(getsockname) + _ABI_SYSCALL_MUX_CHK(getpeername) + _ABI_SYSCALL_MUX_CHK(socketpair) + _ABI_SYSCALL_MUX_CHK(send) + _ABI_SYSCALL_MUX_CHK(recv) + _ABI_SYSCALL_MUX_CHK(sendto) + _ABI_SYSCALL_MUX_CHK(recvfrom) + _ABI_SYSCALL_MUX_CHK(shutdown) + _ABI_SYSCALL_MUX_CHK(setsockopt) + _ABI_SYSCALL_MUX_CHK(getsockopt) + _ABI_SYSCALL_MUX_CHK(sendmsg) + _ABI_SYSCALL_MUX_CHK(recvmsg) + _ABI_SYSCALL_MUX_CHK(accept4) + _ABI_SYSCALL_MUX_CHK(recvmmsg) + _ABI_SYSCALL_MUX_CHK(sendmmsg) + _ABI_SYSCALL_MUX_CHK(semop) + _ABI_SYSCALL_MUX_CHK(semget) + _ABI_SYSCALL_MUX_CHK(semctl) + _ABI_SYSCALL_MUX_CHK(semtimedop) + _ABI_SYSCALL_MUX_CHK(msgsnd) + _ABI_SYSCALL_MUX_CHK(msgrcv) + _ABI_SYSCALL_MUX_CHK(msgget) + _ABI_SYSCALL_MUX_CHK(msgctl) + _ABI_SYSCALL_MUX_CHK(shmat) + _ABI_SYSCALL_MUX_CHK(shmdt) + _ABI_SYSCALL_MUX_CHK(shmget) + _ABI_SYSCALL_MUX_CHK(shmctl) + + return __NR_SCMP_ERROR; +} + +/** + * Rewrite a syscall value to match the architecture + * @param syscall the syscall number + * + * Syscalls can vary across different architectures so this function rewrites + * the syscall into the correct value for the specified architecture. Returns + * zero on success, negative values on failure. + * + */ +int ppc_syscall_rewrite(int *syscall) +{ + int sys = *syscall; + + if (sys <= -100 && sys >= -120) + *syscall = __ppc_NR_socketcall; + else if (sys <= -200 && sys >= -224) + *syscall = __ppc_NR_ipc; + else if (sys < 0) + return -EDOM; + + return 0; +} + +/** + * add a new rule to the ppc seccomp filter + * @param db the seccomp filter db + * @param rule the filter rule + * + * This function adds a new syscall filter to the seccomp filter db, making any + * necessary adjustments for the ppc ABI. Returns zero on success, negative + * values on failure. + * + * It is important to note that in the case of failure the db may be corrupted, + * the caller must use the transaction mechanism if the db integrity is + * important. + * + */ +int ppc_rule_add(struct db_filter *db, struct db_api_rule_list *rule) +{ + int rc = 0; + unsigned int iter; + int sys = rule->syscall; + int sys_a, sys_b; + struct db_api_rule_list *rule_a, *rule_b, *rule_dup = NULL; + + if (_ppc_syscall_socket_test(sys)) { + /* socket syscalls */ + + /* strict check for the multiplexed socket syscalls */ + for (iter = 0; iter < ARG_COUNT_MAX; iter++) { + if ((rule->args[iter].valid != 0) && (rule->strict)) { + rc = -EINVAL; + goto add_return; + } + } + + /* determine both the muxed and direct syscall numbers */ + if (sys > 0) { + sys_a = _ppc_syscall_mux(sys); + if (sys_a == __NR_SCMP_ERROR) { + rc = __NR_SCMP_ERROR; + goto add_return; + } + sys_b = sys; + } else { + sys_a = sys; + sys_b = _ppc_syscall_demux(sys); + if (sys_b == __NR_SCMP_ERROR) { + rc = __NR_SCMP_ERROR; + goto add_return; + } + } + + /* use rule_a for the multiplexed syscall and use rule_b for + * the direct wired syscall */ + + if (sys_a == __NR_SCMP_UNDEF) { + rule_a = NULL; + rule_b = rule; + } else if (sys_b == __NR_SCMP_UNDEF) { + rule_a = rule; + rule_b = NULL; + } else { + /* need two rules, dup the first and link together */ + rule_a = rule; + rule_dup = db_rule_dup(rule_a); + rule_b = rule_dup; + if (rule_b == NULL) + goto add_return; + rule_b->prev = rule_a; + rule_b->next = NULL; + rule_a->next = rule_b; + } + + /* multiplexed socket syscalls */ + if (rule_a != NULL) { + rule_a->syscall = __ppc_NR_socketcall; + rule_a->args[0].arg = 0; + rule_a->args[0].op = SCMP_CMP_EQ; + rule_a->args[0].mask = DATUM_MAX; + rule_a->args[0].datum = (-sys_a) % 100; + rule_a->args[0].valid = 1; + } + + /* direct wired socket syscalls */ + if (rule_b != NULL) + rule_b->syscall = sys_b; + + /* we should be protected by a transaction checkpoint */ + if (rule_a != NULL) { + rc = db_rule_add(db, rule_a); + if (rc < 0) + goto add_return; + } + if (rule_b != NULL) { + rc = db_rule_add(db, rule_b); + if (rc < 0) + goto add_return; + } + } else if (_ppc_syscall_ipc_test(sys)) { + /* ipc syscalls */ + + /* strict check for the multiplexed socket syscalls */ + for (iter = 0; iter < ARG_COUNT_MAX; iter++) { + if ((rule->args[iter].valid != 0) && (rule->strict)) { + rc = -EINVAL; + goto add_return; + } + } + + /* determine both the muxed and direct syscall numbers */ + if (sys > 0) { + sys_a = _ppc_syscall_mux(sys); + if (sys_a == __NR_SCMP_ERROR) { + rc = __NR_SCMP_ERROR; + goto add_return; + } + sys_b = sys; + } else { + sys_a = sys; + sys_b = _ppc_syscall_demux(sys); + if (sys_b == __NR_SCMP_ERROR) { + rc = __NR_SCMP_ERROR; + goto add_return; + } + } + + /* use rule_a for the multiplexed syscall and use rule_b for + * the direct wired syscall */ + + if (sys_a == __NR_SCMP_UNDEF) { + rule_a = NULL; + rule_b = rule; + } else if (sys_b == __NR_SCMP_UNDEF) { + rule_a = rule; + rule_b = NULL; + } else { + /* need two rules, dup the first and link together */ + rule_a = rule; + rule_dup = db_rule_dup(rule_a); + rule_b = rule_dup; + if (rule_b == NULL) + goto add_return; + rule_b->prev = rule_a; + rule_b->next = NULL; + rule_a->next = rule_b; + } + + /* multiplexed socket syscalls */ + if (rule_a != NULL) { + rule_a->syscall = __ppc_NR_ipc; + rule_a->args[0].arg = 0; + rule_a->args[0].op = SCMP_CMP_EQ; + rule_a->args[0].mask = DATUM_MAX; + rule_a->args[0].datum = (-sys_a) % 200; + rule_a->args[0].valid = 1; + } + + /* direct wired socket syscalls */ + if (rule_b != NULL) + rule_b->syscall = sys_b; + + /* we should be protected by a transaction checkpoint */ + if (rule_a != NULL) { + rc = db_rule_add(db, rule_a); + if (rc < 0) + goto add_return; + } + if (rule_b != NULL) { + rc = db_rule_add(db, rule_b); + if (rc < 0) + goto add_return; + } + } else if (sys >= 0) { + /* normal syscall processing */ + rc = db_rule_add(db, rule); + if (rc < 0) + goto add_return; + } else if (rule->strict) { + rc = -EDOM; + goto add_return; + } + +add_return: + if (rule_dup != NULL) + free(rule_dup); + return rc; +} + const struct arch_def arch_def_ppc = { .token = SCMP_ARCH_PPC, .token_bpf = AUDIT_ARCH_PPC, .size = ARCH_SIZE_32, .endian = ARCH_ENDIAN_BIG, - .sys_socketcall = __ppc_NR_socketcall, - .sys_ipc = __ppc_NR_ipc, - .syscall_resolve_name = abi_syscall_resolve_name_munge, - .syscall_resolve_name_raw = ppc_syscall_resolve_name, - .syscall_resolve_num = abi_syscall_resolve_num_munge, - .syscall_resolve_num_raw = ppc_syscall_resolve_num, - .syscall_rewrite = abi_syscall_rewrite, - .rule_add = abi_rule_add, + .syscall_resolve_name = ppc_syscall_resolve_name_munge, + .syscall_resolve_num = ppc_syscall_resolve_num_munge, + .syscall_rewrite = ppc_syscall_rewrite, + .rule_add = ppc_rule_add, }; diff --git a/src/arch-ppc64.c b/src/arch-ppc64.c index 27f31a5..8cccbb8 100644 --- a/src/arch-ppc64.c +++ b/src/arch-ppc64.c @@ -26,7 +26,6 @@ #include #include "db.h" -#include "syscalls.h" #include "arch.h" #include "arch-ppc64.h" @@ -34,19 +33,605 @@ #define __ppc64_NR_socketcall 102 #define __ppc64_NR_ipc 117 +/** + * Resolve a syscall name to a number + * @param name the syscall name + * + * Resolve the given syscall name to the syscall number using the syscall table. + * Returns the syscall number on success, including negative pseudo syscall + * numbers; returns __NR_SCMP_ERROR on failure. + * + */ +int ppc64_syscall_resolve_name_munge(const char *name) +{ + if (strcmp(name, "accept") == 0) + return __PNR_accept; + if (strcmp(name, "accept4") == 0) + return __PNR_accept4; + else if (strcmp(name, "bind") == 0) + return __PNR_bind; + else if (strcmp(name, "connect") == 0) + return __PNR_connect; + else if (strcmp(name, "getpeername") == 0) + return __PNR_getpeername; + else if (strcmp(name, "getsockname") == 0) + return __PNR_getsockname; + else if (strcmp(name, "getsockopt") == 0) + return __PNR_getsockopt; + else if (strcmp(name, "listen") == 0) + return __PNR_listen; + else if (strcmp(name, "msgctl") == 0) + return __PNR_msgctl; + else if (strcmp(name, "msgget") == 0) + return __PNR_msgget; + else if (strcmp(name, "msgrcv") == 0) + return __PNR_msgrcv; + else if (strcmp(name, "msgsnd") == 0) + return __PNR_msgsnd; + else if (strcmp(name, "recv") == 0) + return __PNR_recv; + else if (strcmp(name, "recvfrom") == 0) + return __PNR_recvfrom; + else if (strcmp(name, "recvmsg") == 0) + return __PNR_recvmsg; + else if (strcmp(name, "recvmmsg") == 0) + return __PNR_recvmmsg; + else if (strcmp(name, "semctl") == 0) + return __PNR_semctl; + else if (strcmp(name, "semget") == 0) + return __PNR_semget; + else if (strcmp(name, "semtimedop") == 0) + return __PNR_semtimedop; + else if (strcmp(name, "send") == 0) + return __PNR_send; + else if (strcmp(name, "sendmsg") == 0) + return __PNR_sendmsg; + else if (strcmp(name, "sendmmsg") == 0) + return __PNR_sendmmsg; + else if (strcmp(name, "sendto") == 0) + return __PNR_sendto; + else if (strcmp(name, "setsockopt") == 0) + return __PNR_setsockopt; + else if (strcmp(name, "shmat") == 0) + return __PNR_shmat; + else if (strcmp(name, "shmdt") == 0) + return __PNR_shmdt; + else if (strcmp(name, "shmget") == 0) + return __PNR_shmget; + else if (strcmp(name, "shmctl") == 0) + return __PNR_shmctl; + else if (strcmp(name, "shutdown") == 0) + return __PNR_shutdown; + else if (strcmp(name, "socket") == 0) + return __PNR_socket; + else if (strcmp(name, "socketpair") == 0) + return __PNR_socketpair; + + return ppc64_syscall_resolve_name(name); +} + +/** + * Resolve a syscall number to a name + * @param num the syscall number + * + * Resolve the given syscall number to the syscall name using the syscall table. + * Returns a pointer to the syscall name string on success, including pseudo + * syscall names; returns NULL on failure. + * + */ +const char *ppc64_syscall_resolve_num_munge(int num) +{ + if (num == __PNR_accept) + return "accept"; + else if (num == __PNR_accept4) + return "accept4"; + else if (num == __PNR_bind) + return "bind"; + else if (num == __PNR_connect) + return "connect"; + else if (num == __PNR_getpeername) + return "getpeername"; + else if (num == __PNR_getsockname) + return "getsockname"; + else if (num == __PNR_getsockopt) + return "getsockopt"; + else if (num == __PNR_listen) + return "listen"; + else if (num == __PNR_msgctl) + return "msgctl"; + else if (num == __PNR_msgget) + return "msgget"; + else if (num == __PNR_msgrcv) + return "msgrcv"; + else if (num == __PNR_msgsnd) + return "msgsnd"; + else if (num == __PNR_recv) + return "recv"; + else if (num == __PNR_recvfrom) + return "recvfrom"; + else if (num == __PNR_recvmsg) + return "recvmsg"; + else if (num == __PNR_recvmmsg) + return "recvmmsg"; + else if (num == __PNR_semctl) + return "semctl"; + else if (num == __PNR_semget) + return "semget"; + else if (num == __PNR_semtimedop) + return "semtimedop"; + else if (num == __PNR_send) + return "send"; + else if (num == __PNR_sendmsg) + return "sendmsg"; + else if (num == __PNR_sendmmsg) + return "sendmmsg"; + else if (num == __PNR_sendto) + return "sendto"; + else if (num == __PNR_setsockopt) + return "setsockopt"; + else if (num == __PNR_shmat) + return "shmat"; + else if (num == __PNR_shmdt) + return "shmdt"; + else if (num == __PNR_shmget) + return "shmget"; + else if (num == __PNR_shmctl) + return "shmctl"; + else if (num == __PNR_shutdown) + return "shutdown"; + else if (num == __PNR_socket) + return "socket"; + else if (num == __PNR_socketpair) + return "socketpair"; + + return ppc64_syscall_resolve_num(num); +} + +/** + * Convert a multiplexed pseudo socket syscall into a direct syscall + * @param syscall the multiplexed pseudo syscall number + * + * Return the related direct syscall number, __NR_SCMP_UNDEF is there is + * no related syscall, or __NR_SCMP_ERROR otherwise. + * + */ +static int _ppc64_syscall_demux(int syscall) +{ + switch (syscall) { + case -101: + /* socket */ + return 326; + case -102: + /* bind */ + return 327; + case -103: + /* connect */ + return 328; + case -104: + /* listen */ + return 329; + case -105: + /* accept */ + return 330; + case -106: + /* getsockname */ + return 331; + case -107: + /* getpeername */ + return 332; + case -108: + /* socketpair */ + return 333; + case -109: + /* send */ + return 334; + case -110: + /* recv */ + return 336; + case -111: + /* sendto */ + return 335; + case -112: + /* recvfrom */ + return 337; + case -113: + /* shutdown */ + return 338; + case -114: + /* setsockopt */ + return 339; + case -115: + /* getsockopt */ + return 340; + case -116: + /* sendmsg */ + return 341; + case -117: + /* recvmsg */ + return 342; + case -118: + /* accept4 */ + return 344; + case -119: + /* recvmmsg */ + return 343; + case -120: + /* sendmmsg */ + return 349; + case -201: + /* semop - not defined */ + return __NR_SCMP_UNDEF; + case -202: + /* semget */ + return 393; + case -203: + /* semctl */ + return 394; + case -204: + /* semtimedop */ + return 392; + case -211: + /* msgsnd */ + return 400; + case -212: + /* msgrcv */ + return 401; + case -213: + /* msgget */ + return 399; + case -214: + /* msgctl */ + return 402; + case -221: + /* shmat */ + return 397; + case -222: + /* shmdt */ + return 398; + case -223: + /* shmget */ + return 395; + case -224: + /* shmctl */ + return 396; + } + + return __NR_SCMP_ERROR; +} + +/** + * Convert a direct socket syscall into multiplexed pseudo socket syscall + * @param syscall the direct syscall + * + * Return the related multiplexed pseduo syscall number, __NR_SCMP_UNDEF is + * there is no related pseudo syscall, or __NR_SCMP_ERROR otherwise. + * + */ +static int _ppc64_syscall_mux(int syscall) +{ + switch (syscall) { + case 326: + /* socket */ + return -101; + case 327: + /* bind */ + return -102; + case 328: + /* connect */ + return -103; + case 329: + /* listen */ + return -104; + case 330: + /* accept */ + return -105; + case 331: + /* getsockname */ + return -106; + case 332: + /* getpeername */ + return -107; + case 333: + /* socketpair */ + return -108; + case 334: + /* send */ + return -109; + case 335: + /* sendto */ + return -111; + case 336: + /* recv */ + return -110; + case 337: + /* recvfrom */ + return -112; + case 338: + /* shutdown */ + return -113; + case 339: + /* setsockopt */ + return -114; + case 340: + /* getsockopt */ + return -115; + case 341: + /* sendmsg */ + return -116; + case 342: + /* recvmsg */ + return -117; + case 343: + /* recvmmsg */ + return -119; + case 344: + /* accept4 */ + return -118; + case 349: + /* sendmmsg */ + return -120; + case 392: + /* semtimedop */ + return -204; + case 393: + /* semget */ + return -202; + case 394: + /* semctl */ + return -203; + case 395: + /* shmget */ + return -223; + case 396: + /* shmctl */ + return -224; + case 397: + /* shmat */ + return -221; + case 398: + /* shmdt */ + return -222; + case 399: + /* msgget */ + return -213; + case 400: + /* msgsnd */ + return -211; + case 401: + /* msgrcv */ + return -212; + case 402: + /* msgctl */ + return -214; + } + + return __NR_SCMP_ERROR; +} + +/** + * Rewrite a syscall value to match the architecture + * @param syscall the syscall number + * + * Syscalls can vary across different architectures so this function rewrites + * the syscall into the correct value for the specified architecture. Returns + * zero on success, negative values on failure. + * + */ +int ppc64_syscall_rewrite(int *syscall) +{ + int sys = *syscall; + + if (sys <= -100 && sys >= -120) + *syscall = __ppc64_NR_socketcall; + else if (sys <= -200 && sys >= -224) + *syscall = __ppc64_NR_ipc; + else if (sys < 0) + return -EDOM; + + return 0; +} + +/** + * add a new rule to the ppc64 seccomp filter + * @param db the seccomp filter db + * @param rule the filter rule + * + * This function adds a new syscall filter to the seccomp filter db, making any + * necessary adjustments for the ppc64 ABI. Returns zero on success, negative + * values on failure. + * + * It is important to note that in the case of failure the db may be corrupted, + * the caller must use the transaction mechanism if the db integrity is + * important. + * + */ +int ppc64_rule_add(struct db_filter *db, struct db_api_rule_list *rule) +{ + int rc = 0; + unsigned int iter; + int sys = rule->syscall; + int sys_a, sys_b; + struct db_api_rule_list *rule_a, *rule_b, *rule_dup = NULL; + + if ((sys <= -100 && sys >= -120) || (sys >= 326 && sys <= 344) || + (sys == 349)) { + /* (-100 to -120) : multiplexed socket syscalls + (326 to 344) : direct socket syscalls, Linux 4.3+ + (349) : sendmmsg */ + + /* strict check for the multiplexed socket syscalls */ + for (iter = 0; iter < ARG_COUNT_MAX; iter++) { + if ((rule->args[iter].valid != 0) && (rule->strict)) { + rc = -EINVAL; + goto add_return; + } + } + + /* determine both the muxed and direct syscall numbers */ + if (sys > 0) { + sys_a = _ppc64_syscall_mux(sys); + if (sys_a == __NR_SCMP_ERROR) { + rc = __NR_SCMP_ERROR; + goto add_return; + } + sys_b = sys; + } else { + sys_a = sys; + sys_b = _ppc64_syscall_demux(sys); + if (sys_b == __NR_SCMP_ERROR) { + rc = __NR_SCMP_ERROR; + goto add_return; + } + } + + /* use rule_a for the multiplexed syscall and use rule_b for + * the direct wired syscall */ + + if (sys_a == __NR_SCMP_UNDEF) { + rule_a = NULL; + rule_b = rule; + } else if (sys_b == __NR_SCMP_UNDEF) { + rule_a = rule; + rule_b = NULL; + } else { + /* need two rules, dup the first and link together */ + rule_a = rule; + rule_dup = db_rule_dup(rule_a); + rule_b = rule_dup; + if (rule_b == NULL) { + rc = -ENOMEM; + goto add_return; + } + rule_b->prev = rule_a; + rule_b->next = NULL; + rule_a->next = rule_b; + } + + /* multiplexed socket syscalls */ + if (rule_a != NULL) { + rule_a->syscall = __ppc64_NR_socketcall; + rule_a->args[0].arg = 0; + rule_a->args[0].op = SCMP_CMP_EQ; + rule_a->args[0].mask = DATUM_MAX; + rule_a->args[0].datum = (-sys_a) % 100; + rule_a->args[0].valid = 1; + } + + /* direct wired socket syscalls */ + if (rule_b != NULL) + rule_b->syscall = sys_b; + + /* we should be protected by a transaction checkpoint */ + if (rule_a != NULL) { + rc = db_rule_add(db, rule_a); + if (rc < 0) + goto add_return; + } + if (rule_b != NULL) { + rc = db_rule_add(db, rule_b); + if (rc < 0) + goto add_return; + } + } else if ((sys <= -200 && sys >= -224) || (sys >= 392 && sys <= 402)) { + /* (-200 to -224) : multiplexed ipc syscalls + (392 to 402) : direct ipc syscalls */ + + /* strict check for the multiplexed socket syscalls */ + for (iter = 0; iter < ARG_COUNT_MAX; iter++) { + if ((rule->args[iter].valid != 0) && (rule->strict)) { + rc = -EINVAL; + goto add_return; + } + } + + /* determine both the muxed and direct syscall numbers */ + if (sys > 0) { + sys_a = _ppc64_syscall_mux(sys); + if (sys_a == __NR_SCMP_ERROR) { + rc = __NR_SCMP_ERROR; + goto add_return; + } + sys_b = sys; + } else { + sys_a = sys; + sys_b = _ppc64_syscall_demux(sys); + if (sys_b == __NR_SCMP_ERROR) { + rc = __NR_SCMP_ERROR; + goto add_return; + } + } + + /* use rule_a for the multiplexed syscall and use rule_b for + * the direct wired syscall */ + + if (sys_a == __NR_SCMP_UNDEF) { + rule_a = NULL; + rule_b = rule; + } else if (sys_b == __NR_SCMP_UNDEF) { + rule_a = rule; + rule_b = NULL; + } else { + /* need two rules, dup the first and link together */ + rule_a = rule; + rule_dup = db_rule_dup(rule_a); + rule_b = rule_dup; + if (rule_b == NULL) + goto add_return; + rule_b->prev = rule_a; + rule_b->next = NULL; + rule_a->next = rule_b; + } + + /* multiplexed socket syscalls */ + if (rule_a != NULL) { + rule_a->syscall = __ppc64_NR_ipc; + rule_a->args[0].arg = 0; + rule_a->args[0].op = SCMP_CMP_EQ; + rule_a->args[0].mask = DATUM_MAX; + rule_a->args[0].datum = (-sys_a) % 200; + rule_a->args[0].valid = 1; + } + + /* direct wired socket syscalls */ + if (rule_b != NULL) + rule_b->syscall = sys_b; + + /* we should be protected by a transaction checkpoint */ + if (rule_a != NULL) { + rc = db_rule_add(db, rule_a); + if (rc < 0) + goto add_return; + } + if (rule_b != NULL) { + rc = db_rule_add(db, rule_b); + if (rc < 0) + goto add_return; + } + } else if (sys >= 0) { + /* normal syscall processing */ + rc = db_rule_add(db, rule); + if (rc < 0) + goto add_return; + } else if (rule->strict) { + rc = -EDOM; + goto add_return; + } + +add_return: + if (rule_dup != NULL) + free(rule_dup); + return rc; +} + const struct arch_def arch_def_ppc64 = { .token = SCMP_ARCH_PPC64, .token_bpf = AUDIT_ARCH_PPC64, .size = ARCH_SIZE_64, .endian = ARCH_ENDIAN_BIG, - .sys_socketcall = __ppc64_NR_socketcall, - .sys_ipc = __ppc64_NR_ipc, - .syscall_resolve_name = abi_syscall_resolve_name_munge, - .syscall_resolve_name_raw = ppc64_syscall_resolve_name, - .syscall_resolve_num = abi_syscall_resolve_num_munge, - .syscall_resolve_num_raw = ppc64_syscall_resolve_num, - .syscall_rewrite = abi_syscall_rewrite, - .rule_add = abi_rule_add, + .syscall_resolve_name = ppc64_syscall_resolve_name_munge, + .syscall_resolve_num = ppc64_syscall_resolve_num_munge, + .syscall_rewrite = ppc64_syscall_rewrite, + .rule_add = ppc64_rule_add, }; const struct arch_def arch_def_ppc64le = { @@ -54,12 +639,8 @@ const struct arch_def arch_def_ppc64le = { .token_bpf = AUDIT_ARCH_PPC64LE, .size = ARCH_SIZE_64, .endian = ARCH_ENDIAN_LITTLE, - .sys_socketcall = __ppc64_NR_socketcall, - .sys_ipc = __ppc64_NR_ipc, - .syscall_resolve_name = abi_syscall_resolve_name_munge, - .syscall_resolve_name_raw = ppc64_syscall_resolve_name, - .syscall_resolve_num = abi_syscall_resolve_num_munge, - .syscall_resolve_num_raw = ppc64_syscall_resolve_num, - .syscall_rewrite = abi_syscall_rewrite, - .rule_add = abi_rule_add, + .syscall_resolve_name = ppc64_syscall_resolve_name_munge, + .syscall_resolve_num = ppc64_syscall_resolve_num_munge, + .syscall_rewrite = ppc64_syscall_rewrite, + .rule_add = ppc64_rule_add, }; diff --git a/src/arch-riscv64.c b/src/arch-riscv64.c index df4f5c8..67bc926 100644 --- a/src/arch-riscv64.c +++ b/src/arch-riscv64.c @@ -24,8 +24,8 @@ const struct arch_def arch_def_riscv64 = { .token_bpf = AUDIT_ARCH_RISCV64, .size = ARCH_SIZE_64, .endian = ARCH_ENDIAN_LITTLE, - .syscall_resolve_name_raw = riscv64_syscall_resolve_name, - .syscall_resolve_num_raw = riscv64_syscall_resolve_num, + .syscall_resolve_name = riscv64_syscall_resolve_name, + .syscall_resolve_num = riscv64_syscall_resolve_num, .syscall_rewrite = NULL, .rule_add = NULL, }; diff --git a/src/arch-s390.c b/src/arch-s390.c index f2c8fda..c2990c0 100644 --- a/src/arch-s390.c +++ b/src/arch-s390.c @@ -17,17 +17,593 @@ #define __s390_NR_socketcall 102 #define __s390_NR_ipc 117 +/** + * Resolve a syscall name to a number + * @param name the syscall name + * + * Resolve the given syscall name to the syscall number using the syscall table. + * Returns the syscall number on success, including negative pseudo syscall + * numbers; returns __NR_SCMP_ERROR on failure. + * + */ +int s390_syscall_resolve_name_munge(const char *name) +{ + if (strcmp(name, "accept") == 0) + return __PNR_accept; + if (strcmp(name, "accept4") == 0) + return __PNR_accept4; + else if (strcmp(name, "bind") == 0) + return __PNR_bind; + else if (strcmp(name, "connect") == 0) + return __PNR_connect; + else if (strcmp(name, "getpeername") == 0) + return __PNR_getpeername; + else if (strcmp(name, "getsockname") == 0) + return __PNR_getsockname; + else if (strcmp(name, "getsockopt") == 0) + return __PNR_getsockopt; + else if (strcmp(name, "listen") == 0) + return __PNR_listen; + else if (strcmp(name, "msgctl") == 0) + return __PNR_msgctl; + else if (strcmp(name, "msgget") == 0) + return __PNR_msgget; + else if (strcmp(name, "msgrcv") == 0) + return __PNR_msgrcv; + else if (strcmp(name, "msgsnd") == 0) + return __PNR_msgsnd; + else if (strcmp(name, "recv") == 0) + return __PNR_recv; + else if (strcmp(name, "recvfrom") == 0) + return __PNR_recvfrom; + else if (strcmp(name, "recvmsg") == 0) + return __PNR_recvmsg; + else if (strcmp(name, "semctl") == 0) + return __PNR_semctl; + else if (strcmp(name, "semget") == 0) + return __PNR_semget; + else if (strcmp(name, "semtimedop") == 0) + return __PNR_semtimedop; + else if (strcmp(name, "recvmmsg") == 0) + return __PNR_recvmmsg; + else if (strcmp(name, "send") == 0) + return __PNR_send; + else if (strcmp(name, "sendmsg") == 0) + return __PNR_sendmsg; + else if (strcmp(name, "sendmmsg") == 0) + return __PNR_sendmmsg; + else if (strcmp(name, "sendto") == 0) + return __PNR_sendto; + else if (strcmp(name, "setsockopt") == 0) + return __PNR_setsockopt; + else if (strcmp(name, "shmat") == 0) + return __PNR_shmat; + else if (strcmp(name, "shmdt") == 0) + return __PNR_shmdt; + else if (strcmp(name, "shmget") == 0) + return __PNR_shmget; + else if (strcmp(name, "shmctl") == 0) + return __PNR_shmctl; + else if (strcmp(name, "shutdown") == 0) + return __PNR_shutdown; + else if (strcmp(name, "socket") == 0) + return __PNR_socket; + else if (strcmp(name, "socketpair") == 0) + return __PNR_socketpair; + + return s390_syscall_resolve_name(name); +} + +/** + * Resolve a syscall number to a name + * @param num the syscall number + * + * Resolve the given syscall number to the syscall name using the syscall table. + * Returns a pointer to the syscall name string on success, including pseudo + * syscall names; returns NULL on failure. + * + */ +const char *s390_syscall_resolve_num_munge(int num) +{ + if (num == __PNR_accept) + return "accept"; + else if (num == __PNR_accept4) + return "accept4"; + else if (num == __PNR_bind) + return "bind"; + else if (num == __PNR_connect) + return "connect"; + else if (num == __PNR_getpeername) + return "getpeername"; + else if (num == __PNR_getsockname) + return "getsockname"; + else if (num == __PNR_getsockopt) + return "getsockopt"; + else if (num == __PNR_listen) + return "listen"; + else if (num == __PNR_msgctl) + return "msgctl"; + else if (num == __PNR_msgget) + return "msgget"; + else if (num == __PNR_msgrcv) + return "msgrcv"; + else if (num == __PNR_msgsnd) + return "msgsnd"; + else if (num == __PNR_recv) + return "recv"; + else if (num == __PNR_recvfrom) + return "recvfrom"; + else if (num == __PNR_recvmsg) + return "recvmsg"; + else if (num == __PNR_recvmmsg) + return "recvmmsg"; + else if (num == __PNR_semctl) + return "semctl"; + else if (num == __PNR_semget) + return "semget"; + else if (num == __PNR_semtimedop) + return "semtimedop"; + else if (num == __PNR_send) + return "send"; + else if (num == __PNR_sendmsg) + return "sendmsg"; + else if (num == __PNR_sendmmsg) + return "sendmmsg"; + else if (num == __PNR_sendto) + return "sendto"; + else if (num == __PNR_setsockopt) + return "setsockopt"; + else if (num == __PNR_shmat) + return "shmat"; + else if (num == __PNR_shmdt) + return "shmdt"; + else if (num == __PNR_shmget) + return "shmget"; + else if (num == __PNR_shmctl) + return "shmctl"; + else if (num == __PNR_shutdown) + return "shutdown"; + else if (num == __PNR_socket) + return "socket"; + else if (num == __PNR_socketpair) + return "socketpair"; + + return s390_syscall_resolve_num(num); +} + +/** + * Convert a multiplexed pseudo syscall into a direct syscall + * @param syscall the multiplexed pseudo syscall number + * + * Return the related direct syscall number, __NR_SCMP_UNDEF is there is + * no related syscall, or __NR_SCMP_ERROR otherwise. + * + */ +static int _s390_syscall_demux(int syscall) +{ + switch (syscall) { + case -101: + /* socket */ + return 359; + case -102: + /* bind */ + return 361; + case -103: + /* connect */ + return 362; + case -104: + /* listen */ + return 363; + case -105: + /* accept - not defined */ + return __NR_SCMP_UNDEF; + case -106: + /* getsockname */ + return 367; + case -107: + /* getpeername */ + return 368; + case -108: + /* socketpair */ + return 360; + case -109: + /* send - not defined */ + return __NR_SCMP_UNDEF; + case -110: + /* recv - not defined */ + return __NR_SCMP_UNDEF; + case -111: + /* sendto */ + return 369; + case -112: + /* recvfrom */ + return 371; + case -113: + /* shutdown */ + return 373; + case -114: + /* setsockopt */ + return 366; + case -115: + /* getsockopt */ + return 365; + case -116: + /* sendmsg */ + return 370; + case -117: + /* recvmsg */ + return 372; + case -118: + /* accept4 */ + return 364; + case -119: + /* recvmmsg */ + return 337; + case -120: + /* sendmmsg */ + return 345; + case -201: + /* semop - not defined */ + return __NR_SCMP_UNDEF; + case -202: + /* semget */ + return 393; + case -203: + /* semctl */ + return 394; + case -204: + /* semtimedop */ + return 392; + case -211: + /* msgsnd */ + return 400; + case -212: + /* msgrcv */ + return 401; + case -213: + /* msgget */ + return 399; + case -214: + /* msgctl */ + return 402; + case -221: + /* shmat */ + return 397; + case -222: + /* shmdt */ + return 398; + case -223: + /* shmget */ + return 395; + case -224: + /* shmctl */ + return 396; + + } + + return __NR_SCMP_ERROR; +} + +/** + * Convert a direct socket syscall into multiplexed pseudo socket syscall + * @param syscall the direct syscall + * + * Return the related multiplexed pseduo syscall number, __NR_SCMP_UNDEF is + * there is no related pseudo syscall, or __NR_SCMP_ERROR otherwise. + * + */ +static int _s390_syscall_mux(int syscall) +{ + switch (syscall) { + case 337: + /* recvmmsg */ + return -119; + case 345: + /* sendmmsg */ + return -120; + case 359: + /* socket */ + return -101; + case 360: + /* socketpair */ + return -108; + case 361: + /* bind */ + return -102; + case 362: + /* connect */ + return -103; + case 363: + /* listen */ + return -104; + case 364: + /* accept4 */ + return -118; + case 365: + /* getsockopt */ + return -115; + case 366: + /* setsockopt */ + return -114; + case 367: + /* getsockname */ + return -106; + case 368: + /* getpeername */ + return -107; + case 369: + /* sendto */ + return -111; + case 370: + /* sendmsg */ + return -116; + case 371: + /* recvfrom */ + return -112; + case 372: + /* recvmsg */ + return -117; + case 373: + /* shutdown */ + return -113; + case 393: + /* semget */ + return -202; + case 394: + /* semctl */ + return -203; + case 400: + /* msgsnd */ + return -211; + case 401: + /* msgrcv */ + return -212; + case 399: + /* msgget */ + return -213; + case 402: + /* msgctl */ + return -214; + case 397: + /* shmat */ + return -221; + case 398: + /* shmdt */ + return -222; + case 395: + /* shmget */ + return -223; + case 396: + /* shmctl */ + return -224; + case 392: + /* semtimedop */ + return -204; + } + + return __NR_SCMP_ERROR; +} + +/** + * Rewrite a syscall value to match the architecture + * @param syscall the syscall number + * + * Syscalls can vary across different architectures so this function rewrites + * the syscall into the correct value for the specified architecture. Returns + * zero on success, negative values on failure. + * + */ +int s390_syscall_rewrite(int *syscall) +{ + int sys = *syscall; + + if (sys <= -100 && sys >= -120) + *syscall = __s390_NR_socketcall; + else if (sys <= -200 && sys >= -224) + *syscall = __s390_NR_ipc; + else if (sys < 0) + return -EDOM; + + return 0; +} + +/** + * add a new rule to the s390 seccomp filter + * @param db the seccomp filter db + * @param rule the filter rule + * + * This function adds a new syscall filter to the seccomp filter db, making any + * necessary adjustments for the s390 ABI. Returns zero on success, negative + * values on failure. + * + * It is important to note that in the case of failure the db may be corrupted, + * the caller must use the transaction mechanism if the db integrity is + * important. + * + */ +int s390_rule_add(struct db_filter *db, struct db_api_rule_list *rule) +{ + int rc = 0; + unsigned int iter; + int sys = rule->syscall; + int sys_a, sys_b; + struct db_api_rule_list *rule_a, *rule_b, *rule_dup = NULL; + + if ((sys <= -100 && sys >= -120) || (sys >= 359 && sys <= 373)) { + /* (-100 to -120) : multiplexed socket syscalls + (359 to 373) : direct socket syscalls, Linux 4.3+ */ + + /* strict check for the multiplexed socket syscalls */ + for (iter = 0; iter < ARG_COUNT_MAX; iter++) { + if ((rule->args[iter].valid != 0) && (rule->strict)) { + rc = -EINVAL; + goto add_return; + } + } + + /* determine both the muxed and direct syscall numbers */ + if (sys > 0) { + sys_a = _s390_syscall_mux(sys); + if (sys_a == __NR_SCMP_ERROR) { + rc = __NR_SCMP_ERROR; + goto add_return; + } + sys_b = sys; + } else { + sys_a = sys; + sys_b = _s390_syscall_demux(sys); + if (sys_b == __NR_SCMP_ERROR) { + rc = __NR_SCMP_ERROR; + goto add_return; + } + } + + /* use rule_a for the multiplexed syscall and use rule_b for + * the direct wired syscall */ + + if (sys_a == __NR_SCMP_UNDEF) { + rule_a = NULL; + rule_b = rule; + } else if (sys_b == __NR_SCMP_UNDEF) { + rule_a = rule; + rule_b = NULL; + } else { + /* need two rules, dup the first and link together */ + rule_a = rule; + rule_dup = db_rule_dup(rule_a); + rule_b = rule_dup; + if (rule_b == NULL) { + rc = -ENOMEM; + goto add_return; + } + rule_b->prev = rule_a; + rule_b->next = NULL; + rule_a->next = rule_b; + } + + /* multiplexed socket syscalls */ + if (rule_a != NULL) { + rule_a->syscall = __s390_NR_socketcall; + rule_a->args[0].arg = 0; + rule_a->args[0].op = SCMP_CMP_EQ; + rule_a->args[0].mask = DATUM_MAX; + rule_a->args[0].datum = (-sys_a) % 100; + rule_a->args[0].valid = 1; + } + + /* direct wired socket syscalls */ + if (rule_b != NULL) + rule_b->syscall = sys_b; + + /* we should be protected by a transaction checkpoint */ + if (rule_a != NULL) { + rc = db_rule_add(db, rule_a); + if (rc < 0) + goto add_return; + } + if (rule_b != NULL) { + rc = db_rule_add(db, rule_b); + if (rc < 0) + goto add_return; + } + } else if ((sys <= -200 && sys >= -224) || (sys >= 393 && sys <= 402)) { + /* (-200 to -224) : multiplexed ipc syscalls + (393 to 402) : direct ipc syscalls */ + + /* strict check for the multiplexed socket syscalls */ + for (iter = 0; iter < ARG_COUNT_MAX; iter++) { + if ((rule->args[iter].valid != 0) && (rule->strict)) { + rc = -EINVAL; + goto add_return; + } + } + + /* determine both the muxed and direct syscall numbers */ + if (sys > 0) { + sys_a = _s390_syscall_mux(sys); + if (sys_a == __NR_SCMP_ERROR) { + rc = __NR_SCMP_ERROR; + goto add_return; + } + sys_b = sys; + } else { + sys_a = sys; + sys_b = _s390_syscall_demux(sys); + if (sys_b == __NR_SCMP_ERROR) { + rc = __NR_SCMP_ERROR; + goto add_return; + } + } + + /* use rule_a for the multiplexed syscall and use rule_b for + * the direct wired syscall */ + + if (sys_a == __NR_SCMP_UNDEF) { + rule_a = NULL; + rule_b = rule; + } else if (sys_b == __NR_SCMP_UNDEF) { + rule_a = rule; + rule_b = NULL; + } else { + /* need two rules, dup the first and link together */ + rule_a = rule; + rule_dup = db_rule_dup(rule_a); + rule_b = rule_dup; + if (rule_b == NULL) + goto add_return; + rule_b->prev = rule_a; + rule_b->next = NULL; + rule_a->next = rule_b; + } + + /* multiplexed socket syscalls */ + if (rule_a != NULL) { + rule_a->syscall = __s390_NR_ipc; + rule_a->args[0].arg = 0; + rule_a->args[0].op = SCMP_CMP_EQ; + rule_a->args[0].mask = DATUM_MAX; + rule_a->args[0].datum = (-sys_a) % 200; + rule_a->args[0].valid = 1; + } + + /* direct wired socket syscalls */ + if (rule_b != NULL) + rule_b->syscall = sys_b; + + /* we should be protected by a transaction checkpoint */ + if (rule_a != NULL) { + rc = db_rule_add(db, rule_a); + if (rc < 0) + goto add_return; + } + if (rule_b != NULL) { + rc = db_rule_add(db, rule_b); + if (rc < 0) + goto add_return; + } + } else if (sys >= 0) { + /* normal syscall processing */ + rc = db_rule_add(db, rule); + if (rc < 0) + goto add_return; + } else if (rule->strict) { + rc = -EDOM; + goto add_return; + } + +add_return: + if (rule_dup != NULL) + free(rule_dup); + return rc; +} + const struct arch_def arch_def_s390 = { .token = SCMP_ARCH_S390, .token_bpf = AUDIT_ARCH_S390, .size = ARCH_SIZE_32, .endian = ARCH_ENDIAN_BIG, - .sys_socketcall = __s390_NR_socketcall, - .sys_ipc = __s390_NR_ipc, - .syscall_resolve_name = abi_syscall_resolve_name_munge, - .syscall_resolve_name_raw = s390_syscall_resolve_name, - .syscall_resolve_num = abi_syscall_resolve_num_munge, - .syscall_resolve_num_raw = s390_syscall_resolve_num, - .syscall_rewrite = abi_syscall_rewrite, - .rule_add = abi_rule_add, + .syscall_resolve_name = s390_syscall_resolve_name_munge, + .syscall_resolve_num = s390_syscall_resolve_num_munge, + .syscall_rewrite = s390_syscall_rewrite, + .rule_add = s390_rule_add, }; diff --git a/src/arch-s390x.c b/src/arch-s390x.c index ddae21b..45d67ec 100644 --- a/src/arch-s390x.c +++ b/src/arch-s390x.c @@ -17,17 +17,592 @@ #define __s390x_NR_socketcall 102 #define __s390x_NR_ipc 117 +/** + * Resolve a syscall name to a number + * @param name the syscall name + * + * Resolve the given syscall name to the syscall number using the syscall table. + * Returns the syscall number on success, including negative pseudo syscall + * numbers; returns __NR_SCMP_ERROR on failure. + * + */ +int s390x_syscall_resolve_name_munge(const char *name) +{ + if (strcmp(name, "accept") == 0) + return __PNR_accept; + if (strcmp(name, "accept4") == 0) + return __PNR_accept4; + else if (strcmp(name, "bind") == 0) + return __PNR_bind; + else if (strcmp(name, "connect") == 0) + return __PNR_connect; + else if (strcmp(name, "getpeername") == 0) + return __PNR_getpeername; + else if (strcmp(name, "getsockname") == 0) + return __PNR_getsockname; + else if (strcmp(name, "getsockopt") == 0) + return __PNR_getsockopt; + else if (strcmp(name, "listen") == 0) + return __PNR_listen; + else if (strcmp(name, "msgctl") == 0) + return __PNR_msgctl; + else if (strcmp(name, "msgget") == 0) + return __PNR_msgget; + else if (strcmp(name, "msgrcv") == 0) + return __PNR_msgrcv; + else if (strcmp(name, "msgsnd") == 0) + return __PNR_msgsnd; + else if (strcmp(name, "recv") == 0) + return __PNR_recv; + else if (strcmp(name, "recvfrom") == 0) + return __PNR_recvfrom; + else if (strcmp(name, "recvmsg") == 0) + return __PNR_recvmsg; + else if (strcmp(name, "recvmmsg") == 0) + return __PNR_recvmmsg; + else if (strcmp(name, "semctl") == 0) + return __PNR_semctl; + else if (strcmp(name, "semget") == 0) + return __PNR_semget; + else if (strcmp(name, "semtimedop") == 0) + return __PNR_semtimedop; + else if (strcmp(name, "send") == 0) + return __PNR_send; + else if (strcmp(name, "sendmsg") == 0) + return __PNR_sendmsg; + else if (strcmp(name, "sendmmsg") == 0) + return __PNR_sendmmsg; + else if (strcmp(name, "sendto") == 0) + return __PNR_sendto; + else if (strcmp(name, "setsockopt") == 0) + return __PNR_setsockopt; + else if (strcmp(name, "shmat") == 0) + return __PNR_shmat; + else if (strcmp(name, "shmdt") == 0) + return __PNR_shmdt; + else if (strcmp(name, "shmget") == 0) + return __PNR_shmget; + else if (strcmp(name, "shmctl") == 0) + return __PNR_shmctl; + else if (strcmp(name, "shutdown") == 0) + return __PNR_shutdown; + else if (strcmp(name, "socket") == 0) + return __PNR_socket; + else if (strcmp(name, "socketpair") == 0) + return __PNR_socketpair; + + return s390x_syscall_resolve_name(name); +} + +/** + * Resolve a syscall number to a name + * @param num the syscall number + * + * Resolve the given syscall number to the syscall name using the syscall table. + * Returns a pointer to the syscall name string on success, including pseudo + * syscall names; returns NULL on failure. + * + */ +const char *s390x_syscall_resolve_num_munge(int num) +{ + if (num == __PNR_accept) + return "accept"; + else if (num == __PNR_accept4) + return "accept4"; + else if (num == __PNR_bind) + return "bind"; + else if (num == __PNR_connect) + return "connect"; + else if (num == __PNR_getpeername) + return "getpeername"; + else if (num == __PNR_getsockname) + return "getsockname"; + else if (num == __PNR_getsockopt) + return "getsockopt"; + else if (num == __PNR_listen) + return "listen"; + else if (num == __PNR_msgctl) + return "msgctl"; + else if (num == __PNR_msgget) + return "msgget"; + else if (num == __PNR_msgrcv) + return "msgrcv"; + else if (num == __PNR_msgsnd) + return "msgsnd"; + else if (num == __PNR_recv) + return "recv"; + else if (num == __PNR_recvfrom) + return "recvfrom"; + else if (num == __PNR_recvmsg) + return "recvmsg"; + else if (num == __PNR_recvmmsg) + return "recvmmsg"; + else if (num == __PNR_semctl) + return "semctl"; + else if (num == __PNR_semget) + return "semget"; + else if (num == __PNR_semtimedop) + return "semtimedop"; + else if (num == __PNR_send) + return "send"; + else if (num == __PNR_sendmsg) + return "sendmsg"; + else if (num == __PNR_sendmmsg) + return "sendmmsg"; + else if (num == __PNR_sendto) + return "sendto"; + else if (num == __PNR_setsockopt) + return "setsockopt"; + else if (num == __PNR_shmat) + return "shmat"; + else if (num == __PNR_shmdt) + return "shmdt"; + else if (num == __PNR_shmget) + return "shmget"; + else if (num == __PNR_shmctl) + return "shmctl"; + else if (num == __PNR_shutdown) + return "shutdown"; + else if (num == __PNR_socket) + return "socket"; + else if (num == __PNR_socketpair) + return "socketpair"; + + return s390x_syscall_resolve_num(num); +} + +/** + * Convert a multiplexed pseudo socket syscall into a direct syscall + * @param syscall the multiplexed pseudo syscall number + * + * Return the related direct syscall number, __NR_SCMP_UNDEF is there is + * no related syscall, or __NR_SCMP_ERROR otherwise. + * + */ +static int _s390x_syscall_demux(int syscall) +{ + switch (syscall) { + case -101: + /* socket */ + return 359; + case -102: + /* bind */ + return 361; + case -103: + /* connect */ + return 362; + case -104: + /* listen */ + return 363; + case -105: + /* accept - not defined */ + return __NR_SCMP_UNDEF; + case -106: + /* getsockname */ + return 367; + case -107: + /* getpeername */ + return 368; + case -108: + /* socketpair */ + return 360; + case -109: + /* send - not defined */ + return __NR_SCMP_UNDEF; + case -110: + /* recv - not defined */ + return __NR_SCMP_UNDEF; + case -111: + /* sendto */ + return 369; + case -112: + /* recvfrom */ + return 371; + case -113: + /* shutdown */ + return 373; + case -114: + /* setsockopt */ + return 366; + case -115: + /* getsockopt */ + return 365; + case -116: + /* sendmsg */ + return 370; + case -117: + /* recvmsg */ + return 372; + case -118: + /* accept4 */ + return 364; + case -119: + /* recvmmsg */ + return 337; + case -120: + /* sendmmsg */ + return 345; + case -201: + /* semop - not defined */ + return __NR_SCMP_UNDEF; + case -202: + /* semget */ + return 393; + case -203: + /* semctl */ + return 394; + case -204: + /* semtimedop */ + return 392; + case -211: + /* msgsnd */ + return 400; + case -212: + /* msgrcv */ + return 401; + case -213: + /* msgget */ + return 399; + case -214: + /* msgctl */ + return 402; + case -221: + /* shmat */ + return 397; + case -222: + /* shmdt */ + return 398; + case -223: + /* shmget */ + return 395; + case -224: + /* shmctl */ + return 396; + } + + return __NR_SCMP_ERROR; +} + +/** + * Convert a direct socket syscall into multiplexed pseudo socket syscall + * @param syscall the direct syscall + * + * Return the related multiplexed pseduo syscall number, __NR_SCMP_UNDEF is + * there is no related pseudo syscall, or __NR_SCMP_ERROR otherwise. + * + */ +static int _s390x_syscall_mux(int syscall) +{ + switch (syscall) { + case 337: + /* recvmmsg */ + return -119; + case 345: + /* sendmmsg */ + return -120; + case 359: + /* socket */ + return -101; + case 360: + /* socketpair */ + return -108; + case 361: + /* bind */ + return -102; + case 362: + /* connect */ + return -103; + case 363: + /* listen */ + return -104; + case 364: + /* accept4 */ + return -118; + case 365: + /* getsockopt */ + return -115; + case 366: + /* setsockopt */ + return -114; + case 367: + /* getsockname */ + return -106; + case 368: + /* getpeername */ + return -107; + case 369: + /* sendto */ + return -111; + case 370: + /* sendmsg */ + return -116; + case 371: + /* recvfrom */ + return -112; + case 372: + /* recvmsg */ + return -117; + case 373: + /* shutdown */ + return -113; + case 392: + /* semtimedop */ + return -204; + case 393: + /* semget */ + return -202; + case 394: + /* semctl */ + return -203; + case 400: + /* msgsnd */ + return -211; + case 401: + /* msgrcv */ + return -212; + case 399: + /* msgget */ + return -213; + case 402: + /* msgctl */ + return -214; + case 397: + /* shmat */ + return -221; + case 398: + /* shmdt */ + return -222; + case 395: + /* shmget */ + return -223; + case 396: + /* shmctl */ + return -224; + } + + return __NR_SCMP_ERROR; +} + +/** + * Rewrite a syscall value to match the architecture + * @param syscall the syscall number + * + * Syscalls can vary across different architectures so this function rewrites + * the syscall into the correct value for the specified architecture. Returns + * zero on success, negative values on failure. + * + */ +int s390x_syscall_rewrite(int *syscall) +{ + int sys = *syscall; + + if (sys <= -100 && sys >= -120) + *syscall = __s390x_NR_socketcall; + else if (sys <= -200 && sys >= -224) + *syscall = __s390x_NR_ipc; + else if (sys < 0) + return -EDOM; + + return 0; +} + +/** + * add a new rule to the s390x seccomp filter + * @param db the seccomp filter db + * @param rule the filter rule + * + * This function adds a new syscall filter to the seccomp filter db, making any + * necessary adjustments for the s390x ABI. Returns zero on success, negative + * values on failure. + * + * It is important to note that in the case of failure the db may be corrupted, + * the caller must use the transaction mechanism if the db integrity is + * important. + * + */ +int s390x_rule_add(struct db_filter *db, struct db_api_rule_list *rule) +{ + int rc = 0; + unsigned int iter; + int sys = rule->syscall; + int sys_a, sys_b; + struct db_api_rule_list *rule_a, *rule_b, *rule_dup = NULL; + + if ((sys <= -100 && sys >= -120) || (sys >= 359 && sys <= 373)) { + /* (-100 to -120) : multiplexed socket syscalls + (359 to 373) : direct socket syscalls, Linux 4.3+ */ + + /* strict check for the multiplexed socket syscalls */ + for (iter = 0; iter < ARG_COUNT_MAX; iter++) { + if ((rule->args[iter].valid != 0) && (rule->strict)) { + rc = -EINVAL; + goto add_return; + } + } + + /* determine both the muxed and direct syscall numbers */ + if (sys > 0) { + sys_a = _s390x_syscall_mux(sys); + if (sys_a == __NR_SCMP_ERROR) { + rc = __NR_SCMP_ERROR; + goto add_return; + } + sys_b = sys; + } else { + sys_a = sys; + sys_b = _s390x_syscall_demux(sys); + if (sys_b == __NR_SCMP_ERROR) { + rc = __NR_SCMP_ERROR; + goto add_return; + } + } + + /* use rule_a for the multiplexed syscall and use rule_b for + * the direct wired syscall */ + + if (sys_a == __NR_SCMP_UNDEF) { + rule_a = NULL; + rule_b = rule; + } else if (sys_b == __NR_SCMP_UNDEF) { + rule_a = rule; + rule_b = NULL; + } else { + /* need two rules, dup the first and link together */ + rule_a = rule; + rule_dup = db_rule_dup(rule_a); + rule_b = rule_dup; + if (rule_b == NULL) { + rc = -ENOMEM; + goto add_return; + } + rule_b->prev = rule_a; + rule_b->next = NULL; + rule_a->next = rule_b; + } + + /* multiplexed socket syscalls */ + if (rule_a != NULL) { + rule_a->syscall = __s390x_NR_socketcall; + rule_a->args[0].arg = 0; + rule_a->args[0].op = SCMP_CMP_EQ; + rule_a->args[0].mask = DATUM_MAX; + rule_a->args[0].datum = (-sys_a) % 100; + rule_a->args[0].valid = 1; + } + + /* direct wired socket syscalls */ + if (rule_b != NULL) + rule_b->syscall = sys_b; + + /* we should be protected by a transaction checkpoint */ + if (rule_a != NULL) { + rc = db_rule_add(db, rule_a); + if (rc < 0) + goto add_return; + } + if (rule_b != NULL) { + rc = db_rule_add(db, rule_b); + if (rc < 0) + goto add_return; + } + } else if ((sys <= -200 && sys >= -224) || (sys >= 392 && sys <= 402)) { + /* (-200 to -224) : multiplexed ipc syscalls + (392 to 402) : direct ipc syscalls */ + + /* strict check for the multiplexed socket syscalls */ + for (iter = 0; iter < ARG_COUNT_MAX; iter++) { + if ((rule->args[iter].valid != 0) && (rule->strict)) { + rc = -EINVAL; + goto add_return; + } + } + + /* determine both the muxed and direct syscall numbers */ + if (sys > 0) { + sys_a = _s390x_syscall_mux(sys); + if (sys_a == __NR_SCMP_ERROR) { + rc = __NR_SCMP_ERROR; + goto add_return; + } + sys_b = sys; + } else { + sys_a = sys; + sys_b = _s390x_syscall_demux(sys); + if (sys_b == __NR_SCMP_ERROR) { + rc = __NR_SCMP_ERROR; + goto add_return; + } + } + + /* use rule_a for the multiplexed syscall and use rule_b for + * the direct wired syscall */ + + if (sys_a == __NR_SCMP_UNDEF) { + rule_a = NULL; + rule_b = rule; + } else if (sys_b == __NR_SCMP_UNDEF) { + rule_a = rule; + rule_b = NULL; + } else { + /* need two rules, dup the first and link together */ + rule_a = rule; + rule_dup = db_rule_dup(rule_a); + rule_b = rule_dup; + if (rule_b == NULL) + goto add_return; + rule_b->prev = rule_a; + rule_b->next = NULL; + rule_a->next = rule_b; + } + + /* multiplexed socket syscalls */ + if (rule_a != NULL) { + rule_a->syscall = __s390x_NR_ipc; + rule_a->args[0].arg = 0; + rule_a->args[0].op = SCMP_CMP_EQ; + rule_a->args[0].mask = DATUM_MAX; + rule_a->args[0].datum = (-sys_a) % 200; + rule_a->args[0].valid = 1; + } + + /* direct wired socket syscalls */ + if (rule_b != NULL) + rule_b->syscall = sys_b; + + /* we should be protected by a transaction checkpoint */ + if (rule_a != NULL) { + rc = db_rule_add(db, rule_a); + if (rc < 0) + goto add_return; + } + if (rule_b != NULL) { + rc = db_rule_add(db, rule_b); + if (rc < 0) + goto add_return; + } + } else if (sys >= 0) { + /* normal syscall processing */ + rc = db_rule_add(db, rule); + if (rc < 0) + goto add_return; + } else if (rule->strict) { + rc = -EDOM; + goto add_return; + } + +add_return: + if (rule_dup != NULL) + free(rule_dup); + return rc; +} + const struct arch_def arch_def_s390x = { .token = SCMP_ARCH_S390X, .token_bpf = AUDIT_ARCH_S390X, .size = ARCH_SIZE_64, .endian = ARCH_ENDIAN_BIG, - .sys_socketcall = __s390x_NR_socketcall, - .sys_ipc = __s390x_NR_ipc, - .syscall_resolve_name = abi_syscall_resolve_name_munge, - .syscall_resolve_name_raw = s390x_syscall_resolve_name, - .syscall_resolve_num = abi_syscall_resolve_num_munge, - .syscall_resolve_num_raw = s390x_syscall_resolve_num, - .syscall_rewrite = abi_syscall_rewrite, - .rule_add = abi_rule_add, + .syscall_resolve_name = s390x_syscall_resolve_name_munge, + .syscall_resolve_num = s390x_syscall_resolve_num_munge, + .syscall_rewrite = s390x_syscall_rewrite, + .rule_add = s390x_rule_add, }; diff --git a/src/arch-x32.c b/src/arch-x32.c index 0a73923..50c502e 100644 --- a/src/arch-x32.c +++ b/src/arch-x32.c @@ -28,7 +28,6 @@ /** * Resolve a syscall name to a number - * @param arch the architecture definition * @param name the syscall name * * Resolve the given syscall name to the syscall number using the syscall table. @@ -36,13 +35,12 @@ * numbers; returns __NR_SCMP_ERROR on failure. * */ -int x32_syscall_resolve_name_munge(const struct arch_def *arch, - const char *name) +int x32_syscall_resolve_name_munge(const char *name) { int sys; /* NOTE: we don't want to modify the pseudo-syscall numbers */ - sys = arch->syscall_resolve_name_raw(name); + sys = x32_syscall_resolve_name(name); if (sys == __NR_SCMP_ERROR || sys < 0) return sys; @@ -51,7 +49,6 @@ int x32_syscall_resolve_name_munge(const struct arch_def *arch, /** * Resolve a syscall number to a name - * @param arch the architecture definition * @param num the syscall number * * Resolve the given syscall number to the syscall name using the syscall table. @@ -59,13 +56,12 @@ int x32_syscall_resolve_name_munge(const struct arch_def *arch, * syscall names; returns NULL on failure. * */ -const char *x32_syscall_resolve_num_munge(const struct arch_def *arch, - int num) +const char *x32_syscall_resolve_num_munge(int num) { /* NOTE: we don't want to modify the pseudo-syscall numbers */ if (num >= 0) num &= ~X32_SYSCALL_BIT; - return arch->syscall_resolve_num_raw(num); + return x32_syscall_resolve_num(num); } const struct arch_def arch_def_x32 = { @@ -75,9 +71,7 @@ const struct arch_def arch_def_x32 = { .size = ARCH_SIZE_32, .endian = ARCH_ENDIAN_LITTLE, .syscall_resolve_name = x32_syscall_resolve_name_munge, - .syscall_resolve_name_raw = x32_syscall_resolve_name, .syscall_resolve_num = x32_syscall_resolve_num_munge, - .syscall_resolve_num_raw = x32_syscall_resolve_num, .syscall_rewrite = NULL, .rule_add = NULL, }; diff --git a/src/arch-x86.c b/src/arch-x86.c index af33137..2a4c074 100644 --- a/src/arch-x86.c +++ b/src/arch-x86.c @@ -33,17 +33,593 @@ #define __x86_NR_socketcall 102 #define __x86_NR_ipc 117 +/** + * Resolve a syscall name to a number + * @param name the syscall name + * + * Resolve the given syscall name to the syscall number using the syscall table. + * Returns the syscall number on success, including negative pseudo syscall + * numbers; returns __NR_SCMP_ERROR on failure. + * + */ +int x86_syscall_resolve_name_munge(const char *name) +{ + if (strcmp(name, "accept") == 0) + return __PNR_accept; + else if (strcmp(name, "accept4") == 0) + return __PNR_accept4; + else if (strcmp(name, "bind") == 0) + return __PNR_bind; + else if (strcmp(name, "connect") == 0) + return __PNR_connect; + else if (strcmp(name, "getpeername") == 0) + return __PNR_getpeername; + else if (strcmp(name, "getsockname") == 0) + return __PNR_getsockname; + else if (strcmp(name, "getsockopt") == 0) + return __PNR_getsockopt; + else if (strcmp(name, "listen") == 0) + return __PNR_listen; + else if (strcmp(name, "recv") == 0) + return __PNR_recv; + else if (strcmp(name, "recvfrom") == 0) + return __PNR_recvfrom; + else if (strcmp(name, "recvmsg") == 0) + return __PNR_recvmsg; + else if (strcmp(name, "recvmmsg") == 0) + return __PNR_recvmmsg; + else if (strcmp(name, "send") == 0) + return __PNR_send; + else if (strcmp(name, "sendmsg") == 0) + return __PNR_sendmsg; + else if (strcmp(name, "sendmmsg") == 0) + return __PNR_sendmmsg; + else if (strcmp(name, "sendto") == 0) + return __PNR_sendto; + else if (strcmp(name, "setsockopt") == 0) + return __PNR_setsockopt; + else if (strcmp(name, "shutdown") == 0) + return __PNR_shutdown; + else if (strcmp(name, "socket") == 0) + return __PNR_socket; + else if (strcmp(name, "socketpair") == 0) + return __PNR_socketpair; + + if (strcmp(name, "semop") == 0) + return __PNR_semop; + else if (strcmp(name, "semget") == 0) + return __PNR_semget; + else if (strcmp(name, "semctl") == 0) + return __PNR_semctl; + else if (strcmp(name, "semtimedop") == 0) + return __PNR_semtimedop; + else if (strcmp(name, "msgsnd") == 0) + return __PNR_msgsnd; + else if (strcmp(name, "msgrcv") == 0) + return __PNR_msgrcv; + else if (strcmp(name, "msgget") == 0) + return __PNR_msgget; + else if (strcmp(name, "msgctl") == 0) + return __PNR_msgctl; + else if (strcmp(name, "shmat") == 0) + return __PNR_shmat; + else if (strcmp(name, "shmdt") == 0) + return __PNR_shmdt; + else if (strcmp(name, "shmget") == 0) + return __PNR_shmget; + else if (strcmp(name, "shmctl") == 0) + return __PNR_shmctl; + + return x86_syscall_resolve_name(name); +} + +/** + * Resolve a syscall number to a name + * @param num the syscall number + * + * Resolve the given syscall number to the syscall name using the syscall table. + * Returns a pointer to the syscall name string on success, including pseudo + * syscall names; returns NULL on failure. + * + */ +const char *x86_syscall_resolve_num_munge(int num) +{ + if (num == __PNR_accept) + return "accept"; + else if (num == __PNR_accept4) + return "accept4"; + else if (num == __PNR_bind) + return "bind"; + else if (num == __PNR_connect) + return "connect"; + else if (num == __PNR_getpeername) + return "getpeername"; + else if (num == __PNR_getsockname) + return "getsockname"; + else if (num == __PNR_getsockopt) + return "getsockopt"; + else if (num == __PNR_listen) + return "listen"; + else if (num == __PNR_recv) + return "recv"; + else if (num == __PNR_recvfrom) + return "recvfrom"; + else if (num == __PNR_recvmsg) + return "recvmsg"; + else if (num == __PNR_recvmmsg) + return "recvmmsg"; + else if (num == __PNR_send) + return "send"; + else if (num == __PNR_sendmsg) + return "sendmsg"; + else if (num == __PNR_sendmmsg) + return "sendmmsg"; + else if (num == __PNR_sendto) + return "sendto"; + else if (num == __PNR_setsockopt) + return "setsockopt"; + else if (num == __PNR_shutdown) + return "shutdown"; + else if (num == __PNR_socket) + return "socket"; + else if (num == __PNR_socketpair) + return "socketpair"; + + if (num == __PNR_semop) + return "semop"; + else if (num == __PNR_semget) + return "semget"; + else if (num == __PNR_semctl) + return "semctl"; + else if (num == __PNR_semtimedop) + return "semtimedop"; + else if (num == __PNR_msgsnd) + return "msgsnd"; + else if (num == __PNR_msgrcv) + return "msgrcv"; + else if (num == __PNR_msgget) + return "msgget"; + else if (num == __PNR_msgctl) + return "msgctl"; + else if (num == __PNR_shmat) + return "shmat"; + else if (num == __PNR_shmdt) + return "shmdt"; + else if (num == __PNR_shmget) + return "shmget"; + else if (num == __PNR_shmctl) + return "shmctl"; + + return x86_syscall_resolve_num(num); +} + +/** + * Convert a multiplexed pseudo syscall into a direct syscall + * @param syscall the multiplexed pseudo syscall number + * + * Return the related direct syscall number, __NR_SCMP_UNDEF is there is + * no related syscall, or __NR_SCMP_ERROR otherwise. + * + */ +static int _x86_syscall_demux(int syscall) +{ + switch (syscall) { + case -101: + /* socket */ + return 359; + case -102: + /* bind */ + return 361; + case -103: + /* connect */ + return 362; + case -104: + /* listen */ + return 363; + case -105: + /* accept - not defined */ + return __NR_SCMP_UNDEF; + case -106: + /* getsockname */ + return 367; + case -107: + /* getpeername */ + return 368; + case -108: + /* socketpair */ + return 360; + case -109: + /* send - not defined */ + return __NR_SCMP_UNDEF; + case -110: + /* recv - not defined */ + return __NR_SCMP_UNDEF; + case -111: + /* sendto */ + return 369; + case -112: + /* recvfrom */ + return 371; + case -113: + /* shutdown */ + return 373; + case -114: + /* setsockopt */ + return 366; + case -115: + /* getsockopt */ + return 365; + case -116: + /* sendmsg */ + return 370; + case -117: + /* recvmsg */ + return 372; + case -118: + /* accept4 */ + return 364; + case -119: + /* recvmmsg */ + return 337; + case -120: + /* sendmmsg */ + return 345; + case -201: + /* semop - not defined */ + return __NR_SCMP_UNDEF; + case -202: + /* semget */ + return 393; + case -203: + /* semctl */ + return 394; + case -204: + /* semtimedop - not defined */ + return __NR_SCMP_UNDEF; + case -211: + /* msgsnd */ + return 400; + case -212: + /* msgrcv */ + return 401; + case -213: + /* msgget */ + return 399; + case -214: + /* msgctl */ + return 402; + case -221: + /* shmat */ + return 397; + case -222: + /* shmdt */ + return 398; + case -223: + /* shmget */ + return 395; + case -224: + /* shmctl */ + return 396; + } + + return __NR_SCMP_ERROR; +} + +/** + * Convert a direct syscall into multiplexed pseudo socket syscall + * @param syscall the direct syscall + * + * Return the related multiplexed pseduo syscall number, __NR_SCMP_UNDEF is + * there is no related pseudo syscall, or __NR_SCMP_ERROR otherwise. + * + */ +static int _x86_syscall_mux(int syscall) +{ + switch (syscall) { + case 337: + /* recvmmsg */ + return -119; + case 345: + /* sendmmsg */ + return -120; + case 359: + /* socket */ + return -101; + case 360: + /* socketpair */ + return -108; + case 361: + /* bind */ + return -102; + case 362: + /* connect */ + return -103; + case 363: + /* listen */ + return -104; + case 364: + /* accept4 */ + return -118; + case 365: + /* getsockopt */ + return -115; + case 366: + /* setsockopt */ + return -114; + case 367: + /* getsockname */ + return -106; + case 368: + /* getpeername */ + return -107; + case 369: + /* sendto */ + return -111; + case 370: + /* sendmsg */ + return -116; + case 371: + /* recvfrom */ + return -112; + case 372: + /* recvmsg */ + return -117; + case 373: + /* shutdown */ + return -113; + case 393: + /* semget */ + return -202; + case 394: + /* semctl */ + return -203; + case 400: + /* msgsnd */ + return -211; + case 401: + /* msgrcv */ + return -212; + case 399: + /* msgget */ + return -213; + case 402: + /* msgctl */ + return -214; + case 397: + /* shmat */ + return -221; + case 398: + /* shmdt */ + return -222; + case 395: + /* shmget */ + return -223; + case 396: + /* shmctl */ + return -224; + } + + return __NR_SCMP_ERROR; +} + +/** + * Rewrite a syscall value to match the architecture + * @param syscall the syscall number + * + * Syscalls can vary across different architectures so this function rewrites + * the syscall into the correct value for the specified architecture. Returns + * zero on success, negative values on failure. + * + */ +int x86_syscall_rewrite(int *syscall) +{ + int sys = *syscall; + + if (sys <= -100 && sys >= -120) + *syscall = __x86_NR_socketcall; + else if (sys <= -200 && sys >= -224) + *syscall = __x86_NR_ipc; + else if (sys < 0) + return -EDOM; + + return 0; +} + +/** + * add a new rule to the x86 seccomp filter + * @param db the seccomp filter db + * @param rule the filter rule + * + * This function adds a new syscall filter to the seccomp filter db, making any + * necessary adjustments for the x86 ABI. Returns zero on success, negative + * values on failure. + * + * It is important to note that in the case of failure the db may be corrupted, + * the caller must use the transaction mechanism if the db integrity is + * important. + * + */ +int x86_rule_add(struct db_filter *db, struct db_api_rule_list *rule) +{ + int rc = 0; + unsigned int iter; + int sys = rule->syscall; + int sys_a, sys_b; + struct db_api_rule_list *rule_a, *rule_b, *rule_dup = NULL; + + if ((sys <= -100 && sys >= -120) || (sys >= 359 && sys <= 373)) { + /* (-100 to -120) : multiplexed socket syscalls + (359 to 373) : direct socket syscalls, Linux 4.3+ */ + + /* strict check for the multiplexed socket syscalls */ + for (iter = 0; iter < ARG_COUNT_MAX; iter++) { + if ((rule->args[iter].valid != 0) && (rule->strict)) { + rc = -EINVAL; + goto add_return; + } + } + + /* determine both the muxed and direct syscall numbers */ + if (sys > 0) { + sys_a = _x86_syscall_mux(sys); + if (sys_a == __NR_SCMP_ERROR) { + rc = __NR_SCMP_ERROR; + goto add_return; + } + sys_b = sys; + } else { + sys_a = sys; + sys_b = _x86_syscall_demux(sys); + if (sys_b == __NR_SCMP_ERROR) { + rc = __NR_SCMP_ERROR; + goto add_return; + } + } + + /* use rule_a for the multiplexed syscall and use rule_b for + * the direct wired syscall */ + + if (sys_a == __NR_SCMP_UNDEF) { + rule_a = NULL; + rule_b = rule; + } else if (sys_b == __NR_SCMP_UNDEF) { + rule_a = rule; + rule_b = NULL; + } else { + /* need two rules, dup the first and link together */ + rule_a = rule; + rule_dup = db_rule_dup(rule_a); + rule_b = rule_dup; + if (rule_b == NULL) + goto add_return; + rule_b->prev = rule_a; + rule_b->next = NULL; + rule_a->next = rule_b; + } + + /* multiplexed socket syscalls */ + if (rule_a != NULL) { + rule_a->syscall = __x86_NR_socketcall; + rule_a->args[0].arg = 0; + rule_a->args[0].op = SCMP_CMP_EQ; + rule_a->args[0].mask = DATUM_MAX; + rule_a->args[0].datum = (-sys_a) % 100; + rule_a->args[0].valid = 1; + } + + /* direct wired socket syscalls */ + if (rule_b != NULL) + rule_b->syscall = sys_b; + + /* we should be protected by a transaction checkpoint */ + if (rule_a != NULL) { + rc = db_rule_add(db, rule_a); + if (rc < 0) + goto add_return; + } + if (rule_b != NULL) { + rc = db_rule_add(db, rule_b); + if (rc < 0) + goto add_return; + } + } else if ((sys <= -200 && sys >= -224) || (sys >= 393 && sys <= 402)) { + /* (-200 to -224) : multiplexed ipc syscalls + (393 to 402) : direct ipc syscalls */ + + /* strict check for the multiplexed socket syscalls */ + for (iter = 0; iter < ARG_COUNT_MAX; iter++) { + if ((rule->args[iter].valid != 0) && (rule->strict)) { + rc = -EINVAL; + goto add_return; + } + } + + /* determine both the muxed and direct syscall numbers */ + if (sys > 0) { + sys_a = _x86_syscall_mux(sys); + if (sys_a == __NR_SCMP_ERROR) { + rc = __NR_SCMP_ERROR; + goto add_return; + } + sys_b = sys; + } else { + sys_a = sys; + sys_b = _x86_syscall_demux(sys); + if (sys_b == __NR_SCMP_ERROR) { + rc = __NR_SCMP_ERROR; + goto add_return; + } + } + + /* use rule_a for the multiplexed syscall and use rule_b for + * the direct wired syscall */ + + if (sys_a == __NR_SCMP_UNDEF) { + rule_a = NULL; + rule_b = rule; + } else if (sys_b == __NR_SCMP_UNDEF) { + rule_a = rule; + rule_b = NULL; + } else { + /* need two rules, dup the first and link together */ + rule_a = rule; + rule_dup = db_rule_dup(rule_a); + rule_b = rule_dup; + if (rule_b == NULL) + goto add_return; + rule_b->prev = rule_a; + rule_b->next = NULL; + rule_a->next = rule_b; + } + + /* multiplexed socket syscalls */ + if (rule_a != NULL) { + rule_a->syscall = __x86_NR_ipc; + rule_a->args[0].arg = 0; + rule_a->args[0].op = SCMP_CMP_EQ; + rule_a->args[0].mask = DATUM_MAX; + rule_a->args[0].datum = (-sys_a) % 200; + rule_a->args[0].valid = 1; + } + + /* direct wired socket syscalls */ + if (rule_b != NULL) + rule_b->syscall = sys_b; + + /* we should be protected by a transaction checkpoint */ + if (rule_a != NULL) { + rc = db_rule_add(db, rule_a); + if (rc < 0) + goto add_return; + } + if (rule_b != NULL) { + rc = db_rule_add(db, rule_b); + if (rc < 0) + goto add_return; + } + } else if (sys >= 0) { + /* normal syscall processing */ + rc = db_rule_add(db, rule); + if (rc < 0) + goto add_return; + } else if (rule->strict) { + rc = -EDOM; + goto add_return; + } + +add_return: + if (rule_dup != NULL) + free(rule_dup); + return rc; +} + const struct arch_def arch_def_x86 = { .token = SCMP_ARCH_X86, .token_bpf = AUDIT_ARCH_I386, .size = ARCH_SIZE_32, .endian = ARCH_ENDIAN_LITTLE, - .sys_socketcall = __x86_NR_socketcall, - .sys_ipc = __x86_NR_ipc, - .syscall_resolve_name = abi_syscall_resolve_name_munge, - .syscall_resolve_name_raw = x86_syscall_resolve_name, - .syscall_resolve_num = abi_syscall_resolve_num_munge, - .syscall_resolve_num_raw = x86_syscall_resolve_num, - .syscall_rewrite = abi_syscall_rewrite, - .rule_add = abi_rule_add, + .syscall_resolve_name = x86_syscall_resolve_name_munge, + .syscall_resolve_num = x86_syscall_resolve_num_munge, + .syscall_rewrite = x86_syscall_rewrite, + .rule_add = x86_rule_add, }; diff --git a/src/arch-x86_64.c b/src/arch-x86_64.c index 9c0e5ac..a5fccad 100644 --- a/src/arch-x86_64.c +++ b/src/arch-x86_64.c @@ -31,8 +31,8 @@ const struct arch_def arch_def_x86_64 = { .token_bpf = AUDIT_ARCH_X86_64, .size = ARCH_SIZE_64, .endian = ARCH_ENDIAN_LITTLE, - .syscall_resolve_name_raw = x86_64_syscall_resolve_name, - .syscall_resolve_num_raw = x86_64_syscall_resolve_num, + .syscall_resolve_name = x86_64_syscall_resolve_name, + .syscall_resolve_num = x86_64_syscall_resolve_num, .syscall_rewrite = NULL, .rule_add = NULL, }; diff --git a/src/arch.c b/src/arch.c index 8ef77b1..5485eb8 100644 --- a/src/arch.c +++ b/src/arch.c @@ -300,9 +300,7 @@ int arch_arg_offset(const struct arch_def *arch, unsigned int arg) int arch_syscall_resolve_name(const struct arch_def *arch, const char *name) { if (arch->syscall_resolve_name) - return (*arch->syscall_resolve_name)(arch, name); - if (arch->syscall_resolve_name_raw) - return (*arch->syscall_resolve_name_raw)(name); + return (*arch->syscall_resolve_name)(name); return __NR_SCMP_ERROR; } @@ -320,9 +318,7 @@ int arch_syscall_resolve_name(const struct arch_def *arch, const char *name) const char *arch_syscall_resolve_num(const struct arch_def *arch, int num) { if (arch->syscall_resolve_num) - return (*arch->syscall_resolve_num)(arch, num); - if (arch->syscall_resolve_num_raw) - return (*arch->syscall_resolve_num_raw)(num); + return (*arch->syscall_resolve_num)(num); return NULL; } @@ -385,7 +381,7 @@ int arch_syscall_rewrite(const struct arch_def *arch, int *syscall) } else if (sys > -10000) { /* rewritable syscalls */ if (arch->syscall_rewrite) - (*arch->syscall_rewrite)(arch, syscall); + (*arch->syscall_rewrite)(syscall); } /* syscalls not defined on this architecture */ diff --git a/src/arch.h b/src/arch.h index b6484f9..38c3a9c 100644 --- a/src/arch.h +++ b/src/arch.h @@ -49,18 +49,10 @@ struct arch_def { ARCH_ENDIAN_BIG, } endian; - /* arch specific constants */ - int sys_socketcall; - int sys_ipc; - /* arch specific functions */ - int (*syscall_resolve_name)(const struct arch_def *arch, - const char *name); - int (*syscall_resolve_name_raw)(const char *name); - const char *(*syscall_resolve_num)(const struct arch_def *arch, - int num); - const char *(*syscall_resolve_num_raw)(int num); - int (*syscall_rewrite)(const struct arch_def *arch, int *syscall); + int (*syscall_resolve_name)(const char *name); + const char *(*syscall_resolve_num)(int num); + int (*syscall_rewrite)(int *syscall); int (*rule_add)(struct db_filter *db, struct db_api_rule_list *rule); }; diff --git a/src/syscalls.c b/src/syscalls.c index bd6acb5..9091fa9 100644 --- a/src/syscalls.c +++ b/src/syscalls.c @@ -1,5 +1,5 @@ /** - * Enhanced Seccomp Syscall Table Functions + * Enhanced Seccomp x86_64 Syscall Table * * Copyright (c) 2012, 2020 Red Hat * Author: Paul Moore @@ -19,13 +19,9 @@ * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, see . */ - -#include -#include -#include #include +#include -#include "db.h" #include "arch.h" #include "syscalls.h" @@ -58,524 +54,3 @@ ARCH_DEF(s390x) ARCH_DEF(x32) ARCH_DEF(x86) ARCH_DEF(riscv64) - -/** - * Resolve a syscall name to a number - * @param arch the arch definition - * @param name the syscall name - * - * Resolve the given syscall name to the syscall number using the syscall table. - * Returns the syscall number on success, including negative pseudo syscall - * numbers; returns __NR_SCMP_ERROR on failure. - * - */ -int abi_syscall_resolve_name_munge(const struct arch_def *arch, - const char *name) -{ - -#define _ABI_SYSCALL_RES_NAME_CHK(NAME) \ - if (!strcmp(name, #NAME)) return __PNR_##NAME; - - _ABI_SYSCALL_RES_NAME_CHK(socket) - _ABI_SYSCALL_RES_NAME_CHK(bind) - _ABI_SYSCALL_RES_NAME_CHK(connect) - _ABI_SYSCALL_RES_NAME_CHK(listen) - _ABI_SYSCALL_RES_NAME_CHK(accept) - _ABI_SYSCALL_RES_NAME_CHK(getsockname) - _ABI_SYSCALL_RES_NAME_CHK(getpeername) - _ABI_SYSCALL_RES_NAME_CHK(socketpair) - _ABI_SYSCALL_RES_NAME_CHK(send) - _ABI_SYSCALL_RES_NAME_CHK(recv) - _ABI_SYSCALL_RES_NAME_CHK(sendto) - _ABI_SYSCALL_RES_NAME_CHK(recvfrom) - _ABI_SYSCALL_RES_NAME_CHK(shutdown) - _ABI_SYSCALL_RES_NAME_CHK(setsockopt) - _ABI_SYSCALL_RES_NAME_CHK(getsockopt) - _ABI_SYSCALL_RES_NAME_CHK(sendmsg) - _ABI_SYSCALL_RES_NAME_CHK(recvmsg) - _ABI_SYSCALL_RES_NAME_CHK(accept4) - _ABI_SYSCALL_RES_NAME_CHK(recvmmsg) - _ABI_SYSCALL_RES_NAME_CHK(sendmmsg) - _ABI_SYSCALL_RES_NAME_CHK(semop) - _ABI_SYSCALL_RES_NAME_CHK(semget) - _ABI_SYSCALL_RES_NAME_CHK(semctl) - _ABI_SYSCALL_RES_NAME_CHK(semtimedop) - _ABI_SYSCALL_RES_NAME_CHK(msgsnd) - _ABI_SYSCALL_RES_NAME_CHK(msgrcv) - _ABI_SYSCALL_RES_NAME_CHK(msgget) - _ABI_SYSCALL_RES_NAME_CHK(msgctl) - _ABI_SYSCALL_RES_NAME_CHK(shmat) - _ABI_SYSCALL_RES_NAME_CHK(shmdt) - _ABI_SYSCALL_RES_NAME_CHK(shmget) - _ABI_SYSCALL_RES_NAME_CHK(shmctl) - - return arch->syscall_resolve_name_raw(name); -} - -/** - * Resolve a syscall number to a name - * @param arch the arch definition - * @param num the syscall number - * - * Resolve the given syscall number to the syscall name using the syscall table. - * Returns a pointer to the syscall name string on success, including pseudo - * syscall names; returns NULL on failure. - * - */ -const char *abi_syscall_resolve_num_munge(const struct arch_def *arch, int num) -{ - -#define _ABI_SYSCALL_RES_NUM_CHK(NAME) \ - if (num == __PNR_##NAME) return #NAME; - - _ABI_SYSCALL_RES_NUM_CHK(socket) - _ABI_SYSCALL_RES_NUM_CHK(bind) - _ABI_SYSCALL_RES_NUM_CHK(connect) - _ABI_SYSCALL_RES_NUM_CHK(listen) - _ABI_SYSCALL_RES_NUM_CHK(accept) - _ABI_SYSCALL_RES_NUM_CHK(getsockname) - _ABI_SYSCALL_RES_NUM_CHK(getpeername) - _ABI_SYSCALL_RES_NUM_CHK(socketpair) - _ABI_SYSCALL_RES_NUM_CHK(send) - _ABI_SYSCALL_RES_NUM_CHK(recv) - _ABI_SYSCALL_RES_NUM_CHK(sendto) - _ABI_SYSCALL_RES_NUM_CHK(recvfrom) - _ABI_SYSCALL_RES_NUM_CHK(shutdown) - _ABI_SYSCALL_RES_NUM_CHK(setsockopt) - _ABI_SYSCALL_RES_NUM_CHK(getsockopt) - _ABI_SYSCALL_RES_NUM_CHK(sendmsg) - _ABI_SYSCALL_RES_NUM_CHK(recvmsg) - _ABI_SYSCALL_RES_NUM_CHK(accept4) - _ABI_SYSCALL_RES_NUM_CHK(recvmmsg) - _ABI_SYSCALL_RES_NUM_CHK(sendmmsg) - _ABI_SYSCALL_RES_NUM_CHK(semop) - _ABI_SYSCALL_RES_NUM_CHK(semget) - _ABI_SYSCALL_RES_NUM_CHK(semctl) - _ABI_SYSCALL_RES_NUM_CHK(semtimedop) - _ABI_SYSCALL_RES_NUM_CHK(msgsnd) - _ABI_SYSCALL_RES_NUM_CHK(msgrcv) - _ABI_SYSCALL_RES_NUM_CHK(msgget) - _ABI_SYSCALL_RES_NUM_CHK(msgctl) - _ABI_SYSCALL_RES_NUM_CHK(shmat) - _ABI_SYSCALL_RES_NUM_CHK(shmdt) - _ABI_SYSCALL_RES_NUM_CHK(shmget) - _ABI_SYSCALL_RES_NUM_CHK(shmctl) - - return arch->syscall_resolve_num_raw(num); -} - -/** - * Check if a syscall is a socket syscall - * @param arch the arch definition - * @param sys the syscall number - * - * Returns true if the syscall is a socket related syscall, false otherwise. - * - */ -static bool _abi_syscall_socket_test(const struct arch_def *arch, int sys) -{ - const char *name; - - /* multiplexed pseduo-syscalls */ - if (sys <= -100 && sys >= -120) - return true; - - name = arch->syscall_resolve_num_raw(sys); - if (!name) - return false; - -#define _ABI_SYSCALL_SOCK_CHK(NAME) \ - if (!strcmp(name, #NAME)) return true; - - _ABI_SYSCALL_SOCK_CHK(socket) - _ABI_SYSCALL_SOCK_CHK(bind) - _ABI_SYSCALL_SOCK_CHK(connect) - _ABI_SYSCALL_SOCK_CHK(listen) - _ABI_SYSCALL_SOCK_CHK(accept) - _ABI_SYSCALL_SOCK_CHK(getsockname) - _ABI_SYSCALL_SOCK_CHK(getpeername) - _ABI_SYSCALL_SOCK_CHK(socketpair) - _ABI_SYSCALL_SOCK_CHK(send) - _ABI_SYSCALL_SOCK_CHK(recv) - _ABI_SYSCALL_SOCK_CHK(sendto) - _ABI_SYSCALL_SOCK_CHK(recvfrom) - _ABI_SYSCALL_SOCK_CHK(shutdown) - _ABI_SYSCALL_SOCK_CHK(setsockopt) - _ABI_SYSCALL_SOCK_CHK(getsockopt) - _ABI_SYSCALL_SOCK_CHK(sendmsg) - _ABI_SYSCALL_SOCK_CHK(recvmsg) - _ABI_SYSCALL_SOCK_CHK(accept4) - _ABI_SYSCALL_SOCK_CHK(recvmmsg) - _ABI_SYSCALL_SOCK_CHK(sendmmsg) - - return false; -} - -/** - * Check if a syscall is an ipc syscall - * @param arch the arch definition - * @param sys the syscall number - * - * Returns true if the syscall is an ipc related syscall, false otherwise. - * - */ -static bool _abi_syscall_ipc_test(const struct arch_def *arch, int sys) -{ - const char *name; - - /* multiplexed pseduo-syscalls */ - if (sys <= -200 && sys >= -224) - return true; - - name = arch->syscall_resolve_num_raw(sys); - if (!name) - return false; - -#define _ABI_SYSCALL_IPC_CHK(NAME) \ - if (!strcmp(name, #NAME)) return true; - - _ABI_SYSCALL_IPC_CHK(semop) - _ABI_SYSCALL_IPC_CHK(semget) - _ABI_SYSCALL_IPC_CHK(semctl) - _ABI_SYSCALL_IPC_CHK(semtimedop) - _ABI_SYSCALL_IPC_CHK(msgsnd) - _ABI_SYSCALL_IPC_CHK(msgrcv) - _ABI_SYSCALL_IPC_CHK(msgget) - _ABI_SYSCALL_IPC_CHK(msgctl) - _ABI_SYSCALL_IPC_CHK(shmat) - _ABI_SYSCALL_IPC_CHK(shmdt) - _ABI_SYSCALL_IPC_CHK(shmget) - _ABI_SYSCALL_IPC_CHK(shmctl) - - return false; -} - -/** - * Convert a multiplexed pseudo syscall into a direct syscall - * @param arch the arch definition - * @param syscall the multiplexed pseudo syscall number - * - * Return the related direct syscall number, __NR_SCMP_UNDEF is there is - * no related syscall, or __NR_SCMP_ERROR otherwise. - * - */ -static int _abi_syscall_demux(const struct arch_def *arch, int syscall) -{ - int sys = __NR_SCMP_UNDEF; - -#define _ABI_SYSCALL_DEMUX_CHK(NAME) \ -case __PNR_##NAME: \ - sys = arch->syscall_resolve_name_raw(#NAME); break; - - switch (syscall) { - _ABI_SYSCALL_DEMUX_CHK(socket) - _ABI_SYSCALL_DEMUX_CHK(bind) - _ABI_SYSCALL_DEMUX_CHK(connect) - _ABI_SYSCALL_DEMUX_CHK(listen) - _ABI_SYSCALL_DEMUX_CHK(accept) - _ABI_SYSCALL_DEMUX_CHK(getsockname) - _ABI_SYSCALL_DEMUX_CHK(getpeername) - _ABI_SYSCALL_DEMUX_CHK(socketpair) - _ABI_SYSCALL_DEMUX_CHK(send) - _ABI_SYSCALL_DEMUX_CHK(recv) - _ABI_SYSCALL_DEMUX_CHK(sendto) - _ABI_SYSCALL_DEMUX_CHK(recvfrom) - _ABI_SYSCALL_DEMUX_CHK(shutdown) - _ABI_SYSCALL_DEMUX_CHK(setsockopt) - _ABI_SYSCALL_DEMUX_CHK(getsockopt) - _ABI_SYSCALL_DEMUX_CHK(sendmsg) - _ABI_SYSCALL_DEMUX_CHK(recvmsg) - _ABI_SYSCALL_DEMUX_CHK(accept4) - _ABI_SYSCALL_DEMUX_CHK(recvmmsg) - _ABI_SYSCALL_DEMUX_CHK(sendmmsg) - _ABI_SYSCALL_DEMUX_CHK(semop) - _ABI_SYSCALL_DEMUX_CHK(semget) - _ABI_SYSCALL_DEMUX_CHK(semctl) - _ABI_SYSCALL_DEMUX_CHK(semtimedop) - _ABI_SYSCALL_DEMUX_CHK(msgsnd) - _ABI_SYSCALL_DEMUX_CHK(msgrcv) - _ABI_SYSCALL_DEMUX_CHK(msgget) - _ABI_SYSCALL_DEMUX_CHK(msgctl) - _ABI_SYSCALL_DEMUX_CHK(shmat) - _ABI_SYSCALL_DEMUX_CHK(shmdt) - _ABI_SYSCALL_DEMUX_CHK(shmget) - _ABI_SYSCALL_DEMUX_CHK(shmctl) - } - - /* this looks odd because the arch resolver returns _ERROR if it can't - * resolve the syscall, but we want to use _UNDEF for that, so we set - * 'sys' to a sentinel value of _UNDEF and if it is error here we know - * the resolve failed to find a match */ - if (sys == __NR_SCMP_UNDEF) - sys = __NR_SCMP_ERROR; - else if (sys == __NR_SCMP_ERROR) - sys = __NR_SCMP_UNDEF; - - return sys; -} - -/** - * Convert a direct syscall into multiplexed pseudo socket syscall - * @param arch the arch definition - * @param syscall the direct syscall - * - * Return the related multiplexed pseduo syscall number, __NR_SCMP_UNDEF is - * there is no related pseudo syscall, or __NR_SCMP_ERROR otherwise. - * - */ -static int _abi_syscall_mux(const struct arch_def *arch, int syscall) -{ - const char *sys; - - sys = arch->syscall_resolve_num_raw(syscall); - if (!sys) - return __NR_SCMP_ERROR; - -#define _ABI_SYSCALL_MUX_CHK(NAME) \ - if (!strcmp(sys, #NAME)) return __PNR_##NAME; - - _ABI_SYSCALL_MUX_CHK(socket) - _ABI_SYSCALL_MUX_CHK(bind) - _ABI_SYSCALL_MUX_CHK(connect) - _ABI_SYSCALL_MUX_CHK(listen) - _ABI_SYSCALL_MUX_CHK(accept) - _ABI_SYSCALL_MUX_CHK(getsockname) - _ABI_SYSCALL_MUX_CHK(getpeername) - _ABI_SYSCALL_MUX_CHK(socketpair) - _ABI_SYSCALL_MUX_CHK(send) - _ABI_SYSCALL_MUX_CHK(recv) - _ABI_SYSCALL_MUX_CHK(sendto) - _ABI_SYSCALL_MUX_CHK(recvfrom) - _ABI_SYSCALL_MUX_CHK(shutdown) - _ABI_SYSCALL_MUX_CHK(setsockopt) - _ABI_SYSCALL_MUX_CHK(getsockopt) - _ABI_SYSCALL_MUX_CHK(sendmsg) - _ABI_SYSCALL_MUX_CHK(recvmsg) - _ABI_SYSCALL_MUX_CHK(accept4) - _ABI_SYSCALL_MUX_CHK(recvmmsg) - _ABI_SYSCALL_MUX_CHK(sendmmsg) - _ABI_SYSCALL_MUX_CHK(semop) - _ABI_SYSCALL_MUX_CHK(semget) - _ABI_SYSCALL_MUX_CHK(semctl) - _ABI_SYSCALL_MUX_CHK(semtimedop) - _ABI_SYSCALL_MUX_CHK(msgsnd) - _ABI_SYSCALL_MUX_CHK(msgrcv) - _ABI_SYSCALL_MUX_CHK(msgget) - _ABI_SYSCALL_MUX_CHK(msgctl) - _ABI_SYSCALL_MUX_CHK(shmat) - _ABI_SYSCALL_MUX_CHK(shmdt) - _ABI_SYSCALL_MUX_CHK(shmget) - _ABI_SYSCALL_MUX_CHK(shmctl) - - return __NR_SCMP_ERROR; -} - -/** - * Rewrite a syscall value to match the architecture - * @param arch the arch definition - * @param syscall the syscall number - * - * Syscalls can vary across different architectures so this function rewrites - * the syscall into the correct value for the specified architecture. Returns - * zero on success, negative values on failure. - * - */ -int abi_syscall_rewrite(const struct arch_def *arch, int *syscall) -{ - int sys = *syscall; - - if (sys <= -100 && sys >= -120) - *syscall = arch->sys_socketcall; - else if (sys <= -200 && sys >= -224) - *syscall = arch->sys_ipc; - else if (sys < 0) - return -EDOM; - - return 0; -} - -/** - * add a new rule to the abi seccomp filter - * @param db the seccomp filter db - * @param rule the filter rule - * - * This function adds a new syscall filter to the seccomp filter db, making any - * necessary adjustments for the abi ABI. Returns zero on success, negative - * values on failure. - * - * It is important to note that in the case of failure the db may be corrupted, - * the caller must use the transaction mechanism if the db integrity is - * important. - * - */ -int abi_rule_add(struct db_filter *db, struct db_api_rule_list *rule) -{ - int rc = 0; - unsigned int iter; - int sys = rule->syscall; - int sys_a, sys_b; - struct db_api_rule_list *rule_a, *rule_b, *rule_dup = NULL; - - if (_abi_syscall_socket_test(db->arch, sys)) { - /* socket syscalls */ - - /* strict check for the multiplexed socket syscalls */ - for (iter = 0; iter < ARG_COUNT_MAX; iter++) { - if ((rule->args[iter].valid != 0) && (rule->strict)) { - rc = -EINVAL; - goto add_return; - } - } - - /* determine both the muxed and direct syscall numbers */ - if (sys > 0) { - sys_a = _abi_syscall_mux(db->arch, sys); - if (sys_a == __NR_SCMP_ERROR) { - rc = __NR_SCMP_ERROR; - goto add_return; - } - sys_b = sys; - } else { - sys_a = sys; - sys_b = _abi_syscall_demux(db->arch, sys); - if (sys_b == __NR_SCMP_ERROR) { - rc = __NR_SCMP_ERROR; - goto add_return; - } - } - - /* use rule_a for the multiplexed syscall and use rule_b for - * the direct wired syscall */ - - if (sys_a == __NR_SCMP_UNDEF) { - rule_a = NULL; - rule_b = rule; - } else if (sys_b == __NR_SCMP_UNDEF) { - rule_a = rule; - rule_b = NULL; - } else { - /* need two rules, dup the first and link together */ - rule_a = rule; - rule_dup = db_rule_dup(rule_a); - rule_b = rule_dup; - if (rule_b == NULL) - goto add_return; - rule_b->prev = rule_a; - rule_b->next = NULL; - rule_a->next = rule_b; - } - - /* multiplexed socket syscalls */ - if (rule_a != NULL) { - rule_a->syscall = db->arch->sys_socketcall; - rule_a->args[0].arg = 0; - rule_a->args[0].op = SCMP_CMP_EQ; - rule_a->args[0].mask = DATUM_MAX; - rule_a->args[0].datum = (-sys_a) % 100; - rule_a->args[0].valid = 1; - } - - /* direct wired socket syscalls */ - if (rule_b != NULL) - rule_b->syscall = sys_b; - - /* we should be protected by a transaction checkpoint */ - if (rule_a != NULL) { - rc = db_rule_add(db, rule_a); - if (rc < 0) - goto add_return; - } - if (rule_b != NULL) { - rc = db_rule_add(db, rule_b); - if (rc < 0) - goto add_return; - } - } else if (_abi_syscall_ipc_test(db->arch, sys)) { - /* ipc syscalls */ - - /* strict check for the multiplexed socket syscalls */ - for (iter = 0; iter < ARG_COUNT_MAX; iter++) { - if ((rule->args[iter].valid != 0) && (rule->strict)) { - rc = -EINVAL; - goto add_return; - } - } - - /* determine both the muxed and direct syscall numbers */ - if (sys > 0) { - sys_a = _abi_syscall_mux(db->arch, sys); - if (sys_a == __NR_SCMP_ERROR) { - rc = __NR_SCMP_ERROR; - goto add_return; - } - sys_b = sys; - } else { - sys_a = sys; - sys_b = _abi_syscall_demux(db->arch, sys); - if (sys_b == __NR_SCMP_ERROR) { - rc = __NR_SCMP_ERROR; - goto add_return; - } - } - - /* use rule_a for the multiplexed syscall and use rule_b for - * the direct wired syscall */ - - if (sys_a == __NR_SCMP_UNDEF) { - rule_a = NULL; - rule_b = rule; - } else if (sys_b == __NR_SCMP_UNDEF) { - rule_a = rule; - rule_b = NULL; - } else { - /* need two rules, dup the first and link together */ - rule_a = rule; - rule_dup = db_rule_dup(rule_a); - rule_b = rule_dup; - if (rule_b == NULL) - goto add_return; - rule_b->prev = rule_a; - rule_b->next = NULL; - rule_a->next = rule_b; - } - - /* multiplexed socket syscalls */ - if (rule_a != NULL) { - rule_a->syscall = db->arch->sys_ipc; - rule_a->args[0].arg = 0; - rule_a->args[0].op = SCMP_CMP_EQ; - rule_a->args[0].mask = DATUM_MAX; - rule_a->args[0].datum = (-sys_a) % 200; - rule_a->args[0].valid = 1; - } - - /* direct wired socket syscalls */ - if (rule_b != NULL) - rule_b->syscall = sys_b; - - /* we should be protected by a transaction checkpoint */ - if (rule_a != NULL) { - rc = db_rule_add(db, rule_a); - if (rc < 0) - goto add_return; - } - if (rule_b != NULL) { - rc = db_rule_add(db, rule_b); - if (rc < 0) - goto add_return; - } - } else if (sys >= 0) { - /* normal syscall processing */ - rc = db_rule_add(db, rule); - if (rc < 0) - goto add_return; - } else if (rule->strict) { - rc = -EDOM; - goto add_return; - } - -add_return: - if (rule_dup != NULL) - free(rule_dup); - return rc; -} diff --git a/src/syscalls.h b/src/syscalls.h index af468a1..d638733 100644 --- a/src/syscalls.h +++ b/src/syscalls.h @@ -59,12 +59,4 @@ int syscall_resolve_name(const char *name, int offset); const char *syscall_resolve_num(int num, int offset); const struct arch_syscall_def *syscall_iterate(unsigned int spot, int offset); -/* helper functions for multiplexed syscalls, e.g. socketcall(2) and ipc(2) */ -int abi_syscall_resolve_name_munge(const struct arch_def *arch, - const char *name); -const char *abi_syscall_resolve_num_munge(const struct arch_def *arch, int num); -int abi_syscall_rewrite(const struct arch_def *arch, int *syscall); -int abi_rule_add(struct db_filter *db, struct db_api_rule_list *rule); - - #endif -- 2.30.2