revert_arch_consolidate_all_of_the_multiplexed_syscall_handling
authorKees Cook <kees@debian.org>
Sun, 3 Oct 2021 21:26:59 +0000 (22:26 +0100)
committerFelix Geyer <fgeyer@debian.org>
Sun, 3 Oct 2021 21:26:59 +0000 (22:26 +0100)
REVERTS

From f454456e261930d94b3a1a444b6bac75c11c3cb0 Mon Sep 17 00:00:00 2001
From: Paul Moore <paul@paul-moore.com>
Date: Wed, 4 Aug 2021 11:51:12 -0400
Subject: [PATCH] arch: consolidate all of the multiplexed syscall handling

Not only does this reduce the amount of duplicated code
significantly, it removes a lot of the "magic" numbers in the
code, and it happened to catch some bugs too.

Acked-by: Tom Hromatka <tom.hromatka@oracle.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
(imported from commit 17cbd2c253ce63e5e9e3cec867ff58efbe8b5fdc)

Gbp-Pq: Name revert_arch_consolidate_all_of_the_multiplexed_syscall_handling.patch

19 files changed:
src/arch-aarch64.c
src/arch-arm.c
src/arch-mips.c
src/arch-mips64.c
src/arch-mips64n32.c
src/arch-parisc.c
src/arch-parisc64.c
src/arch-ppc.c
src/arch-ppc64.c
src/arch-riscv64.c
src/arch-s390.c
src/arch-s390x.c
src/arch-x32.c
src/arch-x86.c
src/arch-x86_64.c
src/arch.c
src/arch.h
src/syscalls.c
src/syscalls.h

index b2d76c63ef5ebde3b45a97848daa9c0970525935..188bc6f8a2af0bcf17b9c91a5e0a71438b3405a2 100644 (file)
@@ -31,8 +31,8 @@ const struct arch_def arch_def_aarch64 = {
        .token_bpf = AUDIT_ARCH_AARCH64,
        .size = ARCH_SIZE_64,
        .endian = ARCH_ENDIAN_LITTLE,
-       .syscall_resolve_name_raw = aarch64_syscall_resolve_name,
-       .syscall_resolve_num_raw = aarch64_syscall_resolve_num,
+       .syscall_resolve_name = aarch64_syscall_resolve_name,
+       .syscall_resolve_num = aarch64_syscall_resolve_num,
        .syscall_rewrite = NULL,
        .rule_add = NULL,
 };
index 732940e3e784329a2535f41e2b7fe4fc4a787eb6..9c9153ae69b0e9a895c736daf0aea2605f166c9a 100644 (file)
@@ -39,7 +39,6 @@
 
 /**
  * Resolve a syscall name to a number
- * @param arch the architecture definition
  * @param name the syscall name
  *
  * Resolve the given syscall name to the syscall number using the syscall table.
  * numbers; returns __NR_SCMP_ERROR on failure.
  *
  */
