summaryrefslogtreecommitdiff
path: root/src/arch-ppc.c
diff options
context:
space:
mode:
authorPaul Moore <paul@paul-moore.com>2021-08-04 11:51:12 -0400
committerPaul Moore <paul@paul-moore.com>2021-08-12 12:30:34 -0400
commit17cbd2c253ce63e5e9e3cec867ff58efbe8b5fdc (patch)
treedb15f9ddc82f016889ba2c8bf2fafa8002d751a3 /src/arch-ppc.c
parentc261232174c8432e12c39e2fc938a64d562de1d6 (diff)
downloadlibseccomp-17cbd2c253ce63e5e9e3cec867ff58efbe8b5fdc.tar.gz
arch: consolidate all of the multiplexed syscall handling
Not only does this reduce the amount of duplicated code significantly, it removes a lot of the "magic" numbers in the code, and it happened to catch some bugs too. Acked-by: Tom Hromatka <tom.hromatka@oracle.com> Signed-off-by: Paul Moore <paul@paul-moore.com>
Diffstat (limited to 'src/arch-ppc.c')
-rw-r--r--src/arch-ppc.c525
1 files changed, 8 insertions, 517 deletions
diff --git a/src/arch-ppc.c b/src/arch-ppc.c
index 035888c..0c97bf5 100644
--- a/src/arch-ppc.c
+++ b/src/arch-ppc.c
@@ -34,526 +34,17 @@
#define __ppc_NR_socketcall 102
#define __ppc_NR_ipc 117
-/**
- * Resolve a syscall name to a number
- * @param name the syscall name
- *
- * Resolve the given syscall name to the syscall number using the syscall table.
- * Returns the syscall number on success, including negative pseudo syscall
- * numbers; returns __NR_SCMP_ERROR on failure.
- *
- */
-int ppc_syscall_resolve_name_munge(const char *name)
-{
-
-#define _ABI_SYSCALL_RES_NAME_CHK(NAME) \
- if (!strcmp(name, #NAME)) return __PNR_##NAME;
-
- _ABI_SYSCALL_RES_NAME_CHK(socket)
- _ABI_SYSCALL_RES_NAME_CHK(bind)
- _ABI_SYSCALL_RES_NAME_CHK(connect)
- _ABI_SYSCALL_RES_NAME_CHK(listen)
- _ABI_SYSCALL_RES_NAME_CHK(accept)
- _ABI_SYSCALL_RES_NAME_CHK(getsockname)
- _ABI_SYSCALL_RES_NAME_CHK(getpeername)
- _ABI_SYSCALL_RES_NAME_CHK(socketpair)
- _ABI_SYSCALL_RES_NAME_CHK(send)
- _ABI_SYSCALL_RES_NAME_CHK(recv)
- _ABI_SYSCALL_RES_NAME_CHK(sendto)
- _ABI_SYSCALL_RES_NAME_CHK(recvfrom)
- _ABI_SYSCALL_RES_NAME_CHK(shutdown)
- _ABI_SYSCALL_RES_NAME_CHK(setsockopt)
- _ABI_SYSCALL_RES_NAME_CHK(getsockopt)
- _ABI_SYSCALL_RES_NAME_CHK(sendmsg)
- _ABI_SYSCALL_RES_NAME_CHK(recvmsg)
- _ABI_SYSCALL_RES_NAME_CHK(accept4)
- _ABI_SYSCALL_RES_NAME_CHK(recvmmsg)
- _ABI_SYSCALL_RES_NAME_CHK(sendmmsg)
- _ABI_SYSCALL_RES_NAME_CHK(semop)
- _ABI_SYSCALL_RES_NAME_CHK(semget)
- _ABI_SYSCALL_RES_NAME_CHK(semctl)
- _ABI_SYSCALL_RES_NAME_CHK(semtimedop)
- _ABI_SYSCALL_RES_NAME_CHK(msgsnd)
- _ABI_SYSCALL_RES_NAME_CHK(msgrcv)
- _ABI_SYSCALL_RES_NAME_CHK(msgget)
- _ABI_SYSCALL_RES_NAME_CHK(msgctl)
- _ABI_SYSCALL_RES_NAME_CHK(shmat)
- _ABI_SYSCALL_RES_NAME_CHK(shmdt)
- _ABI_SYSCALL_RES_NAME_CHK(shmget)
- _ABI_SYSCALL_RES_NAME_CHK(shmctl)
-
- return ppc_syscall_resolve_name(name);
-}
-
-/**
- * Resolve a syscall number to a name
- * @param num the syscall number
- *
- * Resolve the given syscall number to the syscall name using the syscall table.
- * Returns a pointer to the syscall name string on success, including pseudo
- * syscall names; returns NULL on failure.
- *
- */
-const char *ppc_syscall_resolve_num_munge(int num)
-{
-
-#define _ABI_SYSCALL_RES_NUM_CHK(NAME) \
- if (num == __PNR_##NAME) return #NAME;
-
- _ABI_SYSCALL_RES_NUM_CHK(socket)
- _ABI_SYSCALL_RES_NUM_CHK(bind)
- _ABI_SYSCALL_RES_NUM_CHK(connect)
- _ABI_SYSCALL_RES_NUM_CHK(listen)
- _ABI_SYSCALL_RES_NUM_CHK(accept)
- _ABI_SYSCALL_RES_NUM_CHK(getsockname)
- _ABI_SYSCALL_RES_NUM_CHK(getpeername)
- _ABI_SYSCALL_RES_NUM_CHK(socketpair)
- _ABI_SYSCALL_RES_NUM_CHK(send)
- _ABI_SYSCALL_RES_NUM_CHK(recv)
- _ABI_SYSCALL_RES_NUM_CHK(sendto)
- _ABI_SYSCALL_RES_NUM_CHK(recvfrom)
- _ABI_SYSCALL_RES_NUM_CHK(shutdown)
- _ABI_SYSCALL_RES_NUM_CHK(setsockopt)
- _ABI_SYSCALL_RES_NUM_CHK(getsockopt)
- _ABI_SYSCALL_RES_NUM_CHK(sendmsg)
- _ABI_SYSCALL_RES_NUM_CHK(recvmsg)
- _ABI_SYSCALL_RES_NUM_CHK(accept4)
- _ABI_SYSCALL_RES_NUM_CHK(recvmmsg)
- _ABI_SYSCALL_RES_NUM_CHK(sendmmsg)
- _ABI_SYSCALL_RES_NUM_CHK(semop)
- _ABI_SYSCALL_RES_NUM_CHK(semget)
- _ABI_SYSCALL_RES_NUM_CHK(semctl)
- _ABI_SYSCALL_RES_NUM_CHK(semtimedop)
- _ABI_SYSCALL_RES_NUM_CHK(msgsnd)
- _ABI_SYSCALL_RES_NUM_CHK(msgrcv)
- _ABI_SYSCALL_RES_NUM_CHK(msgget)
- _ABI_SYSCALL_RES_NUM_CHK(msgctl)
- _ABI_SYSCALL_RES_NUM_CHK(shmat)
- _ABI_SYSCALL_RES_NUM_CHK(shmdt)
- _ABI_SYSCALL_RES_NUM_CHK(shmget)
- _ABI_SYSCALL_RES_NUM_CHK(shmctl)
-
- return ppc_syscall_resolve_num(num);
-}
-
-/**
- * Check if a syscall is a socket syscall
- * @param sys the syscall number
- *
- * Returns true if the syscall is a socket related syscall, false otherwise.
- *
- */
-static bool _ppc_syscall_socket_test(int sys)
-{
- const char *name;
-
- /* multiplexed pseduo-syscalls */
- if (sys <= -100 && sys >= -120)
- return true;
-
- name = ppc_syscall_resolve_num(sys);
- if (!name)
- return false;
-
-#define _ABI_SYSCALL_SOCK_CHK(NAME) \
- if (!strcmp(name, #NAME)) return true;
-
- _ABI_SYSCALL_SOCK_CHK(socket)
- _ABI_SYSCALL_SOCK_CHK(bind)
- _ABI_SYSCALL_SOCK_CHK(connect)
- _ABI_SYSCALL_SOCK_CHK(listen)
- _ABI_SYSCALL_SOCK_CHK(accept)
- _ABI_SYSCALL_SOCK_CHK(getsockname)
- _ABI_SYSCALL_SOCK_CHK(getpeername)
- _ABI_SYSCALL_SOCK_CHK(socketpair)
- _ABI_SYSCALL_SOCK_CHK(send)
- _ABI_SYSCALL_SOCK_CHK(recv)
- _ABI_SYSCALL_SOCK_CHK(sendto)
- _ABI_SYSCALL_SOCK_CHK(recvfrom)
- _ABI_SYSCALL_SOCK_CHK(shutdown)
- _ABI_SYSCALL_SOCK_CHK(setsockopt)
- _ABI_SYSCALL_SOCK_CHK(getsockopt)
- _ABI_SYSCALL_SOCK_CHK(sendmsg)
- _ABI_SYSCALL_SOCK_CHK(recvmsg)
- _ABI_SYSCALL_SOCK_CHK(accept4)
- _ABI_SYSCALL_SOCK_CHK(recvmmsg)
- _ABI_SYSCALL_SOCK_CHK(sendmmsg)
-
- return false;
-}
-
-/**
- * Check if a syscall is an ipc syscall
- * @param sys the syscall number
- *
- * Returns true if the syscall is an ipc related syscall, false otherwise.
- *
- */
-static bool _ppc_syscall_ipc_test(int sys)
-{
- const char *name;
-
- /* multiplexed pseduo-syscalls */
- if (sys <= -200 && sys >= -224)
- return true;
-
- name = ppc_syscall_resolve_num(sys);
- if (!name)
- return false;
-
-#define _ABI_SYSCALL_IPC_CHK(NAME) \
- if (!strcmp(name, #NAME)) return true;
-
- _ABI_SYSCALL_IPC_CHK(semop)
- _ABI_SYSCALL_IPC_CHK(semget)
- _ABI_SYSCALL_IPC_CHK(semctl)
- _ABI_SYSCALL_IPC_CHK(semtimedop)
- _ABI_SYSCALL_IPC_CHK(msgsnd)
- _ABI_SYSCALL_IPC_CHK(msgrcv)
- _ABI_SYSCALL_IPC_CHK(msgget)
- _ABI_SYSCALL_IPC_CHK(msgctl)
- _ABI_SYSCALL_IPC_CHK(shmat)
- _ABI_SYSCALL_IPC_CHK(shmdt)
- _ABI_SYSCALL_IPC_CHK(shmget)
- _ABI_SYSCALL_IPC_CHK(shmctl)
-
- return false;
-}
-
-/**
- * Convert a multiplexed pseudo syscall into a direct syscall
- * @param syscall the multiplexed pseudo syscall number
- *
- * Return the related direct syscall number, __NR_SCMP_UNDEF is there is
- * no related syscall, or __NR_SCMP_ERROR otherwise.
- *
- */
-static int _ppc_syscall_demux(int syscall)
-{
- int sys = __NR_SCMP_UNDEF;
-
-#define _ABI_SYSCALL_DEMUX_CHK(NAME) \
-case __PNR_##NAME: \
- sys = ppc_syscall_resolve_name(#NAME); break;
-
- switch (syscall) {
- _ABI_SYSCALL_DEMUX_CHK(socket)
- _ABI_SYSCALL_DEMUX_CHK(bind)
- _ABI_SYSCALL_DEMUX_CHK(connect)
- _ABI_SYSCALL_DEMUX_CHK(listen)
- _ABI_SYSCALL_DEMUX_CHK(accept)
- _ABI_SYSCALL_DEMUX_CHK(getsockname)
- _ABI_SYSCALL_DEMUX_CHK(getpeername)
- _ABI_SYSCALL_DEMUX_CHK(socketpair)
- _ABI_SYSCALL_DEMUX_CHK(send)
- _ABI_SYSCALL_DEMUX_CHK(recv)
- _ABI_SYSCALL_DEMUX_CHK(sendto)
- _ABI_SYSCALL_DEMUX_CHK(recvfrom)
- _ABI_SYSCALL_DEMUX_CHK(shutdown)
- _ABI_SYSCALL_DEMUX_CHK(setsockopt)
- _ABI_SYSCALL_DEMUX_CHK(getsockopt)
- _ABI_SYSCALL_DEMUX_CHK(sendmsg)
- _ABI_SYSCALL_DEMUX_CHK(recvmsg)
- _ABI_SYSCALL_DEMUX_CHK(accept4)
- _ABI_SYSCALL_DEMUX_CHK(recvmmsg)
- _ABI_SYSCALL_DEMUX_CHK(sendmmsg)
- _ABI_SYSCALL_DEMUX_CHK(semop)
- _ABI_SYSCALL_DEMUX_CHK(semget)
- _ABI_SYSCALL_DEMUX_CHK(semctl)
- _ABI_SYSCALL_DEMUX_CHK(semtimedop)
- _ABI_SYSCALL_DEMUX_CHK(msgsnd)
- _ABI_SYSCALL_DEMUX_CHK(msgrcv)
- _ABI_SYSCALL_DEMUX_CHK(msgget)
- _ABI_SYSCALL_DEMUX_CHK(msgctl)
- _ABI_SYSCALL_DEMUX_CHK(shmat)
- _ABI_SYSCALL_DEMUX_CHK(shmdt)
- _ABI_SYSCALL_DEMUX_CHK(shmget)
- _ABI_SYSCALL_DEMUX_CHK(shmctl)
- }
-
- /* this looks odd because the arch resolver returns _ERROR if it can't
- * resolve the syscall, but we want to use _UNDEF for that, so we set
- * 'sys' to a sentinel value of _UNDEF and if it is error here we know
- * the resolve failed to find a match */
- if (sys == __NR_SCMP_UNDEF)
- sys = __NR_SCMP_ERROR;
- else if (sys == __NR_SCMP_ERROR)
- sys = __NR_SCMP_UNDEF;
-
- return sys;
-}
-
-/**
- * Convert a direct syscall into multiplexed pseudo socket syscall
- * @param syscall the direct syscall
- *
- * Return the related multiplexed pseduo syscall number, __NR_SCMP_UNDEF is
- * there is no related pseudo syscall, or __NR_SCMP_ERROR otherwise.
- *
- */
-static int _ppc_syscall_mux(int syscall)
-{
- const char *sys;
-
- sys = ppc_syscall_resolve_num(syscall);
- if (!sys)
- return __NR_SCMP_ERROR;
-
-#define _ABI_SYSCALL_MUX_CHK(NAME) \
- if (!strcmp(sys, #NAME)) return __PNR_##NAME;
-
- _ABI_SYSCALL_MUX_CHK(socket)
- _ABI_SYSCALL_MUX_CHK(bind)
- _ABI_SYSCALL_MUX_CHK(connect)
- _ABI_SYSCALL_MUX_CHK(listen)
- _ABI_SYSCALL_MUX_CHK(accept)
- _ABI_SYSCALL_MUX_CHK(getsockname)
- _ABI_SYSCALL_MUX_CHK(getpeername)
- _ABI_SYSCALL_MUX_CHK(socketpair)
- _ABI_SYSCALL_MUX_CHK(send)
- _ABI_SYSCALL_MUX_CHK(recv)
- _ABI_SYSCALL_MUX_CHK(sendto)
- _ABI_SYSCALL_MUX_CHK(recvfrom)
- _ABI_SYSCALL_MUX_CHK(shutdown)
- _ABI_SYSCALL_MUX_CHK(setsockopt)
- _ABI_SYSCALL_MUX_CHK(getsockopt)
- _ABI_SYSCALL_MUX_CHK(sendmsg)
- _ABI_SYSCALL_MUX_CHK(recvmsg)
- _ABI_SYSCALL_MUX_CHK(accept4)
- _ABI_SYSCALL_MUX_CHK(recvmmsg)
- _ABI_SYSCALL_MUX_CHK(sendmmsg)
- _ABI_SYSCALL_MUX_CHK(semop)
- _ABI_SYSCALL_MUX_CHK(semget)
- _ABI_SYSCALL_MUX_CHK(semctl)
- _ABI_SYSCALL_MUX_CHK(semtimedop)
- _ABI_SYSCALL_MUX_CHK(msgsnd)
- _ABI_SYSCALL_MUX_CHK(msgrcv)
- _ABI_SYSCALL_MUX_CHK(msgget)
- _ABI_SYSCALL_MUX_CHK(msgctl)
- _ABI_SYSCALL_MUX_CHK(shmat)
- _ABI_SYSCALL_MUX_CHK(shmdt)
- _ABI_SYSCALL_MUX_CHK(shmget)
- _ABI_SYSCALL_MUX_CHK(shmctl)
-
- return __NR_SCMP_ERROR;
-}
-
-/**
- * Rewrite a syscall value to match the architecture
- * @param syscall the syscall number
- *
- * Syscalls can vary across different architectures so this function rewrites
- * the syscall into the correct value for the specified architecture. Returns
- * zero on success, negative values on failure.
- *
- */
-int ppc_syscall_rewrite(int *syscall)
-{
- int sys = *syscall;
-
- if (sys <= -100 && sys >= -120)
- *syscall = __ppc_NR_socketcall;
- else if (sys <= -200 && sys >= -224)
- *syscall = __ppc_NR_ipc;
- else if (sys < 0)
- return -EDOM;
-
- return 0;
-}
-
-/**
- * add a new rule to the ppc seccomp filter
- * @param db the seccomp filter db
- * @param rule the filter rule
- *
- * This function adds a new syscall filter to the seccomp filter db, making any
- * necessary adjustments for the ppc ABI. Returns zero on success, negative
- * values on failure.
- *
- * It is important to note that in the case of failure the db may be corrupted,
- * the caller must use the transaction mechanism if the db integrity is
- * important.
- *
- */
-int ppc_rule_add(struct db_filter *db, struct db_api_rule_list *rule)
-{
- int rc = 0;
- unsigned int iter;
- int sys = rule->syscall;
- int sys_a, sys_b;
- struct db_api_rule_list *rule_a, *rule_b, *rule_dup = NULL;
-
- if (_ppc_syscall_socket_test(sys)) {
- /* socket syscalls */
-
- /* strict check for the multiplexed socket syscalls */
- for (iter = 0; iter < ARG_COUNT_MAX; iter++) {
- if ((rule->args[iter].valid != 0) && (rule->strict)) {
- rc = -EINVAL;
- goto add_return;
- }
- }
-
- /* determine both the muxed and direct syscall numbers */
- if (sys > 0) {
- sys_a = _ppc_syscall_mux(sys);
- if (sys_a == __NR_SCMP_ERROR) {
- rc = __NR_SCMP_ERROR;
- goto add_return;
- }
- sys_b = sys;
- } else {
- sys_a = sys;
- sys_b = _ppc_syscall_demux(sys);
- if (sys_b == __NR_SCMP_ERROR) {
- rc = __NR_SCMP_ERROR;
- goto add_return;
- }
- }
-
- /* use rule_a for the multiplexed syscall and use rule_b for
- * the direct wired syscall */
-
- if (sys_a == __NR_SCMP_UNDEF) {
- rule_a = NULL;
- rule_b = rule;
- } else if (sys_b == __NR_SCMP_UNDEF) {
- rule_a = rule;
- rule_b = NULL;
- } else {
- /* need two rules, dup the first and link together */
- rule_a = rule;
- rule_dup = db_rule_dup(rule_a);
- rule_b = rule_dup;
- if (rule_b == NULL)
- goto add_return;
- rule_b->prev = rule_a;
- rule_b->next = NULL;
- rule_a->next = rule_b;
- }
-
- /* multiplexed socket syscalls */
- if (rule_a != NULL) {
- rule_a->syscall = __ppc_NR_socketcall;
- rule_a->args[0].arg = 0;
- rule_a->args[0].op = SCMP_CMP_EQ;
- rule_a->args[0].mask = DATUM_MAX;
- rule_a->args[0].datum = (-sys_a) % 100;
- rule_a->args[0].valid = 1;
- }
-
- /* direct wired socket syscalls */
- if (rule_b != NULL)
- rule_b->syscall = sys_b;
-
- /* we should be protected by a transaction checkpoint */
- if (rule_a != NULL) {
- rc = db_rule_add(db, rule_a);
- if (rc < 0)
- goto add_return;
- }
- if (rule_b != NULL) {
- rc = db_rule_add(db, rule_b);
- if (rc < 0)
- goto add_return;
- }
- } else if (_ppc_syscall_ipc_test(sys)) {
- /* ipc syscalls */
-
- /* strict check for the multiplexed socket syscalls */
- for (iter = 0; iter < ARG_COUNT_MAX; iter++) {
- if ((rule->args[iter].valid != 0) && (rule->strict)) {
- rc = -EINVAL;
- goto add_return;
- }
- }
-
- /* determine both the muxed and direct syscall numbers */
- if (sys > 0) {
- sys_a = _ppc_syscall_mux(sys);
- if (sys_a == __NR_SCMP_ERROR) {
- rc = __NR_SCMP_ERROR;
- goto add_return;
- }
- sys_b = sys;
- } else {
- sys_a = sys;
- sys_b = _ppc_syscall_demux(sys);
- if (sys_b == __NR_SCMP_ERROR) {
- rc = __NR_SCMP_ERROR;
- goto add_return;
- }
- }
-
- /* use rule_a for the multiplexed syscall and use rule_b for
- * the direct wired syscall */
-
- if (sys_a == __NR_SCMP_UNDEF) {
- rule_a = NULL;
- rule_b = rule;
- } else if (sys_b == __NR_SCMP_UNDEF) {
- rule_a = rule;
- rule_b = NULL;
- } else {
- /* need two rules, dup the first and link together */
- rule_a = rule;
- rule_dup = db_rule_dup(rule_a);
- rule_b = rule_dup;
- if (rule_b == NULL)
- goto add_return;
- rule_b->prev = rule_a;
- rule_b->next = NULL;
- rule_a->next = rule_b;
- }
-
- /* multiplexed socket syscalls */
- if (rule_a != NULL) {
- rule_a->syscall = __ppc_NR_ipc;
- rule_a->args[0].arg = 0;
- rule_a->args[0].op = SCMP_CMP_EQ;
- rule_a->args[0].mask = DATUM_MAX;
- rule_a->args[0].datum = (-sys_a) % 200;
- rule_a->args[0].valid = 1;
- }
-
- /* direct wired socket syscalls */
- if (rule_b != NULL)
- rule_b->syscall = sys_b;
-
- /* we should be protected by a transaction checkpoint */
- if (rule_a != NULL) {
- rc = db_rule_add(db, rule_a);
- if (rc < 0)
- goto add_return;
- }
- if (rule_b != NULL) {
- rc = db_rule_add(db, rule_b);
- if (rc < 0)
- goto add_return;
- }
- } else if (sys >= 0) {
- /* normal syscall processing */
- rc = db_rule_add(db, rule);
- if (rc < 0)
- goto add_return;
- } else if (rule->strict) {
- rc = -EDOM;
- goto add_return;
- }
-
-add_return:
- if (rule_dup != NULL)
- free(rule_dup);
- return rc;
-}
-
const struct arch_def arch_def_ppc = {
.token = SCMP_ARCH_PPC,
.token_bpf = AUDIT_ARCH_PPC,
.size = ARCH_SIZE_32,
.endian = ARCH_ENDIAN_BIG,
- .syscall_resolve_name = ppc_syscall_resolve_name_munge,
- .syscall_resolve_num = ppc_syscall_resolve_num_munge,
- .syscall_rewrite = ppc_syscall_rewrite,
- .rule_add = ppc_rule_add,
+ .sys_socketcall = __ppc_NR_socketcall,
+ .sys_ipc = __ppc_NR_ipc,
+ .syscall_resolve_name = abi_syscall_resolve_name_munge,
+ .syscall_resolve_name_raw = ppc_syscall_resolve_name,
+ .syscall_resolve_num = abi_syscall_resolve_num_munge,
+ .syscall_resolve_num_raw = ppc_syscall_resolve_num,
+ .syscall_rewrite = abi_syscall_rewrite,
+ .rule_add = abi_rule_add,
};