.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,
};
/**
* 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.
* 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;
/**
* 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.
* 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 = {
.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,
};
#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 = {
.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,
};
/**
* 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.
* 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;
/**
* 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.
* 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 = {
.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,
};
.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,
};
/**
* 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.
* 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;
/**
* 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.
* 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)
.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,
};
.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,
};
.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,
};
.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,
};
#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,
};
#include <linux/audit.h>
#include "db.h"
-#include "syscalls.h"
#include "arch.h"
#include "arch-ppc64.h"
#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 = {
.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,
};
.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,
};
#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,
};
#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,
};
/**
* 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.
* 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;
/**
* 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.
* 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 = {
.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,
};
#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,
};
.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,
};
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;
}
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;
}
} 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 */
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);
};
/**
- * 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>
* 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"
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;
-}
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