-int arm_syscall_resolve_name_munge(const struct arch_def *arch,
-                                  const char *name)
+int arm_syscall_resolve_name_munge(const char *name)
 {
        int sys;
 
        /* NOTE: we don't want to modify the pseudo-syscall numbers */
-       sys = arch->syscall_resolve_name_raw(name);
+       sys = arm_syscall_resolve_name(name);
        if (sys == __NR_SCMP_ERROR || sys < 0)
                return sys;
 
@@ -62,7 +60,6 @@ int arm_syscall_resolve_name_munge(const struct arch_def *arch,
 
 /**
  * Resolve a syscall number to a name
- * @param arch the architecture definition
  * @param num the syscall number
  *
  * Resolve the given syscall number to the syscall name using the syscall table.
@@ -70,12 +67,12 @@ int arm_syscall_resolve_name_munge(const struct arch_def *arch,
  * syscall names; returns NULL on failure.
  *
  */
-const char *arm_syscall_resolve_num_munge(const struct arch_def *arch, int num)
+const char *arm_syscall_resolve_num_munge(int num)
 {
        /* NOTE: we don't want to modify the pseudo-syscall numbers */
        if (num >= 0)
                num &= ~__SCMP_NR_BASE;
-       return arch->syscall_resolve_num_raw(num);
+       return arm_syscall_resolve_num(num);
 }
 
 const struct arch_def arch_def_arm = {
@@ -84,9 +81,7 @@ const struct arch_def arch_def_arm = {
        .size = ARCH_SIZE_32,
        .endian = ARCH_ENDIAN_LITTLE,
        .syscall_resolve_name = arm_syscall_resolve_name_munge,
-       .syscall_resolve_name_raw = arm_syscall_resolve_name,
        .syscall_resolve_num = arm_syscall_resolve_num_munge,
-       .syscall_resolve_num_raw = arm_syscall_resolve_num,
        .syscall_rewrite = NULL,
        .rule_add = NULL,
 };
index 2625ddcaca15fed9dd390716d60756df5b880238..1510d824c2bb0ef52ef3f40a04cac2bdb4ce8fb5 100644 (file)
 #include "arch.h"
 #include "arch-mips.h"
 
+/* O32 ABI */
+#define __SCMP_NR_BASE                 4000
+
 /* mips syscall numbers */
 #define __mips_NR_socketcall           102
 #define __mips_NR_ipc                  117
 
+/**
+ * Resolve a syscall name to a number
+ * @param name the syscall name
+ *
+ * Resolve the given syscall name to the syscall number using the syscall table.
+ * Returns the syscall number on success, including negative pseudo syscall
+ * numbers; returns __NR_SCMP_ERROR on failure.
+ *
+ */
+int mips_syscall_resolve_name_munge(const char *name)
+{
+
+#define _ABI_SYSCALL_RES_NAME_CHK(NAME) \
+       if (!strcmp(name, #NAME)) return __PNR_##NAME;
+
+       _ABI_SYSCALL_RES_NAME_CHK(socket)
+       _ABI_SYSCALL_RES_NAME_CHK(bind)
+       _ABI_SYSCALL_RES_NAME_CHK(connect)
+       _ABI_SYSCALL_RES_NAME_CHK(listen)
+       _ABI_SYSCALL_RES_NAME_CHK(accept)
+       _ABI_SYSCALL_RES_NAME_CHK(getsockname)
+       _ABI_SYSCALL_RES_NAME_CHK(getpeername)
+       _ABI_SYSCALL_RES_NAME_CHK(socketpair)
+       _ABI_SYSCALL_RES_NAME_CHK(send)
+       _ABI_SYSCALL_RES_NAME_CHK(recv)
+       _ABI_SYSCALL_RES_NAME_CHK(sendto)
+       _ABI_SYSCALL_RES_NAME_CHK(recvfrom)
+       _ABI_SYSCALL_RES_NAME_CHK(shutdown)
+       _ABI_SYSCALL_RES_NAME_CHK(setsockopt)
+       _ABI_SYSCALL_RES_NAME_CHK(getsockopt)
+       _ABI_SYSCALL_RES_NAME_CHK(sendmsg)
+       _ABI_SYSCALL_RES_NAME_CHK(recvmsg)
+       _ABI_SYSCALL_RES_NAME_CHK(accept4)
+       _ABI_SYSCALL_RES_NAME_CHK(recvmmsg)
+       _ABI_SYSCALL_RES_NAME_CHK(sendmmsg)
+       _ABI_SYSCALL_RES_NAME_CHK(semop)
+       _ABI_SYSCALL_RES_NAME_CHK(semget)
+       _ABI_SYSCALL_RES_NAME_CHK(semctl)
+       _ABI_SYSCALL_RES_NAME_CHK(semtimedop)
+       _ABI_SYSCALL_RES_NAME_CHK(msgsnd)
+       _ABI_SYSCALL_RES_NAME_CHK(msgrcv)
+       _ABI_SYSCALL_RES_NAME_CHK(msgget)
+       _ABI_SYSCALL_RES_NAME_CHK(msgctl)
+       _ABI_SYSCALL_RES_NAME_CHK(shmat)
+       _ABI_SYSCALL_RES_NAME_CHK(shmdt)
+       _ABI_SYSCALL_RES_NAME_CHK(shmget)
+       _ABI_SYSCALL_RES_NAME_CHK(shmctl)
+
+       return mips_syscall_resolve_name(name);
+}
+
+/**
+ * Resolve a syscall number to a name
+ * @param num the syscall number
+ *
+ * Resolve the given syscall number to the syscall name using the syscall table.
+ * Returns a pointer to the syscall name string on success, including pseudo
+ * syscall names; returns NULL on failure.
+ *
+ */
+const char *mips_syscall_resolve_num_munge(int num)
+{
+
+#define _ABI_SYSCALL_RES_NUM_CHK(NAME) \
+       if (num == __PNR_##NAME) return #NAME;
+
+       _ABI_SYSCALL_RES_NUM_CHK(socket)
+       _ABI_SYSCALL_RES_NUM_CHK(bind)
+       _ABI_SYSCALL_RES_NUM_CHK(connect)
+       _ABI_SYSCALL_RES_NUM_CHK(listen)
+       _ABI_SYSCALL_RES_NUM_CHK(accept)
+       _ABI_SYSCALL_RES_NUM_CHK(getsockname)
+       _ABI_SYSCALL_RES_NUM_CHK(getpeername)
+       _ABI_SYSCALL_RES_NUM_CHK(socketpair)
+       _ABI_SYSCALL_RES_NUM_CHK(send)
+       _ABI_SYSCALL_RES_NUM_CHK(recv)
+       _ABI_SYSCALL_RES_NUM_CHK(sendto)
+       _ABI_SYSCALL_RES_NUM_CHK(recvfrom)
+       _ABI_SYSCALL_RES_NUM_CHK(shutdown)
+       _ABI_SYSCALL_RES_NUM_CHK(setsockopt)
+       _ABI_SYSCALL_RES_NUM_CHK(getsockopt)
+       _ABI_SYSCALL_RES_NUM_CHK(sendmsg)
+       _ABI_SYSCALL_RES_NUM_CHK(recvmsg)
+       _ABI_SYSCALL_RES_NUM_CHK(accept4)
+       _ABI_SYSCALL_RES_NUM_CHK(recvmmsg)
+       _ABI_SYSCALL_RES_NUM_CHK(sendmmsg)
+       _ABI_SYSCALL_RES_NUM_CHK(semop)
+       _ABI_SYSCALL_RES_NUM_CHK(semget)
+       _ABI_SYSCALL_RES_NUM_CHK(semctl)
+       _ABI_SYSCALL_RES_NUM_CHK(semtimedop)
+       _ABI_SYSCALL_RES_NUM_CHK(msgsnd)
+       _ABI_SYSCALL_RES_NUM_CHK(msgrcv)
+       _ABI_SYSCALL_RES_NUM_CHK(msgget)
+       _ABI_SYSCALL_RES_NUM_CHK(msgctl)
+       _ABI_SYSCALL_RES_NUM_CHK(shmat)
+       _ABI_SYSCALL_RES_NUM_CHK(shmdt)
+       _ABI_SYSCALL_RES_NUM_CHK(shmget)
+       _ABI_SYSCALL_RES_NUM_CHK(shmctl)
+
+       return mips_syscall_resolve_num(num);
+}
+
+/**
+ * Check if a syscall is a socket syscall
+ * @param sys the syscall number
+ *
+ * Returns true if the syscall is a socket related syscall, false otherwise.
+ *
+ */
+static bool _mips_syscall_socket_test(int sys)
+{
+       const char *name;
+
+       /* multiplexed pseduo-syscalls */
+       if (sys <= -100 && sys >= -120)
+               return true;
+
+       name = mips_syscall_resolve_num(sys);
+       if (!name)
+               return false;
+
+#define _ABI_SYSCALL_SOCK_CHK(NAME) \
+       if (!strcmp(name, #NAME)) return true;
+
+       _ABI_SYSCALL_SOCK_CHK(socket)
+       _ABI_SYSCALL_SOCK_CHK(bind)
+       _ABI_SYSCALL_SOCK_CHK(connect)
+       _ABI_SYSCALL_SOCK_CHK(listen)
+       _ABI_SYSCALL_SOCK_CHK(accept)
+       _ABI_SYSCALL_SOCK_CHK(getsockname)
+       _ABI_SYSCALL_SOCK_CHK(getpeername)
+       _ABI_SYSCALL_SOCK_CHK(socketpair)
+       _ABI_SYSCALL_SOCK_CHK(send)
+       _ABI_SYSCALL_SOCK_CHK(recv)
+       _ABI_SYSCALL_SOCK_CHK(sendto)
+       _ABI_SYSCALL_SOCK_CHK(recvfrom)
+       _ABI_SYSCALL_SOCK_CHK(shutdown)
+       _ABI_SYSCALL_SOCK_CHK(setsockopt)
+       _ABI_SYSCALL_SOCK_CHK(getsockopt)
+       _ABI_SYSCALL_SOCK_CHK(sendmsg)
+       _ABI_SYSCALL_SOCK_CHK(recvmsg)
+       _ABI_SYSCALL_SOCK_CHK(accept4)
+       _ABI_SYSCALL_SOCK_CHK(recvmmsg)
+       _ABI_SYSCALL_SOCK_CHK(sendmmsg)
+
+       return false;
+}
+
+/**
+ * Check if a syscall is an ipc syscall
+ * @param sys the syscall number
+ *
+ * Returns true if the syscall is an ipc related syscall, false otherwise.
+ *
+ */
+static bool _mips_syscall_ipc_test(int sys)
+{
+       const char *name;
+
+       /* multiplexed pseduo-syscalls */
+       if (sys <= -200 && sys >= -224)
+               return true;
+
+       name = mips_syscall_resolve_num(sys);
+       if (!name)
+               return false;
+
+#define _ABI_SYSCALL_IPC_CHK(NAME) \
+       if (!strcmp(name, #NAME)) return true;
+
+       _ABI_SYSCALL_IPC_CHK(semop)
+       _ABI_SYSCALL_IPC_CHK(semget)
+       _ABI_SYSCALL_IPC_CHK(semctl)
+       _ABI_SYSCALL_IPC_CHK(semtimedop)
+       _ABI_SYSCALL_IPC_CHK(msgsnd)
+       _ABI_SYSCALL_IPC_CHK(msgrcv)
+       _ABI_SYSCALL_IPC_CHK(msgget)
+       _ABI_SYSCALL_IPC_CHK(msgctl)
+       _ABI_SYSCALL_IPC_CHK(shmat)
+       _ABI_SYSCALL_IPC_CHK(shmdt)
+       _ABI_SYSCALL_IPC_CHK(shmget)
+       _ABI_SYSCALL_IPC_CHK(shmctl)
+
+       return false;
+}
+
+/**
+ * Convert a multiplexed pseudo syscall into a direct syscall
+ * @param syscall the multiplexed pseudo syscall number
+ *
+ * Return the related direct syscall number, __NR_SCMP_UNDEF is there is
+ * no related syscall, or __NR_SCMP_ERROR otherwise.
+ *
+ */
+static int _mips_syscall_demux(int syscall)
+{
+       int sys = __NR_SCMP_UNDEF;
+
+#define _ABI_SYSCALL_DEMUX_CHK(NAME) \
+case __PNR_##NAME: \
+       sys = mips_syscall_resolve_name(#NAME); break;
+
+       switch (syscall) {
+               _ABI_SYSCALL_DEMUX_CHK(socket)
+               _ABI_SYSCALL_DEMUX_CHK(bind)
+               _ABI_SYSCALL_DEMUX_CHK(connect)
+               _ABI_SYSCALL_DEMUX_CHK(listen)
+               _ABI_SYSCALL_DEMUX_CHK(accept)
+               _ABI_SYSCALL_DEMUX_CHK(getsockname)
+               _ABI_SYSCALL_DEMUX_CHK(getpeername)
+               _ABI_SYSCALL_DEMUX_CHK(socketpair)
+               _ABI_SYSCALL_DEMUX_CHK(send)
+               _ABI_SYSCALL_DEMUX_CHK(recv)
+               _ABI_SYSCALL_DEMUX_CHK(sendto)
+               _ABI_SYSCALL_DEMUX_CHK(recvfrom)
+               _ABI_SYSCALL_DEMUX_CHK(shutdown)
+               _ABI_SYSCALL_DEMUX_CHK(setsockopt)
+               _ABI_SYSCALL_DEMUX_CHK(getsockopt)
+               _ABI_SYSCALL_DEMUX_CHK(sendmsg)
+               _ABI_SYSCALL_DEMUX_CHK(recvmsg)
+               _ABI_SYSCALL_DEMUX_CHK(accept4)
+               _ABI_SYSCALL_DEMUX_CHK(recvmmsg)
+               _ABI_SYSCALL_DEMUX_CHK(sendmmsg)
+               _ABI_SYSCALL_DEMUX_CHK(semop)
+               _ABI_SYSCALL_DEMUX_CHK(semget)
+               _ABI_SYSCALL_DEMUX_CHK(semctl)
+               _ABI_SYSCALL_DEMUX_CHK(semtimedop)
+               _ABI_SYSCALL_DEMUX_CHK(msgsnd)
+               _ABI_SYSCALL_DEMUX_CHK(msgrcv)
+               _ABI_SYSCALL_DEMUX_CHK(msgget)
+               _ABI_SYSCALL_DEMUX_CHK(msgctl)
+               _ABI_SYSCALL_DEMUX_CHK(shmat)
+               _ABI_SYSCALL_DEMUX_CHK(shmdt)
+               _ABI_SYSCALL_DEMUX_CHK(shmget)
+               _ABI_SYSCALL_DEMUX_CHK(shmctl)
+       }
+
+       /* this looks odd because the arch resolver returns _ERROR if it can't
+        * resolve the syscall, but we want to use _UNDEF for that, so we set
+        * 'sys' to a sentinel value of _UNDEF and if it is error here we know
+        * the resolve failed to find a match */
+       if (sys == __NR_SCMP_UNDEF)
+               sys = __NR_SCMP_ERROR;
+       else if (sys == __NR_SCMP_ERROR)
+               sys = __NR_SCMP_UNDEF;
+
+       return sys;
+}
+
+/**
+ * Convert a direct syscall into multiplexed pseudo socket syscall
+ * @param syscall the direct syscall
+ *
+ * Return the related multiplexed pseduo syscall number, __NR_SCMP_UNDEF is
+ * there is no related pseudo syscall, or __NR_SCMP_ERROR otherwise.
+ *
+ */
+static int _mips_syscall_mux(int syscall)
+{
+       const char *sys;
+
+       sys = mips_syscall_resolve_num(syscall);
+       if (!sys)
+               return __NR_SCMP_ERROR;
+
+#define _ABI_SYSCALL_MUX_CHK(NAME) \
+       if (!strcmp(sys, #NAME)) return __PNR_##NAME;
+
+       _ABI_SYSCALL_MUX_CHK(socket)
+       _ABI_SYSCALL_MUX_CHK(bind)
+       _ABI_SYSCALL_MUX_CHK(connect)
+       _ABI_SYSCALL_MUX_CHK(listen)
+       _ABI_SYSCALL_MUX_CHK(accept)
+       _ABI_SYSCALL_MUX_CHK(getsockname)
+       _ABI_SYSCALL_MUX_CHK(getpeername)
+       _ABI_SYSCALL_MUX_CHK(socketpair)
+       _ABI_SYSCALL_MUX_CHK(send)
+       _ABI_SYSCALL_MUX_CHK(recv)
+       _ABI_SYSCALL_MUX_CHK(sendto)
+       _ABI_SYSCALL_MUX_CHK(recvfrom)
+       _ABI_SYSCALL_MUX_CHK(shutdown)
+       _ABI_SYSCALL_MUX_CHK(setsockopt)
+       _ABI_SYSCALL_MUX_CHK(getsockopt)
+       _ABI_SYSCALL_MUX_CHK(sendmsg)
+       _ABI_SYSCALL_MUX_CHK(recvmsg)
+       _ABI_SYSCALL_MUX_CHK(accept4)
+       _ABI_SYSCALL_MUX_CHK(recvmmsg)
+       _ABI_SYSCALL_MUX_CHK(sendmmsg)
+       _ABI_SYSCALL_MUX_CHK(semop)
+       _ABI_SYSCALL_MUX_CHK(semget)
+       _ABI_SYSCALL_MUX_CHK(semctl)
+       _ABI_SYSCALL_MUX_CHK(semtimedop)
+       _ABI_SYSCALL_MUX_CHK(msgsnd)
+       _ABI_SYSCALL_MUX_CHK(msgrcv)
+       _ABI_SYSCALL_MUX_CHK(msgget)
+       _ABI_SYSCALL_MUX_CHK(msgctl)
+       _ABI_SYSCALL_MUX_CHK(shmat)
+       _ABI_SYSCALL_MUX_CHK(shmdt)
+       _ABI_SYSCALL_MUX_CHK(shmget)
+       _ABI_SYSCALL_MUX_CHK(shmctl)
+
+       return __NR_SCMP_ERROR;
+}
+
+/**
+ * Rewrite a syscall value to match the architecture
+ * @param syscall the syscall number
+ *
+ * Syscalls can vary across different architectures so this function rewrites
+ * the syscall into the correct value for the specified architecture.  Returns
+ * zero on success, negative values on failure.
+ *
+ */
+int mips_syscall_rewrite(int *syscall)
+{
+       int sys = *syscall;
+
+       if (sys <= -100 && sys >= -120)
+               *syscall = __mips_NR_socketcall;
+       else if (sys <= -200 && sys >= -224)
+               *syscall = __mips_NR_ipc;
+       else if (sys < 0)
+               return -EDOM;
+
+       return 0;
+}
+
+/**
+ * add a new rule to the mips seccomp filter
+ * @param db the seccomp filter db
+ * @param rule the filter rule
+ *
+ * This function adds a new syscall filter to the seccomp filter db, making any
+ * necessary adjustments for the mips ABI.  Returns zero on success, negative
+ * values on failure.
+ *
+ * It is important to note that in the case of failure the db may be corrupted,
+ * the caller must use the transaction mechanism if the db integrity is
+ * important.
+ *
+ */
+int mips_rule_add(struct db_filter *db, struct db_api_rule_list *rule)
+{
+       int rc = 0;
+       unsigned int iter;
+       int sys = rule->syscall;
+       int sys_a, sys_b;
+       struct db_api_rule_list *rule_a, *rule_b, *rule_dup = NULL;
+
+       if (_mips_syscall_socket_test(sys)) {
+               /* socket syscalls */
+
+               /* strict check for the multiplexed socket syscalls */
+               for (iter = 0; iter < ARG_COUNT_MAX; iter++) {
+                       if ((rule->args[iter].valid != 0) && (rule->strict)) {
+                               rc = -EINVAL;
+                               goto add_return;
+                       }
+               }
+
+               /* determine both the muxed and direct syscall numbers */
+               if (sys > 0) {
+                       sys_a = _mips_syscall_mux(sys);
+                       if (sys_a == __NR_SCMP_ERROR) {
+                               rc = __NR_SCMP_ERROR;
+                               goto add_return;
+                       }
+                       sys_b = sys;
+               } else {
+                       sys_a = sys;
+                       sys_b = _mips_syscall_demux(sys);
+                       if (sys_b == __NR_SCMP_ERROR) {
+                               rc = __NR_SCMP_ERROR;
+                               goto add_return;
+                       }
+               }
+
+               /* use rule_a for the multiplexed syscall and use rule_b for
+                * the direct wired syscall */
+
+               if (sys_a == __NR_SCMP_UNDEF) {
+                       rule_a = NULL;
+                       rule_b = rule;
+               } else if (sys_b == __NR_SCMP_UNDEF) {
+                       rule_a = rule;
+                       rule_b = NULL;
+               } else {
+                       /* need two rules, dup the first and link together */
+                       rule_a = rule;
+                       rule_dup = db_rule_dup(rule_a);
+                       rule_b = rule_dup;
+                       if (rule_b == NULL)
+                               goto add_return;
+                       rule_b->prev = rule_a;
+                       rule_b->next = NULL;
+                       rule_a->next = rule_b;
+               }
+
+               /* multiplexed socket syscalls */
+               if (rule_a != NULL) {
+                       rule_a->syscall = __mips_NR_socketcall;
+                       rule_a->args[0].arg = 0;
+                       rule_a->args[0].op = SCMP_CMP_EQ;
+                       rule_a->args[0].mask = DATUM_MAX;
+                       rule_a->args[0].datum = (-sys_a) % 100;
+                       rule_a->args[0].valid = 1;
+               }
+
+               /* direct wired socket syscalls */
+               if (rule_b != NULL)
+                       rule_b->syscall = sys_b;
+
+               /* we should be protected by a transaction checkpoint */
+               if (rule_a != NULL) {
+                       rc = db_rule_add(db, rule_a);
+                       if (rc < 0)
+                               goto add_return;
+               }
+               if (rule_b != NULL) {
+                       rc = db_rule_add(db, rule_b);
+                       if (rc < 0)
+                               goto add_return;
+               }
+       } else if (_mips_syscall_ipc_test(sys)) {
+               /* ipc syscalls */
+
+               /* strict check for the multiplexed socket syscalls */
+               for (iter = 0; iter < ARG_COUNT_MAX; iter++) {
+                       if ((rule->args[iter].valid != 0) && (rule->strict)) {
+                               rc = -EINVAL;
+                               goto add_return;
+                       }
+               }
+
+               /* determine both the muxed and direct syscall numbers */
+               if (sys > 0) {
+                       sys_a = _mips_syscall_mux(sys);
+                       if (sys_a == __NR_SCMP_ERROR) {
+                               rc = __NR_SCMP_ERROR;
+                               goto add_return;
+                       }
+                       sys_b = sys;
+               } else {
+                       sys_a = sys;
+                       sys_b = _mips_syscall_demux(sys);
+                       if (sys_b == __NR_SCMP_ERROR) {
+                               rc = __NR_SCMP_ERROR;
+                               goto add_return;
+                       }
+               }
+
+               /* use rule_a for the multiplexed syscall and use rule_b for
+                * the direct wired syscall */
+
+               if (sys_a == __NR_SCMP_UNDEF) {
+                       rule_a = NULL;
+                       rule_b = rule;
+               } else if (sys_b == __NR_SCMP_UNDEF) {
+                       rule_a = rule;
+                       rule_b = NULL;
+               } else {
+                       /* need two rules, dup the first and link together */
+                       rule_a = rule;
+                       rule_dup = db_rule_dup(rule_a);
+                       rule_b = rule_dup;
+                       if (rule_b == NULL)
+                               goto add_return;
+                       rule_b->prev = rule_a;
+                       rule_b->next = NULL;
+                       rule_a->next = rule_b;
+               }
+
+               /* multiplexed socket syscalls */
+               if (rule_a != NULL) {
+                       rule_a->syscall = __mips_NR_ipc;
+                       rule_a->args[0].arg = 0;
+                       rule_a->args[0].op = SCMP_CMP_EQ;
+                       rule_a->args[0].mask = DATUM_MAX;
+                       rule_a->args[0].datum = (-sys_a) % 200;
+                       rule_a->args[0].valid = 1;
+               }
+
+               /* direct wired socket syscalls */
+               if (rule_b != NULL)
+                       rule_b->syscall = sys_b;
+
+               /* we should be protected by a transaction checkpoint */
+               if (rule_a != NULL) {
+                       rc = db_rule_add(db, rule_a);
+                       if (rc < 0)
+                               goto add_return;
+               }
+               if (rule_b != NULL) {
+                       rc = db_rule_add(db, rule_b);
+                       if (rc < 0)
+                               goto add_return;
+               }
+       } else if (sys >= 0) {
+               /* normal syscall processing */
+               rc = db_rule_add(db, rule);
+               if (rc < 0)
+                       goto add_return;
+       } else if (rule->strict) {
+               rc = -EDOM;
+               goto add_return;
+       }
+
+add_return:
+       if (rule_dup != NULL)
+               free(rule_dup);
+       return rc;
+}
+
 const struct arch_def arch_def_mips = {
        .token = SCMP_ARCH_MIPS,
        .token_bpf = AUDIT_ARCH_MIPS,
        .size = ARCH_SIZE_32,
        .endian = ARCH_ENDIAN_BIG,
-       .sys_socketcall = __mips_NR_socketcall,
-       .sys_ipc = __mips_NR_ipc,
-       .syscall_resolve_name = abi_syscall_resolve_name_munge,
-       .syscall_resolve_name_raw = mips_syscall_resolve_name,
-       .syscall_resolve_num = abi_syscall_resolve_num_munge,
-       .syscall_resolve_num_raw = mips_syscall_resolve_num,
-       .syscall_rewrite = abi_syscall_rewrite,
-       .rule_add = abi_rule_add,
+       .syscall_resolve_name = mips_syscall_resolve_name_munge,
+       .syscall_resolve_num = mips_syscall_resolve_num_munge,
+       .syscall_rewrite = mips_syscall_rewrite,
+       .rule_add = mips_rule_add,
 };
 
 const struct arch_def arch_def_mipsel = {
@@ -54,12 +566,8 @@ const struct arch_def arch_def_mipsel = {
        .token_bpf = AUDIT_ARCH_MIPSEL,
        .size = ARCH_SIZE_32,
        .endian = ARCH_ENDIAN_LITTLE,
-       .sys_socketcall = __mips_NR_socketcall,
-       .sys_ipc = __mips_NR_ipc,
-       .syscall_resolve_name = abi_syscall_resolve_name_munge,
-       .syscall_resolve_name_raw = mips_syscall_resolve_name,
-       .syscall_resolve_num = abi_syscall_resolve_num_munge,
-       .syscall_resolve_num_raw = mips_syscall_resolve_num,
-       .syscall_rewrite = abi_syscall_rewrite,
-       .rule_add = abi_rule_add,
+       .syscall_resolve_name = mips_syscall_resolve_name_munge,
+       .syscall_resolve_num = mips_syscall_resolve_num_munge,
+       .syscall_rewrite = mips_syscall_rewrite,
+       .rule_add = mips_rule_add,
 };
index d0f72b8b09a0ebdb8bda8856a216e1487591f53e..342d0d88ef85c896a01b6275bcc9fb2ddf296f1d 100644 (file)
@@ -30,7 +30,6 @@
 
 /**
  * Resolve a syscall name to a number
- * @param arch the architecture definition
  * @param name the syscall name
  *
  * Resolve the given syscall name to the syscall number using the syscall table.
  * numbers; returns __NR_SCMP_ERROR on failure.
  *
  */
-int mips64_syscall_resolve_name_munge(const struct arch_def *arch,
-                                     const char *name)
+int mips64_syscall_resolve_name_munge(const char *name)
 {
        int sys;
 
        /* NOTE: we don't want to modify the pseudo-syscall numbers */
-       sys = arch->syscall_resolve_name_raw(name);
+       sys = mips64_syscall_resolve_name(name);
        if (sys == __NR_SCMP_ERROR || sys < 0)
                return sys;
 
@@ -53,7 +51,6 @@ int mips64_syscall_resolve_name_munge(const struct arch_def *arch,
 
 /**
  * Resolve a syscall number to a name
- * @param arch the architecture definition
  * @param num the syscall number
  *
  * Resolve the given syscall number to the syscall name using the syscall table.
@@ -61,13 +58,12 @@ int mips64_syscall_resolve_name_munge(const struct arch_def *arch,
  * syscall names; returns NULL on failure.
  *
  */
-const char *mips64_syscall_resolve_num_munge(const struct arch_def *arch,
-                                            int num)
+const char *mips64_syscall_resolve_num_munge(int num)
 {
        /* NOTE: we don't want to modify the pseudo-syscall numbers */
        if (num >= __SCMP_NR_BASE)
                num -= __SCMP_NR_BASE;
-       return arch->syscall_resolve_num_raw(num);
+       return mips64_syscall_resolve_num(num);
 }
 
 const struct arch_def arch_def_mips64 = {
@@ -76,9 +72,7 @@ const struct arch_def arch_def_mips64 = {
        .size = ARCH_SIZE_64,
        .endian = ARCH_ENDIAN_BIG,
        .syscall_resolve_name = mips64_syscall_resolve_name_munge,
-       .syscall_resolve_name_raw = mips64_syscall_resolve_name,
        .syscall_resolve_num = mips64_syscall_resolve_num_munge,
-       .syscall_resolve_num_raw = mips64_syscall_resolve_num,
        .syscall_rewrite = NULL,
        .rule_add = NULL,
 };
@@ -89,9 +83,7 @@ const struct arch_def arch_def_mipsel64 = {
        .size = ARCH_SIZE_64,
        .endian = ARCH_ENDIAN_LITTLE,
        .syscall_resolve_name = mips64_syscall_resolve_name_munge,
-       .syscall_resolve_name_raw = mips64_syscall_resolve_name,
        .syscall_resolve_num = mips64_syscall_resolve_num_munge,
-       .syscall_resolve_num_raw = mips64_syscall_resolve_num,
        .syscall_rewrite = NULL,
        .rule_add = NULL,
 };
index 532c8f3febdca1e88132ccefd8906644b0e8b10c..098864befc21477e2d6ea980bd03c8abb2e69eff 100644 (file)
@@ -32,7 +32,6 @@
 
 /**
  * Resolve a syscall name to a number
- * @param arch the architecture definition
  * @param name the syscall name
  *
  * Resolve the given syscall name to the syscall number using the syscall table.
@@ -40,8 +39,7 @@
  * numbers; returns __NR_SCMP_ERROR on failure.
  *
  */
-int mips64n32_syscall_resolve_name_munge(const struct arch_def *arch,
-                                        const char *name)
+int mips64n32_syscall_resolve_name_munge(const char *name)
 {
        int sys;
 
@@ -55,7 +53,6 @@ int mips64n32_syscall_resolve_name_munge(const struct arch_def *arch,
 
 /**
  * Resolve a syscall number to a name
- * @param arch the architecture definition
  * @param num the syscall number
  *
  * Resolve the given syscall number to the syscall name using the syscall table.
@@ -63,8 +60,7 @@ int mips64n32_syscall_resolve_name_munge(const struct arch_def *arch,
  * syscall names; returns NULL on failure.
  *
  */
-const char *mips64n32_syscall_resolve_num_munge(const struct arch_def *arch,
-                                               int num)
+const char *mips64n32_syscall_resolve_num_munge(int num)
 {
        /* NOTE: we don't want to modify the pseudo-syscall numbers */
        if (num >= __SCMP_NR_BASE)
@@ -78,9 +74,7 @@ const struct arch_def arch_def_mips64n32 = {
        .size = ARCH_SIZE_32,
        .endian = ARCH_ENDIAN_BIG,
        .syscall_resolve_name = mips64n32_syscall_resolve_name_munge,
-       .syscall_resolve_name_raw = mips64n32_syscall_resolve_name,
        .syscall_resolve_num = mips64n32_syscall_resolve_num_munge,
-       .syscall_resolve_num_raw = mips64n32_syscall_resolve_num,
        .syscall_rewrite = NULL,
        .rule_add = NULL,
 };
@@ -91,9 +85,7 @@ const struct arch_def arch_def_mipsel64n32 = {
        .size = ARCH_SIZE_32,
        .endian = ARCH_ENDIAN_LITTLE,
        .syscall_resolve_name = mips64n32_syscall_resolve_name_munge,
-       .syscall_resolve_name_raw = mips64n32_syscall_resolve_name,
        .syscall_resolve_num = mips64n32_syscall_resolve_num_munge,
-       .syscall_resolve_num_raw = mips64n32_syscall_resolve_num,
        .syscall_rewrite = NULL,
        .rule_add = NULL,
 };
index 4440a046baabf3337c2ea3ead84af2bc6bbcbc86..f317fed783f5eacdce4a0a5c4d2ff5120b432a2b 100644 (file)
@@ -15,8 +15,8 @@ const struct arch_def arch_def_parisc = {
        .token_bpf = AUDIT_ARCH_PARISC,
        .size = ARCH_SIZE_32,
        .endian = ARCH_ENDIAN_BIG,
-       .syscall_resolve_name_raw = parisc_syscall_resolve_name,
-       .syscall_resolve_num_raw = parisc_syscall_resolve_num,
+       .syscall_resolve_name = parisc_syscall_resolve_name,
+       .syscall_resolve_num = parisc_syscall_resolve_num,
        .syscall_rewrite = NULL,
        .rule_add = NULL,
 };
index d2d85e6140be18463c11b228218f53867e49d0d9..08e50812c2e01e5b312860e25973333850acbb34 100644 (file)
@@ -15,8 +15,8 @@ const struct arch_def arch_def_parisc64 = {
        .token_bpf = AUDIT_ARCH_PARISC64,
        .size = ARCH_SIZE_64,
        .endian = ARCH_ENDIAN_BIG,
-       .syscall_resolve_name_raw = parisc64_syscall_resolve_name,
-       .syscall_resolve_num_raw = parisc64_syscall_resolve_num,
+       .syscall_resolve_name = parisc64_syscall_resolve_name,
+       .syscall_resolve_num = parisc64_syscall_resolve_num,
        .syscall_rewrite = NULL,
        .rule_add = NULL,
 };
index 0c97bf5381003b77aab54f70b000b6b4018210b4..035888c21d357ba0117cdaaa61279ee7f6bcf304 100644 (file)
 #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,
 };
index 27f31a553b5808ddf98c740b34340cda7ba6e1ca..8cccbb881f0df79fd11512f0aee3c4f90b864e34 100644 (file)
@@ -26,7 +26,6 @@
 #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 = {
@@ -54,12 +639,8 @@ const struct arch_def arch_def_ppc64le = {
        .token_bpf = AUDIT_ARCH_PPC64LE,
        .size = ARCH_SIZE_64,
        .endian = ARCH_ENDIAN_LITTLE,
-       .sys_socketcall = __ppc64_NR_socketcall,
-       .sys_ipc = __ppc64_NR_ipc,
-       .syscall_resolve_name = abi_syscall_resolve_name_munge,
-       .syscall_resolve_name_raw = ppc64_syscall_resolve_name,
-       .syscall_resolve_num = abi_syscall_resolve_num_munge,
-       .syscall_resolve_num_raw = ppc64_syscall_resolve_num,
-       .syscall_rewrite = abi_syscall_rewrite,
-       .rule_add = abi_rule_add,
+       .syscall_resolve_name = ppc64_syscall_resolve_name_munge,
+       .syscall_resolve_num = ppc64_syscall_resolve_num_munge,
+       .syscall_rewrite = ppc64_syscall_rewrite,
+       .rule_add = ppc64_rule_add,
 };
index df4f5c8851b6fa2784e87add98bd3f347a9491d0..67bc9265eee2ec0e7c810b19c78a0ca8d256c26a 100644 (file)
@@ -24,8 +24,8 @@ const struct arch_def arch_def_riscv64 = {
        .token_bpf = AUDIT_ARCH_RISCV64,
        .size = ARCH_SIZE_64,
        .endian = ARCH_ENDIAN_LITTLE,
-       .syscall_resolve_name_raw = riscv64_syscall_resolve_name,
-       .syscall_resolve_num_raw = riscv64_syscall_resolve_num,
+       .syscall_resolve_name = riscv64_syscall_resolve_name,
+       .syscall_resolve_num = riscv64_syscall_resolve_num,
        .syscall_rewrite = NULL,
        .rule_add = NULL,
 };
index f2c8fda0fe1c3e7633a0a8ba871d72773f681025..c2990c0638d5e1a44706d05c5c43c7ad0f399e74 100644 (file)
 #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,
 };
index ddae21b9a8999f93d2aa324d89b3fcdd6009b128..45d67eca7a2192418a7e200fe5ad35c02406f2eb 100644 (file)
 #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,
 };
index 0a73923a951c8468156e0f79b9d31ee6aaa91a5e..50c502eecc2d8a70f2b4351e9a690563910effd0 100644 (file)
@@ -28,7 +28,6 @@
 
 /**
  * Resolve a syscall name to a number
- * @param arch the architecture definition
  * @param name the syscall name
  *
  * Resolve the given syscall name to the syscall number using the syscall table.
  * numbers; returns __NR_SCMP_ERROR on failure.
  *
  */
-int x32_syscall_resolve_name_munge(const struct arch_def *arch,
-                                  const char *name)
+int x32_syscall_resolve_name_munge(const char *name)
 {
        int sys;
 
        /* NOTE: we don't want to modify the pseudo-syscall numbers */
-       sys = arch->syscall_resolve_name_raw(name);
+       sys = x32_syscall_resolve_name(name);
        if (sys == __NR_SCMP_ERROR || sys < 0)
                return sys;
 
@@ -51,7 +49,6 @@ int x32_syscall_resolve_name_munge(const struct arch_def *arch,
 
 /**
  * Resolve a syscall number to a name
- * @param arch the architecture definition
  * @param num the syscall number
  *
  * Resolve the given syscall number to the syscall name using the syscall table.
@@ -59,13 +56,12 @@ int x32_syscall_resolve_name_munge(const struct arch_def *arch,
  * syscall names; returns NULL on failure.
  *
  */
-const char *x32_syscall_resolve_num_munge(const struct arch_def *arch,
-                                         int num)
+const char *x32_syscall_resolve_num_munge(int num)
 {
        /* NOTE: we don't want to modify the pseudo-syscall numbers */
        if (num >= 0)
                num &= ~X32_SYSCALL_BIT;
-       return arch->syscall_resolve_num_raw(num);
+       return x32_syscall_resolve_num(num);
 }
 
 const struct arch_def arch_def_x32 = {
@@ -75,9 +71,7 @@ const struct arch_def arch_def_x32 = {
        .size = ARCH_SIZE_32,
        .endian = ARCH_ENDIAN_LITTLE,
        .syscall_resolve_name = x32_syscall_resolve_name_munge,
-       .syscall_resolve_name_raw = x32_syscall_resolve_name,
        .syscall_resolve_num = x32_syscall_resolve_num_munge,
-       .syscall_resolve_num_raw = x32_syscall_resolve_num,
        .syscall_rewrite = NULL,
        .rule_add = NULL,
 };
index af331371677769c824957d28cf0cc4e4bbc27a1e..2a4c074f067fa914601f2926e97dae789922eb37 100644 (file)
 #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,
 };
index 9c0e5acd3e20bac098699cfcb6a8be6cc48f0c64..a5fccadc63e98c6f2cd6e15e7b38ceaa33090900 100644 (file)
@@ -31,8 +31,8 @@ const struct arch_def arch_def_x86_64 = {
        .token_bpf = AUDIT_ARCH_X86_64,
        .size = ARCH_SIZE_64,
        .endian = ARCH_ENDIAN_LITTLE,
-       .syscall_resolve_name_raw = x86_64_syscall_resolve_name,
-       .syscall_resolve_num_raw = x86_64_syscall_resolve_num,
+       .syscall_resolve_name = x86_64_syscall_resolve_name,
+       .syscall_resolve_num = x86_64_syscall_resolve_num,
        .syscall_rewrite = NULL,
        .rule_add = NULL,
 };
index 8ef77b1a6b04b11cb2489dd7b0ab24ca9cb77953..5485eb8aaa8c27ff3f4eb3a245f97def5234d317 100644 (file)
@@ -300,9 +300,7 @@ int arch_arg_offset(const struct arch_def *arch, unsigned int arg)
 int arch_syscall_resolve_name(const struct arch_def *arch, const char *name)
 {
        if (arch->syscall_resolve_name)
-               return (*arch->syscall_resolve_name)(arch, name);
-       if (arch->syscall_resolve_name_raw)
-               return (*arch->syscall_resolve_name_raw)(name);
+               return (*arch->syscall_resolve_name)(name);
 
        return __NR_SCMP_ERROR;
 }
@@ -320,9 +318,7 @@ int arch_syscall_resolve_name(const struct arch_def *arch, const char *name)
 const char *arch_syscall_resolve_num(const struct arch_def *arch, int num)
 {
        if (arch->syscall_resolve_num)
-               return (*arch->syscall_resolve_num)(arch, num);
-       if (arch->syscall_resolve_num_raw)
-               return (*arch->syscall_resolve_num_raw)(num);
+               return (*arch->syscall_resolve_num)(num);
 
        return NULL;
 }
@@ -385,7 +381,7 @@ int arch_syscall_rewrite(const struct arch_def *arch, int *syscall)
        } else if (sys > -10000) {
                /* rewritable syscalls */
                if (arch->syscall_rewrite)
-                       (*arch->syscall_rewrite)(arch, syscall);
+                       (*arch->syscall_rewrite)(syscall);
        }
 
        /* syscalls not defined on this architecture */
index b6484f937fc715ea4517771521c5adee00d8dd41..38c3a9c538d4fb629a3cb1bc64faffacee2cb7ce 100644 (file)
@@ -49,18 +49,10 @@ struct arch_def {
                ARCH_ENDIAN_BIG,
        } endian;
 
-       /* arch specific constants */
-       int sys_socketcall;
-       int sys_ipc;
-
        /* arch specific functions */
-       int (*syscall_resolve_name)(const struct arch_def *arch,
-                                   const char *name);
-       int (*syscall_resolve_name_raw)(const char *name);
-       const char *(*syscall_resolve_num)(const struct arch_def *arch,
-                                          int num);
-       const char *(*syscall_resolve_num_raw)(int num);
-       int (*syscall_rewrite)(const struct arch_def *arch, int *syscall);
+       int (*syscall_resolve_name)(const char *name);
+       const char *(*syscall_resolve_num)(int num);
+       int (*syscall_rewrite)(int *syscall);
        int (*rule_add)(struct db_filter *db, struct db_api_rule_list *rule);
 };
 
index bd6acb5afaed086cd91e794f7d3bac7efe8cdc84..9091fa96a17e52d255b011c455e807a06fb891a7 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Enhanced Seccomp Syscall Table Functions
+ * Enhanced Seccomp x86_64 Syscall Table
  *
  * Copyright (c) 2012, 2020 Red Hat <pmoore@redhat.com>
  * Author: Paul Moore <paul@paul-moore.com>
  * You should have received a copy of the GNU Lesser General Public License
  * along with this library; if not, see <http://www.gnu.org/licenses>.
  */
-
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
 #include <seccomp.h>
+#include <string.h>
 
-#include "db.h"
 #include "arch.h"
 #include "syscalls.h"
 
@@ -58,524 +54,3 @@ ARCH_DEF(s390x)
 ARCH_DEF(x32)
 ARCH_DEF(x86)
 ARCH_DEF(riscv64)
-
-/**
- * Resolve a syscall name to a number
- * @param arch the arch definition
- * @param name the syscall name
- *
- * Resolve the given syscall name to the syscall number using the syscall table.
- * Returns the syscall number on success, including negative pseudo syscall
- * numbers; returns __NR_SCMP_ERROR on failure.
- *
- */
-int abi_syscall_resolve_name_munge(const struct arch_def *arch,
-                                  const char *name)
-{
-
-#define _ABI_SYSCALL_RES_NAME_CHK(NAME) \
-       if (!strcmp(name, #NAME)) return __PNR_##NAME;
-
-       _ABI_SYSCALL_RES_NAME_CHK(socket)
-       _ABI_SYSCALL_RES_NAME_CHK(bind)
-       _ABI_SYSCALL_RES_NAME_CHK(connect)
-       _ABI_SYSCALL_RES_NAME_CHK(listen)
-       _ABI_SYSCALL_RES_NAME_CHK(accept)
-       _ABI_SYSCALL_RES_NAME_CHK(getsockname)
-       _ABI_SYSCALL_RES_NAME_CHK(getpeername)
-       _ABI_SYSCALL_RES_NAME_CHK(socketpair)
-       _ABI_SYSCALL_RES_NAME_CHK(send)
-       _ABI_SYSCALL_RES_NAME_CHK(recv)
-       _ABI_SYSCALL_RES_NAME_CHK(sendto)
-       _ABI_SYSCALL_RES_NAME_CHK(recvfrom)
-       _ABI_SYSCALL_RES_NAME_CHK(shutdown)
-       _ABI_SYSCALL_RES_NAME_CHK(setsockopt)
-       _ABI_SYSCALL_RES_NAME_CHK(getsockopt)
-       _ABI_SYSCALL_RES_NAME_CHK(sendmsg)
-       _ABI_SYSCALL_RES_NAME_CHK(recvmsg)
-       _ABI_SYSCALL_RES_NAME_CHK(accept4)
-       _ABI_SYSCALL_RES_NAME_CHK(recvmmsg)
-       _ABI_SYSCALL_RES_NAME_CHK(sendmmsg)
-       _ABI_SYSCALL_RES_NAME_CHK(semop)
-       _ABI_SYSCALL_RES_NAME_CHK(semget)
-       _ABI_SYSCALL_RES_NAME_CHK(semctl)
-       _ABI_SYSCALL_RES_NAME_CHK(semtimedop)
-       _ABI_SYSCALL_RES_NAME_CHK(msgsnd)
-       _ABI_SYSCALL_RES_NAME_CHK(msgrcv)
-       _ABI_SYSCALL_RES_NAME_CHK(msgget)
-       _ABI_SYSCALL_RES_NAME_CHK(msgctl)
-       _ABI_SYSCALL_RES_NAME_CHK(shmat)
-       _ABI_SYSCALL_RES_NAME_CHK(shmdt)
-       _ABI_SYSCALL_RES_NAME_CHK(shmget)
-       _ABI_SYSCALL_RES_NAME_CHK(shmctl)
-
-       return arch->syscall_resolve_name_raw(name);
-}
-
-/**
- * Resolve a syscall number to a name
- * @param arch the arch definition
- * @param num the syscall number
- *
- * Resolve the given syscall number to the syscall name using the syscall table.
- * Returns a pointer to the syscall name string on success, including pseudo
- * syscall names; returns NULL on failure.
- *
- */
-const char *abi_syscall_resolve_num_munge(const struct arch_def *arch, int num)
-{
-
-#define _ABI_SYSCALL_RES_NUM_CHK(NAME) \
-       if (num == __PNR_##NAME) return #NAME;
-
-       _ABI_SYSCALL_RES_NUM_CHK(socket)
-       _ABI_SYSCALL_RES_NUM_CHK(bind)
-       _ABI_SYSCALL_RES_NUM_CHK(connect)
-       _ABI_SYSCALL_RES_NUM_CHK(listen)
-       _ABI_SYSCALL_RES_NUM_CHK(accept)
-       _ABI_SYSCALL_RES_NUM_CHK(getsockname)
-       _ABI_SYSCALL_RES_NUM_CHK(getpeername)
-       _ABI_SYSCALL_RES_NUM_CHK(socketpair)
-       _ABI_SYSCALL_RES_NUM_CHK(send)
-       _ABI_SYSCALL_RES_NUM_CHK(recv)
-       _ABI_SYSCALL_RES_NUM_CHK(sendto)
-       _ABI_SYSCALL_RES_NUM_CHK(recvfrom)
-       _ABI_SYSCALL_RES_NUM_CHK(shutdown)
-       _ABI_SYSCALL_RES_NUM_CHK(setsockopt)
-       _ABI_SYSCALL_RES_NUM_CHK(getsockopt)
-       _ABI_SYSCALL_RES_NUM_CHK(sendmsg)
-       _ABI_SYSCALL_RES_NUM_CHK(recvmsg)
-       _ABI_SYSCALL_RES_NUM_CHK(accept4)
-       _ABI_SYSCALL_RES_NUM_CHK(recvmmsg)
-       _ABI_SYSCALL_RES_NUM_CHK(sendmmsg)
-       _ABI_SYSCALL_RES_NUM_CHK(semop)
-       _ABI_SYSCALL_RES_NUM_CHK(semget)
-       _ABI_SYSCALL_RES_NUM_CHK(semctl)
-       _ABI_SYSCALL_RES_NUM_CHK(semtimedop)
-       _ABI_SYSCALL_RES_NUM_CHK(msgsnd)
-       _ABI_SYSCALL_RES_NUM_CHK(msgrcv)
-       _ABI_SYSCALL_RES_NUM_CHK(msgget)
-       _ABI_SYSCALL_RES_NUM_CHK(msgctl)
-       _ABI_SYSCALL_RES_NUM_CHK(shmat)
-       _ABI_SYSCALL_RES_NUM_CHK(shmdt)
-       _ABI_SYSCALL_RES_NUM_CHK(shmget)
-       _ABI_SYSCALL_RES_NUM_CHK(shmctl)
-
-       return arch->syscall_resolve_num_raw(num);
-}
-
-/**
- * Check if a syscall is a socket syscall
- * @param arch the arch definition
- * @param sys the syscall number
- *
- * Returns true if the syscall is a socket related syscall, false otherwise.
- *
- */
-static bool _abi_syscall_socket_test(const struct arch_def *arch, int sys)
-{
-       const char *name;
-
-       /* multiplexed pseduo-syscalls */
-       if (sys <= -100 && sys >= -120)
-               return true;
-
-       name = arch->syscall_resolve_num_raw(sys);
-       if (!name)
-               return false;
-
-#define _ABI_SYSCALL_SOCK_CHK(NAME) \
-       if (!strcmp(name, #NAME)) return true;
-
-       _ABI_SYSCALL_SOCK_CHK(socket)
-       _ABI_SYSCALL_SOCK_CHK(bind)
-       _ABI_SYSCALL_SOCK_CHK(connect)
-       _ABI_SYSCALL_SOCK_CHK(listen)
-       _ABI_SYSCALL_SOCK_CHK(accept)
-       _ABI_SYSCALL_SOCK_CHK(getsockname)
-       _ABI_SYSCALL_SOCK_CHK(getpeername)
-       _ABI_SYSCALL_SOCK_CHK(socketpair)
-       _ABI_SYSCALL_SOCK_CHK(send)
-       _ABI_SYSCALL_SOCK_CHK(recv)
-       _ABI_SYSCALL_SOCK_CHK(sendto)
-       _ABI_SYSCALL_SOCK_CHK(recvfrom)
-       _ABI_SYSCALL_SOCK_CHK(shutdown)
-       _ABI_SYSCALL_SOCK_CHK(setsockopt)
-       _ABI_SYSCALL_SOCK_CHK(getsockopt)
-       _ABI_SYSCALL_SOCK_CHK(sendmsg)
-       _ABI_SYSCALL_SOCK_CHK(recvmsg)
-       _ABI_SYSCALL_SOCK_CHK(accept4)
-       _ABI_SYSCALL_SOCK_CHK(recvmmsg)
-       _ABI_SYSCALL_SOCK_CHK(sendmmsg)
-
-       return false;
-}
-
-/**
- * Check if a syscall is an ipc syscall
- * @param arch the arch definition
- * @param sys the syscall number
- *
- * Returns true if the syscall is an ipc related syscall, false otherwise.
- *
- */
-static bool _abi_syscall_ipc_test(const struct arch_def *arch, int sys)
-{
-       const char *name;
-
-       /* multiplexed pseduo-syscalls */
-       if (sys <= -200 && sys >= -224)
-               return true;
-
-       name = arch->syscall_resolve_num_raw(sys);
-       if (!name)
-               return false;
-
-#define _ABI_SYSCALL_IPC_CHK(NAME) \
-       if (!strcmp(name, #NAME)) return true;
-
-       _ABI_SYSCALL_IPC_CHK(semop)
-       _ABI_SYSCALL_IPC_CHK(semget)
-       _ABI_SYSCALL_IPC_CHK(semctl)
-       _ABI_SYSCALL_IPC_CHK(semtimedop)
-       _ABI_SYSCALL_IPC_CHK(msgsnd)
-       _ABI_SYSCALL_IPC_CHK(msgrcv)
-       _ABI_SYSCALL_IPC_CHK(msgget)
-       _ABI_SYSCALL_IPC_CHK(msgctl)
-       _ABI_SYSCALL_IPC_CHK(shmat)
-       _ABI_SYSCALL_IPC_CHK(shmdt)
-       _ABI_SYSCALL_IPC_CHK(shmget)
-       _ABI_SYSCALL_IPC_CHK(shmctl)
-
-       return false;
-}
-
-/**
- * Convert a multiplexed pseudo syscall into a direct syscall
- * @param arch the arch definition
- * @param syscall the multiplexed pseudo syscall number
- *
- * Return the related direct syscall number, __NR_SCMP_UNDEF is there is
- * no related syscall, or __NR_SCMP_ERROR otherwise.
- *
- */
-static int _abi_syscall_demux(const struct arch_def *arch, int syscall)
-{
-       int sys = __NR_SCMP_UNDEF;
-
-#define _ABI_SYSCALL_DEMUX_CHK(NAME) \
-case __PNR_##NAME: \
-       sys = arch->syscall_resolve_name_raw(#NAME); break;
-
-       switch (syscall) {
-               _ABI_SYSCALL_DEMUX_CHK(socket)
-               _ABI_SYSCALL_DEMUX_CHK(bind)
-               _ABI_SYSCALL_DEMUX_CHK(connect)
-               _ABI_SYSCALL_DEMUX_CHK(listen)
-               _ABI_SYSCALL_DEMUX_CHK(accept)
-               _ABI_SYSCALL_DEMUX_CHK(getsockname)
-               _ABI_SYSCALL_DEMUX_CHK(getpeername)
-               _ABI_SYSCALL_DEMUX_CHK(socketpair)
-               _ABI_SYSCALL_DEMUX_CHK(send)
-               _ABI_SYSCALL_DEMUX_CHK(recv)
-               _ABI_SYSCALL_DEMUX_CHK(sendto)
-               _ABI_SYSCALL_DEMUX_CHK(recvfrom)
-               _ABI_SYSCALL_DEMUX_CHK(shutdown)
-               _ABI_SYSCALL_DEMUX_CHK(setsockopt)
-               _ABI_SYSCALL_DEMUX_CHK(getsockopt)
-               _ABI_SYSCALL_DEMUX_CHK(sendmsg)
-               _ABI_SYSCALL_DEMUX_CHK(recvmsg)
-               _ABI_SYSCALL_DEMUX_CHK(accept4)
-               _ABI_SYSCALL_DEMUX_CHK(recvmmsg)
-               _ABI_SYSCALL_DEMUX_CHK(sendmmsg)
-               _ABI_SYSCALL_DEMUX_CHK(semop)
-               _ABI_SYSCALL_DEMUX_CHK(semget)
-               _ABI_SYSCALL_DEMUX_CHK(semctl)
-               _ABI_SYSCALL_DEMUX_CHK(semtimedop)
-               _ABI_SYSCALL_DEMUX_CHK(msgsnd)
-               _ABI_SYSCALL_DEMUX_CHK(msgrcv)
-               _ABI_SYSCALL_DEMUX_CHK(msgget)
-               _ABI_SYSCALL_DEMUX_CHK(msgctl)
-               _ABI_SYSCALL_DEMUX_CHK(shmat)
-               _ABI_SYSCALL_DEMUX_CHK(shmdt)
-               _ABI_SYSCALL_DEMUX_CHK(shmget)
-               _ABI_SYSCALL_DEMUX_CHK(shmctl)
-       }
-
-       /* this looks odd because the arch resolver returns _ERROR if it can't
-        * resolve the syscall, but we want to use _UNDEF for that, so we set
-        * 'sys' to a sentinel value of _UNDEF and if it is error here we know
-        * the resolve failed to find a match */
-       if (sys == __NR_SCMP_UNDEF)
-               sys = __NR_SCMP_ERROR;
-       else if (sys == __NR_SCMP_ERROR)
-               sys = __NR_SCMP_UNDEF;
-
-       return sys;
-}
-
-/**
- * Convert a direct syscall into multiplexed pseudo socket syscall
- * @param arch the arch definition
- * @param syscall the direct syscall
- *
- * Return the related multiplexed pseduo syscall number, __NR_SCMP_UNDEF is
- * there is no related pseudo syscall, or __NR_SCMP_ERROR otherwise.
- *
- */
-static int _abi_syscall_mux(const struct arch_def *arch, int syscall)
-{
-       const char *sys;
-
-       sys = arch->syscall_resolve_num_raw(syscall);
-       if (!sys)
-               return __NR_SCMP_ERROR;
-
-#define _ABI_SYSCALL_MUX_CHK(NAME) \
-       if (!strcmp(sys, #NAME)) return __PNR_##NAME;
-
-       _ABI_SYSCALL_MUX_CHK(socket)
-       _ABI_SYSCALL_MUX_CHK(bind)
-       _ABI_SYSCALL_MUX_CHK(connect)
-       _ABI_SYSCALL_MUX_CHK(listen)
-       _ABI_SYSCALL_MUX_CHK(accept)
-       _ABI_SYSCALL_MUX_CHK(getsockname)
-       _ABI_SYSCALL_MUX_CHK(getpeername)
-       _ABI_SYSCALL_MUX_CHK(socketpair)
-       _ABI_SYSCALL_MUX_CHK(send)
-       _ABI_SYSCALL_MUX_CHK(recv)
-       _ABI_SYSCALL_MUX_CHK(sendto)
-       _ABI_SYSCALL_MUX_CHK(recvfrom)
-       _ABI_SYSCALL_MUX_CHK(shutdown)
-       _ABI_SYSCALL_MUX_CHK(setsockopt)
-       _ABI_SYSCALL_MUX_CHK(getsockopt)
-       _ABI_SYSCALL_MUX_CHK(sendmsg)
-       _ABI_SYSCALL_MUX_CHK(recvmsg)
-       _ABI_SYSCALL_MUX_CHK(accept4)
-       _ABI_SYSCALL_MUX_CHK(recvmmsg)
-       _ABI_SYSCALL_MUX_CHK(sendmmsg)
-       _ABI_SYSCALL_MUX_CHK(semop)
-       _ABI_SYSCALL_MUX_CHK(semget)
-       _ABI_SYSCALL_MUX_CHK(semctl)
-       _ABI_SYSCALL_MUX_CHK(semtimedop)
-       _ABI_SYSCALL_MUX_CHK(msgsnd)
-       _ABI_SYSCALL_MUX_CHK(msgrcv)
-       _ABI_SYSCALL_MUX_CHK(msgget)
-       _ABI_SYSCALL_MUX_CHK(msgctl)
-       _ABI_SYSCALL_MUX_CHK(shmat)
-       _ABI_SYSCALL_MUX_CHK(shmdt)
-       _ABI_SYSCALL_MUX_CHK(shmget)
-       _ABI_SYSCALL_MUX_CHK(shmctl)
-
-       return __NR_SCMP_ERROR;
-}
-
-/**
- * Rewrite a syscall value to match the architecture
- * @param arch the arch definition
- * @param syscall the syscall number
- *
- * Syscalls can vary across different architectures so this function rewrites
- * the syscall into the correct value for the specified architecture.  Returns
- * zero on success, negative values on failure.
- *
- */
-int abi_syscall_rewrite(const struct arch_def *arch, int *syscall)
-{
-       int sys = *syscall;
-
-       if (sys <= -100 && sys >= -120)
-               *syscall = arch->sys_socketcall;
-       else if (sys <= -200 && sys >= -224)
-               *syscall = arch->sys_ipc;
-       else if (sys < 0)
-               return -EDOM;
-
-       return 0;
-}
-
-/**
- * add a new rule to the abi seccomp filter
- * @param db the seccomp filter db
- * @param rule the filter rule
- *
- * This function adds a new syscall filter to the seccomp filter db, making any
- * necessary adjustments for the abi ABI.  Returns zero on success, negative
- * values on failure.
- *
- * It is important to note that in the case of failure the db may be corrupted,
- * the caller must use the transaction mechanism if the db integrity is
- * important.
- *
- */
-int abi_rule_add(struct db_filter *db, struct db_api_rule_list *rule)
-{
-       int rc = 0;
-       unsigned int iter;
-       int sys = rule->syscall;
-       int sys_a, sys_b;
-       struct db_api_rule_list *rule_a, *rule_b, *rule_dup = NULL;
-
-       if (_abi_syscall_socket_test(db->arch, sys)) {
-               /* socket syscalls */
-
-               /* strict check for the multiplexed socket syscalls */
-               for (iter = 0; iter < ARG_COUNT_MAX; iter++) {
-                       if ((rule->args[iter].valid != 0) && (rule->strict)) {
-                               rc = -EINVAL;
-                               goto add_return;
-                       }
-               }
-
-               /* determine both the muxed and direct syscall numbers */
-               if (sys > 0) {
-                       sys_a = _abi_syscall_mux(db->arch, sys);
-                       if (sys_a == __NR_SCMP_ERROR) {
-                               rc = __NR_SCMP_ERROR;
-                               goto add_return;
-                       }
-                       sys_b = sys;
-               } else {
-                       sys_a = sys;
-                       sys_b = _abi_syscall_demux(db->arch, sys);
-                       if (sys_b == __NR_SCMP_ERROR) {
-                               rc = __NR_SCMP_ERROR;
-                               goto add_return;
-                       }
-               }
-
-               /* use rule_a for the multiplexed syscall and use rule_b for
-                * the direct wired syscall */
-
-               if (sys_a == __NR_SCMP_UNDEF) {
-                       rule_a = NULL;
-                       rule_b = rule;
-               } else if (sys_b == __NR_SCMP_UNDEF) {
-                       rule_a = rule;
-                       rule_b = NULL;
-               } else {
-                       /* need two rules, dup the first and link together */
-                       rule_a = rule;
-                       rule_dup = db_rule_dup(rule_a);
-                       rule_b = rule_dup;
-                       if (rule_b == NULL)
-                               goto add_return;
-                       rule_b->prev = rule_a;
-                       rule_b->next = NULL;
-                       rule_a->next = rule_b;
-               }
-
-               /* multiplexed socket syscalls */
-               if (rule_a != NULL) {
-                       rule_a->syscall = db->arch->sys_socketcall;
-                       rule_a->args[0].arg = 0;
-                       rule_a->args[0].op = SCMP_CMP_EQ;
-                       rule_a->args[0].mask = DATUM_MAX;
-                       rule_a->args[0].datum = (-sys_a) % 100;
-                       rule_a->args[0].valid = 1;
-               }
-
-               /* direct wired socket syscalls */
-               if (rule_b != NULL)
-                       rule_b->syscall = sys_b;
-
-               /* we should be protected by a transaction checkpoint */
-               if (rule_a != NULL) {
-                       rc = db_rule_add(db, rule_a);
-                       if (rc < 0)
-                               goto add_return;
-               }
-               if (rule_b != NULL) {
-                       rc = db_rule_add(db, rule_b);
-                       if (rc < 0)
-                               goto add_return;
-               }
-       } else if (_abi_syscall_ipc_test(db->arch, sys)) {
-               /* ipc syscalls */
-
-               /* strict check for the multiplexed socket syscalls */
-               for (iter = 0; iter < ARG_COUNT_MAX; iter++) {
-                       if ((rule->args[iter].valid != 0) && (rule->strict)) {
-                               rc = -EINVAL;
-                               goto add_return;
-                       }
-               }
-
-               /* determine both the muxed and direct syscall numbers */
-               if (sys > 0) {
-                       sys_a = _abi_syscall_mux(db->arch, sys);
-                       if (sys_a == __NR_SCMP_ERROR) {
-                               rc = __NR_SCMP_ERROR;
-                               goto add_return;
-                       }
-                       sys_b = sys;
-               } else {
-                       sys_a = sys;
-                       sys_b = _abi_syscall_demux(db->arch, sys);
-                       if (sys_b == __NR_SCMP_ERROR) {
-                               rc = __NR_SCMP_ERROR;
-                               goto add_return;
-                       }
-               }
-
-               /* use rule_a for the multiplexed syscall and use rule_b for
-                * the direct wired syscall */
-
-               if (sys_a == __NR_SCMP_UNDEF) {
-                       rule_a = NULL;
-                       rule_b = rule;
-               } else if (sys_b == __NR_SCMP_UNDEF) {
-                       rule_a = rule;
-                       rule_b = NULL;
-               } else {
-                       /* need two rules, dup the first and link together */
-                       rule_a = rule;
-                       rule_dup = db_rule_dup(rule_a);
-                       rule_b = rule_dup;
-                       if (rule_b == NULL)
-                               goto add_return;
-                       rule_b->prev = rule_a;
-                       rule_b->next = NULL;
-                       rule_a->next = rule_b;
-               }
-
-               /* multiplexed socket syscalls */
-               if (rule_a != NULL) {
-                       rule_a->syscall = db->arch->sys_ipc;
-                       rule_a->args[0].arg = 0;
-                       rule_a->args[0].op = SCMP_CMP_EQ;
-                       rule_a->args[0].mask = DATUM_MAX;
-                       rule_a->args[0].datum = (-sys_a) % 200;
-                       rule_a->args[0].valid = 1;
-               }
-
-               /* direct wired socket syscalls */
-               if (rule_b != NULL)
-                       rule_b->syscall = sys_b;
-
-               /* we should be protected by a transaction checkpoint */
-               if (rule_a != NULL) {
-                       rc = db_rule_add(db, rule_a);
-                       if (rc < 0)
-                               goto add_return;
-               }
-               if (rule_b != NULL) {
-                       rc = db_rule_add(db, rule_b);
-                       if (rc < 0)
-                               goto add_return;
-               }
-       } else if (sys >= 0) {
-               /* normal syscall processing */
-               rc = db_rule_add(db, rule);
-               if (rc < 0)
-                       goto add_return;
-       } else if (rule->strict) {
-               rc = -EDOM;
-               goto add_return;
-       }
-
-add_return:
-       if (rule_dup != NULL)
-               free(rule_dup);
-       return rc;
-}
index af468a10f424008000fd25106774dd3f40cf00dd..d638733fad49d8e8d475b78b3a594b2ab4bf24e5 100644 (file)
@@ -59,12 +59,4 @@ int syscall_resolve_name(const char *name, int offset);
 const char *syscall_resolve_num(int num, int offset);
 const struct arch_syscall_def *syscall_iterate(unsigned int spot, int offset);
 
-/* helper functions for multiplexed syscalls, e.g. socketcall(2) and ipc(2) */
-int abi_syscall_resolve_name_munge(const struct arch_def *arch,
-                                  const char *name);
-const char *abi_syscall_resolve_num_munge(const struct arch_def *arch, int num);
-int abi_syscall_rewrite(const struct arch_def *arch, int *syscall);
-int abi_rule_add(struct db_filter *db, struct db_api_rule_list *rule);
-
-
 #endif