--- /dev/null
--- /dev/null
++REVERTS
++
++From f454456e261930d94b3a1a444b6bac75c11c3cb0 Mon Sep 17 00:00:00 2001
++From: Paul Moore <paul@paul-moore.com>
++Date: Wed, 4 Aug 2021 11:51:12 -0400
++Subject: [PATCH] arch: consolidate all of the multiplexed syscall handling
++
++Not only does this reduce the amount of duplicated code
++significantly, it removes a lot of the "magic" numbers in the
++code, and it happened to catch some bugs too.
++
++Acked-by: Tom Hromatka <tom.hromatka@oracle.com>
++Signed-off-by: Paul Moore <paul@paul-moore.com>
++
++(imported from commit 17cbd2c253ce63e5e9e3cec867ff58efbe8b5fdc)
++
++diff --git a/src/arch-aarch64.c b/src/arch-aarch64.c
++--- a/src/arch-aarch64.c
+++++ b/src/arch-aarch64.c
++@@ -31,8 +31,8 @@ const struct arch_def arch_def_aarch64 = {
++ .token_bpf = AUDIT_ARCH_AARCH64,
++ .size = ARCH_SIZE_64,
++ .endian = ARCH_ENDIAN_LITTLE,
++- .syscall_resolve_name_raw = aarch64_syscall_resolve_name,
++- .syscall_resolve_num_raw = aarch64_syscall_resolve_num,
+++ .syscall_resolve_name = aarch64_syscall_resolve_name,
+++ .syscall_resolve_num = aarch64_syscall_resolve_num,
++ .syscall_rewrite = NULL,
++ .rule_add = NULL,
++ };
++diff --git a/src/arch-arm.c b/src/arch-arm.c
++--- a/src/arch-arm.c
+++++ b/src/arch-arm.c
++@@ -39,7 +39,6 @@
++
++ /**
++ * Resolve a syscall name to a number
++- * @param arch the architecture definition
++ * @param name the syscall name
++ *
++ * Resolve the given syscall name to the syscall number using the syscall table.
++@@ -47,13 +46,12 @@
++ * numbers; returns __NR_SCMP_ERROR on failure.
++ *
++ */
++-int arm_syscall_resolve_name_munge(const struct arch_def *arch,
++- const char *name)
+++int arm_syscall_resolve_name_munge(const char *name)
++ {
++ int sys;
++
++ /* NOTE: we don't want to modify the pseudo-syscall numbers */
++- sys = arch->syscall_resolve_name_raw(name);
+++ sys = arm_syscall_resolve_name(name);
++ if (sys == __NR_SCMP_ERROR || sys < 0)
++ return sys;
++
++@@ -62,7 +60,6 @@ int arm_syscall_resolve_name_munge(const struct arch_def *arch,
++
++ /**
++ * Resolve a syscall number to a name
++- * @param arch the architecture definition
++ * @param num the syscall number
++ *
++ * Resolve the given syscall number to the syscall name using the syscall table.
++@@ -70,12 +67,12 @@ int arm_syscall_resolve_name_munge(const struct arch_def *arch,
++ * syscall names; returns NULL on failure.
++ *
++ */
++-const char *arm_syscall_resolve_num_munge(const struct arch_def *arch, int num)
+++const char *arm_syscall_resolve_num_munge(int num)
++ {
++ /* NOTE: we don't want to modify the pseudo-syscall numbers */
++ if (num >= 0)
++ num &= ~__SCMP_NR_BASE;
++- return arch->syscall_resolve_num_raw(num);
+++ return arm_syscall_resolve_num(num);
++ }
++
++ const struct arch_def arch_def_arm = {
++@@ -84,9 +81,7 @@ const struct arch_def arch_def_arm = {
++ .size = ARCH_SIZE_32,
++ .endian = ARCH_ENDIAN_LITTLE,
++ .syscall_resolve_name = arm_syscall_resolve_name_munge,
++- .syscall_resolve_name_raw = arm_syscall_resolve_name,
++ .syscall_resolve_num = arm_syscall_resolve_num_munge,
++- .syscall_resolve_num_raw = arm_syscall_resolve_num,
++ .syscall_rewrite = NULL,
++ .rule_add = NULL,
++ };
++diff --git a/src/arch-mips.c b/src/arch-mips.c
++--- a/src/arch-mips.c
+++++ b/src/arch-mips.c
++@@ -30,23 +30,535 @@
++ #include "arch.h"
++ #include "arch-mips.h"
++
+++/* O32 ABI */
+++#define __SCMP_NR_BASE 4000
+++
++ /* mips syscall numbers */
++ #define __mips_NR_socketcall 102
++ #define __mips_NR_ipc 117
++
+++/**
+++ * Resolve a syscall name to a number
+++ * @param name the syscall name
+++ *
+++ * Resolve the given syscall name to the syscall number using the syscall table.
+++ * Returns the syscall number on success, including negative pseudo syscall
+++ * numbers; returns __NR_SCMP_ERROR on failure.
+++ *
+++ */
+++int mips_syscall_resolve_name_munge(const char *name)
+++{
+++
+++#define _ABI_SYSCALL_RES_NAME_CHK(NAME) \
+++ if (!strcmp(name, #NAME)) return __PNR_##NAME;
+++
+++ _ABI_SYSCALL_RES_NAME_CHK(socket)
+++ _ABI_SYSCALL_RES_NAME_CHK(bind)
+++ _ABI_SYSCALL_RES_NAME_CHK(connect)
+++ _ABI_SYSCALL_RES_NAME_CHK(listen)
+++ _ABI_SYSCALL_RES_NAME_CHK(accept)
+++ _ABI_SYSCALL_RES_NAME_CHK(getsockname)
+++ _ABI_SYSCALL_RES_NAME_CHK(getpeername)
+++ _ABI_SYSCALL_RES_NAME_CHK(socketpair)
+++ _ABI_SYSCALL_RES_NAME_CHK(send)
+++ _ABI_SYSCALL_RES_NAME_CHK(recv)
+++ _ABI_SYSCALL_RES_NAME_CHK(sendto)
+++ _ABI_SYSCALL_RES_NAME_CHK(recvfrom)
+++ _ABI_SYSCALL_RES_NAME_CHK(shutdown)
+++ _ABI_SYSCALL_RES_NAME_CHK(setsockopt)
+++ _ABI_SYSCALL_RES_NAME_CHK(getsockopt)
+++ _ABI_SYSCALL_RES_NAME_CHK(sendmsg)
+++ _ABI_SYSCALL_RES_NAME_CHK(recvmsg)
+++ _ABI_SYSCALL_RES_NAME_CHK(accept4)
+++ _ABI_SYSCALL_RES_NAME_CHK(recvmmsg)
+++ _ABI_SYSCALL_RES_NAME_CHK(sendmmsg)
+++ _ABI_SYSCALL_RES_NAME_CHK(semop)
+++ _ABI_SYSCALL_RES_NAME_CHK(semget)
+++ _ABI_SYSCALL_RES_NAME_CHK(semctl)
+++ _ABI_SYSCALL_RES_NAME_CHK(semtimedop)
+++ _ABI_SYSCALL_RES_NAME_CHK(msgsnd)
+++ _ABI_SYSCALL_RES_NAME_CHK(msgrcv)
+++ _ABI_SYSCALL_RES_NAME_CHK(msgget)
+++ _ABI_SYSCALL_RES_NAME_CHK(msgctl)
+++ _ABI_SYSCALL_RES_NAME_CHK(shmat)
+++ _ABI_SYSCALL_RES_NAME_CHK(shmdt)
+++ _ABI_SYSCALL_RES_NAME_CHK(shmget)
+++ _ABI_SYSCALL_RES_NAME_CHK(shmctl)
+++
+++ return mips_syscall_resolve_name(name);
+++}
+++
+++/**
+++ * Resolve a syscall number to a name
+++ * @param num the syscall number
+++ *
+++ * Resolve the given syscall number to the syscall name using the syscall table.
+++ * Returns a pointer to the syscall name string on success, including pseudo
+++ * syscall names; returns NULL on failure.
+++ *
+++ */
+++const char *mips_syscall_resolve_num_munge(int num)
+++{
+++
+++#define _ABI_SYSCALL_RES_NUM_CHK(NAME) \
+++ if (num == __PNR_##NAME) return #NAME;
+++
+++ _ABI_SYSCALL_RES_NUM_CHK(socket)
+++ _ABI_SYSCALL_RES_NUM_CHK(bind)
+++ _ABI_SYSCALL_RES_NUM_CHK(connect)
+++ _ABI_SYSCALL_RES_NUM_CHK(listen)
+++ _ABI_SYSCALL_RES_NUM_CHK(accept)
+++ _ABI_SYSCALL_RES_NUM_CHK(getsockname)
+++ _ABI_SYSCALL_RES_NUM_CHK(getpeername)
+++ _ABI_SYSCALL_RES_NUM_CHK(socketpair)
+++ _ABI_SYSCALL_RES_NUM_CHK(send)
+++ _ABI_SYSCALL_RES_NUM_CHK(recv)
+++ _ABI_SYSCALL_RES_NUM_CHK(sendto)
+++ _ABI_SYSCALL_RES_NUM_CHK(recvfrom)
+++ _ABI_SYSCALL_RES_NUM_CHK(shutdown)
+++ _ABI_SYSCALL_RES_NUM_CHK(setsockopt)
+++ _ABI_SYSCALL_RES_NUM_CHK(getsockopt)
+++ _ABI_SYSCALL_RES_NUM_CHK(sendmsg)
+++ _ABI_SYSCALL_RES_NUM_CHK(recvmsg)
+++ _ABI_SYSCALL_RES_NUM_CHK(accept4)
+++ _ABI_SYSCALL_RES_NUM_CHK(recvmmsg)
+++ _ABI_SYSCALL_RES_NUM_CHK(sendmmsg)
+++ _ABI_SYSCALL_RES_NUM_CHK(semop)
+++ _ABI_SYSCALL_RES_NUM_CHK(semget)
+++ _ABI_SYSCALL_RES_NUM_CHK(semctl)
+++ _ABI_SYSCALL_RES_NUM_CHK(semtimedop)
+++ _ABI_SYSCALL_RES_NUM_CHK(msgsnd)
+++ _ABI_SYSCALL_RES_NUM_CHK(msgrcv)
+++ _ABI_SYSCALL_RES_NUM_CHK(msgget)
+++ _ABI_SYSCALL_RES_NUM_CHK(msgctl)
+++ _ABI_SYSCALL_RES_NUM_CHK(shmat)
+++ _ABI_SYSCALL_RES_NUM_CHK(shmdt)
+++ _ABI_SYSCALL_RES_NUM_CHK(shmget)
+++ _ABI_SYSCALL_RES_NUM_CHK(shmctl)
+++
+++ return mips_syscall_resolve_num(num);
+++}
+++
+++/**
+++ * Check if a syscall is a socket syscall
+++ * @param sys the syscall number
+++ *
+++ * Returns true if the syscall is a socket related syscall, false otherwise.
+++ *
+++ */
+++static bool _mips_syscall_socket_test(int sys)
+++{
+++ const char *name;
+++
+++ /* multiplexed pseduo-syscalls */
+++ if (sys <= -100 && sys >= -120)
+++ return true;
+++
+++ name = mips_syscall_resolve_num(sys);
+++ if (!name)
+++ return false;
+++
+++#define _ABI_SYSCALL_SOCK_CHK(NAME) \
+++ if (!strcmp(name, #NAME)) return true;
+++
+++ _ABI_SYSCALL_SOCK_CHK(socket)
+++ _ABI_SYSCALL_SOCK_CHK(bind)
+++ _ABI_SYSCALL_SOCK_CHK(connect)
+++ _ABI_SYSCALL_SOCK_CHK(listen)
+++ _ABI_SYSCALL_SOCK_CHK(accept)
+++ _ABI_SYSCALL_SOCK_CHK(getsockname)
+++ _ABI_SYSCALL_SOCK_CHK(getpeername)
+++ _ABI_SYSCALL_SOCK_CHK(socketpair)
+++ _ABI_SYSCALL_SOCK_CHK(send)
+++ _ABI_SYSCALL_SOCK_CHK(recv)
+++ _ABI_SYSCALL_SOCK_CHK(sendto)
+++ _ABI_SYSCALL_SOCK_CHK(recvfrom)
+++ _ABI_SYSCALL_SOCK_CHK(shutdown)
+++ _ABI_SYSCALL_SOCK_CHK(setsockopt)
+++ _ABI_SYSCALL_SOCK_CHK(getsockopt)
+++ _ABI_SYSCALL_SOCK_CHK(sendmsg)
+++ _ABI_SYSCALL_SOCK_CHK(recvmsg)
+++ _ABI_SYSCALL_SOCK_CHK(accept4)
+++ _ABI_SYSCALL_SOCK_CHK(recvmmsg)
+++ _ABI_SYSCALL_SOCK_CHK(sendmmsg)
+++
+++ return false;
+++}
+++
+++/**
+++ * Check if a syscall is an ipc syscall
+++ * @param sys the syscall number
+++ *
+++ * Returns true if the syscall is an ipc related syscall, false otherwise.
+++ *
+++ */
+++static bool _mips_syscall_ipc_test(int sys)
+++{
+++ const char *name;
+++
+++ /* multiplexed pseduo-syscalls */
+++ if (sys <= -200 && sys >= -224)
+++ return true;
+++
+++ name = mips_syscall_resolve_num(sys);
+++ if (!name)
+++ return false;
+++
+++#define _ABI_SYSCALL_IPC_CHK(NAME) \
+++ if (!strcmp(name, #NAME)) return true;
+++
+++ _ABI_SYSCALL_IPC_CHK(semop)
+++ _ABI_SYSCALL_IPC_CHK(semget)
+++ _ABI_SYSCALL_IPC_CHK(semctl)
+++ _ABI_SYSCALL_IPC_CHK(semtimedop)
+++ _ABI_SYSCALL_IPC_CHK(msgsnd)
+++ _ABI_SYSCALL_IPC_CHK(msgrcv)
+++ _ABI_SYSCALL_IPC_CHK(msgget)
+++ _ABI_SYSCALL_IPC_CHK(msgctl)
+++ _ABI_SYSCALL_IPC_CHK(shmat)
+++ _ABI_SYSCALL_IPC_CHK(shmdt)
+++ _ABI_SYSCALL_IPC_CHK(shmget)
+++ _ABI_SYSCALL_IPC_CHK(shmctl)
+++
+++ return false;
+++}
+++
+++/**
+++ * Convert a multiplexed pseudo syscall into a direct syscall
+++ * @param syscall the multiplexed pseudo syscall number
+++ *
+++ * Return the related direct syscall number, __NR_SCMP_UNDEF is there is
+++ * no related syscall, or __NR_SCMP_ERROR otherwise.
+++ *
+++ */
+++static int _mips_syscall_demux(int syscall)
+++{
+++ int sys = __NR_SCMP_UNDEF;
+++
+++#define _ABI_SYSCALL_DEMUX_CHK(NAME) \
+++case __PNR_##NAME: \
+++ sys = mips_syscall_resolve_name(#NAME); break;
+++
+++ switch (syscall) {
+++ _ABI_SYSCALL_DEMUX_CHK(socket)
+++ _ABI_SYSCALL_DEMUX_CHK(bind)
+++ _ABI_SYSCALL_DEMUX_CHK(connect)
+++ _ABI_SYSCALL_DEMUX_CHK(listen)
+++ _ABI_SYSCALL_DEMUX_CHK(accept)
+++ _ABI_SYSCALL_DEMUX_CHK(getsockname)
+++ _ABI_SYSCALL_DEMUX_CHK(getpeername)
+++ _ABI_SYSCALL_DEMUX_CHK(socketpair)
+++ _ABI_SYSCALL_DEMUX_CHK(send)
+++ _ABI_SYSCALL_DEMUX_CHK(recv)
+++ _ABI_SYSCALL_DEMUX_CHK(sendto)
+++ _ABI_SYSCALL_DEMUX_CHK(recvfrom)
+++ _ABI_SYSCALL_DEMUX_CHK(shutdown)
+++ _ABI_SYSCALL_DEMUX_CHK(setsockopt)
+++ _ABI_SYSCALL_DEMUX_CHK(getsockopt)
+++ _ABI_SYSCALL_DEMUX_CHK(sendmsg)
+++ _ABI_SYSCALL_DEMUX_CHK(recvmsg)
+++ _ABI_SYSCALL_DEMUX_CHK(accept4)
+++ _ABI_SYSCALL_DEMUX_CHK(recvmmsg)
+++ _ABI_SYSCALL_DEMUX_CHK(sendmmsg)
+++ _ABI_SYSCALL_DEMUX_CHK(semop)
+++ _ABI_SYSCALL_DEMUX_CHK(semget)
+++ _ABI_SYSCALL_DEMUX_CHK(semctl)
+++ _ABI_SYSCALL_DEMUX_CHK(semtimedop)
+++ _ABI_SYSCALL_DEMUX_CHK(msgsnd)
+++ _ABI_SYSCALL_DEMUX_CHK(msgrcv)
+++ _ABI_SYSCALL_DEMUX_CHK(msgget)
+++ _ABI_SYSCALL_DEMUX_CHK(msgctl)
+++ _ABI_SYSCALL_DEMUX_CHK(shmat)
+++ _ABI_SYSCALL_DEMUX_CHK(shmdt)
+++ _ABI_SYSCALL_DEMUX_CHK(shmget)
+++ _ABI_SYSCALL_DEMUX_CHK(shmctl)
+++ }
+++
+++ /* this looks odd because the arch resolver returns _ERROR if it can't
+++ * resolve the syscall, but we want to use _UNDEF for that, so we set
+++ * 'sys' to a sentinel value of _UNDEF and if it is error here we know
+++ * the resolve failed to find a match */
+++ if (sys == __NR_SCMP_UNDEF)
+++ sys = __NR_SCMP_ERROR;
+++ else if (sys == __NR_SCMP_ERROR)
+++ sys = __NR_SCMP_UNDEF;
+++
+++ return sys;
+++}
+++
+++/**
+++ * Convert a direct syscall into multiplexed pseudo socket syscall
+++ * @param syscall the direct syscall
+++ *
+++ * Return the related multiplexed pseduo syscall number, __NR_SCMP_UNDEF is
+++ * there is no related pseudo syscall, or __NR_SCMP_ERROR otherwise.
+++ *
+++ */
+++static int _mips_syscall_mux(int syscall)
+++{
+++ const char *sys;
+++
+++ sys = mips_syscall_resolve_num(syscall);
+++ if (!sys)
+++ return __NR_SCMP_ERROR;
+++
+++#define _ABI_SYSCALL_MUX_CHK(NAME) \
+++ if (!strcmp(sys, #NAME)) return __PNR_##NAME;
+++
+++ _ABI_SYSCALL_MUX_CHK(socket)
+++ _ABI_SYSCALL_MUX_CHK(bind)
+++ _ABI_SYSCALL_MUX_CHK(connect)
+++ _ABI_SYSCALL_MUX_CHK(listen)
+++ _ABI_SYSCALL_MUX_CHK(accept)
+++ _ABI_SYSCALL_MUX_CHK(getsockname)
+++ _ABI_SYSCALL_MUX_CHK(getpeername)
+++ _ABI_SYSCALL_MUX_CHK(socketpair)
+++ _ABI_SYSCALL_MUX_CHK(send)
+++ _ABI_SYSCALL_MUX_CHK(recv)
+++ _ABI_SYSCALL_MUX_CHK(sendto)
+++ _ABI_SYSCALL_MUX_CHK(recvfrom)
+++ _ABI_SYSCALL_MUX_CHK(shutdown)
+++ _ABI_SYSCALL_MUX_CHK(setsockopt)
+++ _ABI_SYSCALL_MUX_CHK(getsockopt)
+++ _ABI_SYSCALL_MUX_CHK(sendmsg)
+++ _ABI_SYSCALL_MUX_CHK(recvmsg)
+++ _ABI_SYSCALL_MUX_CHK(accept4)
+++ _ABI_SYSCALL_MUX_CHK(recvmmsg)
+++ _ABI_SYSCALL_MUX_CHK(sendmmsg)
+++ _ABI_SYSCALL_MUX_CHK(semop)
+++ _ABI_SYSCALL_MUX_CHK(semget)
+++ _ABI_SYSCALL_MUX_CHK(semctl)
+++ _ABI_SYSCALL_MUX_CHK(semtimedop)
+++ _ABI_SYSCALL_MUX_CHK(msgsnd)
+++ _ABI_SYSCALL_MUX_CHK(msgrcv)
+++ _ABI_SYSCALL_MUX_CHK(msgget)
+++ _ABI_SYSCALL_MUX_CHK(msgctl)
+++ _ABI_SYSCALL_MUX_CHK(shmat)
+++ _ABI_SYSCALL_MUX_CHK(shmdt)
+++ _ABI_SYSCALL_MUX_CHK(shmget)
+++ _ABI_SYSCALL_MUX_CHK(shmctl)
+++
+++ return __NR_SCMP_ERROR;
+++}
+++
+++/**
+++ * Rewrite a syscall value to match the architecture
+++ * @param syscall the syscall number
+++ *
+++ * Syscalls can vary across different architectures so this function rewrites
+++ * the syscall into the correct value for the specified architecture. Returns
+++ * zero on success, negative values on failure.
+++ *
+++ */
+++int mips_syscall_rewrite(int *syscall)
+++{
+++ int sys = *syscall;
+++
+++ if (sys <= -100 && sys >= -120)
+++ *syscall = __mips_NR_socketcall;
+++ else if (sys <= -200 && sys >= -224)
+++ *syscall = __mips_NR_ipc;
+++ else if (sys < 0)
+++ return -EDOM;
+++
+++ return 0;
+++}
+++
+++/**
+++ * add a new rule to the mips seccomp filter
+++ * @param db the seccomp filter db
+++ * @param rule the filter rule
+++ *
+++ * This function adds a new syscall filter to the seccomp filter db, making any
+++ * necessary adjustments for the mips ABI. Returns zero on success, negative
+++ * values on failure.
+++ *
+++ * It is important to note that in the case of failure the db may be corrupted,
+++ * the caller must use the transaction mechanism if the db integrity is
+++ * important.
+++ *
+++ */
+++int mips_rule_add(struct db_filter *db, struct db_api_rule_list *rule)
+++{
+++ int rc = 0;
+++ unsigned int iter;
+++ int sys = rule->syscall;
+++ int sys_a, sys_b;
+++ struct db_api_rule_list *rule_a, *rule_b, *rule_dup = NULL;
+++
+++ if (_mips_syscall_socket_test(sys)) {
+++ /* socket syscalls */
+++
+++ /* strict check for the multiplexed socket syscalls */
+++ for (iter = 0; iter < ARG_COUNT_MAX; iter++) {
+++ if ((rule->args[iter].valid != 0) && (rule->strict)) {
+++ rc = -EINVAL;
+++ goto add_return;
+++ }
+++ }
+++
+++ /* determine both the muxed and direct syscall numbers */
+++ if (sys > 0) {
+++ sys_a = _mips_syscall_mux(sys);
+++ if (sys_a == __NR_SCMP_ERROR) {
+++ rc = __NR_SCMP_ERROR;
+++ goto add_return;
+++ }
+++ sys_b = sys;
+++ } else {
+++ sys_a = sys;
+++ sys_b = _mips_syscall_demux(sys);
+++ if (sys_b == __NR_SCMP_ERROR) {
+++ rc = __NR_SCMP_ERROR;
+++ goto add_return;
+++ }
+++ }
+++
+++ /* use rule_a for the multiplexed syscall and use rule_b for
+++ * the direct wired syscall */
+++
+++ if (sys_a == __NR_SCMP_UNDEF) {
+++ rule_a = NULL;
+++ rule_b = rule;
+++ } else if (sys_b == __NR_SCMP_UNDEF) {
+++ rule_a = rule;
+++ rule_b = NULL;
+++ } else {
+++ /* need two rules, dup the first and link together */
+++ rule_a = rule;
+++ rule_dup = db_rule_dup(rule_a);
+++ rule_b = rule_dup;
+++ if (rule_b == NULL)
+++ goto add_return;
+++ rule_b->prev = rule_a;
+++ rule_b->next = NULL;
+++ rule_a->next = rule_b;
+++ }
+++
+++ /* multiplexed socket syscalls */
+++ if (rule_a != NULL) {
+++ rule_a->syscall = __mips_NR_socketcall;
+++ rule_a->args[0].arg = 0;
+++ rule_a->args[0].op = SCMP_CMP_EQ;
+++ rule_a->args[0].mask = DATUM_MAX;
+++ rule_a->args[0].datum = (-sys_a) % 100;
+++ rule_a->args[0].valid = 1;
+++ }
+++
+++ /* direct wired socket syscalls */
+++ if (rule_b != NULL)
+++ rule_b->syscall = sys_b;
+++
+++ /* we should be protected by a transaction checkpoint */
+++ if (rule_a != NULL) {
+++ rc = db_rule_add(db, rule_a);
+++ if (rc < 0)
+++ goto add_return;
+++ }
+++ if (rule_b != NULL) {
+++ rc = db_rule_add(db, rule_b);
+++ if (rc < 0)
+++ goto add_return;
+++ }
+++ } else if (_mips_syscall_ipc_test(sys)) {
+++ /* ipc syscalls */
+++
+++ /* strict check for the multiplexed socket syscalls */
+++ for (iter = 0; iter < ARG_COUNT_MAX; iter++) {
+++ if ((rule->args[iter].valid != 0) && (rule->strict)) {
+++ rc = -EINVAL;
+++ goto add_return;
+++ }
+++ }
+++
+++ /* determine both the muxed and direct syscall numbers */
+++ if (sys > 0) {
+++ sys_a = _mips_syscall_mux(sys);
+++ if (sys_a == __NR_SCMP_ERROR) {
+++ rc = __NR_SCMP_ERROR;
+++ goto add_return;
+++ }
+++ sys_b = sys;
+++ } else {
+++ sys_a = sys;
+++ sys_b = _mips_syscall_demux(sys);
+++ if (sys_b == __NR_SCMP_ERROR) {
+++ rc = __NR_SCMP_ERROR;
+++ goto add_return;
+++ }
+++ }
+++
+++ /* use rule_a for the multiplexed syscall and use rule_b for
+++ * the direct wired syscall */
+++
+++ if (sys_a == __NR_SCMP_UNDEF) {
+++ rule_a = NULL;
+++ rule_b = rule;
+++ } else if (sys_b == __NR_SCMP_UNDEF) {
+++ rule_a = rule;
+++ rule_b = NULL;
+++ } else {
+++ /* need two rules, dup the first and link together */
+++ rule_a = rule;
+++ rule_dup = db_rule_dup(rule_a);
+++ rule_b = rule_dup;
+++ if (rule_b == NULL)
+++ goto add_return;
+++ rule_b->prev = rule_a;
+++ rule_b->next = NULL;
+++ rule_a->next = rule_b;
+++ }
+++
+++ /* multiplexed socket syscalls */
+++ if (rule_a != NULL) {
+++ rule_a->syscall = __mips_NR_ipc;
+++ rule_a->args[0].arg = 0;
+++ rule_a->args[0].op = SCMP_CMP_EQ;
+++ rule_a->args[0].mask = DATUM_MAX;
+++ rule_a->args[0].datum = (-sys_a) % 200;
+++ rule_a->args[0].valid = 1;
+++ }
+++
+++ /* direct wired socket syscalls */
+++ if (rule_b != NULL)
+++ rule_b->syscall = sys_b;
+++
+++ /* we should be protected by a transaction checkpoint */
+++ if (rule_a != NULL) {
+++ rc = db_rule_add(db, rule_a);
+++ if (rc < 0)
+++ goto add_return;
+++ }
+++ if (rule_b != NULL) {
+++ rc = db_rule_add(db, rule_b);
+++ if (rc < 0)
+++ goto add_return;
+++ }
+++ } else if (sys >= 0) {
+++ /* normal syscall processing */
+++ rc = db_rule_add(db, rule);
+++ if (rc < 0)
+++ goto add_return;
+++ } else if (rule->strict) {
+++ rc = -EDOM;
+++ goto add_return;
+++ }
+++
+++add_return:
+++ if (rule_dup != NULL)
+++ free(rule_dup);
+++ return rc;
+++}
+++
++ const struct arch_def arch_def_mips = {
++ .token = SCMP_ARCH_MIPS,
++ .token_bpf = AUDIT_ARCH_MIPS,
++ .size = ARCH_SIZE_32,
++ .endian = ARCH_ENDIAN_BIG,
++- .sys_socketcall = __mips_NR_socketcall,
++- .sys_ipc = __mips_NR_ipc,
++- .syscall_resolve_name = abi_syscall_resolve_name_munge,
++- .syscall_resolve_name_raw = mips_syscall_resolve_name,
++- .syscall_resolve_num = abi_syscall_resolve_num_munge,
++- .syscall_resolve_num_raw = mips_syscall_resolve_num,
++- .syscall_rewrite = abi_syscall_rewrite,
++- .rule_add = abi_rule_add,
+++ .syscall_resolve_name = mips_syscall_resolve_name_munge,
+++ .syscall_resolve_num = mips_syscall_resolve_num_munge,
+++ .syscall_rewrite = mips_syscall_rewrite,
+++ .rule_add = mips_rule_add,
++ };
++
++ const struct arch_def arch_def_mipsel = {
++@@ -54,12 +566,8 @@ const struct arch_def arch_def_mipsel = {
++ .token_bpf = AUDIT_ARCH_MIPSEL,
++ .size = ARCH_SIZE_32,
++ .endian = ARCH_ENDIAN_LITTLE,
++- .sys_socketcall = __mips_NR_socketcall,
++- .sys_ipc = __mips_NR_ipc,
++- .syscall_resolve_name = abi_syscall_resolve_name_munge,
++- .syscall_resolve_name_raw = mips_syscall_resolve_name,
++- .syscall_resolve_num = abi_syscall_resolve_num_munge,
++- .syscall_resolve_num_raw = mips_syscall_resolve_num,
++- .syscall_rewrite = abi_syscall_rewrite,
++- .rule_add = abi_rule_add,
+++ .syscall_resolve_name = mips_syscall_resolve_name_munge,
+++ .syscall_resolve_num = mips_syscall_resolve_num_munge,
+++ .syscall_rewrite = mips_syscall_rewrite,
+++ .rule_add = mips_rule_add,
++ };
++diff --git a/src/arch-mips64.c b/src/arch-mips64.c
++--- a/src/arch-mips64.c
+++++ b/src/arch-mips64.c
++@@ -30,7 +30,6 @@
++
++ /**
++ * Resolve a syscall name to a number
++- * @param arch the architecture definition
++ * @param name the syscall name
++ *
++ * Resolve the given syscall name to the syscall number using the syscall table.
++@@ -38,13 +37,12 @@
++ * numbers; returns __NR_SCMP_ERROR on failure.
++ *
++ */
++-int mips64_syscall_resolve_name_munge(const struct arch_def *arch,
++- const char *name)
+++int mips64_syscall_resolve_name_munge(const char *name)
++ {
++ int sys;
++
++ /* NOTE: we don't want to modify the pseudo-syscall numbers */
++- sys = arch->syscall_resolve_name_raw(name);
+++ sys = mips64_syscall_resolve_name(name);
++ if (sys == __NR_SCMP_ERROR || sys < 0)
++ return sys;
++
++@@ -53,7 +51,6 @@ int mips64_syscall_resolve_name_munge(const struct arch_def *arch,
++
++ /**
++ * Resolve a syscall number to a name
++- * @param arch the architecture definition
++ * @param num the syscall number
++ *
++ * Resolve the given syscall number to the syscall name using the syscall table.
++@@ -61,13 +58,12 @@ int mips64_syscall_resolve_name_munge(const struct arch_def *arch,
++ * syscall names; returns NULL on failure.
++ *
++ */
++-const char *mips64_syscall_resolve_num_munge(const struct arch_def *arch,
++- int num)
+++const char *mips64_syscall_resolve_num_munge(int num)
++ {
++ /* NOTE: we don't want to modify the pseudo-syscall numbers */
++ if (num >= __SCMP_NR_BASE)
++ num -= __SCMP_NR_BASE;
++- return arch->syscall_resolve_num_raw(num);
+++ return mips64_syscall_resolve_num(num);
++ }
++
++ const struct arch_def arch_def_mips64 = {
++@@ -76,9 +72,7 @@ const struct arch_def arch_def_mips64 = {
++ .size = ARCH_SIZE_64,
++ .endian = ARCH_ENDIAN_BIG,
++ .syscall_resolve_name = mips64_syscall_resolve_name_munge,
++- .syscall_resolve_name_raw = mips64_syscall_resolve_name,
++ .syscall_resolve_num = mips64_syscall_resolve_num_munge,
++- .syscall_resolve_num_raw = mips64_syscall_resolve_num,
++ .syscall_rewrite = NULL,
++ .rule_add = NULL,
++ };
++@@ -89,9 +83,7 @@ const struct arch_def arch_def_mipsel64 = {
++ .size = ARCH_SIZE_64,
++ .endian = ARCH_ENDIAN_LITTLE,
++ .syscall_resolve_name = mips64_syscall_resolve_name_munge,
++- .syscall_resolve_name_raw = mips64_syscall_resolve_name,
++ .syscall_resolve_num = mips64_syscall_resolve_num_munge,
++- .syscall_resolve_num_raw = mips64_syscall_resolve_num,
++ .syscall_rewrite = NULL,
++ .rule_add = NULL,
++ };
++diff --git a/src/arch-mips64n32.c b/src/arch-mips64n32.c
++--- a/src/arch-mips64n32.c
+++++ b/src/arch-mips64n32.c
++@@ -32,7 +32,6 @@
++
++ /**
++ * Resolve a syscall name to a number
++- * @param arch the architecture definition
++ * @param name the syscall name
++ *
++ * Resolve the given syscall name to the syscall number using the syscall table.
++@@ -40,8 +39,7 @@
++ * numbers; returns __NR_SCMP_ERROR on failure.
++ *
++ */
++-int mips64n32_syscall_resolve_name_munge(const struct arch_def *arch,
++- const char *name)
+++int mips64n32_syscall_resolve_name_munge(const char *name)
++ {
++ int sys;
++
++@@ -55,7 +53,6 @@ int mips64n32_syscall_resolve_name_munge(const struct arch_def *arch,
++
++ /**
++ * Resolve a syscall number to a name
++- * @param arch the architecture definition
++ * @param num the syscall number
++ *
++ * Resolve the given syscall number to the syscall name using the syscall table.
++@@ -63,8 +60,7 @@ int mips64n32_syscall_resolve_name_munge(const struct arch_def *arch,
++ * syscall names; returns NULL on failure.
++ *
++ */
++-const char *mips64n32_syscall_resolve_num_munge(const struct arch_def *arch,
++- int num)
+++const char *mips64n32_syscall_resolve_num_munge(int num)
++ {
++ /* NOTE: we don't want to modify the pseudo-syscall numbers */
++ if (num >= __SCMP_NR_BASE)
++@@ -78,9 +74,7 @@ const struct arch_def arch_def_mips64n32 = {
++ .size = ARCH_SIZE_32,
++ .endian = ARCH_ENDIAN_BIG,
++ .syscall_resolve_name = mips64n32_syscall_resolve_name_munge,
++- .syscall_resolve_name_raw = mips64n32_syscall_resolve_name,
++ .syscall_resolve_num = mips64n32_syscall_resolve_num_munge,
++- .syscall_resolve_num_raw = mips64n32_syscall_resolve_num,
++ .syscall_rewrite = NULL,
++ .rule_add = NULL,
++ };
++@@ -91,9 +85,7 @@ const struct arch_def arch_def_mipsel64n32 = {
++ .size = ARCH_SIZE_32,
++ .endian = ARCH_ENDIAN_LITTLE,
++ .syscall_resolve_name = mips64n32_syscall_resolve_name_munge,
++- .syscall_resolve_name_raw = mips64n32_syscall_resolve_name,
++ .syscall_resolve_num = mips64n32_syscall_resolve_num_munge,
++- .syscall_resolve_num_raw = mips64n32_syscall_resolve_num,
++ .syscall_rewrite = NULL,
++ .rule_add = NULL,
++ };
++diff --git a/src/arch-parisc.c b/src/arch-parisc.c
++--- a/src/arch-parisc.c
+++++ b/src/arch-parisc.c
++@@ -15,8 +15,8 @@ const struct arch_def arch_def_parisc = {
++ .token_bpf = AUDIT_ARCH_PARISC,
++ .size = ARCH_SIZE_32,
++ .endian = ARCH_ENDIAN_BIG,
++- .syscall_resolve_name_raw = parisc_syscall_resolve_name,
++- .syscall_resolve_num_raw = parisc_syscall_resolve_num,
+++ .syscall_resolve_name = parisc_syscall_resolve_name,
+++ .syscall_resolve_num = parisc_syscall_resolve_num,
++ .syscall_rewrite = NULL,
++ .rule_add = NULL,
++ };
++diff --git a/src/arch-parisc64.c b/src/arch-parisc64.c
++--- a/src/arch-parisc64.c
+++++ b/src/arch-parisc64.c
++@@ -15,8 +15,8 @@ const struct arch_def arch_def_parisc64 = {
++ .token_bpf = AUDIT_ARCH_PARISC64,
++ .size = ARCH_SIZE_64,
++ .endian = ARCH_ENDIAN_BIG,
++- .syscall_resolve_name_raw = parisc64_syscall_resolve_name,
++- .syscall_resolve_num_raw = parisc64_syscall_resolve_num,
+++ .syscall_resolve_name = parisc64_syscall_resolve_name,
+++ .syscall_resolve_num = parisc64_syscall_resolve_num,
++ .syscall_rewrite = NULL,
++ .rule_add = NULL,
++ };
++diff --git a/src/arch-ppc.c b/src/arch-ppc.c
++--- a/src/arch-ppc.c
+++++ b/src/arch-ppc.c
++@@ -34,17 +34,526 @@
++ #define __ppc_NR_socketcall 102
++ #define __ppc_NR_ipc 117
++
+++/**
+++ * Resolve a syscall name to a number
+++ * @param name the syscall name
+++ *
+++ * Resolve the given syscall name to the syscall number using the syscall table.
+++ * Returns the syscall number on success, including negative pseudo syscall
+++ * numbers; returns __NR_SCMP_ERROR on failure.
+++ *
+++ */
+++int ppc_syscall_resolve_name_munge(const char *name)
+++{
+++
+++#define _ABI_SYSCALL_RES_NAME_CHK(NAME) \
+++ if (!strcmp(name, #NAME)) return __PNR_##NAME;
+++
+++ _ABI_SYSCALL_RES_NAME_CHK(socket)
+++ _ABI_SYSCALL_RES_NAME_CHK(bind)
+++ _ABI_SYSCALL_RES_NAME_CHK(connect)
+++ _ABI_SYSCALL_RES_NAME_CHK(listen)
+++ _ABI_SYSCALL_RES_NAME_CHK(accept)
+++ _ABI_SYSCALL_RES_NAME_CHK(getsockname)
+++ _ABI_SYSCALL_RES_NAME_CHK(getpeername)
+++ _ABI_SYSCALL_RES_NAME_CHK(socketpair)
+++ _ABI_SYSCALL_RES_NAME_CHK(send)
+++ _ABI_SYSCALL_RES_NAME_CHK(recv)
+++ _ABI_SYSCALL_RES_NAME_CHK(sendto)
+++ _ABI_SYSCALL_RES_NAME_CHK(recvfrom)
+++ _ABI_SYSCALL_RES_NAME_CHK(shutdown)
+++ _ABI_SYSCALL_RES_NAME_CHK(setsockopt)
+++ _ABI_SYSCALL_RES_NAME_CHK(getsockopt)
+++ _ABI_SYSCALL_RES_NAME_CHK(sendmsg)
+++ _ABI_SYSCALL_RES_NAME_CHK(recvmsg)
+++ _ABI_SYSCALL_RES_NAME_CHK(accept4)
+++ _ABI_SYSCALL_RES_NAME_CHK(recvmmsg)
+++ _ABI_SYSCALL_RES_NAME_CHK(sendmmsg)
+++ _ABI_SYSCALL_RES_NAME_CHK(semop)
+++ _ABI_SYSCALL_RES_NAME_CHK(semget)
+++ _ABI_SYSCALL_RES_NAME_CHK(semctl)
+++ _ABI_SYSCALL_RES_NAME_CHK(semtimedop)
+++ _ABI_SYSCALL_RES_NAME_CHK(msgsnd)
+++ _ABI_SYSCALL_RES_NAME_CHK(msgrcv)
+++ _ABI_SYSCALL_RES_NAME_CHK(msgget)
+++ _ABI_SYSCALL_RES_NAME_CHK(msgctl)
+++ _ABI_SYSCALL_RES_NAME_CHK(shmat)
+++ _ABI_SYSCALL_RES_NAME_CHK(shmdt)
+++ _ABI_SYSCALL_RES_NAME_CHK(shmget)
+++ _ABI_SYSCALL_RES_NAME_CHK(shmctl)
+++
+++ return ppc_syscall_resolve_name(name);
+++}
+++
+++/**
+++ * Resolve a syscall number to a name
+++ * @param num the syscall number
+++ *
+++ * Resolve the given syscall number to the syscall name using the syscall table.
+++ * Returns a pointer to the syscall name string on success, including pseudo
+++ * syscall names; returns NULL on failure.
+++ *
+++ */
+++const char *ppc_syscall_resolve_num_munge(int num)
+++{
+++
+++#define _ABI_SYSCALL_RES_NUM_CHK(NAME) \
+++ if (num == __PNR_##NAME) return #NAME;
+++
+++ _ABI_SYSCALL_RES_NUM_CHK(socket)
+++ _ABI_SYSCALL_RES_NUM_CHK(bind)
+++ _ABI_SYSCALL_RES_NUM_CHK(connect)
+++ _ABI_SYSCALL_RES_NUM_CHK(listen)
+++ _ABI_SYSCALL_RES_NUM_CHK(accept)
+++ _ABI_SYSCALL_RES_NUM_CHK(getsockname)
+++ _ABI_SYSCALL_RES_NUM_CHK(getpeername)
+++ _ABI_SYSCALL_RES_NUM_CHK(socketpair)
+++ _ABI_SYSCALL_RES_NUM_CHK(send)
+++ _ABI_SYSCALL_RES_NUM_CHK(recv)
+++ _ABI_SYSCALL_RES_NUM_CHK(sendto)
+++ _ABI_SYSCALL_RES_NUM_CHK(recvfrom)
+++ _ABI_SYSCALL_RES_NUM_CHK(shutdown)
+++ _ABI_SYSCALL_RES_NUM_CHK(setsockopt)
+++ _ABI_SYSCALL_RES_NUM_CHK(getsockopt)
+++ _ABI_SYSCALL_RES_NUM_CHK(sendmsg)
+++ _ABI_SYSCALL_RES_NUM_CHK(recvmsg)
+++ _ABI_SYSCALL_RES_NUM_CHK(accept4)
+++ _ABI_SYSCALL_RES_NUM_CHK(recvmmsg)
+++ _ABI_SYSCALL_RES_NUM_CHK(sendmmsg)
+++ _ABI_SYSCALL_RES_NUM_CHK(semop)
+++ _ABI_SYSCALL_RES_NUM_CHK(semget)
+++ _ABI_SYSCALL_RES_NUM_CHK(semctl)
+++ _ABI_SYSCALL_RES_NUM_CHK(semtimedop)
+++ _ABI_SYSCALL_RES_NUM_CHK(msgsnd)
+++ _ABI_SYSCALL_RES_NUM_CHK(msgrcv)
+++ _ABI_SYSCALL_RES_NUM_CHK(msgget)
+++ _ABI_SYSCALL_RES_NUM_CHK(msgctl)
+++ _ABI_SYSCALL_RES_NUM_CHK(shmat)
+++ _ABI_SYSCALL_RES_NUM_CHK(shmdt)
+++ _ABI_SYSCALL_RES_NUM_CHK(shmget)
+++ _ABI_SYSCALL_RES_NUM_CHK(shmctl)
+++
+++ return ppc_syscall_resolve_num(num);
+++}
+++
+++/**
+++ * Check if a syscall is a socket syscall
+++ * @param sys the syscall number
+++ *
+++ * Returns true if the syscall is a socket related syscall, false otherwise.
+++ *
+++ */
+++static bool _ppc_syscall_socket_test(int sys)
+++{
+++ const char *name;
+++
+++ /* multiplexed pseduo-syscalls */
+++ if (sys <= -100 && sys >= -120)
+++ return true;
+++
+++ name = ppc_syscall_resolve_num(sys);
+++ if (!name)
+++ return false;
+++
+++#define _ABI_SYSCALL_SOCK_CHK(NAME) \
+++ if (!strcmp(name, #NAME)) return true;
+++
+++ _ABI_SYSCALL_SOCK_CHK(socket)
+++ _ABI_SYSCALL_SOCK_CHK(bind)
+++ _ABI_SYSCALL_SOCK_CHK(connect)
+++ _ABI_SYSCALL_SOCK_CHK(listen)
+++ _ABI_SYSCALL_SOCK_CHK(accept)
+++ _ABI_SYSCALL_SOCK_CHK(getsockname)
+++ _ABI_SYSCALL_SOCK_CHK(getpeername)
+++ _ABI_SYSCALL_SOCK_CHK(socketpair)
+++ _ABI_SYSCALL_SOCK_CHK(send)
+++ _ABI_SYSCALL_SOCK_CHK(recv)
+++ _ABI_SYSCALL_SOCK_CHK(sendto)
+++ _ABI_SYSCALL_SOCK_CHK(recvfrom)
+++ _ABI_SYSCALL_SOCK_CHK(shutdown)
+++ _ABI_SYSCALL_SOCK_CHK(setsockopt)
+++ _ABI_SYSCALL_SOCK_CHK(getsockopt)
+++ _ABI_SYSCALL_SOCK_CHK(sendmsg)
+++ _ABI_SYSCALL_SOCK_CHK(recvmsg)
+++ _ABI_SYSCALL_SOCK_CHK(accept4)
+++ _ABI_SYSCALL_SOCK_CHK(recvmmsg)
+++ _ABI_SYSCALL_SOCK_CHK(sendmmsg)
+++
+++ return false;
+++}
+++
+++/**
+++ * Check if a syscall is an ipc syscall
+++ * @param sys the syscall number
+++ *
+++ * Returns true if the syscall is an ipc related syscall, false otherwise.
+++ *
+++ */
+++static bool _ppc_syscall_ipc_test(int sys)
+++{
+++ const char *name;
+++
+++ /* multiplexed pseduo-syscalls */
+++ if (sys <= -200 && sys >= -224)
+++ return true;
+++
+++ name = ppc_syscall_resolve_num(sys);
+++ if (!name)
+++ return false;
+++
+++#define _ABI_SYSCALL_IPC_CHK(NAME) \
+++ if (!strcmp(name, #NAME)) return true;
+++
+++ _ABI_SYSCALL_IPC_CHK(semop)
+++ _ABI_SYSCALL_IPC_CHK(semget)
+++ _ABI_SYSCALL_IPC_CHK(semctl)
+++ _ABI_SYSCALL_IPC_CHK(semtimedop)
+++ _ABI_SYSCALL_IPC_CHK(msgsnd)
+++ _ABI_SYSCALL_IPC_CHK(msgrcv)
+++ _ABI_SYSCALL_IPC_CHK(msgget)
+++ _ABI_SYSCALL_IPC_CHK(msgctl)
+++ _ABI_SYSCALL_IPC_CHK(shmat)
+++ _ABI_SYSCALL_IPC_CHK(shmdt)
+++ _ABI_SYSCALL_IPC_CHK(shmget)
+++ _ABI_SYSCALL_IPC_CHK(shmctl)
+++
+++ return false;
+++}
+++
+++/**
+++ * Convert a multiplexed pseudo syscall into a direct syscall
+++ * @param syscall the multiplexed pseudo syscall number
+++ *
+++ * Return the related direct syscall number, __NR_SCMP_UNDEF is there is
+++ * no related syscall, or __NR_SCMP_ERROR otherwise.
+++ *
+++ */
+++static int _ppc_syscall_demux(int syscall)
+++{
+++ int sys = __NR_SCMP_UNDEF;
+++
+++#define _ABI_SYSCALL_DEMUX_CHK(NAME) \
+++case __PNR_##NAME: \
+++ sys = ppc_syscall_resolve_name(#NAME); break;
+++
+++ switch (syscall) {
+++ _ABI_SYSCALL_DEMUX_CHK(socket)
+++ _ABI_SYSCALL_DEMUX_CHK(bind)
+++ _ABI_SYSCALL_DEMUX_CHK(connect)
+++ _ABI_SYSCALL_DEMUX_CHK(listen)
+++ _ABI_SYSCALL_DEMUX_CHK(accept)
+++ _ABI_SYSCALL_DEMUX_CHK(getsockname)
+++ _ABI_SYSCALL_DEMUX_CHK(getpeername)
+++ _ABI_SYSCALL_DEMUX_CHK(socketpair)
+++ _ABI_SYSCALL_DEMUX_CHK(send)
+++ _ABI_SYSCALL_DEMUX_CHK(recv)
+++ _ABI_SYSCALL_DEMUX_CHK(sendto)
+++ _ABI_SYSCALL_DEMUX_CHK(recvfrom)
+++ _ABI_SYSCALL_DEMUX_CHK(shutdown)
+++ _ABI_SYSCALL_DEMUX_CHK(setsockopt)
+++ _ABI_SYSCALL_DEMUX_CHK(getsockopt)
+++ _ABI_SYSCALL_DEMUX_CHK(sendmsg)
+++ _ABI_SYSCALL_DEMUX_CHK(recvmsg)
+++ _ABI_SYSCALL_DEMUX_CHK(accept4)
+++ _ABI_SYSCALL_DEMUX_CHK(recvmmsg)
+++ _ABI_SYSCALL_DEMUX_CHK(sendmmsg)
+++ _ABI_SYSCALL_DEMUX_CHK(semop)
+++ _ABI_SYSCALL_DEMUX_CHK(semget)
+++ _ABI_SYSCALL_DEMUX_CHK(semctl)
+++ _ABI_SYSCALL_DEMUX_CHK(semtimedop)
+++ _ABI_SYSCALL_DEMUX_CHK(msgsnd)
+++ _ABI_SYSCALL_DEMUX_CHK(msgrcv)
+++ _ABI_SYSCALL_DEMUX_CHK(msgget)
+++ _ABI_SYSCALL_DEMUX_CHK(msgctl)
+++ _ABI_SYSCALL_DEMUX_CHK(shmat)
+++ _ABI_SYSCALL_DEMUX_CHK(shmdt)
+++ _ABI_SYSCALL_DEMUX_CHK(shmget)
+++ _ABI_SYSCALL_DEMUX_CHK(shmctl)
+++ }
+++
+++ /* this looks odd because the arch resolver returns _ERROR if it can't
+++ * resolve the syscall, but we want to use _UNDEF for that, so we set
+++ * 'sys' to a sentinel value of _UNDEF and if it is error here we know
+++ * the resolve failed to find a match */
+++ if (sys == __NR_SCMP_UNDEF)
+++ sys = __NR_SCMP_ERROR;
+++ else if (sys == __NR_SCMP_ERROR)
+++ sys = __NR_SCMP_UNDEF;
+++
+++ return sys;
+++}
+++
+++/**
+++ * Convert a direct syscall into multiplexed pseudo socket syscall
+++ * @param syscall the direct syscall
+++ *
+++ * Return the related multiplexed pseduo syscall number, __NR_SCMP_UNDEF is
+++ * there is no related pseudo syscall, or __NR_SCMP_ERROR otherwise.
+++ *
+++ */
+++static int _ppc_syscall_mux(int syscall)
+++{
+++ const char *sys;
+++
+++ sys = ppc_syscall_resolve_num(syscall);
+++ if (!sys)
+++ return __NR_SCMP_ERROR;
+++
+++#define _ABI_SYSCALL_MUX_CHK(NAME) \
+++ if (!strcmp(sys, #NAME)) return __PNR_##NAME;
+++
+++ _ABI_SYSCALL_MUX_CHK(socket)
+++ _ABI_SYSCALL_MUX_CHK(bind)
+++ _ABI_SYSCALL_MUX_CHK(connect)
+++ _ABI_SYSCALL_MUX_CHK(listen)
+++ _ABI_SYSCALL_MUX_CHK(accept)
+++ _ABI_SYSCALL_MUX_CHK(getsockname)
+++ _ABI_SYSCALL_MUX_CHK(getpeername)
+++ _ABI_SYSCALL_MUX_CHK(socketpair)
+++ _ABI_SYSCALL_MUX_CHK(send)
+++ _ABI_SYSCALL_MUX_CHK(recv)
+++ _ABI_SYSCALL_MUX_CHK(sendto)
+++ _ABI_SYSCALL_MUX_CHK(recvfrom)
+++ _ABI_SYSCALL_MUX_CHK(shutdown)
+++ _ABI_SYSCALL_MUX_CHK(setsockopt)
+++ _ABI_SYSCALL_MUX_CHK(getsockopt)
+++ _ABI_SYSCALL_MUX_CHK(sendmsg)
+++ _ABI_SYSCALL_MUX_CHK(recvmsg)
+++ _ABI_SYSCALL_MUX_CHK(accept4)
+++ _ABI_SYSCALL_MUX_CHK(recvmmsg)
+++ _ABI_SYSCALL_MUX_CHK(sendmmsg)
+++ _ABI_SYSCALL_MUX_CHK(semop)
+++ _ABI_SYSCALL_MUX_CHK(semget)
+++ _ABI_SYSCALL_MUX_CHK(semctl)
+++ _ABI_SYSCALL_MUX_CHK(semtimedop)
+++ _ABI_SYSCALL_MUX_CHK(msgsnd)
+++ _ABI_SYSCALL_MUX_CHK(msgrcv)
+++ _ABI_SYSCALL_MUX_CHK(msgget)
+++ _ABI_SYSCALL_MUX_CHK(msgctl)
+++ _ABI_SYSCALL_MUX_CHK(shmat)
+++ _ABI_SYSCALL_MUX_CHK(shmdt)
+++ _ABI_SYSCALL_MUX_CHK(shmget)
+++ _ABI_SYSCALL_MUX_CHK(shmctl)
+++
+++ return __NR_SCMP_ERROR;
+++}
+++
+++/**
+++ * Rewrite a syscall value to match the architecture
+++ * @param syscall the syscall number
+++ *
+++ * Syscalls can vary across different architectures so this function rewrites
+++ * the syscall into the correct value for the specified architecture. Returns
+++ * zero on success, negative values on failure.
+++ *
+++ */
+++int ppc_syscall_rewrite(int *syscall)
+++{
+++ int sys = *syscall;
+++
+++ if (sys <= -100 && sys >= -120)
+++ *syscall = __ppc_NR_socketcall;
+++ else if (sys <= -200 && sys >= -224)
+++ *syscall = __ppc_NR_ipc;
+++ else if (sys < 0)
+++ return -EDOM;
+++
+++ return 0;
+++}
+++
+++/**
+++ * add a new rule to the ppc seccomp filter
+++ * @param db the seccomp filter db
+++ * @param rule the filter rule
+++ *
+++ * This function adds a new syscall filter to the seccomp filter db, making any
+++ * necessary adjustments for the ppc ABI. Returns zero on success, negative
+++ * values on failure.
+++ *
+++ * It is important to note that in the case of failure the db may be corrupted,
+++ * the caller must use the transaction mechanism if the db integrity is
+++ * important.
+++ *
+++ */
+++int ppc_rule_add(struct db_filter *db, struct db_api_rule_list *rule)
+++{
+++ int rc = 0;
+++ unsigned int iter;
+++ int sys = rule->syscall;
+++ int sys_a, sys_b;
+++ struct db_api_rule_list *rule_a, *rule_b, *rule_dup = NULL;
+++
+++ if (_ppc_syscall_socket_test(sys)) {
+++ /* socket syscalls */
+++
+++ /* strict check for the multiplexed socket syscalls */
+++ for (iter = 0; iter < ARG_COUNT_MAX; iter++) {
+++ if ((rule->args[iter].valid != 0) && (rule->strict)) {
+++ rc = -EINVAL;
+++ goto add_return;
+++ }
+++ }
+++
+++ /* determine both the muxed and direct syscall numbers */
+++ if (sys > 0) {
+++ sys_a = _ppc_syscall_mux(sys);
+++ if (sys_a == __NR_SCMP_ERROR) {
+++ rc = __NR_SCMP_ERROR;
+++ goto add_return;
+++ }
+++ sys_b = sys;
+++ } else {
+++ sys_a = sys;
+++ sys_b = _ppc_syscall_demux(sys);
+++ if (sys_b == __NR_SCMP_ERROR) {
+++ rc = __NR_SCMP_ERROR;
+++ goto add_return;
+++ }
+++ }
+++
+++ /* use rule_a for the multiplexed syscall and use rule_b for
+++ * the direct wired syscall */
+++
+++ if (sys_a == __NR_SCMP_UNDEF) {
+++ rule_a = NULL;
+++ rule_b = rule;
+++ } else if (sys_b == __NR_SCMP_UNDEF) {
+++ rule_a = rule;
+++ rule_b = NULL;
+++ } else {
+++ /* need two rules, dup the first and link together */
+++ rule_a = rule;
+++ rule_dup = db_rule_dup(rule_a);
+++ rule_b = rule_dup;
+++ if (rule_b == NULL)
+++ goto add_return;
+++ rule_b->prev = rule_a;
+++ rule_b->next = NULL;
+++ rule_a->next = rule_b;
+++ }
+++
+++ /* multiplexed socket syscalls */
+++ if (rule_a != NULL) {
+++ rule_a->syscall = __ppc_NR_socketcall;
+++ rule_a->args[0].arg = 0;
+++ rule_a->args[0].op = SCMP_CMP_EQ;
+++ rule_a->args[0].mask = DATUM_MAX;
+++ rule_a->args[0].datum = (-sys_a) % 100;
+++ rule_a->args[0].valid = 1;
+++ }
+++
+++ /* direct wired socket syscalls */
+++ if (rule_b != NULL)
+++ rule_b->syscall = sys_b;
+++
+++ /* we should be protected by a transaction checkpoint */
+++ if (rule_a != NULL) {
+++ rc = db_rule_add(db, rule_a);
+++ if (rc < 0)
+++ goto add_return;
+++ }
+++ if (rule_b != NULL) {
+++ rc = db_rule_add(db, rule_b);
+++ if (rc < 0)
+++ goto add_return;
+++ }
+++ } else if (_ppc_syscall_ipc_test(sys)) {
+++ /* ipc syscalls */
+++
+++ /* strict check for the multiplexed socket syscalls */
+++ for (iter = 0; iter < ARG_COUNT_MAX; iter++) {
+++ if ((rule->args[iter].valid != 0) && (rule->strict)) {
+++ rc = -EINVAL;
+++ goto add_return;
+++ }
+++ }
+++
+++ /* determine both the muxed and direct syscall numbers */
+++ if (sys > 0) {
+++ sys_a = _ppc_syscall_mux(sys);
+++ if (sys_a == __NR_SCMP_ERROR) {
+++ rc = __NR_SCMP_ERROR;
+++ goto add_return;
+++ }
+++ sys_b = sys;
+++ } else {
+++ sys_a = sys;
+++ sys_b = _ppc_syscall_demux(sys);
+++ if (sys_b == __NR_SCMP_ERROR) {
+++ rc = __NR_SCMP_ERROR;
+++ goto add_return;
+++ }
+++ }
+++
+++ /* use rule_a for the multiplexed syscall and use rule_b for
+++ * the direct wired syscall */
+++
+++ if (sys_a == __NR_SCMP_UNDEF) {
+++ rule_a = NULL;
+++ rule_b = rule;
+++ } else if (sys_b == __NR_SCMP_UNDEF) {
+++ rule_a = rule;
+++ rule_b = NULL;
+++ } else {
+++ /* need two rules, dup the first and link together */
+++ rule_a = rule;
+++ rule_dup = db_rule_dup(rule_a);
+++ rule_b = rule_dup;
+++ if (rule_b == NULL)
+++ goto add_return;
+++ rule_b->prev = rule_a;
+++ rule_b->next = NULL;
+++ rule_a->next = rule_b;
+++ }
+++
+++ /* multiplexed socket syscalls */
+++ if (rule_a != NULL) {
+++ rule_a->syscall = __ppc_NR_ipc;
+++ rule_a->args[0].arg = 0;
+++ rule_a->args[0].op = SCMP_CMP_EQ;
+++ rule_a->args[0].mask = DATUM_MAX;
+++ rule_a->args[0].datum = (-sys_a) % 200;
+++ rule_a->args[0].valid = 1;
+++ }
+++
+++ /* direct wired socket syscalls */
+++ if (rule_b != NULL)
+++ rule_b->syscall = sys_b;
+++
+++ /* we should be protected by a transaction checkpoint */
+++ if (rule_a != NULL) {
+++ rc = db_rule_add(db, rule_a);
+++ if (rc < 0)
+++ goto add_return;
+++ }
+++ if (rule_b != NULL) {
+++ rc = db_rule_add(db, rule_b);
+++ if (rc < 0)
+++ goto add_return;
+++ }
+++ } else if (sys >= 0) {
+++ /* normal syscall processing */
+++ rc = db_rule_add(db, rule);
+++ if (rc < 0)
+++ goto add_return;
+++ } else if (rule->strict) {
+++ rc = -EDOM;
+++ goto add_return;
+++ }
+++
+++add_return:
+++ if (rule_dup != NULL)
+++ free(rule_dup);
+++ return rc;
+++}
+++
++ const struct arch_def arch_def_ppc = {
++ .token = SCMP_ARCH_PPC,
++ .token_bpf = AUDIT_ARCH_PPC,
++ .size = ARCH_SIZE_32,
++ .endian = ARCH_ENDIAN_BIG,
++- .sys_socketcall = __ppc_NR_socketcall,
++- .sys_ipc = __ppc_NR_ipc,
++- .syscall_resolve_name = abi_syscall_resolve_name_munge,
++- .syscall_resolve_name_raw = ppc_syscall_resolve_name,
++- .syscall_resolve_num = abi_syscall_resolve_num_munge,
++- .syscall_resolve_num_raw = ppc_syscall_resolve_num,
++- .syscall_rewrite = abi_syscall_rewrite,
++- .rule_add = abi_rule_add,
+++ .syscall_resolve_name = ppc_syscall_resolve_name_munge,
+++ .syscall_resolve_num = ppc_syscall_resolve_num_munge,
+++ .syscall_rewrite = ppc_syscall_rewrite,
+++ .rule_add = ppc_rule_add,
++ };
++diff --git a/src/arch-ppc64.c b/src/arch-ppc64.c
++--- a/src/arch-ppc64.c
+++++ b/src/arch-ppc64.c
++@@ -26,7 +26,6 @@
++ #include <linux/audit.h>
++
++ #include "db.h"
++-#include "syscalls.h"
++ #include "arch.h"
++ #include "arch-ppc64.h"
++
++@@ -34,19 +33,605 @@
++ #define __ppc64_NR_socketcall 102
++ #define __ppc64_NR_ipc 117
++
+++/**
+++ * Resolve a syscall name to a number
+++ * @param name the syscall name
+++ *
+++ * Resolve the given syscall name to the syscall number using the syscall table.
+++ * Returns the syscall number on success, including negative pseudo syscall
+++ * numbers; returns __NR_SCMP_ERROR on failure.
+++ *
+++ */
+++int ppc64_syscall_resolve_name_munge(const char *name)
+++{
+++ if (strcmp(name, "accept") == 0)
+++ return __PNR_accept;
+++ if (strcmp(name, "accept4") == 0)
+++ return __PNR_accept4;
+++ else if (strcmp(name, "bind") == 0)
+++ return __PNR_bind;
+++ else if (strcmp(name, "connect") == 0)
+++ return __PNR_connect;
+++ else if (strcmp(name, "getpeername") == 0)
+++ return __PNR_getpeername;
+++ else if (strcmp(name, "getsockname") == 0)
+++ return __PNR_getsockname;
+++ else if (strcmp(name, "getsockopt") == 0)
+++ return __PNR_getsockopt;
+++ else if (strcmp(name, "listen") == 0)
+++ return __PNR_listen;
+++ else if (strcmp(name, "msgctl") == 0)
+++ return __PNR_msgctl;
+++ else if (strcmp(name, "msgget") == 0)
+++ return __PNR_msgget;
+++ else if (strcmp(name, "msgrcv") == 0)
+++ return __PNR_msgrcv;
+++ else if (strcmp(name, "msgsnd") == 0)
+++ return __PNR_msgsnd;
+++ else if (strcmp(name, "recv") == 0)
+++ return __PNR_recv;
+++ else if (strcmp(name, "recvfrom") == 0)
+++ return __PNR_recvfrom;
+++ else if (strcmp(name, "recvmsg") == 0)
+++ return __PNR_recvmsg;
+++ else if (strcmp(name, "recvmmsg") == 0)
+++ return __PNR_recvmmsg;
+++ else if (strcmp(name, "semctl") == 0)
+++ return __PNR_semctl;
+++ else if (strcmp(name, "semget") == 0)
+++ return __PNR_semget;
+++ else if (strcmp(name, "semtimedop") == 0)
+++ return __PNR_semtimedop;
+++ else if (strcmp(name, "send") == 0)
+++ return __PNR_send;
+++ else if (strcmp(name, "sendmsg") == 0)
+++ return __PNR_sendmsg;
+++ else if (strcmp(name, "sendmmsg") == 0)
+++ return __PNR_sendmmsg;
+++ else if (strcmp(name, "sendto") == 0)
+++ return __PNR_sendto;
+++ else if (strcmp(name, "setsockopt") == 0)
+++ return __PNR_setsockopt;
+++ else if (strcmp(name, "shmat") == 0)
+++ return __PNR_shmat;
+++ else if (strcmp(name, "shmdt") == 0)
+++ return __PNR_shmdt;
+++ else if (strcmp(name, "shmget") == 0)
+++ return __PNR_shmget;
+++ else if (strcmp(name, "shmctl") == 0)
+++ return __PNR_shmctl;
+++ else if (strcmp(name, "shutdown") == 0)
+++ return __PNR_shutdown;
+++ else if (strcmp(name, "socket") == 0)
+++ return __PNR_socket;
+++ else if (strcmp(name, "socketpair") == 0)
+++ return __PNR_socketpair;
+++
+++ return ppc64_syscall_resolve_name(name);
+++}
+++
+++/**
+++ * Resolve a syscall number to a name
+++ * @param num the syscall number
+++ *
+++ * Resolve the given syscall number to the syscall name using the syscall table.
+++ * Returns a pointer to the syscall name string on success, including pseudo
+++ * syscall names; returns NULL on failure.
+++ *
+++ */
+++const char *ppc64_syscall_resolve_num_munge(int num)
+++{
+++ if (num == __PNR_accept)
+++ return "accept";
+++ else if (num == __PNR_accept4)
+++ return "accept4";
+++ else if (num == __PNR_bind)
+++ return "bind";
+++ else if (num == __PNR_connect)
+++ return "connect";
+++ else if (num == __PNR_getpeername)
+++ return "getpeername";
+++ else if (num == __PNR_getsockname)
+++ return "getsockname";
+++ else if (num == __PNR_getsockopt)
+++ return "getsockopt";
+++ else if (num == __PNR_listen)
+++ return "listen";
+++ else if (num == __PNR_msgctl)
+++ return "msgctl";
+++ else if (num == __PNR_msgget)
+++ return "msgget";
+++ else if (num == __PNR_msgrcv)
+++ return "msgrcv";
+++ else if (num == __PNR_msgsnd)
+++ return "msgsnd";
+++ else if (num == __PNR_recv)
+++ return "recv";
+++ else if (num == __PNR_recvfrom)
+++ return "recvfrom";
+++ else if (num == __PNR_recvmsg)
+++ return "recvmsg";
+++ else if (num == __PNR_recvmmsg)
+++ return "recvmmsg";
+++ else if (num == __PNR_semctl)
+++ return "semctl";
+++ else if (num == __PNR_semget)
+++ return "semget";
+++ else if (num == __PNR_semtimedop)
+++ return "semtimedop";
+++ else if (num == __PNR_send)
+++ return "send";
+++ else if (num == __PNR_sendmsg)
+++ return "sendmsg";
+++ else if (num == __PNR_sendmmsg)
+++ return "sendmmsg";
+++ else if (num == __PNR_sendto)
+++ return "sendto";
+++ else if (num == __PNR_setsockopt)
+++ return "setsockopt";
+++ else if (num == __PNR_shmat)
+++ return "shmat";
+++ else if (num == __PNR_shmdt)
+++ return "shmdt";
+++ else if (num == __PNR_shmget)
+++ return "shmget";
+++ else if (num == __PNR_shmctl)
+++ return "shmctl";
+++ else if (num == __PNR_shutdown)
+++ return "shutdown";
+++ else if (num == __PNR_socket)
+++ return "socket";
+++ else if (num == __PNR_socketpair)
+++ return "socketpair";
+++
+++ return ppc64_syscall_resolve_num(num);
+++}
+++
+++/**
+++ * Convert a multiplexed pseudo socket syscall into a direct syscall
+++ * @param syscall the multiplexed pseudo syscall number
+++ *
+++ * Return the related direct syscall number, __NR_SCMP_UNDEF is there is
+++ * no related syscall, or __NR_SCMP_ERROR otherwise.
+++ *
+++ */
+++static int _ppc64_syscall_demux(int syscall)
+++{
+++ switch (syscall) {
+++ case -101:
+++ /* socket */
+++ return 326;
+++ case -102:
+++ /* bind */
+++ return 327;
+++ case -103:
+++ /* connect */
+++ return 328;
+++ case -104:
+++ /* listen */
+++ return 329;
+++ case -105:
+++ /* accept */
+++ return 330;
+++ case -106:
+++ /* getsockname */
+++ return 331;
+++ case -107:
+++ /* getpeername */
+++ return 332;
+++ case -108:
+++ /* socketpair */
+++ return 333;
+++ case -109:
+++ /* send */
+++ return 334;
+++ case -110:
+++ /* recv */
+++ return 336;
+++ case -111:
+++ /* sendto */
+++ return 335;
+++ case -112:
+++ /* recvfrom */
+++ return 337;
+++ case -113:
+++ /* shutdown */
+++ return 338;
+++ case -114:
+++ /* setsockopt */
+++ return 339;
+++ case -115:
+++ /* getsockopt */
+++ return 340;
+++ case -116:
+++ /* sendmsg */
+++ return 341;
+++ case -117:
+++ /* recvmsg */
+++ return 342;
+++ case -118:
+++ /* accept4 */
+++ return 344;
+++ case -119:
+++ /* recvmmsg */
+++ return 343;
+++ case -120:
+++ /* sendmmsg */
+++ return 349;
+++ case -201:
+++ /* semop - not defined */
+++ return __NR_SCMP_UNDEF;
+++ case -202:
+++ /* semget */
+++ return 393;
+++ case -203:
+++ /* semctl */
+++ return 394;
+++ case -204:
+++ /* semtimedop */
+++ return 392;
+++ case -211:
+++ /* msgsnd */
+++ return 400;
+++ case -212:
+++ /* msgrcv */
+++ return 401;
+++ case -213:
+++ /* msgget */
+++ return 399;
+++ case -214:
+++ /* msgctl */
+++ return 402;
+++ case -221:
+++ /* shmat */
+++ return 397;
+++ case -222:
+++ /* shmdt */
+++ return 398;
+++ case -223:
+++ /* shmget */
+++ return 395;
+++ case -224:
+++ /* shmctl */
+++ return 396;
+++ }
+++
+++ return __NR_SCMP_ERROR;
+++}
+++
+++/**
+++ * Convert a direct socket syscall into multiplexed pseudo socket syscall
+++ * @param syscall the direct syscall
+++ *
+++ * Return the related multiplexed pseduo syscall number, __NR_SCMP_UNDEF is
+++ * there is no related pseudo syscall, or __NR_SCMP_ERROR otherwise.
+++ *
+++ */
+++static int _ppc64_syscall_mux(int syscall)
+++{
+++ switch (syscall) {
+++ case 326:
+++ /* socket */
+++ return -101;
+++ case 327:
+++ /* bind */
+++ return -102;
+++ case 328:
+++ /* connect */
+++ return -103;
+++ case 329:
+++ /* listen */
+++ return -104;
+++ case 330:
+++ /* accept */
+++ return -105;
+++ case 331:
+++ /* getsockname */
+++ return -106;
+++ case 332:
+++ /* getpeername */
+++ return -107;
+++ case 333:
+++ /* socketpair */
+++ return -108;
+++ case 334:
+++ /* send */
+++ return -109;
+++ case 335:
+++ /* sendto */
+++ return -111;
+++ case 336:
+++ /* recv */
+++ return -110;
+++ case 337:
+++ /* recvfrom */
+++ return -112;
+++ case 338:
+++ /* shutdown */
+++ return -113;
+++ case 339:
+++ /* setsockopt */
+++ return -114;
+++ case 340:
+++ /* getsockopt */
+++ return -115;
+++ case 341:
+++ /* sendmsg */
+++ return -116;
+++ case 342:
+++ /* recvmsg */
+++ return -117;
+++ case 343:
+++ /* recvmmsg */
+++ return -119;
+++ case 344:
+++ /* accept4 */
+++ return -118;
+++ case 349:
+++ /* sendmmsg */
+++ return -120;
+++ case 392:
+++ /* semtimedop */
+++ return -204;
+++ case 393:
+++ /* semget */
+++ return -202;
+++ case 394:
+++ /* semctl */
+++ return -203;
+++ case 395:
+++ /* shmget */
+++ return -223;
+++ case 396:
+++ /* shmctl */
+++ return -224;
+++ case 397:
+++ /* shmat */
+++ return -221;
+++ case 398:
+++ /* shmdt */
+++ return -222;
+++ case 399:
+++ /* msgget */
+++ return -213;
+++ case 400:
+++ /* msgsnd */
+++ return -211;
+++ case 401:
+++ /* msgrcv */
+++ return -212;
+++ case 402:
+++ /* msgctl */
+++ return -214;
+++ }
+++
+++ return __NR_SCMP_ERROR;
+++}
+++
+++/**
+++ * Rewrite a syscall value to match the architecture
+++ * @param syscall the syscall number
+++ *
+++ * Syscalls can vary across different architectures so this function rewrites
+++ * the syscall into the correct value for the specified architecture. Returns
+++ * zero on success, negative values on failure.
+++ *
+++ */
+++int ppc64_syscall_rewrite(int *syscall)
+++{
+++ int sys = *syscall;
+++
+++ if (sys <= -100 && sys >= -120)
+++ *syscall = __ppc64_NR_socketcall;
+++ else if (sys <= -200 && sys >= -224)
+++ *syscall = __ppc64_NR_ipc;
+++ else if (sys < 0)
+++ return -EDOM;
+++
+++ return 0;
+++}
+++
+++/**
+++ * add a new rule to the ppc64 seccomp filter
+++ * @param db the seccomp filter db
+++ * @param rule the filter rule
+++ *
+++ * This function adds a new syscall filter to the seccomp filter db, making any
+++ * necessary adjustments for the ppc64 ABI. Returns zero on success, negative
+++ * values on failure.
+++ *
+++ * It is important to note that in the case of failure the db may be corrupted,
+++ * the caller must use the transaction mechanism if the db integrity is
+++ * important.
+++ *
+++ */
+++int ppc64_rule_add(struct db_filter *db, struct db_api_rule_list *rule)
+++{
+++ int rc = 0;
+++ unsigned int iter;
+++ int sys = rule->syscall;
+++ int sys_a, sys_b;
+++ struct db_api_rule_list *rule_a, *rule_b, *rule_dup = NULL;
+++
+++ if ((sys <= -100 && sys >= -120) || (sys >= 326 && sys <= 344) ||
+++ (sys == 349)) {
+++ /* (-100 to -120) : multiplexed socket syscalls
+++ (326 to 344) : direct socket syscalls, Linux 4.3+
+++ (349) : sendmmsg */
+++
+++ /* strict check for the multiplexed socket syscalls */
+++ for (iter = 0; iter < ARG_COUNT_MAX; iter++) {
+++ if ((rule->args[iter].valid != 0) && (rule->strict)) {
+++ rc = -EINVAL;
+++ goto add_return;
+++ }
+++ }
+++
+++ /* determine both the muxed and direct syscall numbers */
+++ if (sys > 0) {
+++ sys_a = _ppc64_syscall_mux(sys);
+++ if (sys_a == __NR_SCMP_ERROR) {
+++ rc = __NR_SCMP_ERROR;
+++ goto add_return;
+++ }
+++ sys_b = sys;
+++ } else {
+++ sys_a = sys;
+++ sys_b = _ppc64_syscall_demux(sys);
+++ if (sys_b == __NR_SCMP_ERROR) {
+++ rc = __NR_SCMP_ERROR;
+++ goto add_return;
+++ }
+++ }
+++
+++ /* use rule_a for the multiplexed syscall and use rule_b for
+++ * the direct wired syscall */
+++
+++ if (sys_a == __NR_SCMP_UNDEF) {
+++ rule_a = NULL;
+++ rule_b = rule;
+++ } else if (sys_b == __NR_SCMP_UNDEF) {
+++ rule_a = rule;
+++ rule_b = NULL;
+++ } else {
+++ /* need two rules, dup the first and link together */
+++ rule_a = rule;
+++ rule_dup = db_rule_dup(rule_a);
+++ rule_b = rule_dup;
+++ if (rule_b == NULL) {
+++ rc = -ENOMEM;
+++ goto add_return;
+++ }
+++ rule_b->prev = rule_a;
+++ rule_b->next = NULL;
+++ rule_a->next = rule_b;
+++ }
+++
+++ /* multiplexed socket syscalls */
+++ if (rule_a != NULL) {
+++ rule_a->syscall = __ppc64_NR_socketcall;
+++ rule_a->args[0].arg = 0;
+++ rule_a->args[0].op = SCMP_CMP_EQ;
+++ rule_a->args[0].mask = DATUM_MAX;
+++ rule_a->args[0].datum = (-sys_a) % 100;
+++ rule_a->args[0].valid = 1;
+++ }
+++
+++ /* direct wired socket syscalls */
+++ if (rule_b != NULL)
+++ rule_b->syscall = sys_b;
+++
+++ /* we should be protected by a transaction checkpoint */
+++ if (rule_a != NULL) {
+++ rc = db_rule_add(db, rule_a);
+++ if (rc < 0)
+++ goto add_return;
+++ }
+++ if (rule_b != NULL) {
+++ rc = db_rule_add(db, rule_b);
+++ if (rc < 0)
+++ goto add_return;
+++ }
+++ } else if ((sys <= -200 && sys >= -224) || (sys >= 392 && sys <= 402)) {
+++ /* (-200 to -224) : multiplexed ipc syscalls
+++ (392 to 402) : direct ipc syscalls */
+++
+++ /* strict check for the multiplexed socket syscalls */
+++ for (iter = 0; iter < ARG_COUNT_MAX; iter++) {
+++ if ((rule->args[iter].valid != 0) && (rule->strict)) {
+++ rc = -EINVAL;
+++ goto add_return;
+++ }
+++ }
+++
+++ /* determine both the muxed and direct syscall numbers */
+++ if (sys > 0) {
+++ sys_a = _ppc64_syscall_mux(sys);
+++ if (sys_a == __NR_SCMP_ERROR) {
+++ rc = __NR_SCMP_ERROR;
+++ goto add_return;
+++ }
+++ sys_b = sys;
+++ } else {
+++ sys_a = sys;
+++ sys_b = _ppc64_syscall_demux(sys);
+++ if (sys_b == __NR_SCMP_ERROR) {
+++ rc = __NR_SCMP_ERROR;
+++ goto add_return;
+++ }
+++ }
+++
+++ /* use rule_a for the multiplexed syscall and use rule_b for
+++ * the direct wired syscall */
+++
+++ if (sys_a == __NR_SCMP_UNDEF) {
+++ rule_a = NULL;
+++ rule_b = rule;
+++ } else if (sys_b == __NR_SCMP_UNDEF) {
+++ rule_a = rule;
+++ rule_b = NULL;
+++ } else {
+++ /* need two rules, dup the first and link together */
+++ rule_a = rule;
+++ rule_dup = db_rule_dup(rule_a);
+++ rule_b = rule_dup;
+++ if (rule_b == NULL)
+++ goto add_return;
+++ rule_b->prev = rule_a;
+++ rule_b->next = NULL;
+++ rule_a->next = rule_b;
+++ }
+++
+++ /* multiplexed socket syscalls */
+++ if (rule_a != NULL) {
+++ rule_a->syscall = __ppc64_NR_ipc;
+++ rule_a->args[0].arg = 0;
+++ rule_a->args[0].op = SCMP_CMP_EQ;
+++ rule_a->args[0].mask = DATUM_MAX;
+++ rule_a->args[0].datum = (-sys_a) % 200;
+++ rule_a->args[0].valid = 1;
+++ }
+++
+++ /* direct wired socket syscalls */
+++ if (rule_b != NULL)
+++ rule_b->syscall = sys_b;
+++
+++ /* we should be protected by a transaction checkpoint */
+++ if (rule_a != NULL) {
+++ rc = db_rule_add(db, rule_a);
+++ if (rc < 0)
+++ goto add_return;
+++ }
+++ if (rule_b != NULL) {
+++ rc = db_rule_add(db, rule_b);
+++ if (rc < 0)
+++ goto add_return;
+++ }
+++ } else if (sys >= 0) {
+++ /* normal syscall processing */
+++ rc = db_rule_add(db, rule);
+++ if (rc < 0)
+++ goto add_return;
+++ } else if (rule->strict) {
+++ rc = -EDOM;
+++ goto add_return;
+++ }
+++
+++add_return:
+++ if (rule_dup != NULL)
+++ free(rule_dup);
+++ return rc;
+++}
+++
++ const struct arch_def arch_def_ppc64 = {
++ .token = SCMP_ARCH_PPC64,
++ .token_bpf = AUDIT_ARCH_PPC64,
++ .size = ARCH_SIZE_64,
++ .endian = ARCH_ENDIAN_BIG,
++- .sys_socketcall = __ppc64_NR_socketcall,
++- .sys_ipc = __ppc64_NR_ipc,
++- .syscall_resolve_name = abi_syscall_resolve_name_munge,
++- .syscall_resolve_name_raw = ppc64_syscall_resolve_name,
++- .syscall_resolve_num = abi_syscall_resolve_num_munge,
++- .syscall_resolve_num_raw = ppc64_syscall_resolve_num,
++- .syscall_rewrite = abi_syscall_rewrite,
++- .rule_add = abi_rule_add,
+++ .syscall_resolve_name = ppc64_syscall_resolve_name_munge,
+++ .syscall_resolve_num = ppc64_syscall_resolve_num_munge,
+++ .syscall_rewrite = ppc64_syscall_rewrite,
+++ .rule_add = ppc64_rule_add,
++ };
++
++ const struct arch_def arch_def_ppc64le = {
++@@ -54,12 +639,8 @@ const struct arch_def arch_def_ppc64le = {
++ .token_bpf = AUDIT_ARCH_PPC64LE,
++ .size = ARCH_SIZE_64,
++ .endian = ARCH_ENDIAN_LITTLE,
++- .sys_socketcall = __ppc64_NR_socketcall,
++- .sys_ipc = __ppc64_NR_ipc,
++- .syscall_resolve_name = abi_syscall_resolve_name_munge,
++- .syscall_resolve_name_raw = ppc64_syscall_resolve_name,
++- .syscall_resolve_num = abi_syscall_resolve_num_munge,
++- .syscall_resolve_num_raw = ppc64_syscall_resolve_num,
++- .syscall_rewrite = abi_syscall_rewrite,
++- .rule_add = abi_rule_add,
+++ .syscall_resolve_name = ppc64_syscall_resolve_name_munge,
+++ .syscall_resolve_num = ppc64_syscall_resolve_num_munge,
+++ .syscall_rewrite = ppc64_syscall_rewrite,
+++ .rule_add = ppc64_rule_add,
++ };
++diff --git a/src/arch-riscv64.c b/src/arch-riscv64.c
++--- a/src/arch-riscv64.c
+++++ b/src/arch-riscv64.c
++@@ -24,8 +24,8 @@ const struct arch_def arch_def_riscv64 = {
++ .token_bpf = AUDIT_ARCH_RISCV64,
++ .size = ARCH_SIZE_64,
++ .endian = ARCH_ENDIAN_LITTLE,
++- .syscall_resolve_name_raw = riscv64_syscall_resolve_name,
++- .syscall_resolve_num_raw = riscv64_syscall_resolve_num,
+++ .syscall_resolve_name = riscv64_syscall_resolve_name,
+++ .syscall_resolve_num = riscv64_syscall_resolve_num,
++ .syscall_rewrite = NULL,
++ .rule_add = NULL,
++ };
++diff --git a/src/arch-s390.c b/src/arch-s390.c
++--- a/src/arch-s390.c
+++++ b/src/arch-s390.c
++@@ -17,17 +17,593 @@
++ #define __s390_NR_socketcall 102
++ #define __s390_NR_ipc 117
++
+++/**
+++ * Resolve a syscall name to a number
+++ * @param name the syscall name
+++ *
+++ * Resolve the given syscall name to the syscall number using the syscall table.
+++ * Returns the syscall number on success, including negative pseudo syscall
+++ * numbers; returns __NR_SCMP_ERROR on failure.
+++ *
+++ */
+++int s390_syscall_resolve_name_munge(const char *name)
+++{
+++ if (strcmp(name, "accept") == 0)
+++ return __PNR_accept;
+++ if (strcmp(name, "accept4") == 0)
+++ return __PNR_accept4;
+++ else if (strcmp(name, "bind") == 0)
+++ return __PNR_bind;
+++ else if (strcmp(name, "connect") == 0)
+++ return __PNR_connect;
+++ else if (strcmp(name, "getpeername") == 0)
+++ return __PNR_getpeername;
+++ else if (strcmp(name, "getsockname") == 0)
+++ return __PNR_getsockname;
+++ else if (strcmp(name, "getsockopt") == 0)
+++ return __PNR_getsockopt;
+++ else if (strcmp(name, "listen") == 0)
+++ return __PNR_listen;
+++ else if (strcmp(name, "msgctl") == 0)
+++ return __PNR_msgctl;
+++ else if (strcmp(name, "msgget") == 0)
+++ return __PNR_msgget;
+++ else if (strcmp(name, "msgrcv") == 0)
+++ return __PNR_msgrcv;
+++ else if (strcmp(name, "msgsnd") == 0)
+++ return __PNR_msgsnd;
+++ else if (strcmp(name, "recv") == 0)
+++ return __PNR_recv;
+++ else if (strcmp(name, "recvfrom") == 0)
+++ return __PNR_recvfrom;
+++ else if (strcmp(name, "recvmsg") == 0)
+++ return __PNR_recvmsg;
+++ else if (strcmp(name, "semctl") == 0)
+++ return __PNR_semctl;
+++ else if (strcmp(name, "semget") == 0)
+++ return __PNR_semget;
+++ else if (strcmp(name, "semtimedop") == 0)
+++ return __PNR_semtimedop;
+++ else if (strcmp(name, "recvmmsg") == 0)
+++ return __PNR_recvmmsg;
+++ else if (strcmp(name, "send") == 0)
+++ return __PNR_send;
+++ else if (strcmp(name, "sendmsg") == 0)
+++ return __PNR_sendmsg;
+++ else if (strcmp(name, "sendmmsg") == 0)
+++ return __PNR_sendmmsg;
+++ else if (strcmp(name, "sendto") == 0)
+++ return __PNR_sendto;
+++ else if (strcmp(name, "setsockopt") == 0)
+++ return __PNR_setsockopt;
+++ else if (strcmp(name, "shmat") == 0)
+++ return __PNR_shmat;
+++ else if (strcmp(name, "shmdt") == 0)
+++ return __PNR_shmdt;
+++ else if (strcmp(name, "shmget") == 0)
+++ return __PNR_shmget;
+++ else if (strcmp(name, "shmctl") == 0)
+++ return __PNR_shmctl;
+++ else if (strcmp(name, "shutdown") == 0)
+++ return __PNR_shutdown;
+++ else if (strcmp(name, "socket") == 0)
+++ return __PNR_socket;
+++ else if (strcmp(name, "socketpair") == 0)
+++ return __PNR_socketpair;
+++
+++ return s390_syscall_resolve_name(name);
+++}
+++
+++/**
+++ * Resolve a syscall number to a name
+++ * @param num the syscall number
+++ *
+++ * Resolve the given syscall number to the syscall name using the syscall table.
+++ * Returns a pointer to the syscall name string on success, including pseudo
+++ * syscall names; returns NULL on failure.
+++ *
+++ */
+++const char *s390_syscall_resolve_num_munge(int num)
+++{
+++ if (num == __PNR_accept)
+++ return "accept";
+++ else if (num == __PNR_accept4)
+++ return "accept4";
+++ else if (num == __PNR_bind)
+++ return "bind";
+++ else if (num == __PNR_connect)
+++ return "connect";
+++ else if (num == __PNR_getpeername)
+++ return "getpeername";
+++ else if (num == __PNR_getsockname)
+++ return "getsockname";
+++ else if (num == __PNR_getsockopt)
+++ return "getsockopt";
+++ else if (num == __PNR_listen)
+++ return "listen";
+++ else if (num == __PNR_msgctl)
+++ return "msgctl";
+++ else if (num == __PNR_msgget)
+++ return "msgget";
+++ else if (num == __PNR_msgrcv)
+++ return "msgrcv";
+++ else if (num == __PNR_msgsnd)
+++ return "msgsnd";
+++ else if (num == __PNR_recv)
+++ return "recv";
+++ else if (num == __PNR_recvfrom)
+++ return "recvfrom";
+++ else if (num == __PNR_recvmsg)
+++ return "recvmsg";
+++ else if (num == __PNR_recvmmsg)
+++ return "recvmmsg";
+++ else if (num == __PNR_semctl)
+++ return "semctl";
+++ else if (num == __PNR_semget)
+++ return "semget";
+++ else if (num == __PNR_semtimedop)
+++ return "semtimedop";
+++ else if (num == __PNR_send)
+++ return "send";
+++ else if (num == __PNR_sendmsg)
+++ return "sendmsg";
+++ else if (num == __PNR_sendmmsg)
+++ return "sendmmsg";
+++ else if (num == __PNR_sendto)
+++ return "sendto";
+++ else if (num == __PNR_setsockopt)
+++ return "setsockopt";
+++ else if (num == __PNR_shmat)
+++ return "shmat";
+++ else if (num == __PNR_shmdt)
+++ return "shmdt";
+++ else if (num == __PNR_shmget)
+++ return "shmget";
+++ else if (num == __PNR_shmctl)
+++ return "shmctl";
+++ else if (num == __PNR_shutdown)
+++ return "shutdown";
+++ else if (num == __PNR_socket)
+++ return "socket";
+++ else if (num == __PNR_socketpair)
+++ return "socketpair";
+++
+++ return s390_syscall_resolve_num(num);
+++}
+++
+++/**
+++ * Convert a multiplexed pseudo syscall into a direct syscall
+++ * @param syscall the multiplexed pseudo syscall number
+++ *
+++ * Return the related direct syscall number, __NR_SCMP_UNDEF is there is
+++ * no related syscall, or __NR_SCMP_ERROR otherwise.
+++ *
+++ */
+++static int _s390_syscall_demux(int syscall)
+++{
+++ switch (syscall) {
+++ case -101:
+++ /* socket */
+++ return 359;
+++ case -102:
+++ /* bind */
+++ return 361;
+++ case -103:
+++ /* connect */
+++ return 362;
+++ case -104:
+++ /* listen */
+++ return 363;
+++ case -105:
+++ /* accept - not defined */
+++ return __NR_SCMP_UNDEF;
+++ case -106:
+++ /* getsockname */
+++ return 367;
+++ case -107:
+++ /* getpeername */
+++ return 368;
+++ case -108:
+++ /* socketpair */
+++ return 360;
+++ case -109:
+++ /* send - not defined */
+++ return __NR_SCMP_UNDEF;
+++ case -110:
+++ /* recv - not defined */
+++ return __NR_SCMP_UNDEF;
+++ case -111:
+++ /* sendto */
+++ return 369;
+++ case -112:
+++ /* recvfrom */
+++ return 371;
+++ case -113:
+++ /* shutdown */
+++ return 373;
+++ case -114:
+++ /* setsockopt */
+++ return 366;
+++ case -115:
+++ /* getsockopt */
+++ return 365;
+++ case -116:
+++ /* sendmsg */
+++ return 370;
+++ case -117:
+++ /* recvmsg */
+++ return 372;
+++ case -118:
+++ /* accept4 */
+++ return 364;
+++ case -119:
+++ /* recvmmsg */
+++ return 337;
+++ case -120:
+++ /* sendmmsg */
+++ return 345;
+++ case -201:
+++ /* semop - not defined */
+++ return __NR_SCMP_UNDEF;
+++ case -202:
+++ /* semget */
+++ return 393;
+++ case -203:
+++ /* semctl */
+++ return 394;
+++ case -204:
+++ /* semtimedop */
+++ return 392;
+++ case -211:
+++ /* msgsnd */
+++ return 400;
+++ case -212:
+++ /* msgrcv */
+++ return 401;
+++ case -213:
+++ /* msgget */
+++ return 399;
+++ case -214:
+++ /* msgctl */
+++ return 402;
+++ case -221:
+++ /* shmat */
+++ return 397;
+++ case -222:
+++ /* shmdt */
+++ return 398;
+++ case -223:
+++ /* shmget */
+++ return 395;
+++ case -224:
+++ /* shmctl */
+++ return 396;
+++
+++ }
+++
+++ return __NR_SCMP_ERROR;
+++}
+++
+++/**
+++ * Convert a direct socket syscall into multiplexed pseudo socket syscall
+++ * @param syscall the direct syscall
+++ *
+++ * Return the related multiplexed pseduo syscall number, __NR_SCMP_UNDEF is
+++ * there is no related pseudo syscall, or __NR_SCMP_ERROR otherwise.
+++ *
+++ */
+++static int _s390_syscall_mux(int syscall)
+++{
+++ switch (syscall) {
+++ case 337:
+++ /* recvmmsg */
+++ return -119;
+++ case 345:
+++ /* sendmmsg */
+++ return -120;
+++ case 359:
+++ /* socket */
+++ return -101;
+++ case 360:
+++ /* socketpair */
+++ return -108;
+++ case 361:
+++ /* bind */
+++ return -102;
+++ case 362:
+++ /* connect */
+++ return -103;
+++ case 363:
+++ /* listen */
+++ return -104;
+++ case 364:
+++ /* accept4 */
+++ return -118;
+++ case 365:
+++ /* getsockopt */
+++ return -115;
+++ case 366:
+++ /* setsockopt */
+++ return -114;
+++ case 367:
+++ /* getsockname */
+++ return -106;
+++ case 368:
+++ /* getpeername */
+++ return -107;
+++ case 369:
+++ /* sendto */
+++ return -111;
+++ case 370:
+++ /* sendmsg */
+++ return -116;
+++ case 371:
+++ /* recvfrom */
+++ return -112;
+++ case 372:
+++ /* recvmsg */
+++ return -117;
+++ case 373:
+++ /* shutdown */
+++ return -113;
+++ case 393:
+++ /* semget */
+++ return -202;
+++ case 394:
+++ /* semctl */
+++ return -203;
+++ case 400:
+++ /* msgsnd */
+++ return -211;
+++ case 401:
+++ /* msgrcv */
+++ return -212;
+++ case 399:
+++ /* msgget */
+++ return -213;
+++ case 402:
+++ /* msgctl */
+++ return -214;
+++ case 397:
+++ /* shmat */
+++ return -221;
+++ case 398:
+++ /* shmdt */
+++ return -222;
+++ case 395:
+++ /* shmget */
+++ return -223;
+++ case 396:
+++ /* shmctl */
+++ return -224;
+++ case 392:
+++ /* semtimedop */
+++ return -204;
+++ }
+++
+++ return __NR_SCMP_ERROR;
+++}
+++
+++/**
+++ * Rewrite a syscall value to match the architecture
+++ * @param syscall the syscall number
+++ *
+++ * Syscalls can vary across different architectures so this function rewrites
+++ * the syscall into the correct value for the specified architecture. Returns
+++ * zero on success, negative values on failure.
+++ *
+++ */
+++int s390_syscall_rewrite(int *syscall)
+++{
+++ int sys = *syscall;
+++
+++ if (sys <= -100 && sys >= -120)
+++ *syscall = __s390_NR_socketcall;
+++ else if (sys <= -200 && sys >= -224)
+++ *syscall = __s390_NR_ipc;
+++ else if (sys < 0)
+++ return -EDOM;
+++
+++ return 0;
+++}
+++
+++/**
+++ * add a new rule to the s390 seccomp filter
+++ * @param db the seccomp filter db
+++ * @param rule the filter rule
+++ *
+++ * This function adds a new syscall filter to the seccomp filter db, making any
+++ * necessary adjustments for the s390 ABI. Returns zero on success, negative
+++ * values on failure.
+++ *
+++ * It is important to note that in the case of failure the db may be corrupted,
+++ * the caller must use the transaction mechanism if the db integrity is
+++ * important.
+++ *
+++ */
+++int s390_rule_add(struct db_filter *db, struct db_api_rule_list *rule)
+++{
+++ int rc = 0;
+++ unsigned int iter;
+++ int sys = rule->syscall;
+++ int sys_a, sys_b;
+++ struct db_api_rule_list *rule_a, *rule_b, *rule_dup = NULL;
+++
+++ if ((sys <= -100 && sys >= -120) || (sys >= 359 && sys <= 373)) {
+++ /* (-100 to -120) : multiplexed socket syscalls
+++ (359 to 373) : direct socket syscalls, Linux 4.3+ */
+++
+++ /* strict check for the multiplexed socket syscalls */
+++ for (iter = 0; iter < ARG_COUNT_MAX; iter++) {
+++ if ((rule->args[iter].valid != 0) && (rule->strict)) {
+++ rc = -EINVAL;
+++ goto add_return;
+++ }
+++ }
+++
+++ /* determine both the muxed and direct syscall numbers */
+++ if (sys > 0) {
+++ sys_a = _s390_syscall_mux(sys);
+++ if (sys_a == __NR_SCMP_ERROR) {
+++ rc = __NR_SCMP_ERROR;
+++ goto add_return;
+++ }
+++ sys_b = sys;
+++ } else {
+++ sys_a = sys;
+++ sys_b = _s390_syscall_demux(sys);
+++ if (sys_b == __NR_SCMP_ERROR) {
+++ rc = __NR_SCMP_ERROR;
+++ goto add_return;
+++ }
+++ }
+++
+++ /* use rule_a for the multiplexed syscall and use rule_b for
+++ * the direct wired syscall */
+++
+++ if (sys_a == __NR_SCMP_UNDEF) {
+++ rule_a = NULL;
+++ rule_b = rule;
+++ } else if (sys_b == __NR_SCMP_UNDEF) {
+++ rule_a = rule;
+++ rule_b = NULL;
+++ } else {
+++ /* need two rules, dup the first and link together */
+++ rule_a = rule;
+++ rule_dup = db_rule_dup(rule_a);
+++ rule_b = rule_dup;
+++ if (rule_b == NULL) {
+++ rc = -ENOMEM;
+++ goto add_return;
+++ }
+++ rule_b->prev = rule_a;
+++ rule_b->next = NULL;
+++ rule_a->next = rule_b;
+++ }
+++
+++ /* multiplexed socket syscalls */
+++ if (rule_a != NULL) {
+++ rule_a->syscall = __s390_NR_socketcall;
+++ rule_a->args[0].arg = 0;
+++ rule_a->args[0].op = SCMP_CMP_EQ;
+++ rule_a->args[0].mask = DATUM_MAX;
+++ rule_a->args[0].datum = (-sys_a) % 100;
+++ rule_a->args[0].valid = 1;
+++ }
+++
+++ /* direct wired socket syscalls */
+++ if (rule_b != NULL)
+++ rule_b->syscall = sys_b;
+++
+++ /* we should be protected by a transaction checkpoint */
+++ if (rule_a != NULL) {
+++ rc = db_rule_add(db, rule_a);
+++ if (rc < 0)
+++ goto add_return;
+++ }
+++ if (rule_b != NULL) {
+++ rc = db_rule_add(db, rule_b);
+++ if (rc < 0)
+++ goto add_return;
+++ }
+++ } else if ((sys <= -200 && sys >= -224) || (sys >= 393 && sys <= 402)) {
+++ /* (-200 to -224) : multiplexed ipc syscalls
+++ (393 to 402) : direct ipc syscalls */
+++
+++ /* strict check for the multiplexed socket syscalls */
+++ for (iter = 0; iter < ARG_COUNT_MAX; iter++) {
+++ if ((rule->args[iter].valid != 0) && (rule->strict)) {
+++ rc = -EINVAL;
+++ goto add_return;
+++ }
+++ }
+++
+++ /* determine both the muxed and direct syscall numbers */
+++ if (sys > 0) {
+++ sys_a = _s390_syscall_mux(sys);
+++ if (sys_a == __NR_SCMP_ERROR) {
+++ rc = __NR_SCMP_ERROR;
+++ goto add_return;
+++ }
+++ sys_b = sys;
+++ } else {
+++ sys_a = sys;
+++ sys_b = _s390_syscall_demux(sys);
+++ if (sys_b == __NR_SCMP_ERROR) {
+++ rc = __NR_SCMP_ERROR;
+++ goto add_return;
+++ }
+++ }
+++
+++ /* use rule_a for the multiplexed syscall and use rule_b for
+++ * the direct wired syscall */
+++
+++ if (sys_a == __NR_SCMP_UNDEF) {
+++ rule_a = NULL;
+++ rule_b = rule;
+++ } else if (sys_b == __NR_SCMP_UNDEF) {
+++ rule_a = rule;
+++ rule_b = NULL;
+++ } else {
+++ /* need two rules, dup the first and link together */
+++ rule_a = rule;
+++ rule_dup = db_rule_dup(rule_a);
+++ rule_b = rule_dup;
+++ if (rule_b == NULL)
+++ goto add_return;
+++ rule_b->prev = rule_a;
+++ rule_b->next = NULL;
+++ rule_a->next = rule_b;
+++ }
+++
+++ /* multiplexed socket syscalls */
+++ if (rule_a != NULL) {
+++ rule_a->syscall = __s390_NR_ipc;
+++ rule_a->args[0].arg = 0;
+++ rule_a->args[0].op = SCMP_CMP_EQ;
+++ rule_a->args[0].mask = DATUM_MAX;
+++ rule_a->args[0].datum = (-sys_a) % 200;
+++ rule_a->args[0].valid = 1;
+++ }
+++
+++ /* direct wired socket syscalls */
+++ if (rule_b != NULL)
+++ rule_b->syscall = sys_b;
+++
+++ /* we should be protected by a transaction checkpoint */
+++ if (rule_a != NULL) {
+++ rc = db_rule_add(db, rule_a);
+++ if (rc < 0)
+++ goto add_return;
+++ }
+++ if (rule_b != NULL) {
+++ rc = db_rule_add(db, rule_b);
+++ if (rc < 0)
+++ goto add_return;
+++ }
+++ } else if (sys >= 0) {
+++ /* normal syscall processing */
+++ rc = db_rule_add(db, rule);
+++ if (rc < 0)
+++ goto add_return;
+++ } else if (rule->strict) {
+++ rc = -EDOM;
+++ goto add_return;
+++ }
+++
+++add_return:
+++ if (rule_dup != NULL)
+++ free(rule_dup);
+++ return rc;
+++}
+++
++ const struct arch_def arch_def_s390 = {
++ .token = SCMP_ARCH_S390,
++ .token_bpf = AUDIT_ARCH_S390,
++ .size = ARCH_SIZE_32,
++ .endian = ARCH_ENDIAN_BIG,
++- .sys_socketcall = __s390_NR_socketcall,
++- .sys_ipc = __s390_NR_ipc,
++- .syscall_resolve_name = abi_syscall_resolve_name_munge,
++- .syscall_resolve_name_raw = s390_syscall_resolve_name,
++- .syscall_resolve_num = abi_syscall_resolve_num_munge,
++- .syscall_resolve_num_raw = s390_syscall_resolve_num,
++- .syscall_rewrite = abi_syscall_rewrite,
++- .rule_add = abi_rule_add,
+++ .syscall_resolve_name = s390_syscall_resolve_name_munge,
+++ .syscall_resolve_num = s390_syscall_resolve_num_munge,
+++ .syscall_rewrite = s390_syscall_rewrite,
+++ .rule_add = s390_rule_add,
++ };
++diff --git a/src/arch-s390x.c b/src/arch-s390x.c
++--- a/src/arch-s390x.c
+++++ b/src/arch-s390x.c
++@@ -17,17 +17,592 @@
++ #define __s390x_NR_socketcall 102
++ #define __s390x_NR_ipc 117
++
+++/**
+++ * Resolve a syscall name to a number
+++ * @param name the syscall name
+++ *
+++ * Resolve the given syscall name to the syscall number using the syscall table.
+++ * Returns the syscall number on success, including negative pseudo syscall
+++ * numbers; returns __NR_SCMP_ERROR on failure.
+++ *
+++ */
+++int s390x_syscall_resolve_name_munge(const char *name)
+++{
+++ if (strcmp(name, "accept") == 0)
+++ return __PNR_accept;
+++ if (strcmp(name, "accept4") == 0)
+++ return __PNR_accept4;
+++ else if (strcmp(name, "bind") == 0)
+++ return __PNR_bind;
+++ else if (strcmp(name, "connect") == 0)
+++ return __PNR_connect;
+++ else if (strcmp(name, "getpeername") == 0)
+++ return __PNR_getpeername;
+++ else if (strcmp(name, "getsockname") == 0)
+++ return __PNR_getsockname;
+++ else if (strcmp(name, "getsockopt") == 0)
+++ return __PNR_getsockopt;
+++ else if (strcmp(name, "listen") == 0)
+++ return __PNR_listen;
+++ else if (strcmp(name, "msgctl") == 0)
+++ return __PNR_msgctl;
+++ else if (strcmp(name, "msgget") == 0)
+++ return __PNR_msgget;
+++ else if (strcmp(name, "msgrcv") == 0)
+++ return __PNR_msgrcv;
+++ else if (strcmp(name, "msgsnd") == 0)
+++ return __PNR_msgsnd;
+++ else if (strcmp(name, "recv") == 0)
+++ return __PNR_recv;
+++ else if (strcmp(name, "recvfrom") == 0)
+++ return __PNR_recvfrom;
+++ else if (strcmp(name, "recvmsg") == 0)
+++ return __PNR_recvmsg;
+++ else if (strcmp(name, "recvmmsg") == 0)
+++ return __PNR_recvmmsg;
+++ else if (strcmp(name, "semctl") == 0)
+++ return __PNR_semctl;
+++ else if (strcmp(name, "semget") == 0)
+++ return __PNR_semget;
+++ else if (strcmp(name, "semtimedop") == 0)
+++ return __PNR_semtimedop;
+++ else if (strcmp(name, "send") == 0)
+++ return __PNR_send;
+++ else if (strcmp(name, "sendmsg") == 0)
+++ return __PNR_sendmsg;
+++ else if (strcmp(name, "sendmmsg") == 0)
+++ return __PNR_sendmmsg;
+++ else if (strcmp(name, "sendto") == 0)
+++ return __PNR_sendto;
+++ else if (strcmp(name, "setsockopt") == 0)
+++ return __PNR_setsockopt;
+++ else if (strcmp(name, "shmat") == 0)
+++ return __PNR_shmat;
+++ else if (strcmp(name, "shmdt") == 0)
+++ return __PNR_shmdt;
+++ else if (strcmp(name, "shmget") == 0)
+++ return __PNR_shmget;
+++ else if (strcmp(name, "shmctl") == 0)
+++ return __PNR_shmctl;
+++ else if (strcmp(name, "shutdown") == 0)
+++ return __PNR_shutdown;
+++ else if (strcmp(name, "socket") == 0)
+++ return __PNR_socket;
+++ else if (strcmp(name, "socketpair") == 0)
+++ return __PNR_socketpair;
+++
+++ return s390x_syscall_resolve_name(name);
+++}
+++
+++/**
+++ * Resolve a syscall number to a name
+++ * @param num the syscall number
+++ *
+++ * Resolve the given syscall number to the syscall name using the syscall table.
+++ * Returns a pointer to the syscall name string on success, including pseudo
+++ * syscall names; returns NULL on failure.
+++ *
+++ */
+++const char *s390x_syscall_resolve_num_munge(int num)
+++{
+++ if (num == __PNR_accept)
+++ return "accept";
+++ else if (num == __PNR_accept4)
+++ return "accept4";
+++ else if (num == __PNR_bind)
+++ return "bind";
+++ else if (num == __PNR_connect)
+++ return "connect";
+++ else if (num == __PNR_getpeername)
+++ return "getpeername";
+++ else if (num == __PNR_getsockname)
+++ return "getsockname";
+++ else if (num == __PNR_getsockopt)
+++ return "getsockopt";
+++ else if (num == __PNR_listen)
+++ return "listen";
+++ else if (num == __PNR_msgctl)
+++ return "msgctl";
+++ else if (num == __PNR_msgget)
+++ return "msgget";
+++ else if (num == __PNR_msgrcv)
+++ return "msgrcv";
+++ else if (num == __PNR_msgsnd)
+++ return "msgsnd";
+++ else if (num == __PNR_recv)
+++ return "recv";
+++ else if (num == __PNR_recvfrom)
+++ return "recvfrom";
+++ else if (num == __PNR_recvmsg)
+++ return "recvmsg";
+++ else if (num == __PNR_recvmmsg)
+++ return "recvmmsg";
+++ else if (num == __PNR_semctl)
+++ return "semctl";
+++ else if (num == __PNR_semget)
+++ return "semget";
+++ else if (num == __PNR_semtimedop)
+++ return "semtimedop";
+++ else if (num == __PNR_send)
+++ return "send";
+++ else if (num == __PNR_sendmsg)
+++ return "sendmsg";
+++ else if (num == __PNR_sendmmsg)
+++ return "sendmmsg";
+++ else if (num == __PNR_sendto)
+++ return "sendto";
+++ else if (num == __PNR_setsockopt)
+++ return "setsockopt";
+++ else if (num == __PNR_shmat)
+++ return "shmat";
+++ else if (num == __PNR_shmdt)
+++ return "shmdt";
+++ else if (num == __PNR_shmget)
+++ return "shmget";
+++ else if (num == __PNR_shmctl)
+++ return "shmctl";
+++ else if (num == __PNR_shutdown)
+++ return "shutdown";
+++ else if (num == __PNR_socket)
+++ return "socket";
+++ else if (num == __PNR_socketpair)
+++ return "socketpair";
+++
+++ return s390x_syscall_resolve_num(num);
+++}
+++
+++/**
+++ * Convert a multiplexed pseudo socket syscall into a direct syscall
+++ * @param syscall the multiplexed pseudo syscall number
+++ *
+++ * Return the related direct syscall number, __NR_SCMP_UNDEF is there is
+++ * no related syscall, or __NR_SCMP_ERROR otherwise.
+++ *
+++ */
+++static int _s390x_syscall_demux(int syscall)
+++{
+++ switch (syscall) {
+++ case -101:
+++ /* socket */
+++ return 359;
+++ case -102:
+++ /* bind */
+++ return 361;
+++ case -103:
+++ /* connect */
+++ return 362;
+++ case -104:
+++ /* listen */
+++ return 363;
+++ case -105:
+++ /* accept - not defined */
+++ return __NR_SCMP_UNDEF;
+++ case -106:
+++ /* getsockname */
+++ return 367;
+++ case -107:
+++ /* getpeername */
+++ return 368;
+++ case -108:
+++ /* socketpair */
+++ return 360;
+++ case -109:
+++ /* send - not defined */
+++ return __NR_SCMP_UNDEF;
+++ case -110:
+++ /* recv - not defined */
+++ return __NR_SCMP_UNDEF;
+++ case -111:
+++ /* sendto */
+++ return 369;
+++ case -112:
+++ /* recvfrom */
+++ return 371;
+++ case -113:
+++ /* shutdown */
+++ return 373;
+++ case -114:
+++ /* setsockopt */
+++ return 366;
+++ case -115:
+++ /* getsockopt */
+++ return 365;
+++ case -116:
+++ /* sendmsg */
+++ return 370;
+++ case -117:
+++ /* recvmsg */
+++ return 372;
+++ case -118:
+++ /* accept4 */
+++ return 364;
+++ case -119:
+++ /* recvmmsg */
+++ return 337;
+++ case -120:
+++ /* sendmmsg */
+++ return 345;
+++ case -201:
+++ /* semop - not defined */
+++ return __NR_SCMP_UNDEF;
+++ case -202:
+++ /* semget */
+++ return 393;
+++ case -203:
+++ /* semctl */
+++ return 394;
+++ case -204:
+++ /* semtimedop */
+++ return 392;
+++ case -211:
+++ /* msgsnd */
+++ return 400;
+++ case -212:
+++ /* msgrcv */
+++ return 401;
+++ case -213:
+++ /* msgget */
+++ return 399;
+++ case -214:
+++ /* msgctl */
+++ return 402;
+++ case -221:
+++ /* shmat */
+++ return 397;
+++ case -222:
+++ /* shmdt */
+++ return 398;
+++ case -223:
+++ /* shmget */
+++ return 395;
+++ case -224:
+++ /* shmctl */
+++ return 396;
+++ }
+++
+++ return __NR_SCMP_ERROR;
+++}
+++
+++/**
+++ * Convert a direct socket syscall into multiplexed pseudo socket syscall
+++ * @param syscall the direct syscall
+++ *
+++ * Return the related multiplexed pseduo syscall number, __NR_SCMP_UNDEF is
+++ * there is no related pseudo syscall, or __NR_SCMP_ERROR otherwise.
+++ *
+++ */
+++static int _s390x_syscall_mux(int syscall)
+++{
+++ switch (syscall) {
+++ case 337:
+++ /* recvmmsg */
+++ return -119;
+++ case 345:
+++ /* sendmmsg */
+++ return -120;
+++ case 359:
+++ /* socket */
+++ return -101;
+++ case 360:
+++ /* socketpair */
+++ return -108;
+++ case 361:
+++ /* bind */
+++ return -102;
+++ case 362:
+++ /* connect */
+++ return -103;
+++ case 363:
+++ /* listen */
+++ return -104;
+++ case 364:
+++ /* accept4 */
+++ return -118;
+++ case 365:
+++ /* getsockopt */
+++ return -115;
+++ case 366:
+++ /* setsockopt */
+++ return -114;
+++ case 367:
+++ /* getsockname */
+++ return -106;
+++ case 368:
+++ /* getpeername */
+++ return -107;
+++ case 369:
+++ /* sendto */
+++ return -111;
+++ case 370:
+++ /* sendmsg */
+++ return -116;
+++ case 371:
+++ /* recvfrom */
+++ return -112;
+++ case 372:
+++ /* recvmsg */
+++ return -117;
+++ case 373:
+++ /* shutdown */
+++ return -113;
+++ case 392:
+++ /* semtimedop */
+++ return -204;
+++ case 393:
+++ /* semget */
+++ return -202;
+++ case 394:
+++ /* semctl */
+++ return -203;
+++ case 400:
+++ /* msgsnd */
+++ return -211;
+++ case 401:
+++ /* msgrcv */
+++ return -212;
+++ case 399:
+++ /* msgget */
+++ return -213;
+++ case 402:
+++ /* msgctl */
+++ return -214;
+++ case 397:
+++ /* shmat */
+++ return -221;
+++ case 398:
+++ /* shmdt */
+++ return -222;
+++ case 395:
+++ /* shmget */
+++ return -223;
+++ case 396:
+++ /* shmctl */
+++ return -224;
+++ }
+++
+++ return __NR_SCMP_ERROR;
+++}
+++
+++/**
+++ * Rewrite a syscall value to match the architecture
+++ * @param syscall the syscall number
+++ *
+++ * Syscalls can vary across different architectures so this function rewrites
+++ * the syscall into the correct value for the specified architecture. Returns
+++ * zero on success, negative values on failure.
+++ *
+++ */
+++int s390x_syscall_rewrite(int *syscall)
+++{
+++ int sys = *syscall;
+++
+++ if (sys <= -100 && sys >= -120)
+++ *syscall = __s390x_NR_socketcall;
+++ else if (sys <= -200 && sys >= -224)
+++ *syscall = __s390x_NR_ipc;
+++ else if (sys < 0)
+++ return -EDOM;
+++
+++ return 0;
+++}
+++
+++/**
+++ * add a new rule to the s390x seccomp filter
+++ * @param db the seccomp filter db
+++ * @param rule the filter rule
+++ *
+++ * This function adds a new syscall filter to the seccomp filter db, making any
+++ * necessary adjustments for the s390x ABI. Returns zero on success, negative
+++ * values on failure.
+++ *
+++ * It is important to note that in the case of failure the db may be corrupted,
+++ * the caller must use the transaction mechanism if the db integrity is
+++ * important.
+++ *
+++ */
+++int s390x_rule_add(struct db_filter *db, struct db_api_rule_list *rule)
+++{
+++ int rc = 0;
+++ unsigned int iter;
+++ int sys = rule->syscall;
+++ int sys_a, sys_b;
+++ struct db_api_rule_list *rule_a, *rule_b, *rule_dup = NULL;
+++
+++ if ((sys <= -100 && sys >= -120) || (sys >= 359 && sys <= 373)) {
+++ /* (-100 to -120) : multiplexed socket syscalls
+++ (359 to 373) : direct socket syscalls, Linux 4.3+ */
+++
+++ /* strict check for the multiplexed socket syscalls */
+++ for (iter = 0; iter < ARG_COUNT_MAX; iter++) {
+++ if ((rule->args[iter].valid != 0) && (rule->strict)) {
+++ rc = -EINVAL;
+++ goto add_return;
+++ }
+++ }
+++
+++ /* determine both the muxed and direct syscall numbers */
+++ if (sys > 0) {
+++ sys_a = _s390x_syscall_mux(sys);
+++ if (sys_a == __NR_SCMP_ERROR) {
+++ rc = __NR_SCMP_ERROR;
+++ goto add_return;
+++ }
+++ sys_b = sys;
+++ } else {
+++ sys_a = sys;
+++ sys_b = _s390x_syscall_demux(sys);
+++ if (sys_b == __NR_SCMP_ERROR) {
+++ rc = __NR_SCMP_ERROR;
+++ goto add_return;
+++ }
+++ }
+++
+++ /* use rule_a for the multiplexed syscall and use rule_b for
+++ * the direct wired syscall */
+++
+++ if (sys_a == __NR_SCMP_UNDEF) {
+++ rule_a = NULL;
+++ rule_b = rule;
+++ } else if (sys_b == __NR_SCMP_UNDEF) {
+++ rule_a = rule;
+++ rule_b = NULL;
+++ } else {
+++ /* need two rules, dup the first and link together */
+++ rule_a = rule;
+++ rule_dup = db_rule_dup(rule_a);
+++ rule_b = rule_dup;
+++ if (rule_b == NULL) {
+++ rc = -ENOMEM;
+++ goto add_return;
+++ }
+++ rule_b->prev = rule_a;
+++ rule_b->next = NULL;
+++ rule_a->next = rule_b;
+++ }
+++
+++ /* multiplexed socket syscalls */
+++ if (rule_a != NULL) {
+++ rule_a->syscall = __s390x_NR_socketcall;
+++ rule_a->args[0].arg = 0;
+++ rule_a->args[0].op = SCMP_CMP_EQ;
+++ rule_a->args[0].mask = DATUM_MAX;
+++ rule_a->args[0].datum = (-sys_a) % 100;
+++ rule_a->args[0].valid = 1;
+++ }
+++
+++ /* direct wired socket syscalls */
+++ if (rule_b != NULL)
+++ rule_b->syscall = sys_b;
+++
+++ /* we should be protected by a transaction checkpoint */
+++ if (rule_a != NULL) {
+++ rc = db_rule_add(db, rule_a);
+++ if (rc < 0)
+++ goto add_return;
+++ }
+++ if (rule_b != NULL) {
+++ rc = db_rule_add(db, rule_b);
+++ if (rc < 0)
+++ goto add_return;
+++ }
+++ } else if ((sys <= -200 && sys >= -224) || (sys >= 392 && sys <= 402)) {
+++ /* (-200 to -224) : multiplexed ipc syscalls
+++ (392 to 402) : direct ipc syscalls */
+++
+++ /* strict check for the multiplexed socket syscalls */
+++ for (iter = 0; iter < ARG_COUNT_MAX; iter++) {
+++ if ((rule->args[iter].valid != 0) && (rule->strict)) {
+++ rc = -EINVAL;
+++ goto add_return;
+++ }
+++ }
+++
+++ /* determine both the muxed and direct syscall numbers */
+++ if (sys > 0) {
+++ sys_a = _s390x_syscall_mux(sys);
+++ if (sys_a == __NR_SCMP_ERROR) {
+++ rc = __NR_SCMP_ERROR;
+++ goto add_return;
+++ }
+++ sys_b = sys;
+++ } else {
+++ sys_a = sys;
+++ sys_b = _s390x_syscall_demux(sys);
+++ if (sys_b == __NR_SCMP_ERROR) {
+++ rc = __NR_SCMP_ERROR;
+++ goto add_return;
+++ }
+++ }
+++
+++ /* use rule_a for the multiplexed syscall and use rule_b for
+++ * the direct wired syscall */
+++
+++ if (sys_a == __NR_SCMP_UNDEF) {
+++ rule_a = NULL;
+++ rule_b = rule;
+++ } else if (sys_b == __NR_SCMP_UNDEF) {
+++ rule_a = rule;
+++ rule_b = NULL;
+++ } else {
+++ /* need two rules, dup the first and link together */
+++ rule_a = rule;
+++ rule_dup = db_rule_dup(rule_a);
+++ rule_b = rule_dup;
+++ if (rule_b == NULL)
+++ goto add_return;
+++ rule_b->prev = rule_a;
+++ rule_b->next = NULL;
+++ rule_a->next = rule_b;
+++ }
+++
+++ /* multiplexed socket syscalls */
+++ if (rule_a != NULL) {
+++ rule_a->syscall = __s390x_NR_ipc;
+++ rule_a->args[0].arg = 0;
+++ rule_a->args[0].op = SCMP_CMP_EQ;
+++ rule_a->args[0].mask = DATUM_MAX;
+++ rule_a->args[0].datum = (-sys_a) % 200;
+++ rule_a->args[0].valid = 1;
+++ }
+++
+++ /* direct wired socket syscalls */
+++ if (rule_b != NULL)
+++ rule_b->syscall = sys_b;
+++
+++ /* we should be protected by a transaction checkpoint */
+++ if (rule_a != NULL) {
+++ rc = db_rule_add(db, rule_a);
+++ if (rc < 0)
+++ goto add_return;
+++ }
+++ if (rule_b != NULL) {
+++ rc = db_rule_add(db, rule_b);
+++ if (rc < 0)
+++ goto add_return;
+++ }
+++ } else if (sys >= 0) {
+++ /* normal syscall processing */
+++ rc = db_rule_add(db, rule);
+++ if (rc < 0)
+++ goto add_return;
+++ } else if (rule->strict) {
+++ rc = -EDOM;
+++ goto add_return;
+++ }
+++
+++add_return:
+++ if (rule_dup != NULL)
+++ free(rule_dup);
+++ return rc;
+++}
+++
++ const struct arch_def arch_def_s390x = {
++ .token = SCMP_ARCH_S390X,
++ .token_bpf = AUDIT_ARCH_S390X,
++ .size = ARCH_SIZE_64,
++ .endian = ARCH_ENDIAN_BIG,
++- .sys_socketcall = __s390x_NR_socketcall,
++- .sys_ipc = __s390x_NR_ipc,
++- .syscall_resolve_name = abi_syscall_resolve_name_munge,
++- .syscall_resolve_name_raw = s390x_syscall_resolve_name,
++- .syscall_resolve_num = abi_syscall_resolve_num_munge,
++- .syscall_resolve_num_raw = s390x_syscall_resolve_num,
++- .syscall_rewrite = abi_syscall_rewrite,
++- .rule_add = abi_rule_add,
+++ .syscall_resolve_name = s390x_syscall_resolve_name_munge,
+++ .syscall_resolve_num = s390x_syscall_resolve_num_munge,
+++ .syscall_rewrite = s390x_syscall_rewrite,
+++ .rule_add = s390x_rule_add,
++ };
++diff --git a/src/arch-x32.c b/src/arch-x32.c
++--- a/src/arch-x32.c
+++++ b/src/arch-x32.c
++@@ -28,7 +28,6 @@
++
++ /**
++ * Resolve a syscall name to a number
++- * @param arch the architecture definition
++ * @param name the syscall name
++ *
++ * Resolve the given syscall name to the syscall number using the syscall table.
++@@ -36,13 +35,12 @@
++ * numbers; returns __NR_SCMP_ERROR on failure.
++ *
++ */
++-int x32_syscall_resolve_name_munge(const struct arch_def *arch,
++- const char *name)
+++int x32_syscall_resolve_name_munge(const char *name)
++ {
++ int sys;
++
++ /* NOTE: we don't want to modify the pseudo-syscall numbers */
++- sys = arch->syscall_resolve_name_raw(name);
+++ sys = x32_syscall_resolve_name(name);
++ if (sys == __NR_SCMP_ERROR || sys < 0)
++ return sys;
++
++@@ -51,7 +49,6 @@ int x32_syscall_resolve_name_munge(const struct arch_def *arch,
++
++ /**
++ * Resolve a syscall number to a name
++- * @param arch the architecture definition
++ * @param num the syscall number
++ *
++ * Resolve the given syscall number to the syscall name using the syscall table.
++@@ -59,13 +56,12 @@ int x32_syscall_resolve_name_munge(const struct arch_def *arch,
++ * syscall names; returns NULL on failure.
++ *
++ */
++-const char *x32_syscall_resolve_num_munge(const struct arch_def *arch,
++- int num)
+++const char *x32_syscall_resolve_num_munge(int num)
++ {
++ /* NOTE: we don't want to modify the pseudo-syscall numbers */
++ if (num >= 0)
++ num &= ~X32_SYSCALL_BIT;
++- return arch->syscall_resolve_num_raw(num);
+++ return x32_syscall_resolve_num(num);
++ }
++
++ const struct arch_def arch_def_x32 = {
++@@ -75,9 +71,7 @@ const struct arch_def arch_def_x32 = {
++ .size = ARCH_SIZE_32,
++ .endian = ARCH_ENDIAN_LITTLE,
++ .syscall_resolve_name = x32_syscall_resolve_name_munge,
++- .syscall_resolve_name_raw = x32_syscall_resolve_name,
++ .syscall_resolve_num = x32_syscall_resolve_num_munge,
++- .syscall_resolve_num_raw = x32_syscall_resolve_num,
++ .syscall_rewrite = NULL,
++ .rule_add = NULL,
++ };
++diff --git a/src/arch-x86.c b/src/arch-x86.c
++--- a/src/arch-x86.c
+++++ b/src/arch-x86.c
++@@ -33,17 +33,593 @@
++ #define __x86_NR_socketcall 102
++ #define __x86_NR_ipc 117
++
+++/**
+++ * Resolve a syscall name to a number
+++ * @param name the syscall name
+++ *
+++ * Resolve the given syscall name to the syscall number using the syscall table.
+++ * Returns the syscall number on success, including negative pseudo syscall
+++ * numbers; returns __NR_SCMP_ERROR on failure.
+++ *
+++ */
+++int x86_syscall_resolve_name_munge(const char *name)
+++{
+++ if (strcmp(name, "accept") == 0)
+++ return __PNR_accept;
+++ else if (strcmp(name, "accept4") == 0)
+++ return __PNR_accept4;
+++ else if (strcmp(name, "bind") == 0)
+++ return __PNR_bind;
+++ else if (strcmp(name, "connect") == 0)
+++ return __PNR_connect;
+++ else if (strcmp(name, "getpeername") == 0)
+++ return __PNR_getpeername;
+++ else if (strcmp(name, "getsockname") == 0)
+++ return __PNR_getsockname;
+++ else if (strcmp(name, "getsockopt") == 0)
+++ return __PNR_getsockopt;
+++ else if (strcmp(name, "listen") == 0)
+++ return __PNR_listen;
+++ else if (strcmp(name, "recv") == 0)
+++ return __PNR_recv;
+++ else if (strcmp(name, "recvfrom") == 0)
+++ return __PNR_recvfrom;
+++ else if (strcmp(name, "recvmsg") == 0)
+++ return __PNR_recvmsg;
+++ else if (strcmp(name, "recvmmsg") == 0)
+++ return __PNR_recvmmsg;
+++ else if (strcmp(name, "send") == 0)
+++ return __PNR_send;
+++ else if (strcmp(name, "sendmsg") == 0)
+++ return __PNR_sendmsg;
+++ else if (strcmp(name, "sendmmsg") == 0)
+++ return __PNR_sendmmsg;
+++ else if (strcmp(name, "sendto") == 0)
+++ return __PNR_sendto;
+++ else if (strcmp(name, "setsockopt") == 0)
+++ return __PNR_setsockopt;
+++ else if (strcmp(name, "shutdown") == 0)
+++ return __PNR_shutdown;
+++ else if (strcmp(name, "socket") == 0)
+++ return __PNR_socket;
+++ else if (strcmp(name, "socketpair") == 0)
+++ return __PNR_socketpair;
+++
+++ if (strcmp(name, "semop") == 0)
+++ return __PNR_semop;
+++ else if (strcmp(name, "semget") == 0)
+++ return __PNR_semget;
+++ else if (strcmp(name, "semctl") == 0)
+++ return __PNR_semctl;
+++ else if (strcmp(name, "semtimedop") == 0)
+++ return __PNR_semtimedop;
+++ else if (strcmp(name, "msgsnd") == 0)
+++ return __PNR_msgsnd;
+++ else if (strcmp(name, "msgrcv") == 0)
+++ return __PNR_msgrcv;
+++ else if (strcmp(name, "msgget") == 0)
+++ return __PNR_msgget;
+++ else if (strcmp(name, "msgctl") == 0)
+++ return __PNR_msgctl;
+++ else if (strcmp(name, "shmat") == 0)
+++ return __PNR_shmat;
+++ else if (strcmp(name, "shmdt") == 0)
+++ return __PNR_shmdt;
+++ else if (strcmp(name, "shmget") == 0)
+++ return __PNR_shmget;
+++ else if (strcmp(name, "shmctl") == 0)
+++ return __PNR_shmctl;
+++
+++ return x86_syscall_resolve_name(name);
+++}
+++
+++/**
+++ * Resolve a syscall number to a name
+++ * @param num the syscall number
+++ *
+++ * Resolve the given syscall number to the syscall name using the syscall table.
+++ * Returns a pointer to the syscall name string on success, including pseudo
+++ * syscall names; returns NULL on failure.
+++ *
+++ */
+++const char *x86_syscall_resolve_num_munge(int num)
+++{
+++ if (num == __PNR_accept)
+++ return "accept";
+++ else if (num == __PNR_accept4)
+++ return "accept4";
+++ else if (num == __PNR_bind)
+++ return "bind";
+++ else if (num == __PNR_connect)
+++ return "connect";
+++ else if (num == __PNR_getpeername)
+++ return "getpeername";
+++ else if (num == __PNR_getsockname)
+++ return "getsockname";
+++ else if (num == __PNR_getsockopt)
+++ return "getsockopt";
+++ else if (num == __PNR_listen)
+++ return "listen";
+++ else if (num == __PNR_recv)
+++ return "recv";
+++ else if (num == __PNR_recvfrom)
+++ return "recvfrom";
+++ else if (num == __PNR_recvmsg)
+++ return "recvmsg";
+++ else if (num == __PNR_recvmmsg)
+++ return "recvmmsg";
+++ else if (num == __PNR_send)
+++ return "send";
+++ else if (num == __PNR_sendmsg)
+++ return "sendmsg";
+++ else if (num == __PNR_sendmmsg)
+++ return "sendmmsg";
+++ else if (num == __PNR_sendto)
+++ return "sendto";
+++ else if (num == __PNR_setsockopt)
+++ return "setsockopt";
+++ else if (num == __PNR_shutdown)
+++ return "shutdown";
+++ else if (num == __PNR_socket)
+++ return "socket";
+++ else if (num == __PNR_socketpair)
+++ return "socketpair";
+++
+++ if (num == __PNR_semop)
+++ return "semop";
+++ else if (num == __PNR_semget)
+++ return "semget";
+++ else if (num == __PNR_semctl)
+++ return "semctl";
+++ else if (num == __PNR_semtimedop)
+++ return "semtimedop";
+++ else if (num == __PNR_msgsnd)
+++ return "msgsnd";
+++ else if (num == __PNR_msgrcv)
+++ return "msgrcv";
+++ else if (num == __PNR_msgget)
+++ return "msgget";
+++ else if (num == __PNR_msgctl)
+++ return "msgctl";
+++ else if (num == __PNR_shmat)
+++ return "shmat";
+++ else if (num == __PNR_shmdt)
+++ return "shmdt";
+++ else if (num == __PNR_shmget)
+++ return "shmget";
+++ else if (num == __PNR_shmctl)
+++ return "shmctl";
+++
+++ return x86_syscall_resolve_num(num);
+++}
+++
+++/**
+++ * Convert a multiplexed pseudo syscall into a direct syscall
+++ * @param syscall the multiplexed pseudo syscall number
+++ *
+++ * Return the related direct syscall number, __NR_SCMP_UNDEF is there is
+++ * no related syscall, or __NR_SCMP_ERROR otherwise.
+++ *
+++ */
+++static int _x86_syscall_demux(int syscall)
+++{
+++ switch (syscall) {
+++ case -101:
+++ /* socket */
+++ return 359;
+++ case -102:
+++ /* bind */
+++ return 361;
+++ case -103:
+++ /* connect */
+++ return 362;
+++ case -104:
+++ /* listen */
+++ return 363;
+++ case -105:
+++ /* accept - not defined */
+++ return __NR_SCMP_UNDEF;
+++ case -106:
+++ /* getsockname */
+++ return 367;
+++ case -107:
+++ /* getpeername */
+++ return 368;
+++ case -108:
+++ /* socketpair */
+++ return 360;
+++ case -109:
+++ /* send - not defined */
+++ return __NR_SCMP_UNDEF;
+++ case -110:
+++ /* recv - not defined */
+++ return __NR_SCMP_UNDEF;
+++ case -111:
+++ /* sendto */
+++ return 369;
+++ case -112:
+++ /* recvfrom */
+++ return 371;
+++ case -113:
+++ /* shutdown */
+++ return 373;
+++ case -114:
+++ /* setsockopt */
+++ return 366;
+++ case -115:
+++ /* getsockopt */
+++ return 365;
+++ case -116:
+++ /* sendmsg */
+++ return 370;
+++ case -117:
+++ /* recvmsg */
+++ return 372;
+++ case -118:
+++ /* accept4 */
+++ return 364;
+++ case -119:
+++ /* recvmmsg */
+++ return 337;
+++ case -120:
+++ /* sendmmsg */
+++ return 345;
+++ case -201:
+++ /* semop - not defined */
+++ return __NR_SCMP_UNDEF;
+++ case -202:
+++ /* semget */
+++ return 393;
+++ case -203:
+++ /* semctl */
+++ return 394;
+++ case -204:
+++ /* semtimedop - not defined */
+++ return __NR_SCMP_UNDEF;
+++ case -211:
+++ /* msgsnd */
+++ return 400;
+++ case -212:
+++ /* msgrcv */
+++ return 401;
+++ case -213:
+++ /* msgget */
+++ return 399;
+++ case -214:
+++ /* msgctl */
+++ return 402;
+++ case -221:
+++ /* shmat */
+++ return 397;
+++ case -222:
+++ /* shmdt */
+++ return 398;
+++ case -223:
+++ /* shmget */
+++ return 395;
+++ case -224:
+++ /* shmctl */
+++ return 396;
+++ }
+++
+++ return __NR_SCMP_ERROR;
+++}
+++
+++/**
+++ * Convert a direct syscall into multiplexed pseudo socket syscall
+++ * @param syscall the direct syscall
+++ *
+++ * Return the related multiplexed pseduo syscall number, __NR_SCMP_UNDEF is
+++ * there is no related pseudo syscall, or __NR_SCMP_ERROR otherwise.
+++ *
+++ */
+++static int _x86_syscall_mux(int syscall)
+++{
+++ switch (syscall) {
+++ case 337:
+++ /* recvmmsg */
+++ return -119;
+++ case 345:
+++ /* sendmmsg */
+++ return -120;
+++ case 359:
+++ /* socket */
+++ return -101;
+++ case 360:
+++ /* socketpair */
+++ return -108;
+++ case 361:
+++ /* bind */
+++ return -102;
+++ case 362:
+++ /* connect */
+++ return -103;
+++ case 363:
+++ /* listen */
+++ return -104;
+++ case 364:
+++ /* accept4 */
+++ return -118;
+++ case 365:
+++ /* getsockopt */
+++ return -115;
+++ case 366:
+++ /* setsockopt */
+++ return -114;
+++ case 367:
+++ /* getsockname */
+++ return -106;
+++ case 368:
+++ /* getpeername */
+++ return -107;
+++ case 369:
+++ /* sendto */
+++ return -111;
+++ case 370:
+++ /* sendmsg */
+++ return -116;
+++ case 371:
+++ /* recvfrom */
+++ return -112;
+++ case 372:
+++ /* recvmsg */
+++ return -117;
+++ case 373:
+++ /* shutdown */
+++ return -113;
+++ case 393:
+++ /* semget */
+++ return -202;
+++ case 394:
+++ /* semctl */
+++ return -203;
+++ case 400:
+++ /* msgsnd */
+++ return -211;
+++ case 401:
+++ /* msgrcv */
+++ return -212;
+++ case 399:
+++ /* msgget */
+++ return -213;
+++ case 402:
+++ /* msgctl */
+++ return -214;
+++ case 397:
+++ /* shmat */
+++ return -221;
+++ case 398:
+++ /* shmdt */
+++ return -222;
+++ case 395:
+++ /* shmget */
+++ return -223;
+++ case 396:
+++ /* shmctl */
+++ return -224;
+++ }
+++
+++ return __NR_SCMP_ERROR;
+++}
+++
+++/**
+++ * Rewrite a syscall value to match the architecture
+++ * @param syscall the syscall number
+++ *
+++ * Syscalls can vary across different architectures so this function rewrites
+++ * the syscall into the correct value for the specified architecture. Returns
+++ * zero on success, negative values on failure.
+++ *
+++ */
+++int x86_syscall_rewrite(int *syscall)
+++{
+++ int sys = *syscall;
+++
+++ if (sys <= -100 && sys >= -120)
+++ *syscall = __x86_NR_socketcall;
+++ else if (sys <= -200 && sys >= -224)
+++ *syscall = __x86_NR_ipc;
+++ else if (sys < 0)
+++ return -EDOM;
+++
+++ return 0;
+++}
+++
+++/**
+++ * add a new rule to the x86 seccomp filter
+++ * @param db the seccomp filter db
+++ * @param rule the filter rule
+++ *
+++ * This function adds a new syscall filter to the seccomp filter db, making any
+++ * necessary adjustments for the x86 ABI. Returns zero on success, negative
+++ * values on failure.
+++ *
+++ * It is important to note that in the case of failure the db may be corrupted,
+++ * the caller must use the transaction mechanism if the db integrity is
+++ * important.
+++ *
+++ */
+++int x86_rule_add(struct db_filter *db, struct db_api_rule_list *rule)
+++{
+++ int rc = 0;
+++ unsigned int iter;
+++ int sys = rule->syscall;
+++ int sys_a, sys_b;
+++ struct db_api_rule_list *rule_a, *rule_b, *rule_dup = NULL;
+++
+++ if ((sys <= -100 && sys >= -120) || (sys >= 359 && sys <= 373)) {
+++ /* (-100 to -120) : multiplexed socket syscalls
+++ (359 to 373) : direct socket syscalls, Linux 4.3+ */
+++
+++ /* strict check for the multiplexed socket syscalls */
+++ for (iter = 0; iter < ARG_COUNT_MAX; iter++) {
+++ if ((rule->args[iter].valid != 0) && (rule->strict)) {
+++ rc = -EINVAL;
+++ goto add_return;
+++ }
+++ }
+++
+++ /* determine both the muxed and direct syscall numbers */
+++ if (sys > 0) {
+++ sys_a = _x86_syscall_mux(sys);
+++ if (sys_a == __NR_SCMP_ERROR) {
+++ rc = __NR_SCMP_ERROR;
+++ goto add_return;
+++ }
+++ sys_b = sys;
+++ } else {
+++ sys_a = sys;
+++ sys_b = _x86_syscall_demux(sys);
+++ if (sys_b == __NR_SCMP_ERROR) {
+++ rc = __NR_SCMP_ERROR;
+++ goto add_return;
+++ }
+++ }
+++
+++ /* use rule_a for the multiplexed syscall and use rule_b for
+++ * the direct wired syscall */
+++
+++ if (sys_a == __NR_SCMP_UNDEF) {
+++ rule_a = NULL;
+++ rule_b = rule;
+++ } else if (sys_b == __NR_SCMP_UNDEF) {
+++ rule_a = rule;
+++ rule_b = NULL;
+++ } else {
+++ /* need two rules, dup the first and link together */
+++ rule_a = rule;
+++ rule_dup = db_rule_dup(rule_a);
+++ rule_b = rule_dup;
+++ if (rule_b == NULL)
+++ goto add_return;
+++ rule_b->prev = rule_a;
+++ rule_b->next = NULL;
+++ rule_a->next = rule_b;
+++ }
+++
+++ /* multiplexed socket syscalls */
+++ if (rule_a != NULL) {
+++ rule_a->syscall = __x86_NR_socketcall;
+++ rule_a->args[0].arg = 0;
+++ rule_a->args[0].op = SCMP_CMP_EQ;
+++ rule_a->args[0].mask = DATUM_MAX;
+++ rule_a->args[0].datum = (-sys_a) % 100;
+++ rule_a->args[0].valid = 1;
+++ }
+++
+++ /* direct wired socket syscalls */
+++ if (rule_b != NULL)
+++ rule_b->syscall = sys_b;
+++
+++ /* we should be protected by a transaction checkpoint */
+++ if (rule_a != NULL) {
+++ rc = db_rule_add(db, rule_a);
+++ if (rc < 0)
+++ goto add_return;
+++ }
+++ if (rule_b != NULL) {
+++ rc = db_rule_add(db, rule_b);
+++ if (rc < 0)
+++ goto add_return;
+++ }
+++ } else if ((sys <= -200 && sys >= -224) || (sys >= 393 && sys <= 402)) {
+++ /* (-200 to -224) : multiplexed ipc syscalls
+++ (393 to 402) : direct ipc syscalls */
+++
+++ /* strict check for the multiplexed socket syscalls */
+++ for (iter = 0; iter < ARG_COUNT_MAX; iter++) {
+++ if ((rule->args[iter].valid != 0) && (rule->strict)) {
+++ rc = -EINVAL;
+++ goto add_return;
+++ }
+++ }
+++
+++ /* determine both the muxed and direct syscall numbers */
+++ if (sys > 0) {
+++ sys_a = _x86_syscall_mux(sys);
+++ if (sys_a == __NR_SCMP_ERROR) {
+++ rc = __NR_SCMP_ERROR;
+++ goto add_return;
+++ }
+++ sys_b = sys;
+++ } else {
+++ sys_a = sys;
+++ sys_b = _x86_syscall_demux(sys);
+++ if (sys_b == __NR_SCMP_ERROR) {
+++ rc = __NR_SCMP_ERROR;
+++ goto add_return;
+++ }
+++ }
+++
+++ /* use rule_a for the multiplexed syscall and use rule_b for
+++ * the direct wired syscall */
+++
+++ if (sys_a == __NR_SCMP_UNDEF) {
+++ rule_a = NULL;
+++ rule_b = rule;
+++ } else if (sys_b == __NR_SCMP_UNDEF) {
+++ rule_a = rule;
+++ rule_b = NULL;
+++ } else {
+++ /* need two rules, dup the first and link together */
+++ rule_a = rule;
+++ rule_dup = db_rule_dup(rule_a);
+++ rule_b = rule_dup;
+++ if (rule_b == NULL)
+++ goto add_return;
+++ rule_b->prev = rule_a;
+++ rule_b->next = NULL;
+++ rule_a->next = rule_b;
+++ }
+++
+++ /* multiplexed socket syscalls */
+++ if (rule_a != NULL) {
+++ rule_a->syscall = __x86_NR_ipc;
+++ rule_a->args[0].arg = 0;
+++ rule_a->args[0].op = SCMP_CMP_EQ;
+++ rule_a->args[0].mask = DATUM_MAX;
+++ rule_a->args[0].datum = (-sys_a) % 200;
+++ rule_a->args[0].valid = 1;
+++ }
+++
+++ /* direct wired socket syscalls */
+++ if (rule_b != NULL)
+++ rule_b->syscall = sys_b;
+++
+++ /* we should be protected by a transaction checkpoint */
+++ if (rule_a != NULL) {
+++ rc = db_rule_add(db, rule_a);
+++ if (rc < 0)
+++ goto add_return;
+++ }
+++ if (rule_b != NULL) {
+++ rc = db_rule_add(db, rule_b);
+++ if (rc < 0)
+++ goto add_return;
+++ }
+++ } else if (sys >= 0) {
+++ /* normal syscall processing */
+++ rc = db_rule_add(db, rule);
+++ if (rc < 0)
+++ goto add_return;
+++ } else if (rule->strict) {
+++ rc = -EDOM;
+++ goto add_return;
+++ }
+++
+++add_return:
+++ if (rule_dup != NULL)
+++ free(rule_dup);
+++ return rc;
+++}
+++
++ const struct arch_def arch_def_x86 = {
++ .token = SCMP_ARCH_X86,
++ .token_bpf = AUDIT_ARCH_I386,
++ .size = ARCH_SIZE_32,
++ .endian = ARCH_ENDIAN_LITTLE,
++- .sys_socketcall = __x86_NR_socketcall,
++- .sys_ipc = __x86_NR_ipc,
++- .syscall_resolve_name = abi_syscall_resolve_name_munge,
++- .syscall_resolve_name_raw = x86_syscall_resolve_name,
++- .syscall_resolve_num = abi_syscall_resolve_num_munge,
++- .syscall_resolve_num_raw = x86_syscall_resolve_num,
++- .syscall_rewrite = abi_syscall_rewrite,
++- .rule_add = abi_rule_add,
+++ .syscall_resolve_name = x86_syscall_resolve_name_munge,
+++ .syscall_resolve_num = x86_syscall_resolve_num_munge,
+++ .syscall_rewrite = x86_syscall_rewrite,
+++ .rule_add = x86_rule_add,
++ };
++diff --git a/src/arch-x86_64.c b/src/arch-x86_64.c
++--- a/src/arch-x86_64.c
+++++ b/src/arch-x86_64.c
++@@ -31,8 +31,8 @@ const struct arch_def arch_def_x86_64 = {
++ .token_bpf = AUDIT_ARCH_X86_64,
++ .size = ARCH_SIZE_64,
++ .endian = ARCH_ENDIAN_LITTLE,
++- .syscall_resolve_name_raw = x86_64_syscall_resolve_name,
++- .syscall_resolve_num_raw = x86_64_syscall_resolve_num,
+++ .syscall_resolve_name = x86_64_syscall_resolve_name,
+++ .syscall_resolve_num = x86_64_syscall_resolve_num,
++ .syscall_rewrite = NULL,
++ .rule_add = NULL,
++ };
++diff --git a/src/arch.c b/src/arch.c
++--- a/src/arch.c
+++++ b/src/arch.c
++@@ -300,9 +300,7 @@ int arch_arg_offset(const struct arch_def *arch, unsigned int arg)
++ int arch_syscall_resolve_name(const struct arch_def *arch, const char *name)
++ {
++ if (arch->syscall_resolve_name)
++- return (*arch->syscall_resolve_name)(arch, name);
++- if (arch->syscall_resolve_name_raw)
++- return (*arch->syscall_resolve_name_raw)(name);
+++ return (*arch->syscall_resolve_name)(name);
++
++ return __NR_SCMP_ERROR;
++ }
++@@ -320,9 +318,7 @@ int arch_syscall_resolve_name(const struct arch_def *arch, const char *name)
++ const char *arch_syscall_resolve_num(const struct arch_def *arch, int num)
++ {
++ if (arch->syscall_resolve_num)
++- return (*arch->syscall_resolve_num)(arch, num);
++- if (arch->syscall_resolve_num_raw)
++- return (*arch->syscall_resolve_num_raw)(num);
+++ return (*arch->syscall_resolve_num)(num);
++
++ return NULL;
++ }
++@@ -385,7 +381,7 @@ int arch_syscall_rewrite(const struct arch_def *arch, int *syscall)
++ } else if (sys > -10000) {
++ /* rewritable syscalls */
++ if (arch->syscall_rewrite)
++- (*arch->syscall_rewrite)(arch, syscall);
+++ (*arch->syscall_rewrite)(syscall);
++ }
++
++ /* syscalls not defined on this architecture */
++diff --git a/src/arch.h b/src/arch.h
++--- a/src/arch.h
+++++ b/src/arch.h
++@@ -49,18 +49,10 @@ struct arch_def {
++ ARCH_ENDIAN_BIG,
++ } endian;
++
++- /* arch specific constants */
++- int sys_socketcall;
++- int sys_ipc;
++-
++ /* arch specific functions */
++- int (*syscall_resolve_name)(const struct arch_def *arch,
++- const char *name);
++- int (*syscall_resolve_name_raw)(const char *name);
++- const char *(*syscall_resolve_num)(const struct arch_def *arch,
++- int num);
++- const char *(*syscall_resolve_num_raw)(int num);
++- int (*syscall_rewrite)(const struct arch_def *arch, int *syscall);
+++ int (*syscall_resolve_name)(const char *name);
+++ const char *(*syscall_resolve_num)(int num);
+++ int (*syscall_rewrite)(int *syscall);
++ int (*rule_add)(struct db_filter *db, struct db_api_rule_list *rule);
++ };
++
++diff --git a/src/syscalls.c b/src/syscalls.c
++--- a/src/syscalls.c
+++++ b/src/syscalls.c
++@@ -1,5 +1,5 @@
++ /**
++- * Enhanced Seccomp Syscall Table Functions
+++ * Enhanced Seccomp x86_64 Syscall Table
++ *
++ * Copyright (c) 2012, 2020 Red Hat <pmoore@redhat.com>
++ * Author: Paul Moore <paul@paul-moore.com>
++@@ -19,13 +19,9 @@
++ * 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 <stdlib.h>
++-#include <errno.h>
++-#include <string.h>
++ #include <seccomp.h>
+++#include <string.h>
++
++-#include "db.h"
++ #include "arch.h"
++ #include "syscalls.h"
++
++@@ -58,524 +54,3 @@ ARCH_DEF(s390x)
++ ARCH_DEF(x32)
++ ARCH_DEF(x86)
++ ARCH_DEF(riscv64)
++-
++-/**
++- * Resolve a syscall name to a number
++- * @param arch the arch definition
++- * @param name the syscall name
++- *
++- * Resolve the given syscall name to the syscall number using the syscall table.
++- * Returns the syscall number on success, including negative pseudo syscall
++- * numbers; returns __NR_SCMP_ERROR on failure.
++- *
++- */
++-int abi_syscall_resolve_name_munge(const struct arch_def *arch,
++- const char *name)
++-{
++-
++-#define _ABI_SYSCALL_RES_NAME_CHK(NAME) \
++- if (!strcmp(name, #NAME)) return __PNR_##NAME;
++-
++- _ABI_SYSCALL_RES_NAME_CHK(socket)
++- _ABI_SYSCALL_RES_NAME_CHK(bind)
++- _ABI_SYSCALL_RES_NAME_CHK(connect)
++- _ABI_SYSCALL_RES_NAME_CHK(listen)
++- _ABI_SYSCALL_RES_NAME_CHK(accept)
++- _ABI_SYSCALL_RES_NAME_CHK(getsockname)
++- _ABI_SYSCALL_RES_NAME_CHK(getpeername)
++- _ABI_SYSCALL_RES_NAME_CHK(socketpair)
++- _ABI_SYSCALL_RES_NAME_CHK(send)
++- _ABI_SYSCALL_RES_NAME_CHK(recv)
++- _ABI_SYSCALL_RES_NAME_CHK(sendto)
++- _ABI_SYSCALL_RES_NAME_CHK(recvfrom)
++- _ABI_SYSCALL_RES_NAME_CHK(shutdown)
++- _ABI_SYSCALL_RES_NAME_CHK(setsockopt)
++- _ABI_SYSCALL_RES_NAME_CHK(getsockopt)
++- _ABI_SYSCALL_RES_NAME_CHK(sendmsg)
++- _ABI_SYSCALL_RES_NAME_CHK(recvmsg)
++- _ABI_SYSCALL_RES_NAME_CHK(accept4)
++- _ABI_SYSCALL_RES_NAME_CHK(recvmmsg)
++- _ABI_SYSCALL_RES_NAME_CHK(sendmmsg)
++- _ABI_SYSCALL_RES_NAME_CHK(semop)
++- _ABI_SYSCALL_RES_NAME_CHK(semget)
++- _ABI_SYSCALL_RES_NAME_CHK(semctl)
++- _ABI_SYSCALL_RES_NAME_CHK(semtimedop)
++- _ABI_SYSCALL_RES_NAME_CHK(msgsnd)
++- _ABI_SYSCALL_RES_NAME_CHK(msgrcv)
++- _ABI_SYSCALL_RES_NAME_CHK(msgget)
++- _ABI_SYSCALL_RES_NAME_CHK(msgctl)
++- _ABI_SYSCALL_RES_NAME_CHK(shmat)
++- _ABI_SYSCALL_RES_NAME_CHK(shmdt)
++- _ABI_SYSCALL_RES_NAME_CHK(shmget)
++- _ABI_SYSCALL_RES_NAME_CHK(shmctl)
++-
++- return arch->syscall_resolve_name_raw(name);
++-}
++-
++-/**
++- * Resolve a syscall number to a name
++- * @param arch the arch definition
++- * @param num the syscall number
++- *
++- * Resolve the given syscall number to the syscall name using the syscall table.
++- * Returns a pointer to the syscall name string on success, including pseudo
++- * syscall names; returns NULL on failure.
++- *
++- */
++-const char *abi_syscall_resolve_num_munge(const struct arch_def *arch, int num)
++-{
++-
++-#define _ABI_SYSCALL_RES_NUM_CHK(NAME) \
++- if (num == __PNR_##NAME) return #NAME;
++-
++- _ABI_SYSCALL_RES_NUM_CHK(socket)
++- _ABI_SYSCALL_RES_NUM_CHK(bind)
++- _ABI_SYSCALL_RES_NUM_CHK(connect)
++- _ABI_SYSCALL_RES_NUM_CHK(listen)
++- _ABI_SYSCALL_RES_NUM_CHK(accept)
++- _ABI_SYSCALL_RES_NUM_CHK(getsockname)
++- _ABI_SYSCALL_RES_NUM_CHK(getpeername)
++- _ABI_SYSCALL_RES_NUM_CHK(socketpair)
++- _ABI_SYSCALL_RES_NUM_CHK(send)
++- _ABI_SYSCALL_RES_NUM_CHK(recv)
++- _ABI_SYSCALL_RES_NUM_CHK(sendto)
++- _ABI_SYSCALL_RES_NUM_CHK(recvfrom)
++- _ABI_SYSCALL_RES_NUM_CHK(shutdown)
++- _ABI_SYSCALL_RES_NUM_CHK(setsockopt)
++- _ABI_SYSCALL_RES_NUM_CHK(getsockopt)
++- _ABI_SYSCALL_RES_NUM_CHK(sendmsg)
++- _ABI_SYSCALL_RES_NUM_CHK(recvmsg)
++- _ABI_SYSCALL_RES_NUM_CHK(accept4)
++- _ABI_SYSCALL_RES_NUM_CHK(recvmmsg)
++- _ABI_SYSCALL_RES_NUM_CHK(sendmmsg)
++- _ABI_SYSCALL_RES_NUM_CHK(semop)
++- _ABI_SYSCALL_RES_NUM_CHK(semget)
++- _ABI_SYSCALL_RES_NUM_CHK(semctl)
++- _ABI_SYSCALL_RES_NUM_CHK(semtimedop)
++- _ABI_SYSCALL_RES_NUM_CHK(msgsnd)
++- _ABI_SYSCALL_RES_NUM_CHK(msgrcv)
++- _ABI_SYSCALL_RES_NUM_CHK(msgget)
++- _ABI_SYSCALL_RES_NUM_CHK(msgctl)
++- _ABI_SYSCALL_RES_NUM_CHK(shmat)
++- _ABI_SYSCALL_RES_NUM_CHK(shmdt)
++- _ABI_SYSCALL_RES_NUM_CHK(shmget)
++- _ABI_SYSCALL_RES_NUM_CHK(shmctl)
++-
++- return arch->syscall_resolve_num_raw(num);
++-}
++-
++-/**
++- * Check if a syscall is a socket syscall
++- * @param arch the arch definition
++- * @param sys the syscall number
++- *
++- * Returns true if the syscall is a socket related syscall, false otherwise.
++- *
++- */
++-static bool _abi_syscall_socket_test(const struct arch_def *arch, int sys)
++-{
++- const char *name;
++-
++- /* multiplexed pseduo-syscalls */
++- if (sys <= -100 && sys >= -120)
++- return true;
++-
++- name = arch->syscall_resolve_num_raw(sys);
++- if (!name)
++- return false;
++-
++-#define _ABI_SYSCALL_SOCK_CHK(NAME) \
++- if (!strcmp(name, #NAME)) return true;
++-
++- _ABI_SYSCALL_SOCK_CHK(socket)
++- _ABI_SYSCALL_SOCK_CHK(bind)
++- _ABI_SYSCALL_SOCK_CHK(connect)
++- _ABI_SYSCALL_SOCK_CHK(listen)
++- _ABI_SYSCALL_SOCK_CHK(accept)
++- _ABI_SYSCALL_SOCK_CHK(getsockname)
++- _ABI_SYSCALL_SOCK_CHK(getpeername)
++- _ABI_SYSCALL_SOCK_CHK(socketpair)
++- _ABI_SYSCALL_SOCK_CHK(send)
++- _ABI_SYSCALL_SOCK_CHK(recv)
++- _ABI_SYSCALL_SOCK_CHK(sendto)
++- _ABI_SYSCALL_SOCK_CHK(recvfrom)
++- _ABI_SYSCALL_SOCK_CHK(shutdown)
++- _ABI_SYSCALL_SOCK_CHK(setsockopt)
++- _ABI_SYSCALL_SOCK_CHK(getsockopt)
++- _ABI_SYSCALL_SOCK_CHK(sendmsg)
++- _ABI_SYSCALL_SOCK_CHK(recvmsg)
++- _ABI_SYSCALL_SOCK_CHK(accept4)
++- _ABI_SYSCALL_SOCK_CHK(recvmmsg)
++- _ABI_SYSCALL_SOCK_CHK(sendmmsg)
++-
++- return false;
++-}
++-
++-/**
++- * Check if a syscall is an ipc syscall
++- * @param arch the arch definition
++- * @param sys the syscall number
++- *
++- * Returns true if the syscall is an ipc related syscall, false otherwise.
++- *
++- */
++-static bool _abi_syscall_ipc_test(const struct arch_def *arch, int sys)
++-{
++- const char *name;
++-
++- /* multiplexed pseduo-syscalls */
++- if (sys <= -200 && sys >= -224)
++- return true;
++-
++- name = arch->syscall_resolve_num_raw(sys);
++- if (!name)
++- return false;
++-
++-#define _ABI_SYSCALL_IPC_CHK(NAME) \
++- if (!strcmp(name, #NAME)) return true;
++-
++- _ABI_SYSCALL_IPC_CHK(semop)
++- _ABI_SYSCALL_IPC_CHK(semget)
++- _ABI_SYSCALL_IPC_CHK(semctl)
++- _ABI_SYSCALL_IPC_CHK(semtimedop)
++- _ABI_SYSCALL_IPC_CHK(msgsnd)
++- _ABI_SYSCALL_IPC_CHK(msgrcv)
++- _ABI_SYSCALL_IPC_CHK(msgget)
++- _ABI_SYSCALL_IPC_CHK(msgctl)
++- _ABI_SYSCALL_IPC_CHK(shmat)
++- _ABI_SYSCALL_IPC_CHK(shmdt)
++- _ABI_SYSCALL_IPC_CHK(shmget)
++- _ABI_SYSCALL_IPC_CHK(shmctl)
++-
++- return false;
++-}
++-
++-/**
++- * Convert a multiplexed pseudo syscall into a direct syscall
++- * @param arch the arch definition
++- * @param syscall the multiplexed pseudo syscall number
++- *
++- * Return the related direct syscall number, __NR_SCMP_UNDEF is there is
++- * no related syscall, or __NR_SCMP_ERROR otherwise.
++- *
++- */
++-static int _abi_syscall_demux(const struct arch_def *arch, int syscall)
++-{
++- int sys = __NR_SCMP_UNDEF;
++-
++-#define _ABI_SYSCALL_DEMUX_CHK(NAME) \
++-case __PNR_##NAME: \
++- sys = arch->syscall_resolve_name_raw(#NAME); break;
++-
++- switch (syscall) {
++- _ABI_SYSCALL_DEMUX_CHK(socket)
++- _ABI_SYSCALL_DEMUX_CHK(bind)
++- _ABI_SYSCALL_DEMUX_CHK(connect)
++- _ABI_SYSCALL_DEMUX_CHK(listen)
++- _ABI_SYSCALL_DEMUX_CHK(accept)
++- _ABI_SYSCALL_DEMUX_CHK(getsockname)
++- _ABI_SYSCALL_DEMUX_CHK(getpeername)
++- _ABI_SYSCALL_DEMUX_CHK(socketpair)
++- _ABI_SYSCALL_DEMUX_CHK(send)
++- _ABI_SYSCALL_DEMUX_CHK(recv)
++- _ABI_SYSCALL_DEMUX_CHK(sendto)
++- _ABI_SYSCALL_DEMUX_CHK(recvfrom)
++- _ABI_SYSCALL_DEMUX_CHK(shutdown)
++- _ABI_SYSCALL_DEMUX_CHK(setsockopt)
++- _ABI_SYSCALL_DEMUX_CHK(getsockopt)
++- _ABI_SYSCALL_DEMUX_CHK(sendmsg)
++- _ABI_SYSCALL_DEMUX_CHK(recvmsg)
++- _ABI_SYSCALL_DEMUX_CHK(accept4)
++- _ABI_SYSCALL_DEMUX_CHK(recvmmsg)
++- _ABI_SYSCALL_DEMUX_CHK(sendmmsg)
++- _ABI_SYSCALL_DEMUX_CHK(semop)
++- _ABI_SYSCALL_DEMUX_CHK(semget)
++- _ABI_SYSCALL_DEMUX_CHK(semctl)
++- _ABI_SYSCALL_DEMUX_CHK(semtimedop)
++- _ABI_SYSCALL_DEMUX_CHK(msgsnd)
++- _ABI_SYSCALL_DEMUX_CHK(msgrcv)
++- _ABI_SYSCALL_DEMUX_CHK(msgget)
++- _ABI_SYSCALL_DEMUX_CHK(msgctl)
++- _ABI_SYSCALL_DEMUX_CHK(shmat)
++- _ABI_SYSCALL_DEMUX_CHK(shmdt)
++- _ABI_SYSCALL_DEMUX_CHK(shmget)
++- _ABI_SYSCALL_DEMUX_CHK(shmctl)
++- }
++-
++- /* this looks odd because the arch resolver returns _ERROR if it can't
++- * resolve the syscall, but we want to use _UNDEF for that, so we set
++- * 'sys' to a sentinel value of _UNDEF and if it is error here we know
++- * the resolve failed to find a match */
++- if (sys == __NR_SCMP_UNDEF)
++- sys = __NR_SCMP_ERROR;
++- else if (sys == __NR_SCMP_ERROR)
++- sys = __NR_SCMP_UNDEF;
++-
++- return sys;
++-}
++-
++-/**
++- * Convert a direct syscall into multiplexed pseudo socket syscall
++- * @param arch the arch definition
++- * @param syscall the direct syscall
++- *
++- * Return the related multiplexed pseduo syscall number, __NR_SCMP_UNDEF is
++- * there is no related pseudo syscall, or __NR_SCMP_ERROR otherwise.
++- *
++- */
++-static int _abi_syscall_mux(const struct arch_def *arch, int syscall)
++-{
++- const char *sys;
++-
++- sys = arch->syscall_resolve_num_raw(syscall);
++- if (!sys)
++- return __NR_SCMP_ERROR;
++-
++-#define _ABI_SYSCALL_MUX_CHK(NAME) \
++- if (!strcmp(sys, #NAME)) return __PNR_##NAME;
++-
++- _ABI_SYSCALL_MUX_CHK(socket)
++- _ABI_SYSCALL_MUX_CHK(bind)
++- _ABI_SYSCALL_MUX_CHK(connect)
++- _ABI_SYSCALL_MUX_CHK(listen)
++- _ABI_SYSCALL_MUX_CHK(accept)
++- _ABI_SYSCALL_MUX_CHK(getsockname)
++- _ABI_SYSCALL_MUX_CHK(getpeername)
++- _ABI_SYSCALL_MUX_CHK(socketpair)
++- _ABI_SYSCALL_MUX_CHK(send)
++- _ABI_SYSCALL_MUX_CHK(recv)
++- _ABI_SYSCALL_MUX_CHK(sendto)
++- _ABI_SYSCALL_MUX_CHK(recvfrom)
++- _ABI_SYSCALL_MUX_CHK(shutdown)
++- _ABI_SYSCALL_MUX_CHK(setsockopt)
++- _ABI_SYSCALL_MUX_CHK(getsockopt)
++- _ABI_SYSCALL_MUX_CHK(sendmsg)
++- _ABI_SYSCALL_MUX_CHK(recvmsg)
++- _ABI_SYSCALL_MUX_CHK(accept4)
++- _ABI_SYSCALL_MUX_CHK(recvmmsg)
++- _ABI_SYSCALL_MUX_CHK(sendmmsg)
++- _ABI_SYSCALL_MUX_CHK(semop)
++- _ABI_SYSCALL_MUX_CHK(semget)
++- _ABI_SYSCALL_MUX_CHK(semctl)
++- _ABI_SYSCALL_MUX_CHK(semtimedop)
++- _ABI_SYSCALL_MUX_CHK(msgsnd)
++- _ABI_SYSCALL_MUX_CHK(msgrcv)
++- _ABI_SYSCALL_MUX_CHK(msgget)
++- _ABI_SYSCALL_MUX_CHK(msgctl)
++- _ABI_SYSCALL_MUX_CHK(shmat)
++- _ABI_SYSCALL_MUX_CHK(shmdt)
++- _ABI_SYSCALL_MUX_CHK(shmget)
++- _ABI_SYSCALL_MUX_CHK(shmctl)
++-
++- return __NR_SCMP_ERROR;
++-}
++-
++-/**
++- * Rewrite a syscall value to match the architecture
++- * @param arch the arch definition
++- * @param syscall the syscall number
++- *
++- * Syscalls can vary across different architectures so this function rewrites
++- * the syscall into the correct value for the specified architecture. Returns
++- * zero on success, negative values on failure.
++- *
++- */
++-int abi_syscall_rewrite(const struct arch_def *arch, int *syscall)
++-{
++- int sys = *syscall;
++-
++- if (sys <= -100 && sys >= -120)
++- *syscall = arch->sys_socketcall;
++- else if (sys <= -200 && sys >= -224)
++- *syscall = arch->sys_ipc;
++- else if (sys < 0)
++- return -EDOM;
++-
++- return 0;
++-}
++-
++-/**
++- * add a new rule to the abi seccomp filter
++- * @param db the seccomp filter db
++- * @param rule the filter rule
++- *
++- * This function adds a new syscall filter to the seccomp filter db, making any
++- * necessary adjustments for the abi ABI. Returns zero on success, negative
++- * values on failure.
++- *
++- * It is important to note that in the case of failure the db may be corrupted,
++- * the caller must use the transaction mechanism if the db integrity is
++- * important.
++- *
++- */
++-int abi_rule_add(struct db_filter *db, struct db_api_rule_list *rule)
++-{
++- int rc = 0;
++- unsigned int iter;
++- int sys = rule->syscall;
++- int sys_a, sys_b;
++- struct db_api_rule_list *rule_a, *rule_b, *rule_dup = NULL;
++-
++- if (_abi_syscall_socket_test(db->arch, sys)) {
++- /* socket syscalls */
++-
++- /* strict check for the multiplexed socket syscalls */
++- for (iter = 0; iter < ARG_COUNT_MAX; iter++) {
++- if ((rule->args[iter].valid != 0) && (rule->strict)) {
++- rc = -EINVAL;
++- goto add_return;
++- }
++- }
++-
++- /* determine both the muxed and direct syscall numbers */
++- if (sys > 0) {
++- sys_a = _abi_syscall_mux(db->arch, sys);
++- if (sys_a == __NR_SCMP_ERROR) {
++- rc = __NR_SCMP_ERROR;
++- goto add_return;
++- }
++- sys_b = sys;
++- } else {
++- sys_a = sys;
++- sys_b = _abi_syscall_demux(db->arch, sys);
++- if (sys_b == __NR_SCMP_ERROR) {
++- rc = __NR_SCMP_ERROR;
++- goto add_return;
++- }
++- }
++-
++- /* use rule_a for the multiplexed syscall and use rule_b for
++- * the direct wired syscall */
++-
++- if (sys_a == __NR_SCMP_UNDEF) {
++- rule_a = NULL;
++- rule_b = rule;
++- } else if (sys_b == __NR_SCMP_UNDEF) {
++- rule_a = rule;
++- rule_b = NULL;
++- } else {
++- /* need two rules, dup the first and link together */
++- rule_a = rule;
++- rule_dup = db_rule_dup(rule_a);
++- rule_b = rule_dup;
++- if (rule_b == NULL)
++- goto add_return;
++- rule_b->prev = rule_a;
++- rule_b->next = NULL;
++- rule_a->next = rule_b;
++- }
++-
++- /* multiplexed socket syscalls */
++- if (rule_a != NULL) {
++- rule_a->syscall = db->arch->sys_socketcall;
++- rule_a->args[0].arg = 0;
++- rule_a->args[0].op = SCMP_CMP_EQ;
++- rule_a->args[0].mask = DATUM_MAX;
++- rule_a->args[0].datum = (-sys_a) % 100;
++- rule_a->args[0].valid = 1;
++- }
++-
++- /* direct wired socket syscalls */
++- if (rule_b != NULL)
++- rule_b->syscall = sys_b;
++-
++- /* we should be protected by a transaction checkpoint */
++- if (rule_a != NULL) {
++- rc = db_rule_add(db, rule_a);
++- if (rc < 0)
++- goto add_return;
++- }
++- if (rule_b != NULL) {
++- rc = db_rule_add(db, rule_b);
++- if (rc < 0)
++- goto add_return;
++- }
++- } else if (_abi_syscall_ipc_test(db->arch, sys)) {
++- /* ipc syscalls */
++-
++- /* strict check for the multiplexed socket syscalls */
++- for (iter = 0; iter < ARG_COUNT_MAX; iter++) {
++- if ((rule->args[iter].valid != 0) && (rule->strict)) {
++- rc = -EINVAL;
++- goto add_return;
++- }
++- }
++-
++- /* determine both the muxed and direct syscall numbers */
++- if (sys > 0) {
++- sys_a = _abi_syscall_mux(db->arch, sys);
++- if (sys_a == __NR_SCMP_ERROR) {
++- rc = __NR_SCMP_ERROR;
++- goto add_return;
++- }
++- sys_b = sys;
++- } else {
++- sys_a = sys;
++- sys_b = _abi_syscall_demux(db->arch, sys);
++- if (sys_b == __NR_SCMP_ERROR) {
++- rc = __NR_SCMP_ERROR;
++- goto add_return;
++- }
++- }
++-
++- /* use rule_a for the multiplexed syscall and use rule_b for
++- * the direct wired syscall */
++-
++- if (sys_a == __NR_SCMP_UNDEF) {
++- rule_a = NULL;
++- rule_b = rule;
++- } else if (sys_b == __NR_SCMP_UNDEF) {
++- rule_a = rule;
++- rule_b = NULL;
++- } else {
++- /* need two rules, dup the first and link together */
++- rule_a = rule;
++- rule_dup = db_rule_dup(rule_a);
++- rule_b = rule_dup;
++- if (rule_b == NULL)
++- goto add_return;
++- rule_b->prev = rule_a;
++- rule_b->next = NULL;
++- rule_a->next = rule_b;
++- }
++-
++- /* multiplexed socket syscalls */
++- if (rule_a != NULL) {
++- rule_a->syscall = db->arch->sys_ipc;
++- rule_a->args[0].arg = 0;
++- rule_a->args[0].op = SCMP_CMP_EQ;
++- rule_a->args[0].mask = DATUM_MAX;
++- rule_a->args[0].datum = (-sys_a) % 200;
++- rule_a->args[0].valid = 1;
++- }
++-
++- /* direct wired socket syscalls */
++- if (rule_b != NULL)
++- rule_b->syscall = sys_b;
++-
++- /* we should be protected by a transaction checkpoint */
++- if (rule_a != NULL) {
++- rc = db_rule_add(db, rule_a);
++- if (rc < 0)
++- goto add_return;
++- }
++- if (rule_b != NULL) {
++- rc = db_rule_add(db, rule_b);
++- if (rc < 0)
++- goto add_return;
++- }
++- } else if (sys >= 0) {
++- /* normal syscall processing */
++- rc = db_rule_add(db, rule);
++- if (rc < 0)
++- goto add_return;
++- } else if (rule->strict) {
++- rc = -EDOM;
++- goto add_return;
++- }
++-
++-add_return:
++- if (rule_dup != NULL)
++- free(rule_dup);
++- return rc;
++-}
++diff --git a/src/syscalls.h b/src/syscalls.h
++--- a/src/syscalls.h
+++++ b/src/syscalls.h
++@@ -59,12 +59,4 @@ int syscall_resolve_name(const char *name, int offset);
++ const char *syscall_resolve_num(int num, int offset);
++ const struct arch_syscall_def *syscall_iterate(unsigned int spot, int offset);
++
++-/* helper functions for multiplexed syscalls, e.g. socketcall(2) and ipc(2) */
++-int abi_syscall_resolve_name_munge(const struct arch_def *arch,
++- const char *name);
++-const char *abi_syscall_resolve_num_munge(const struct arch_def *arch, int num);
++-int abi_syscall_rewrite(const struct arch_def *arch, int *syscall);
++-int abi_rule_add(struct db_filter *db, struct db_api_rule_list *rule);
++-
++-
++ #endif
--- /dev/null
--- /dev/null
++REVERTS
++
++From aa0f858aa58d51c93a176c60a4c83a4a303bcffd Mon Sep 17 00:00:00 2001
++From: Paul Moore <paul@paul-moore.com>
++Date: Tue, 3 Aug 2021 14:12:50 -0400
++Subject: [PATCH] tests: various additions to improve code coverage
++
++Acked-by: Tom Hromatka <tom.hromatka@oracle.com>
++Signed-off-by: Paul Moore <paul@paul-moore.com>
++
++(imported from commit fcc601279004a7f4c2f6ebf766acb4556b0f5e65)
++---
++ tests/11-basic-basic_errors.c | 52 +++
++ tests/15-basic-resolver.c | 40 ++
++ tests/30-sim-socket_syscalls.c | 62 ++-
++ tests/33-sim-socket_syscalls_be.c | 3 +
++ tests/33-sim-socket_syscalls_be.py | 1 +
++ tests/33-sim-socket_syscalls_be.tests | 42 +-
++ tests/36-sim-ipc_syscalls.c | 3 +
++ tests/36-sim-ipc_syscalls.py | 1 +
++ tests/36-sim-ipc_syscalls.tests | 50 +--
++ tests/37-sim-ipc_syscalls_be.c | 3 +
++ tests/37-sim-ipc_syscalls_be.py | 1 +
++ tests/37-sim-ipc_syscalls_be.tests | 26 +-
++ tests/38-basic-pfc_coverage.c | 27 ++
++ tests/38-basic-pfc_coverage.pfc | 534 ++++++++++++++++++++++++++
++ tests/52-basic-load.c | 23 ++
++ 15 files changed, 804 insertions(+), 64 deletions(-)
++
++diff --git a/tests/11-basic-basic_errors.c b/tests/11-basic-basic_errors.c
++--- a/tests/11-basic-basic_errors.c
+++++ b/tests/11-basic-basic_errors.c
++@@ -29,8 +29,6 @@ int main(int argc, char *argv[])
++ int rc;
++ scmp_filter_ctx ctx;
++ uint32_t attr;
++- struct seccomp_notif *req = NULL;
++- struct seccomp_notif_resp *resp = NULL;
++
++ /* seccomp_init errors */
++ ctx = seccomp_init(SCMP_ACT_ALLOW + 1);
++@@ -125,9 +123,6 @@ int main(int argc, char *argv[])
++ return -1;
++ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_KILL, SCMP_SYS(socket), 1,
++ SCMP_A0(SCMP_CMP_EQ, 2));
++- if (rc != -EINVAL)
++- return -1;
++- rc = seccomp_rule_add_exact(ctx, 0xdeadbeef, SCMP_SYS(open), 0);
++ if (rc != -EINVAL)
++ return -1;
++ seccomp_release(ctx);
++@@ -185,53 +180,6 @@ int main(int argc, char *argv[])
++ rc = seccomp_attr_set(ctx, 1000, 1);
++ if (rc != -EINVAL)
++ return -1;
++- seccomp_release(ctx);
++- ctx = NULL;
++-
++- /* seccomp_merge() errors */
++- ctx = seccomp_init(SCMP_ACT_ALLOW);
++- if (ctx == NULL)
++- return -1;
++- rc = seccomp_merge(ctx, NULL);
++- if (rc == 0)
++- return -1;
++- seccomp_release(ctx);
++- ctx = NULL;
++-
++- /* seccomp notify errors */
++- ctx = seccomp_init(SCMP_ACT_ALLOW);
++- if (ctx == NULL)
++- return -1;
++- rc = seccomp_notify_alloc(NULL, NULL);
++- if (rc != 0)
++- return -1;
++- rc = seccomp_notify_alloc(&req, NULL);
++- if (rc != 0)
++- return -1;
++- rc = seccomp_notify_alloc(NULL, &resp);
++- if (rc != 0)
++- return -1;
++- seccomp_notify_free(NULL, NULL);
++- seccomp_notify_free(req, resp);
++- req = NULL;
++- resp = NULL;
++- rc = seccomp_notify_receive(-1, NULL);
++- if (rc == 0)
++- return -1;
++- rc = seccomp_notify_respond(-1, NULL);
++- if (rc == 0)
++- return -1;
++- rc = seccomp_notify_id_valid(-1, 0);
++- if (rc == 0)
++- return -1;
++- rc = seccomp_notify_fd(NULL);
++- if (rc == 0)
++- return -1;
++- rc = seccomp_notify_fd(ctx);
++- if (rc == 0)
++- return -1;
++- seccomp_release(ctx);
++- ctx = NULL;
++
++ return 0;
++ }
++diff --git a/tests/15-basic-resolver.c b/tests/15-basic-resolver.c
++--- a/tests/15-basic-resolver.c
+++++ b/tests/15-basic-resolver.c
++@@ -68,7 +68,6 @@ int main(int argc, char *argv[])
++ goto fail;
++
++ while ((arch = arch_list[iter++]) != -1) {
++- int sys;
++ int nr_open;
++ int nr_read;
++ int nr_socket;
++@@ -120,45 +119,6 @@ int main(int argc, char *argv[])
++ goto fail;
++ free(name);
++ name = NULL;
++-
++- /* socket pseudo-syscalls */
++- if (seccomp_syscall_resolve_name_arch(arch, "socketcall") > 0) {
++- for (sys = -101; sys >= -120; sys--) {
++- name = seccomp_syscall_resolve_num_arch(arch,
++- sys);
++- if (name == NULL)
++- goto fail;
++- free(name);
++- name = NULL;
++- }
++- }
++- /* ipc pseudo-syscalls */
++- if (seccomp_syscall_resolve_name_arch(arch, "ipc") > 0) {
++- for (sys = -201; sys >= -204; sys--) {
++- name = seccomp_syscall_resolve_num_arch(arch,
++- sys);
++- if (name == NULL)
++- goto fail;
++- free(name);
++- name = NULL;
++- }
++- for (sys = -211; sys >= -214; sys--) {
++- name = seccomp_syscall_resolve_num_arch(arch,
++- sys);
++- if (name == NULL)
++- goto fail;
++- free(name);
++- name = NULL;
++- }
++- for (sys = -221; sys >= -224; sys--) {
++- name = seccomp_syscall_resolve_num_arch(arch,
++- sys);
++- if (name == NULL)
++- goto fail;
++- free(name);
++- name = NULL;
++- }
++- }
++ }
++
++ return 0;
++diff --git a/tests/30-sim-socket_syscalls.c b/tests/30-sim-socket_syscalls.c
++--- a/tests/30-sim-socket_syscalls.c
+++++ b/tests/30-sim-socket_syscalls.c
++@@ -61,79 +61,19 @@ int main(int argc, char *argv[])
++ if (rc != 0)
++ goto out;
++
++- rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(bind), 0);
++- if (rc != 0)
++- goto out;
++-
++ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(connect), 0);
++ if (rc != 0)
++ goto out;
++
++- rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(listen), 0);
++- if (rc != 0)
++- goto out;
++-
++ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept), 0);
++ if (rc != 0)
++ goto out;
++
++- rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockname), 0);
++- if (rc != 0)
++- goto out;
++-
++- rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getpeername), 0);
++- if (rc != 0)
++- goto out;
++-
++- rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair), 0);
++- if (rc != 0)
++- goto out;
++-
++- rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(send), 0);
++- if (rc != 0)
++- goto out;
++-
++- rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(recv), 0);
++- if (rc != 0)
++- goto out;
++-
++- rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(sendto), 0);
++- if (rc != 0)
++- goto out;
++-
++- rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(recvfrom), 0);
++- if (rc != 0)
++- goto out;
++-
++- rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(shutdown), 0);
++- if (rc != 0)
++- goto out;
++-
++- rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt), 0);
++- if (rc != 0)
++- goto out;
++-
++- rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt), 0);
++- if (rc != 0)
++- goto out;
++-
++- rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(sendmsg), 0);
++- if (rc != 0)
++- goto out;
++-
++- rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(recvmsg), 0);
++- if (rc != 0)
++- goto out;
++-
++ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept4), 0);
++ if (rc != 0)
++ goto out;
++
++- rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(sendmmsg), 0);
++- if (rc != 0)
++- goto out;
++-
++- rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(recvmmsg), 0);
+++ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(shutdown), 0);
++ if (rc != 0)
++ goto out;
++
++diff --git a/tests/33-sim-socket_syscalls_be.c b/tests/33-sim-socket_syscalls_be.c
++--- a/tests/33-sim-socket_syscalls_be.c
+++++ b/tests/33-sim-socket_syscalls_be.c
++@@ -48,9 +48,6 @@ int main(int argc, char *argv[])
++ if (rc != 0)
++ goto out;
++ rc = seccomp_arch_add(ctx, SCMP_ARCH_S390X);
++- if (rc != 0)
++- goto out;
++- rc = seccomp_arch_add(ctx, SCMP_ARCH_PPC);
++ if (rc != 0)
++ goto out;
++
++diff --git a/tests/33-sim-socket_syscalls_be.py b/tests/33-sim-socket_syscalls_be.py
++--- a/tests/33-sim-socket_syscalls_be.py
+++++ b/tests/33-sim-socket_syscalls_be.py
++@@ -33,7 +33,6 @@ def test(args):
++ f.remove_arch(Arch())
++ f.add_arch(Arch("s390"))
++ f.add_arch(Arch("s390x"))
++- f.add_arch(Arch("ppc"))
++ f.add_rule(ALLOW, "socket")
++ f.add_rule(ALLOW, "connect")
++ f.add_rule(ALLOW, "accept")
++diff --git a/tests/33-sim-socket_syscalls_be.tests b/tests/33-sim-socket_syscalls_be.tests
++--- a/tests/33-sim-socket_syscalls_be.tests
+++++ b/tests/33-sim-socket_syscalls_be.tests
++@@ -7,23 +7,31 @@
++
++ test type: bpf-sim
++
++-# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result
++-33-sim-socket_syscalls_be +s390,+s390x,+ppc socketcall 1 N N N N N ALLOW
++-33-sim-socket_syscalls_be +s390,+s390x,+ppc socketcall 3 N N N N N ALLOW
++-33-sim-socket_syscalls_be +s390,+s390x,+ppc socketcall 5 N N N N N ALLOW
++-33-sim-socket_syscalls_be +s390,+s390x,+ppc socketcall 13 N N N N N ALLOW
++-33-sim-socket_syscalls_be +s390,+s390x 359 0 1 2 N N N ALLOW
++-33-sim-socket_syscalls_be +ppc 326 0 1 2 N N N ALLOW
++-33-sim-socket_syscalls_be +s390,+s390x 362 0 1 2 N N N ALLOW
++-33-sim-socket_syscalls_be +ppc 328 0 1 2 N N N ALLOW
++-33-sim-socket_syscalls_be +s390,+s390x 364 0 1 2 N N N ALLOW
++-33-sim-socket_syscalls_be +ppc 344 0 1 2 N N N ALLOW
++-33-sim-socket_syscalls_be +s390,+s390x 373 0 1 2 N N N ALLOW
++-33-sim-socket_syscalls_be +ppc 338 0 1 2 N N N ALLOW
++-33-sim-socket_syscalls_be +s390,+s390x,+ppc accept 5 N N N N N ALLOW
++-33-sim-socket_syscalls_be +s390,+s390x,+ppc accept 0 1 2 N N N KILL
++-33-sim-socket_syscalls_be +s390,+s390x,+ppc accept4 18 1 2 N N N ALLOW
++-33-sim-socket_syscalls_be +s390,+s390x,+ppc accept4 0 1 2 N N N KILL
+++# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result
+++33-sim-socket_syscalls_be +s390 socketcall 1 N N N N N ALLOW
+++33-sim-socket_syscalls_be +s390 socketcall 3 N N N N N ALLOW
+++33-sim-socket_syscalls_be +s390 socketcall 5 N N N N N ALLOW
+++33-sim-socket_syscalls_be +s390 socketcall 13 N N N N N ALLOW
+++33-sim-socket_syscalls_be +s390 359 0 1 2 N N N ALLOW
+++33-sim-socket_syscalls_be +s390 362 0 1 2 N N N ALLOW
+++33-sim-socket_syscalls_be +s390 364 0 1 2 N N N ALLOW
+++33-sim-socket_syscalls_be +s390 373 0 1 2 N N N ALLOW
+++33-sim-socket_syscalls_be +s390 accept 5 N N N N N ALLOW
+++33-sim-socket_syscalls_be +s390 accept 0 1 2 N N N KILL
+++33-sim-socket_syscalls_be +s390 accept4 18 1 2 N N N ALLOW
+++33-sim-socket_syscalls_be +s390 accept4 0 1 2 N N N KILL
+++33-sim-socket_syscalls_be +s390x socketcall 1 N N N N N ALLOW
+++33-sim-socket_syscalls_be +s390x socketcall 3 N N N N N ALLOW
+++33-sim-socket_syscalls_be +s390x socketcall 5 N N N N N ALLOW
+++33-sim-socket_syscalls_be +s390x socketcall 13 N N N N N ALLOW
+++33-sim-socket_syscalls_be +s390x 359 0 1 2 N N N ALLOW
+++33-sim-socket_syscalls_be +s390x 362 0 1 2 N N N ALLOW
+++33-sim-socket_syscalls_be +s390x 364 0 1 2 N N N ALLOW
+++33-sim-socket_syscalls_be +s390x 373 0 1 2 N N N ALLOW
+++33-sim-socket_syscalls_be +s390x accept 5 N N N N N ALLOW
+++33-sim-socket_syscalls_be +s390x accept 0 1 2 N N N KILL
+++33-sim-socket_syscalls_be +s390x accept4 18 1 2 N N N ALLOW
+++33-sim-socket_syscalls_be +s390x accept4 0 1 2 N N N KILL
++
++ test type: bpf-valgrind
++
++diff --git a/tests/36-sim-ipc_syscalls.c b/tests/36-sim-ipc_syscalls.c
++--- a/tests/36-sim-ipc_syscalls.c
+++++ b/tests/36-sim-ipc_syscalls.c
++@@ -54,9 +54,6 @@ int main(int argc, char *argv[])
++ if (rc != 0)
++ goto out;
++ rc = seccomp_arch_add(ctx, SCMP_ARCH_PPC64LE);
++- if (rc != 0)
++- goto out;
++- rc = seccomp_arch_add(ctx, SCMP_ARCH_MIPSEL);
++ if (rc != 0)
++ goto out;
++
++diff --git a/tests/36-sim-ipc_syscalls.py b/tests/36-sim-ipc_syscalls.py
++--- a/tests/36-sim-ipc_syscalls.py
+++++ b/tests/36-sim-ipc_syscalls.py
++@@ -35,7 +35,6 @@ def test(args):
++ f.add_arch(Arch("x86_64"))
++ f.add_arch(Arch("x32"))
++ f.add_arch(Arch("ppc64le"))
++- f.add_arch(Arch("mipsel"))
++ f.add_rule(ALLOW, "semop")
++ f.add_rule(ALLOW, "semtimedop")
++ f.add_rule(ALLOW, "semget")
++diff --git a/tests/36-sim-ipc_syscalls.tests b/tests/36-sim-ipc_syscalls.tests
++--- a/tests/36-sim-ipc_syscalls.tests
+++++ b/tests/36-sim-ipc_syscalls.tests
++@@ -7,31 +7,31 @@
++
++ test type: bpf-sim
++
++-# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result
++-36-sim-ipc_syscalls +x86,+ppc64le,+mipsel ipc 1 N N N N N ALLOW
++-36-sim-ipc_syscalls +x86,+ppc64le,+mipsel ipc 2 N N N N N ALLOW
++-36-sim-ipc_syscalls +x86,+ppc64le,+mipsel ipc 3 N N N N N ALLOW
++-36-sim-ipc_syscalls +x86,+ppc64le,+mipsel ipc 4 N N N N N ALLOW
++-36-sim-ipc_syscalls +x86,+ppc64le,+mipsel ipc 11 N N N N N ALLOW
++-36-sim-ipc_syscalls +x86,+ppc64le,+mipsel ipc 12 N N N N N ALLOW
++-36-sim-ipc_syscalls +x86,+ppc64le,+mipsel ipc 13 N N N N N ALLOW
++-36-sim-ipc_syscalls +x86,+ppc64le,+mipsel ipc 14 N N N N N ALLOW
++-36-sim-ipc_syscalls +x86,+ppc64le,+mipsel ipc 21 N N N N N ALLOW
++-36-sim-ipc_syscalls +x86,+ppc64le,+mipsel ipc 22 N N N N N ALLOW
++-36-sim-ipc_syscalls +x86,+ppc64le,+mipsel ipc 23 N N N N N ALLOW
++-36-sim-ipc_syscalls +x86,+ppc64le,+mipsel ipc 24 N N N N N ALLOW
++-36-sim-ipc_syscalls +x86_64 semop N N N N N N ALLOW
++-36-sim-ipc_syscalls +x86_64 semget N N N N N N ALLOW
++-36-sim-ipc_syscalls +x86_64 semctl N N N N N N ALLOW
++-36-sim-ipc_syscalls +x86_64 semtimedop N N N N N N ALLOW
++-36-sim-ipc_syscalls +x86_64 msgsnd N N N N N N ALLOW
++-36-sim-ipc_syscalls +x86_64 msgrcv N N N N N N ALLOW
++-36-sim-ipc_syscalls +x86_64 msgget N N N N N N ALLOW
++-36-sim-ipc_syscalls +x86_64 msgctl N N N N N N ALLOW
++-36-sim-ipc_syscalls +x86_64 shmat N N N N N N ALLOW
++-36-sim-ipc_syscalls +x86_64 shmdt N N N N N N ALLOW
++-36-sim-ipc_syscalls +x86_64 shmget N N N N N N ALLOW
++-36-sim-ipc_syscalls +x86_64 shmctl N N N N N N ALLOW
+++# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result
+++36-sim-ipc_syscalls +x86,+ppc64le ipc 1 N N N N N ALLOW
+++36-sim-ipc_syscalls +x86,+ppc64le ipc 2 N N N N N ALLOW
+++36-sim-ipc_syscalls +x86,+ppc64le ipc 3 N N N N N ALLOW
+++36-sim-ipc_syscalls +x86,+ppc64le ipc 4 N N N N N ALLOW
+++36-sim-ipc_syscalls +x86,+ppc64le ipc 11 N N N N N ALLOW
+++36-sim-ipc_syscalls +x86,+ppc64le ipc 12 N N N N N ALLOW
+++36-sim-ipc_syscalls +x86,+ppc64le ipc 13 N N N N N ALLOW
+++36-sim-ipc_syscalls +x86,+ppc64le ipc 14 N N N N N ALLOW
+++36-sim-ipc_syscalls +x86,+ppc64le ipc 21 N N N N N ALLOW
+++36-sim-ipc_syscalls +x86,+ppc64le ipc 22 N N N N N ALLOW
+++36-sim-ipc_syscalls +x86,+ppc64le ipc 23 N N N N N ALLOW
+++36-sim-ipc_syscalls +x86,+ppc64le ipc 24 N N N N N ALLOW
+++36-sim-ipc_syscalls +x86_64 semop N N N N N N ALLOW
+++36-sim-ipc_syscalls +x86_64 semget N N N N N N ALLOW
+++36-sim-ipc_syscalls +x86_64 semctl N N N N N N ALLOW
+++36-sim-ipc_syscalls +x86_64 semtimedop N N N N N N ALLOW
+++36-sim-ipc_syscalls +x86_64 msgsnd N N N N N N ALLOW
+++36-sim-ipc_syscalls +x86_64 msgrcv N N N N N N ALLOW
+++36-sim-ipc_syscalls +x86_64 msgget N N N N N N ALLOW
+++36-sim-ipc_syscalls +x86_64 msgctl N N N N N N ALLOW
+++36-sim-ipc_syscalls +x86_64 shmat N N N N N N ALLOW
+++36-sim-ipc_syscalls +x86_64 shmdt N N N N N N ALLOW
+++36-sim-ipc_syscalls +x86_64 shmget N N N N N N ALLOW
+++36-sim-ipc_syscalls +x86_64 shmctl N N N N N N ALLOW
++
++ test type: bpf-valgrind
++
++diff --git a/tests/37-sim-ipc_syscalls_be.c b/tests/37-sim-ipc_syscalls_be.c
++--- a/tests/37-sim-ipc_syscalls_be.c
+++++ b/tests/37-sim-ipc_syscalls_be.c
++@@ -48,9 +48,6 @@ int main(int argc, char *argv[])
++ if (rc != 0)
++ goto out;
++ rc = seccomp_arch_add(ctx, SCMP_ARCH_S390X);
++- if (rc != 0)
++- goto out;
++- rc = seccomp_arch_add(ctx, SCMP_ARCH_PPC);
++ if (rc != 0)
++ goto out;
++
++diff --git a/tests/37-sim-ipc_syscalls_be.py b/tests/37-sim-ipc_syscalls_be.py
++--- a/tests/37-sim-ipc_syscalls_be.py
+++++ b/tests/37-sim-ipc_syscalls_be.py
++@@ -33,7 +33,6 @@ def test(args):
++ f.remove_arch(Arch())
++ f.add_arch(Arch("s390"))
++ f.add_arch(Arch("s390x"))
++- f.add_arch(Arch("ppc"))
++ f.add_rule(ALLOW, "semop")
++ f.add_rule(ALLOW, "semtimedop")
++ f.add_rule(ALLOW, "semget")
++diff --git a/tests/37-sim-ipc_syscalls_be.tests b/tests/37-sim-ipc_syscalls_be.tests
++--- a/tests/37-sim-ipc_syscalls_be.tests
+++++ b/tests/37-sim-ipc_syscalls_be.tests
++@@ -7,19 +7,19 @@
++
++ test type: bpf-sim
++
++-# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result
++-37-sim-ipc_syscalls_be +s390,+s390x,+ppc ipc 1 N N N N N ALLOW
++-37-sim-ipc_syscalls_be +s390,+s390x,+ppc ipc 2 N N N N N ALLOW
++-37-sim-ipc_syscalls_be +s390,+s390x,+ppc ipc 3 N N N N N ALLOW
++-37-sim-ipc_syscalls_be +s390,+s390x,+ppc ipc 4 N N N N N ALLOW
++-37-sim-ipc_syscalls_be +s390,+s390x,+ppc ipc 11 N N N N N ALLOW
++-37-sim-ipc_syscalls_be +s390,+s390x,+ppc ipc 12 N N N N N ALLOW
++-37-sim-ipc_syscalls_be +s390,+s390x,+ppc ipc 13 N N N N N ALLOW
++-37-sim-ipc_syscalls_be +s390,+s390x,+ppc ipc 14 N N N N N ALLOW
++-37-sim-ipc_syscalls_be +s390,+s390x,+ppc ipc 21 N N N N N ALLOW
++-37-sim-ipc_syscalls_be +s390,+s390x,+ppc ipc 22 N N N N N ALLOW
++-37-sim-ipc_syscalls_be +s390,+s390x,+ppc ipc 23 N N N N N ALLOW
++-37-sim-ipc_syscalls_be +s390,+s390x,+ppc ipc 24 N N N N N ALLOW
+++# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result
+++37-sim-ipc_syscalls_be +s390,+s390x ipc 1 N N N N N ALLOW
+++37-sim-ipc_syscalls_be +s390,+s390x ipc 2 N N N N N ALLOW
+++37-sim-ipc_syscalls_be +s390,+s390x ipc 3 N N N N N ALLOW
+++37-sim-ipc_syscalls_be +s390,+s390x ipc 4 N N N N N ALLOW
+++37-sim-ipc_syscalls_be +s390,+s390x ipc 11 N N N N N ALLOW
+++37-sim-ipc_syscalls_be +s390,+s390x ipc 12 N N N N N ALLOW
+++37-sim-ipc_syscalls_be +s390,+s390x ipc 13 N N N N N ALLOW
+++37-sim-ipc_syscalls_be +s390,+s390x ipc 14 N N N N N ALLOW
+++37-sim-ipc_syscalls_be +s390,+s390x ipc 21 N N N N N ALLOW
+++37-sim-ipc_syscalls_be +s390,+s390x ipc 22 N N N N N ALLOW
+++37-sim-ipc_syscalls_be +s390,+s390x ipc 23 N N N N N ALLOW
+++37-sim-ipc_syscalls_be +s390,+s390x ipc 24 N N N N N ALLOW
++
++ test type: bpf-valgrind
++
++diff --git a/tests/38-basic-pfc_coverage.c b/tests/38-basic-pfc_coverage.c
++--- a/tests/38-basic-pfc_coverage.c
+++++ b/tests/38-basic-pfc_coverage.c
++@@ -55,30 +55,6 @@ int main(int argc, char *argv[])
++ if (rc < 0)
++ goto out;
++ rc = seccomp_arch_add(ctx, SCMP_ARCH_X86);
++- if (rc < 0)
++- goto out;
++- rc = seccomp_arch_add(ctx, SCMP_ARCH_X32);
++- if (rc < 0)
++- goto out;
++- rc = seccomp_arch_add(ctx, SCMP_ARCH_ARM);
++- if (rc < 0)
++- goto out;
++- rc = seccomp_arch_add(ctx, SCMP_ARCH_AARCH64);
++- if (rc < 0)
++- goto out;
++- rc = seccomp_arch_add(ctx, SCMP_ARCH_MIPSEL);
++- if (rc < 0)
++- goto out;
++- rc = seccomp_arch_add(ctx, SCMP_ARCH_MIPSEL64);
++- if (rc < 0)
++- goto out;
++- rc = seccomp_arch_add(ctx, SCMP_ARCH_MIPSEL64N32);
++- if (rc < 0)
++- goto out;
++- rc = seccomp_arch_add(ctx, SCMP_ARCH_PPC64LE);
++- if (rc < 0)
++- goto out;
++- rc = seccomp_arch_add(ctx, SCMP_ARCH_RISCV64);
++ if (rc < 0)
++ goto out;
++
++@@ -109,9 +85,6 @@ int main(int argc, char *argv[])
++ if (rc < 0)
++ goto out;
++ rc = seccomp_rule_add(ctx, SCMP_ACT_KILL_PROCESS, SCMP_SYS(fstat), 0);
++- if (rc < 0)
++- goto out;
++- rc = seccomp_rule_add(ctx, SCMP_ACT_LOG, SCMP_SYS(exit_group), 0);
++ if (rc < 0)
++ goto out;
++
++diff --git a/tests/38-basic-pfc_coverage.pfc b/tests/38-basic-pfc_coverage.pfc
++--- a/tests/38-basic-pfc_coverage.pfc
+++++ b/tests/38-basic-pfc_coverage.pfc
++@@ -3,9 +3,6 @@
++ #
++ # filter for arch x86_64 (3221225534)
++ if ($arch == 3221225534)
++- # filter for syscall "exit_group" (231) [priority: 65535]
++- if ($syscall == 231)
++- action LOG;
++ # filter for syscall "exit" (60) [priority: 65535]
++ if ($syscall == 60)
++ action TRACE(1);
++@@ -100,9 +97,6 @@ if ($arch == 3221225534)
++ action ALLOW;
++ # filter for arch x86 (1073741827)
++ if ($arch == 1073741827)
++- # filter for syscall "exit_group" (252) [priority: 65535]
++- if ($syscall == 252)
++- action LOG;
++ # filter for syscall "fstat" (108) [priority: 65535]
++ if ($syscall == 108)
++ action KILL_PROCESS;
++@@ -133,534 +127,6 @@ if ($arch == 1073741827)
++ action KILL;
++ # default action
++ action ALLOW;
++-# filter for arch x32 (3221225534)
++-if ($arch == 3221225534)
++- # filter for syscall "exit_group" (1073742055) [priority: 65535]
++- if ($syscall == 1073742055)
++- action LOG;
++- # filter for syscall "exit" (1073741884) [priority: 65535]
++- if ($syscall == 1073741884)
++- action TRACE(1);
++- # filter for syscall "fstat" (1073741829) [priority: 65535]
++- if ($syscall == 1073741829)
++- action KILL_PROCESS;
++- # filter for syscall "close" (1073741827) [priority: 65535]
++- if ($syscall == 1073741827)
++- action ERRNO(1);
++- # filter for syscall "open" (1073741826) [priority: 65535]
++- if ($syscall == 1073741826)
++- action KILL;
++- # filter for syscall "write" (1073741825) [priority: 65532]
++- if ($syscall == 1073741825)
++- if ($a0 == 0)
++- else
++- if ($a1 > 1)
++- else
++- if ($a2 >= 2)
++- else
++- action TRAP;
++- # filter for syscall "read" (1073741824) [priority: 65531]
++- if ($syscall == 1073741824)
++- if ($a0 == 0)
++- if ($a1 >= 1)
++- if ($a2 > 2)
++- if ($a3 & 0x0000000f == 3)
++- action KILL;
++- # default action
++- action ALLOW;
++-# filter for arch arm (1073741864)
++-if ($arch == 1073741864)
++- # filter for syscall "exit_group" (248) [priority: 65535]
++- if ($syscall == 248)
++- action LOG;
++- # filter for syscall "fstat" (108) [priority: 65535]
++- if ($syscall == 108)
++- action KILL_PROCESS;
++- # filter for syscall "close" (6) [priority: 65535]
++- if ($syscall == 6)
++- action ERRNO(1);
++- # filter for syscall "open" (5) [priority: 65535]
++- if ($syscall == 5)
++- action KILL;
++- # filter for syscall "exit" (1) [priority: 65535]
++- if ($syscall == 1)
++- action TRACE(1);
++- # filter for syscall "write" (4) [priority: 65532]
++- if ($syscall == 4)
++- if ($a0 == 0)
++- else
++- if ($a1 > 1)
++- else
++- if ($a2 >= 2)
++- else
++- action TRAP;
++- # filter for syscall "read" (3) [priority: 65531]
++- if ($syscall == 3)
++- if ($a0 == 0)
++- if ($a1 >= 1)
++- if ($a2 > 2)
++- if ($a3 & 0x0000000f == 3)
++- action KILL;
++- # default action
++- action ALLOW;
++-# filter for arch aarch64 (3221225655)
++-if ($arch == 3221225655)
++- # filter for syscall "open" (4294957130) [priority: 65535]
++- if ($syscall == 4294957130)
++- action KILL;
++- # filter for syscall "exit_group" (94) [priority: 65535]
++- if ($syscall == 94)
++- action LOG;
++- # filter for syscall "exit" (93) [priority: 65535]
++- if ($syscall == 93)
++- action TRACE(1);
++- # filter for syscall "fstat" (80) [priority: 65535]
++- if ($syscall == 80)
++- action KILL_PROCESS;
++- # filter for syscall "close" (57) [priority: 65535]
++- if ($syscall == 57)
++- action ERRNO(1);
++- # filter for syscall "write" (64) [priority: 65527]
++- if ($syscall == 64)
++- if ($a0.hi32 == 0)
++- if ($a0.lo32 == 0)
++- else
++- if ($a1.hi32 > 0)
++- else
++- if ($a1.hi32 == 0)
++- if ($a1.lo32 > 1)
++- else
++- if ($a2.hi32 > 0)
++- else
++- if ($a2.hi32 == 0)
++- if ($a2.lo32 >= 2)
++- else
++- action TRAP;
++- else
++- action TRAP;
++- else
++- if ($a2.hi32 > 0)
++- else
++- if ($a2.hi32 == 0)
++- if ($a2.lo32 >= 2)
++- else
++- action TRAP;
++- else
++- action TRAP;
++- else
++- if ($a1.hi32 > 0)
++- else
++- if ($a1.hi32 == 0)
++- if ($a1.lo32 > 1)
++- else
++- if ($a2.hi32 > 0)
++- else
++- if ($a2.hi32 == 0)
++- if ($a2.lo32 >= 2)
++- else
++- action TRAP;
++- else
++- action TRAP;
++- else
++- if ($a2.hi32 > 0)
++- else
++- if ($a2.hi32 == 0)
++- if ($a2.lo32 >= 2)
++- else
++- action TRAP;
++- else
++- action TRAP;
++- # filter for syscall "read" (63) [priority: 65525]
++- if ($syscall == 63)
++- if ($a0.hi32 == 0)
++- if ($a0.lo32 == 0)
++- if ($a1.hi32 > 0)
++- if ($a2.hi32 > 0)
++- if ($a3.hi32 & 0x00000000 == 0)
++- if ($a3.lo32 & 0x0000000f == 3)
++- action KILL;
++- else
++- if ($a2.hi32 == 0)
++- if ($a2.lo32 > 2)
++- if ($a3.hi32 & 0x00000000 == 0)
++- if ($a3.lo32 & 0x0000000f == 3)
++- action KILL;
++- else
++- if ($a1.hi32 == 0)
++- if ($a1.lo32 >= 1)
++- if ($a2.hi32 > 0)
++- if ($a3.hi32 & 0x00000000 == 0)
++- if ($a3.lo32 & 0x0000000f == 3)
++- action KILL;
++- else
++- if ($a2.hi32 == 0)
++- if ($a2.lo32 > 2)
++- if ($a3.hi32 & 0x00000000 == 0)
++- if ($a3.lo32 & 0x0000000f == 3)
++- action KILL;
++- # default action
++- action ALLOW;
++-# filter for arch mipsel (1073741832)
++-if ($arch == 1073741832)
++- # filter for syscall "exit_group" (246) [priority: 65535]
++- if ($syscall == 246)
++- action LOG;
++- # filter for syscall "fstat" (108) [priority: 65535]
++- if ($syscall == 108)
++- action KILL_PROCESS;
++- # filter for syscall "close" (6) [priority: 65535]
++- if ($syscall == 6)
++- action ERRNO(1);
++- # filter for syscall "open" (5) [priority: 65535]
++- if ($syscall == 5)
++- action KILL;
++- # filter for syscall "exit" (1) [priority: 65535]
++- if ($syscall == 1)
++- action TRACE(1);
++- # filter for syscall "write" (4) [priority: 65532]
++- if ($syscall == 4)
++- if ($a0 == 0)
++- else
++- if ($a1 > 1)
++- else
++- if ($a2 >= 2)
++- else
++- action TRAP;
++- # filter for syscall "read" (3) [priority: 65531]
++- if ($syscall == 3)
++- if ($a0 == 0)
++- if ($a1 >= 1)
++- if ($a2 > 2)
++- if ($a3 & 0x0000000f == 3)
++- action KILL;
++- # default action
++- action ALLOW;
++-# filter for arch mipsel64 (3221225480)
++-if ($arch == 3221225480)
++- # filter for syscall "exit_group" (5205) [priority: 65535]
++- if ($syscall == 5205)
++- action LOG;
++- # filter for syscall "exit" (5058) [priority: 65535]
++- if ($syscall == 5058)
++- action TRACE(1);
++- # filter for syscall "fstat" (5005) [priority: 65535]
++- if ($syscall == 5005)
++- action KILL_PROCESS;
++- # filter for syscall "close" (5003) [priority: 65535]
++- if ($syscall == 5003)
++- action ERRNO(1);
++- # filter for syscall "open" (5002) [priority: 65535]
++- if ($syscall == 5002)
++- action KILL;
++- # filter for syscall "write" (5001) [priority: 65527]
++- if ($syscall == 5001)
++- if ($a0.hi32 == 0)
++- if ($a0.lo32 == 0)
++- else
++- if ($a1.hi32 > 0)
++- else
++- if ($a1.hi32 == 0)
++- if ($a1.lo32 > 1)
++- else
++- if ($a2.hi32 > 0)
++- else
++- if ($a2.hi32 == 0)
++- if ($a2.lo32 >= 2)
++- else
++- action TRAP;
++- else
++- action TRAP;
++- else
++- if ($a2.hi32 > 0)
++- else
++- if ($a2.hi32 == 0)
++- if ($a2.lo32 >= 2)
++- else
++- action TRAP;
++- else
++- action TRAP;
++- else
++- if ($a1.hi32 > 0)
++- else
++- if ($a1.hi32 == 0)
++- if ($a1.lo32 > 1)
++- else
++- if ($a2.hi32 > 0)
++- else
++- if ($a2.hi32 == 0)
++- if ($a2.lo32 >= 2)
++- else
++- action TRAP;
++- else
++- action TRAP;
++- else
++- if ($a2.hi32 > 0)
++- else
++- if ($a2.hi32 == 0)
++- if ($a2.lo32 >= 2)
++- else
++- action TRAP;
++- else
++- action TRAP;
++- # filter for syscall "read" (5000) [priority: 65525]
++- if ($syscall == 5000)
++- if ($a0.hi32 == 0)
++- if ($a0.lo32 == 0)
++- if ($a1.hi32 > 0)
++- if ($a2.hi32 > 0)
++- if ($a3.hi32 & 0x00000000 == 0)
++- if ($a3.lo32 & 0x0000000f == 3)
++- action KILL;
++- else
++- if ($a2.hi32 == 0)
++- if ($a2.lo32 > 2)
++- if ($a3.hi32 & 0x00000000 == 0)
++- if ($a3.lo32 & 0x0000000f == 3)
++- action KILL;
++- else
++- if ($a1.hi32 == 0)
++- if ($a1.lo32 >= 1)
++- if ($a2.hi32 > 0)
++- if ($a3.hi32 & 0x00000000 == 0)
++- if ($a3.lo32 & 0x0000000f == 3)
++- action KILL;
++- else
++- if ($a2.hi32 == 0)
++- if ($a2.lo32 > 2)
++- if ($a3.hi32 & 0x00000000 == 0)
++- if ($a3.lo32 & 0x0000000f == 3)
++- action KILL;
++- # default action
++- action ALLOW;
++-# filter for arch mipsel64n32 (3758096392)
++-if ($arch == 3758096392)
++- # filter for syscall "exit_group" (6205) [priority: 65535]
++- if ($syscall == 6205)
++- action LOG;
++- # filter for syscall "exit" (6058) [priority: 65535]
++- if ($syscall == 6058)
++- action TRACE(1);
++- # filter for syscall "fstat" (6005) [priority: 65535]
++- if ($syscall == 6005)
++- action KILL_PROCESS;
++- # filter for syscall "close" (6003) [priority: 65535]
++- if ($syscall == 6003)
++- action ERRNO(1);
++- # filter for syscall "open" (6002) [priority: 65535]
++- if ($syscall == 6002)
++- action KILL;
++- # filter for syscall "write" (6001) [priority: 65532]
++- if ($syscall == 6001)
++- if ($a0 == 0)
++- else
++- if ($a1 > 1)
++- else
++- if ($a2 >= 2)
++- else
++- action TRAP;
++- # filter for syscall "read" (6000) [priority: 65531]
++- if ($syscall == 6000)
++- if ($a0 == 0)
++- if ($a1 >= 1)
++- if ($a2 > 2)
++- if ($a3 & 0x0000000f == 3)
++- action KILL;
++- # default action
++- action ALLOW;
++-# filter for arch ppc64le (3221225493)
++-if ($arch == 3221225493)
++- # filter for syscall "exit_group" (234) [priority: 65535]
++- if ($syscall == 234)
++- action LOG;
++- # filter for syscall "fstat" (108) [priority: 65535]
++- if ($syscall == 108)
++- action KILL_PROCESS;
++- # filter for syscall "close" (6) [priority: 65535]
++- if ($syscall == 6)
++- action ERRNO(1);
++- # filter for syscall "open" (5) [priority: 65535]
++- if ($syscall == 5)
++- action KILL;
++- # filter for syscall "exit" (1) [priority: 65535]
++- if ($syscall == 1)
++- action TRACE(1);
++- # filter for syscall "write" (4) [priority: 65527]
++- if ($syscall == 4)
++- if ($a0.hi32 == 0)
++- if ($a0.lo32 == 0)
++- else
++- if ($a1.hi32 > 0)
++- else
++- if ($a1.hi32 == 0)
++- if ($a1.lo32 > 1)
++- else
++- if ($a2.hi32 > 0)
++- else
++- if ($a2.hi32 == 0)
++- if ($a2.lo32 >= 2)
++- else
++- action TRAP;
++- else
++- action TRAP;
++- else
++- if ($a2.hi32 > 0)
++- else
++- if ($a2.hi32 == 0)
++- if ($a2.lo32 >= 2)
++- else
++- action TRAP;
++- else
++- action TRAP;
++- else
++- if ($a1.hi32 > 0)
++- else
++- if ($a1.hi32 == 0)
++- if ($a1.lo32 > 1)
++- else
++- if ($a2.hi32 > 0)
++- else
++- if ($a2.hi32 == 0)
++- if ($a2.lo32 >= 2)
++- else
++- action TRAP;
++- else
++- action TRAP;
++- else
++- if ($a2.hi32 > 0)
++- else
++- if ($a2.hi32 == 0)
++- if ($a2.lo32 >= 2)
++- else
++- action TRAP;
++- else
++- action TRAP;
++- # filter for syscall "read" (3) [priority: 65525]
++- if ($syscall == 3)
++- if ($a0.hi32 == 0)
++- if ($a0.lo32 == 0)
++- if ($a1.hi32 > 0)
++- if ($a2.hi32 > 0)
++- if ($a3.hi32 & 0x00000000 == 0)
++- if ($a3.lo32 & 0x0000000f == 3)
++- action KILL;
++- else
++- if ($a2.hi32 == 0)
++- if ($a2.lo32 > 2)
++- if ($a3.hi32 & 0x00000000 == 0)
++- if ($a3.lo32 & 0x0000000f == 3)
++- action KILL;
++- else
++- if ($a1.hi32 == 0)
++- if ($a1.lo32 >= 1)
++- if ($a2.hi32 > 0)
++- if ($a3.hi32 & 0x00000000 == 0)
++- if ($a3.lo32 & 0x0000000f == 3)
++- action KILL;
++- else
++- if ($a2.hi32 == 0)
++- if ($a2.lo32 > 2)
++- if ($a3.hi32 & 0x00000000 == 0)
++- if ($a3.lo32 & 0x0000000f == 3)
++- action KILL;
++- # default action
++- action ALLOW;
++-# filter for arch riscv64 (3221225715)
++-if ($arch == 3221225715)
++- # filter for syscall "open" (4294957130) [priority: 65535]
++- if ($syscall == 4294957130)
++- action KILL;
++- # filter for syscall "exit_group" (94) [priority: 65535]
++- if ($syscall == 94)
++- action LOG;
++- # filter for syscall "exit" (93) [priority: 65535]
++- if ($syscall == 93)
++- action TRACE(1);
++- # filter for syscall "fstat" (80) [priority: 65535]
++- if ($syscall == 80)
++- action KILL_PROCESS;
++- # filter for syscall "close" (57) [priority: 65535]
++- if ($syscall == 57)
++- action ERRNO(1);
++- # filter for syscall "write" (64) [priority: 65527]
++- if ($syscall == 64)
++- if ($a0.hi32 == 0)
++- if ($a0.lo32 == 0)
++- else
++- if ($a1.hi32 > 0)
++- else
++- if ($a1.hi32 == 0)
++- if ($a1.lo32 > 1)
++- else
++- if ($a2.hi32 > 0)
++- else
++- if ($a2.hi32 == 0)
++- if ($a2.lo32 >= 2)
++- else
++- action TRAP;
++- else
++- action TRAP;
++- else
++- if ($a2.hi32 > 0)
++- else
++- if ($a2.hi32 == 0)
++- if ($a2.lo32 >= 2)
++- else
++- action TRAP;
++- else
++- action TRAP;
++- else
++- if ($a1.hi32 > 0)
++- else
++- if ($a1.hi32 == 0)
++- if ($a1.lo32 > 1)
++- else
++- if ($a2.hi32 > 0)
++- else
++- if ($a2.hi32 == 0)
++- if ($a2.lo32 >= 2)
++- else
++- action TRAP;
++- else
++- action TRAP;
++- else
++- if ($a2.hi32 > 0)
++- else
++- if ($a2.hi32 == 0)
++- if ($a2.lo32 >= 2)
++- else
++- action TRAP;
++- else
++- action TRAP;
++- # filter for syscall "read" (63) [priority: 65525]
++- if ($syscall == 63)
++- if ($a0.hi32 == 0)
++- if ($a0.lo32 == 0)
++- if ($a1.hi32 > 0)
++- if ($a2.hi32 > 0)
++- if ($a3.hi32 & 0x00000000 == 0)
++- if ($a3.lo32 & 0x0000000f == 3)
++- action KILL;
++- else
++- if ($a2.hi32 == 0)
++- if ($a2.lo32 > 2)
++- if ($a3.hi32 & 0x00000000 == 0)
++- if ($a3.lo32 & 0x0000000f == 3)
++- action KILL;
++- else
++- if ($a1.hi32 == 0)
++- if ($a1.lo32 >= 1)
++- if ($a2.hi32 > 0)
++- if ($a3.hi32 & 0x00000000 == 0)
++- if ($a3.lo32 & 0x0000000f == 3)
++- action KILL;
++- else
++- if ($a2.hi32 == 0)
++- if ($a2.lo32 > 2)
++- if ($a3.hi32 & 0x00000000 == 0)
++- if ($a3.lo32 & 0x0000000f == 3)
++- action KILL;
++- # default action
++- action ALLOW;
++ # invalid architecture action
++ action KILL;
++ #
++diff --git a/tests/52-basic-load.c b/tests/52-basic-load.c
++--- a/tests/52-basic-load.c
+++++ b/tests/52-basic-load.c
++@@ -31,38 +31,15 @@ int main(int argc, char *argv[])
++ int rc;
++ struct util_options opts;
++ scmp_filter_ctx ctx = NULL;
++- unsigned int api;
++
++ rc = util_getopt(argc, argv, &opts);
++ if (rc < 0)
++ goto out;
++
++- api = seccomp_api_get();
++- if (api == 0) {
++- rc = -EFAULT;
++- goto out;
++- }
++-
++ ctx = seccomp_init(SCMP_ACT_ALLOW);
++ if (ctx == NULL)
++ return ENOMEM;
++
++- if (api >= 2) {
++- rc = seccomp_attr_set(ctx, SCMP_FLTATR_CTL_TSYNC, 1);
++- if (rc != 0)
++- goto out;
++- }
++- if (api >= 3) {
++- rc = seccomp_attr_set(ctx, SCMP_FLTATR_CTL_LOG, 1);
++- if (rc != 0)
++- goto out;
++- }
++- if (api >= 4) {
++- rc = seccomp_attr_set(ctx, SCMP_FLTATR_CTL_SSB, 1);
++- if (rc != 0)
++- goto out;
++- }
++-
++ rc = seccomp_load(ctx);
++
++ out: