summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Moore <paul@paul-moore.com>2021-08-04 11:51:12 -0400
committerPaul Moore <paul@paul-moore.com>2021-08-12 12:30:34 -0400
commit17cbd2c253ce63e5e9e3cec867ff58efbe8b5fdc (patch)
treedb15f9ddc82f016889ba2c8bf2fafa8002d751a3 /src
parentc261232174c8432e12c39e2fc938a64d562de1d6 (diff)
downloadlibseccomp-17cbd2c253ce63e5e9e3cec867ff58efbe8b5fdc.tar.gz
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 <tom.hromatka@oracle.com> Signed-off-by: Paul Moore <paul@paul-moore.com>
Diffstat (limited to 'src')
-rw-r--r--src/arch-aarch64.c4
-rw-r--r--src/arch-arm.c13
-rw-r--r--src/arch-mips.c540
-rw-r--r--src/arch-mips64.c16
-rw-r--r--src/arch-mips64n32.c12
-rw-r--r--src/arch-parisc.c4
-rw-r--r--src/arch-parisc64.c4
-rw-r--r--src/arch-ppc.c525
-rw-r--r--src/arch-ppc64.c615
-rw-r--r--src/arch-riscv64.c4
-rw-r--r--src/arch-s390.c592
-rw-r--r--src/arch-s390x.c591
-rw-r--r--src/arch-sh.c537
-rw-r--r--src/arch-x32.c14
-rw-r--r--src/arch-x86.c592
-rw-r--r--src/arch-x86_64.c4
-rw-r--r--src/arch.c10
-rw-r--r--src/arch.h14
-rw-r--r--src/syscalls.c529
-rw-r--r--src/syscalls.h8
20 files changed, 685 insertions, 3943 deletions
diff --git a/src/arch-aarch64.c b/src/arch-aarch64.c
index 188bc6f..b2d76c6 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 = aarch64_syscall_resolve_name,
- .syscall_resolve_num = aarch64_syscall_resolve_num,
+ .syscall_resolve_name_raw = aarch64_syscall_resolve_name,
+ .syscall_resolve_num_raw = aarch64_syscall_resolve_num,
.syscall_rewrite = NULL,
.rule_add = NULL,
};
diff --git a/src/arch-arm.c b/src/arch-arm.c
index 9c9153a..732940e 100644
--- a/src/arch-arm.c
+++ b/src/arch-arm.c
@@ -39,6 +39,7 @@
/**
* 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.
@@ -46,12 +47,13 @@
* numbers; returns __NR_SCMP_ERROR on failure.
*
*/
-int arm_syscall_resolve_name_munge(const char *name)
+int arm_syscall_resolve_name_munge(const struct arch_def *arch,
+ const char *name)
{
int sys;
/* NOTE: we don't want to modify the pseudo-syscall numbers */
- sys = arm_syscall_resolve_name(name);
+ sys = arch->syscall_resolve_name_raw(name);
if (sys == __NR_SCMP_ERROR || sys < 0)
return sys;
@@ -60,6 +62,7 @@ int arm_syscall_resolve_name_munge(const char *name)
/**
* 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.
@@ -67,12 +70,12 @@ int arm_syscall_resolve_name_munge(const char *name)
* syscall names; returns NULL on failure.
*
*/
-const char *arm_syscall_resolve_num_munge(int num)
+const char *arm_syscall_resolve_num_munge(const struct arch_def *arch, int num)
{
/* NOTE: we don't want to modify the pseudo-syscall numbers */
if (num >= 0)
num &= ~__SCMP_NR_BASE;
- return arm_syscall_resolve_num(num);
+ return arch->syscall_resolve_num_raw(num);
}
const struct arch_def arch_def_arm = {
@@ -81,7 +84,9 @@ 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 1510d82..2625ddc 100644
--- a/src/arch-mips.c
+++ b/src/arch-mips.c
@@ -30,535 +30,23 @@
#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,
- .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,
+ .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,
};
const struct arch_def arch_def_mipsel = {
@@ -566,8 +54,12 @@ const struct arch_def arch_def_mipsel = {
.token_bpf = AUDIT_ARCH_MIPSEL,
.size = ARCH_SIZE_32,
.endian = ARCH_ENDIAN_LITTLE,
- .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,
+ .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,
};
diff --git a/src/arch-mips64.c b/src/arch-mips64.c
index 342d0d8..d0f72b8 100644
--- a/src/arch-mips64.c
+++ b/src/arch-mips64.c
@@ -30,6 +30,7 @@
/**
* 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.
@@ -37,12 +38,13 @@
* numbers; returns __NR_SCMP_ERROR on failure.
*
*/
-int mips64_syscall_resolve_name_munge(const char *name)
+int mips64_syscall_resolve_name_munge(const struct arch_def *arch,
+ const char *name)
{
int sys;
/* NOTE: we don't want to modify the pseudo-syscall numbers */
- sys = mips64_syscall_resolve_name(name);
+ sys = arch->syscall_resolve_name_raw(name);
if (sys == __NR_SCMP_ERROR || sys < 0)
return sys;
@@ -51,6 +53,7 @@ int mips64_syscall_resolve_name_munge(const char *name)
/**
* 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.
@@ -58,12 +61,13 @@ int mips64_syscall_resolve_name_munge(const char *name)
* syscall names; returns NULL on failure.
*
*/
-const char *mips64_syscall_resolve_num_munge(int num)
+const char *mips64_syscall_resolve_num_munge(const struct arch_def *arch,
+ int num)
{
/* NOTE: we don't want to modify the pseudo-syscall numbers */
if (num >= __SCMP_NR_BASE)
num -= __SCMP_NR_BASE;
- return mips64_syscall_resolve_num(num);
+ return arch->syscall_resolve_num_raw(num);
}
const struct arch_def arch_def_mips64 = {
@@ -72,7 +76,9 @@ 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,
};
@@ -83,7 +89,9 @@ 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 098864b..532c8f3 100644
--- a/src/arch-mips64n32.c
+++ b/src/arch-mips64n32.c
@@ -32,6 +32,7 @@
/**
* 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.
@@ -39,7 +40,8 @@
* numbers; returns __NR_SCMP_ERROR on failure.
*
*/
-int mips64n32_syscall_resolve_name_munge(const char *name)
+int mips64n32_syscall_resolve_name_munge(const struct arch_def *arch,
+ const char *name)
{
int sys;
@@ -53,6 +55,7 @@ int mips64n32_syscall_resolve_name_munge(const char *name)
/**
* 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.
@@ -60,7 +63,8 @@ int mips64n32_syscall_resolve_name_munge(const char *name)
* syscall names; returns NULL on failure.
*
*/
-const char *mips64n32_syscall_resolve_num_munge(int num)
+const char *mips64n32_syscall_resolve_num_munge(const struct arch_def *arch,
+ int num)
{
/* NOTE: we don't want to modify the pseudo-syscall numbers */
if (num >= __SCMP_NR_BASE)
@@ -74,7 +78,9 @@ 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,
};
@@ -85,7 +91,9 @@ 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 f317fed..4440a04 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 = parisc_syscall_resolve_name,
- .syscall_resolve_num = parisc_syscall_resolve_num,
+ .syscall_resolve_name_raw = parisc_syscall_resolve_name,
+ .syscall_resolve_num_raw = parisc_syscall_resolve_num,
.syscall_rewrite = NULL,
.rule_add = NULL,
};
diff --git a/src/arch-parisc64.c b/src/arch-parisc64.c
index 08e5081..d2d85e6 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 = parisc64_syscall_resolve_name,
- .syscall_resolve_num = parisc64_syscall_resolve_num,
+ .syscall_resolve_name_raw = parisc64_syscall_resolve_name,
+ .syscall_resolve_num_raw = parisc64_syscall_resolve_num,
.syscall_rewrite = NULL,
.rule_add = NULL,
};
diff --git a/src/arch-ppc.c b/src/arch-ppc.c
index 035888c..0c97bf5 100644
--- a/src/arch-ppc.c
+++ b/src/arch-ppc.c
@@ -34,526 +34,17 @@
#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,
- .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,
+ .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,
};
diff --git a/src/arch-ppc64.c b/src/arch-ppc64.c
index 8cccbb8..27f31a5 100644
--- a/src/arch-ppc64.c
+++ b/src/arch-ppc64.c
@@ -26,6 +26,7 @@
#include <linux/audit.h>
#include "db.h"
+#include "syscalls.h"
#include "arch.h"
#include "arch-ppc64.h"
@@ -33,605 +34,19 @@
#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,
- .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,
+ .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,
};
const struct arch_def arch_def_ppc64le = {
@@ -639,8 +54,12 @@ const struct arch_def arch_def_ppc64le = {
.token_bpf = AUDIT_ARCH_PPC64LE,
.size = ARCH_SIZE_64,
.endian = ARCH_ENDIAN_LITTLE,
- .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,
+ .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,
};
diff --git a/src/arch-riscv64.c b/src/arch-riscv64.c
index 67bc926..df4f5c8 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 = riscv64_syscall_resolve_name,
- .syscall_resolve_num = riscv64_syscall_resolve_num,
+ .syscall_resolve_name_raw = riscv64_syscall_resolve_name,
+ .syscall_resolve_num_raw = riscv64_syscall_resolve_num,
.syscall_rewrite = NULL,
.rule_add = NULL,
};
diff --git a/src/arch-s390.c b/src/arch-s390.c
index c2990c0..f2c8fda 100644
--- a/src/arch-s390.c
+++ b/src/arch-s390.c
@@ -17,593 +17,17 @@
#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,
- .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,
+ .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,
};
diff --git a/src/arch-s390x.c b/src/arch-s390x.c
index 45d67ec..ddae21b 100644
--- a/src/arch-s390x.c
+++ b/src/arch-s390x.c
@@ -17,592 +17,17 @@
#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,
- .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,
+ .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,
};
diff --git a/src/arch-sh.c b/src/arch-sh.c
index 1172236..f40fcb8 100644
--- a/src/arch-sh.c
+++ b/src/arch-sh.c
@@ -26,528 +26,19 @@
#define __sh_NR_socketcall 102
#define __sh_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 sh_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 sh_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 *sh_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 sh_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 _sh_syscall_socket_test(int sys)
-{
- const char *name;
-
- /* multiplexed pseduo-syscalls */
- if (sys <= -100 && sys >= -120)
- return true;
-
- name = sh_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 _sh_syscall_ipc_test(int sys)
-{
- const char *name;
-
- /* multiplexed pseduo-syscalls */
- if (sys <= -200 && sys >= -224)
- return true;
-
- name = sh_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 _sh_syscall_demux(int syscall)
-{
- int sys = __NR_SCMP_UNDEF;
-
-#define _ABI_SYSCALL_DEMUX_CHK(NAME) \
-case __PNR_##NAME: \
- sys = sh_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 _sh_syscall_mux(int syscall)
-{
- const char *sys;
-
- sys = sh_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 sh_syscall_rewrite(int *syscall)
-{
- int sys = *syscall;
-
- if (sys <= -100 && sys >= -120)
- *syscall = __sh_NR_socketcall;
- else if (sys <= -200 && sys >= -224)
- *syscall = __sh_NR_ipc;
- else if (sys < 0)
- return -EDOM;
-
- return 0;
-}
-
-/**
- * add a new rule to the sh 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 sh 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 sh_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 (_sh_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 = _sh_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 = _sh_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 = __sh_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 (_sh_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 = _sh_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 = _sh_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 = __sh_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_sheb = {
.token = SCMP_ARCH_SHEB,
.token_bpf = AUDIT_ARCH_SH,
.size = ARCH_SIZE_32,
.endian = ARCH_ENDIAN_BIG,
- .syscall_resolve_name = sh_syscall_resolve_name_munge,
- .syscall_resolve_num = sh_syscall_resolve_num_munge,
- .syscall_rewrite = sh_syscall_rewrite,
- .rule_add = sh_rule_add,
+ .sys_socketcall = __sh_NR_socketcall,
+ .sys_ipc = __sh_NR_ipc,
+ .syscall_resolve_name = abi_syscall_resolve_name_munge,
+ .syscall_resolve_name_raw = sh_syscall_resolve_name,
+ .syscall_resolve_num = abi_syscall_resolve_num_munge,
+ .syscall_resolve_num_raw = sh_syscall_resolve_num,
+ .syscall_rewrite = abi_syscall_rewrite,
+ .rule_add = abi_rule_add,
};
const struct arch_def arch_def_sh = {
@@ -555,8 +46,12 @@ const struct arch_def arch_def_sh = {
.token_bpf = AUDIT_ARCH_SHEL,
.size = ARCH_SIZE_32,
.endian = ARCH_ENDIAN_LITTLE,
- .syscall_resolve_name = sh_syscall_resolve_name_munge,
- .syscall_resolve_num = sh_syscall_resolve_num_munge,
- .syscall_rewrite = sh_syscall_rewrite,
- .rule_add = sh_rule_add,
+ .sys_socketcall = __sh_NR_socketcall,
+ .sys_ipc = __sh_NR_ipc,
+ .syscall_resolve_name = abi_syscall_resolve_name_munge,
+ .syscall_resolve_name_raw = sh_syscall_resolve_name,
+ .syscall_resolve_num = abi_syscall_resolve_num_munge,
+ .syscall_resolve_num_raw = sh_syscall_resolve_num,
+ .syscall_rewrite = abi_syscall_rewrite,
+ .rule_add = abi_rule_add,
};
diff --git a/src/arch-x32.c b/src/arch-x32.c
index 50c502e..0a73923 100644
--- a/src/arch-x32.c
+++ b/src/arch-x32.c
@@ -28,6 +28,7 @@
/**
* 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.
@@ -35,12 +36,13 @@
* numbers; returns __NR_SCMP_ERROR on failure.
*
*/
-int x32_syscall_resolve_name_munge(const char *name)
+int x32_syscall_resolve_name_munge(const struct arch_def *arch,
+ const char *name)
{
int sys;
/* NOTE: we don't want to modify the pseudo-syscall numbers */
- sys = x32_syscall_resolve_name(name);
+ sys = arch->syscall_resolve_name_raw(name);
if (sys == __NR_SCMP_ERROR || sys < 0)
return sys;
@@ -49,6 +51,7 @@ int x32_syscall_resolve_name_munge(const char *name)
/**
* 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.
@@ -56,12 +59,13 @@ int x32_syscall_resolve_name_munge(const char *name)
* syscall names; returns NULL on failure.
*
*/
-const char *x32_syscall_resolve_num_munge(int num)
+const char *x32_syscall_resolve_num_munge(const struct arch_def *arch,
+ int num)
{
/* NOTE: we don't want to modify the pseudo-syscall numbers */
if (num >= 0)
num &= ~X32_SYSCALL_BIT;
- return x32_syscall_resolve_num(num);
+ return arch->syscall_resolve_num_raw(num);
}
const struct arch_def arch_def_x32 = {
@@ -71,7 +75,9 @@ 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 2a4c074..af33137 100644
--- a/src/arch-x86.c
+++ b/src/arch-x86.c
@@ -33,593 +33,17 @@
#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,
- .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,
+ .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,
};
diff --git a/src/arch-x86_64.c b/src/arch-x86_64.c
index a5fccad..9c0e5ac 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 = x86_64_syscall_resolve_name,
- .syscall_resolve_num = x86_64_syscall_resolve_num,
+ .syscall_resolve_name_raw = x86_64_syscall_resolve_name,
+ .syscall_resolve_num_raw = x86_64_syscall_resolve_num,
.syscall_rewrite = NULL,
.rule_add = NULL,
};
diff --git a/src/arch.c b/src/arch.c
index 6ab922f..921e455 100644
--- a/src/arch.c
+++ b/src/arch.c
@@ -315,7 +315,9 @@ 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)(name);
+ return (*arch->syscall_resolve_name)(arch, name);
+ if (arch->syscall_resolve_name_raw)
+ return (*arch->syscall_resolve_name_raw)(name);
return __NR_SCMP_ERROR;
}
@@ -333,7 +335,9 @@ 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)(num);
+ return (*arch->syscall_resolve_num)(arch, num);
+ if (arch->syscall_resolve_num_raw)
+ return (*arch->syscall_resolve_num_raw)(num);
return NULL;
}
@@ -396,7 +400,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)(syscall);
+ (*arch->syscall_rewrite)(arch, syscall);
}
/* syscalls not defined on this architecture */
diff --git a/src/arch.h b/src/arch.h
index 38c3a9c..b6484f9 100644
--- a/src/arch.h
+++ b/src/arch.h
@@ -49,10 +49,18 @@ struct arch_def {
ARCH_ENDIAN_BIG,
} endian;
+ /* arch specific constants */
+ int sys_socketcall;
+ int sys_ipc;
+
/* arch specific functions */
- int (*syscall_resolve_name)(const char *name);
- const char *(*syscall_resolve_num)(int num);
- int (*syscall_rewrite)(int *syscall);
+ 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 (*rule_add)(struct db_filter *db, struct db_api_rule_list *rule);
};
diff --git a/src/syscalls.c b/src/syscalls.c
index ddb84fa..faddff0 100644
--- a/src/syscalls.c
+++ b/src/syscalls.c
@@ -1,5 +1,5 @@
/**
- * Enhanced Seccomp x86_64 Syscall Table
+ * Enhanced Seccomp Syscall Table Functions
*
* Copyright (c) 2012, 2020 Red Hat <pmoore@redhat.com>
* Author: Paul Moore <paul@paul-moore.com>
@@ -19,9 +19,13 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, see <http://www.gnu.org/licenses>.
*/
-#include <seccomp.h>
+
+#include <stdlib.h>
+#include <errno.h>
#include <string.h>
+#include <seccomp.h>
+#include "db.h"
#include "arch.h"
#include "syscalls.h"
@@ -55,3 +59,524 @@ ARCH_DEF(sh)
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 4f959af..58a788c 100644
--- a/src/syscalls.h
+++ b/src/syscalls.h
@@ -61,4 +61,12 @@ 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