summaryrefslogtreecommitdiff
path: root/src/arch-mips.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch-mips.c')
-rw-r--r--src/arch-mips.c540
1 files changed, 16 insertions, 524 deletions
diff --git a/src/arch-mips.c b/src/arch-mips.c
index 1510d82..2625ddc 100644
--- a/src/arch-mips.c
+++ b/src/arch-mips.c
@@ -30,535 +30,23 @@
#include "arch.h"
#include "arch-mips.h"
-/* O32 ABI */
-#define __SCMP_NR_BASE 4000
-
/* mips syscall numbers */
#define __mips_NR_socketcall 102
#define __mips_NR_ipc 117
-/**
- * Resolve a syscall name to a number
- * @param name the syscall name
- *
- * Resolve the given syscall name to the syscall number using the syscall table.
- * Returns the syscall number on success, including negative pseudo syscall
- * numbers; returns __NR_SCMP_ERROR on failure.
- *
- */
-int mips_syscall_resolve_name_munge(const char *name)
-{
-
-#define _ABI_SYSCALL_RES_NAME_CHK(NAME) \
- if (!strcmp(name, #NAME)) return __PNR_##NAME;
-
- _ABI_SYSCALL_RES_NAME_CHK(socket)
- _ABI_SYSCALL_RES_NAME_CHK(bind)
- _ABI_SYSCALL_RES_NAME_CHK(connect)
- _ABI_SYSCALL_RES_NAME_CHK(listen)
- _ABI_SYSCALL_RES_NAME_CHK(accept)
- _ABI_SYSCALL_RES_NAME_CHK(getsockname)
- _ABI_SYSCALL_RES_NAME_CHK(getpeername)
- _ABI_SYSCALL_RES_NAME_CHK(socketpair)
- _ABI_SYSCALL_RES_NAME_CHK(send)
- _ABI_SYSCALL_RES_NAME_CHK(recv)
- _ABI_SYSCALL_RES_NAME_CHK(sendto)
- _ABI_SYSCALL_RES_NAME_CHK(recvfrom)
- _ABI_SYSCALL_RES_NAME_CHK(shutdown)
- _ABI_SYSCALL_RES_NAME_CHK(setsockopt)
- _ABI_SYSCALL_RES_NAME_CHK(getsockopt)
- _ABI_SYSCALL_RES_NAME_CHK(sendmsg)
- _ABI_SYSCALL_RES_NAME_CHK(recvmsg)
- _ABI_SYSCALL_RES_NAME_CHK(accept4)
- _ABI_SYSCALL_RES_NAME_CHK(recvmmsg)
- _ABI_SYSCALL_RES_NAME_CHK(sendmmsg)
- _ABI_SYSCALL_RES_NAME_CHK(semop)
- _ABI_SYSCALL_RES_NAME_CHK(semget)
- _ABI_SYSCALL_RES_NAME_CHK(semctl)
- _ABI_SYSCALL_RES_NAME_CHK(semtimedop)
- _ABI_SYSCALL_RES_NAME_CHK(msgsnd)
- _ABI_SYSCALL_RES_NAME_CHK(msgrcv)
- _ABI_SYSCALL_RES_NAME_CHK(msgget)
- _ABI_SYSCALL_RES_NAME_CHK(msgctl)
- _ABI_SYSCALL_RES_NAME_CHK(shmat)
- _ABI_SYSCALL_RES_NAME_CHK(shmdt)
- _ABI_SYSCALL_RES_NAME_CHK(shmget)
- _ABI_SYSCALL_RES_NAME_CHK(shmctl)
-
- return mips_syscall_resolve_name(name);
-}
-
-/**
- * Resolve a syscall number to a name
- * @param num the syscall number
- *
- * Resolve the given syscall number to the syscall name using the syscall table.
- * Returns a pointer to the syscall name string on success, including pseudo
- * syscall names; returns NULL on failure.
- *
- */
-const char *mips_syscall_resolve_num_munge(int num)
-{
-
-#define _ABI_SYSCALL_RES_NUM_CHK(NAME) \
- if (num == __PNR_##NAME) return #NAME;
-
- _ABI_SYSCALL_RES_NUM_CHK(socket)
- _ABI_SYSCALL_RES_NUM_CHK(bind)
- _ABI_SYSCALL_RES_NUM_CHK(connect)
- _ABI_SYSCALL_RES_NUM_CHK(listen)
- _ABI_SYSCALL_RES_NUM_CHK(accept)
- _ABI_SYSCALL_RES_NUM_CHK(getsockname)
- _ABI_SYSCALL_RES_NUM_CHK(getpeername)
- _ABI_SYSCALL_RES_NUM_CHK(socketpair)
- _ABI_SYSCALL_RES_NUM_CHK(send)
- _ABI_SYSCALL_RES_NUM_CHK(recv)
- _ABI_SYSCALL_RES_NUM_CHK(sendto)
- _ABI_SYSCALL_RES_NUM_CHK(recvfrom)
- _ABI_SYSCALL_RES_NUM_CHK(shutdown)
- _ABI_SYSCALL_RES_NUM_CHK(setsockopt)
- _ABI_SYSCALL_RES_NUM_CHK(getsockopt)
- _ABI_SYSCALL_RES_NUM_CHK(sendmsg)
- _ABI_SYSCALL_RES_NUM_CHK(recvmsg)
- _ABI_SYSCALL_RES_NUM_CHK(accept4)
- _ABI_SYSCALL_RES_NUM_CHK(recvmmsg)
- _ABI_SYSCALL_RES_NUM_CHK(sendmmsg)
- _ABI_SYSCALL_RES_NUM_CHK(semop)
- _ABI_SYSCALL_RES_NUM_CHK(semget)
- _ABI_SYSCALL_RES_NUM_CHK(semctl)
- _ABI_SYSCALL_RES_NUM_CHK(semtimedop)
- _ABI_SYSCALL_RES_NUM_CHK(msgsnd)
- _ABI_SYSCALL_RES_NUM_CHK(msgrcv)
- _ABI_SYSCALL_RES_NUM_CHK(msgget)
- _ABI_SYSCALL_RES_NUM_CHK(msgctl)
- _ABI_SYSCALL_RES_NUM_CHK(shmat)
- _ABI_SYSCALL_RES_NUM_CHK(shmdt)
- _ABI_SYSCALL_RES_NUM_CHK(shmget)
- _ABI_SYSCALL_RES_NUM_CHK(shmctl)
-
- return mips_syscall_resolve_num(num);
-}
-
-/**
- * Check if a syscall is a socket syscall
- * @param sys the syscall number
- *
- * Returns true if the syscall is a socket related syscall, false otherwise.
- *
- */
-static bool _mips_syscall_socket_test(int sys)
-{
- const char *name;
-
- /* multiplexed pseduo-syscalls */
- if (sys <= -100 && sys >= -120)
- return true;
-
- name = mips_syscall_resolve_num(sys);
- if (!name)
- return false;
-
-#define _ABI_SYSCALL_SOCK_CHK(NAME) \
- if (!strcmp(name, #NAME)) return true;
-
- _ABI_SYSCALL_SOCK_CHK(socket)
- _ABI_SYSCALL_SOCK_CHK(bind)
- _ABI_SYSCALL_SOCK_CHK(connect)
- _ABI_SYSCALL_SOCK_CHK(listen)
- _ABI_SYSCALL_SOCK_CHK(accept)
- _ABI_SYSCALL_SOCK_CHK(getsockname)
- _ABI_SYSCALL_SOCK_CHK(getpeername)
- _ABI_SYSCALL_SOCK_CHK(socketpair)
- _ABI_SYSCALL_SOCK_CHK(send)
- _ABI_SYSCALL_SOCK_CHK(recv)
- _ABI_SYSCALL_SOCK_CHK(sendto)
- _ABI_SYSCALL_SOCK_CHK(recvfrom)
- _ABI_SYSCALL_SOCK_CHK(shutdown)
- _ABI_SYSCALL_SOCK_CHK(setsockopt)
- _ABI_SYSCALL_SOCK_CHK(getsockopt)
- _ABI_SYSCALL_SOCK_CHK(sendmsg)
- _ABI_SYSCALL_SOCK_CHK(recvmsg)
- _ABI_SYSCALL_SOCK_CHK(accept4)
- _ABI_SYSCALL_SOCK_CHK(recvmmsg)
- _ABI_SYSCALL_SOCK_CHK(sendmmsg)
-
- return false;
-}
-
-/**
- * Check if a syscall is an ipc syscall
- * @param sys the syscall number
- *
- * Returns true if the syscall is an ipc related syscall, false otherwise.
- *
- */
-static bool _mips_syscall_ipc_test(int sys)
-{
- const char *name;
-
- /* multiplexed pseduo-syscalls */
- if (sys <= -200 && sys >= -224)
- return true;
-
- name = mips_syscall_resolve_num(sys);
- if (!name)
- return false;
-
-#define _ABI_SYSCALL_IPC_CHK(NAME) \
- if (!strcmp(name, #NAME)) return true;
-
- _ABI_SYSCALL_IPC_CHK(semop)
- _ABI_SYSCALL_IPC_CHK(semget)
- _ABI_SYSCALL_IPC_CHK(semctl)
- _ABI_SYSCALL_IPC_CHK(semtimedop)
- _ABI_SYSCALL_IPC_CHK(msgsnd)
- _ABI_SYSCALL_IPC_CHK(msgrcv)
- _ABI_SYSCALL_IPC_CHK(msgget)
- _ABI_SYSCALL_IPC_CHK(msgctl)
- _ABI_SYSCALL_IPC_CHK(shmat)
- _ABI_SYSCALL_IPC_CHK(shmdt)
- _ABI_SYSCALL_IPC_CHK(shmget)
- _ABI_SYSCALL_IPC_CHK(shmctl)
-
- return false;
-}
-
-/**
- * Convert a multiplexed pseudo syscall into a direct syscall
- * @param syscall the multiplexed pseudo syscall number
- *
- * Return the related direct syscall number, __NR_SCMP_UNDEF is there is
- * no related syscall, or __NR_SCMP_ERROR otherwise.
- *
- */
-static int _mips_syscall_demux(int syscall)
-{
- int sys = __NR_SCMP_UNDEF;
-
-#define _ABI_SYSCALL_DEMUX_CHK(NAME) \
-case __PNR_##NAME: \
- sys = mips_syscall_resolve_name(#NAME); break;
-
- switch (syscall) {
- _ABI_SYSCALL_DEMUX_CHK(socket)
- _ABI_SYSCALL_DEMUX_CHK(bind)
- _ABI_SYSCALL_DEMUX_CHK(connect)
- _ABI_SYSCALL_DEMUX_CHK(listen)
- _ABI_SYSCALL_DEMUX_CHK(accept)
- _ABI_SYSCALL_DEMUX_CHK(getsockname)
- _ABI_SYSCALL_DEMUX_CHK(getpeername)
- _ABI_SYSCALL_DEMUX_CHK(socketpair)
- _ABI_SYSCALL_DEMUX_CHK(send)
- _ABI_SYSCALL_DEMUX_CHK(recv)
- _ABI_SYSCALL_DEMUX_CHK(sendto)
- _ABI_SYSCALL_DEMUX_CHK(recvfrom)
- _ABI_SYSCALL_DEMUX_CHK(shutdown)
- _ABI_SYSCALL_DEMUX_CHK(setsockopt)
- _ABI_SYSCALL_DEMUX_CHK(getsockopt)
- _ABI_SYSCALL_DEMUX_CHK(sendmsg)
- _ABI_SYSCALL_DEMUX_CHK(recvmsg)
- _ABI_SYSCALL_DEMUX_CHK(accept4)
- _ABI_SYSCALL_DEMUX_CHK(recvmmsg)
- _ABI_SYSCALL_DEMUX_CHK(sendmmsg)
- _ABI_SYSCALL_DEMUX_CHK(semop)
- _ABI_SYSCALL_DEMUX_CHK(semget)
- _ABI_SYSCALL_DEMUX_CHK(semctl)
- _ABI_SYSCALL_DEMUX_CHK(semtimedop)
- _ABI_SYSCALL_DEMUX_CHK(msgsnd)
- _ABI_SYSCALL_DEMUX_CHK(msgrcv)
- _ABI_SYSCALL_DEMUX_CHK(msgget)
- _ABI_SYSCALL_DEMUX_CHK(msgctl)
- _ABI_SYSCALL_DEMUX_CHK(shmat)
- _ABI_SYSCALL_DEMUX_CHK(shmdt)
- _ABI_SYSCALL_DEMUX_CHK(shmget)
- _ABI_SYSCALL_DEMUX_CHK(shmctl)
- }
-
- /* this looks odd because the arch resolver returns _ERROR if it can't
- * resolve the syscall, but we want to use _UNDEF for that, so we set
- * 'sys' to a sentinel value of _UNDEF and if it is error here we know
- * the resolve failed to find a match */
- if (sys == __NR_SCMP_UNDEF)
- sys = __NR_SCMP_ERROR;
- else if (sys == __NR_SCMP_ERROR)
- sys = __NR_SCMP_UNDEF;
-
- return sys;
-}
-
-/**
- * Convert a direct syscall into multiplexed pseudo socket syscall
- * @param syscall the direct syscall
- *
- * Return the related multiplexed pseduo syscall number, __NR_SCMP_UNDEF is
- * there is no related pseudo syscall, or __NR_SCMP_ERROR otherwise.
- *
- */
-static int _mips_syscall_mux(int syscall)
-{
- const char *sys;
-
- sys = mips_syscall_resolve_num(syscall);
- if (!sys)
- return __NR_SCMP_ERROR;
-
-#define _ABI_SYSCALL_MUX_CHK(NAME) \
- if (!strcmp(sys, #NAME)) return __PNR_##NAME;
-
- _ABI_SYSCALL_MUX_CHK(socket)
- _ABI_SYSCALL_MUX_CHK(bind)
- _ABI_SYSCALL_MUX_CHK(connect)
- _ABI_SYSCALL_MUX_CHK(listen)
- _ABI_SYSCALL_MUX_CHK(accept)
- _ABI_SYSCALL_MUX_CHK(getsockname)
- _ABI_SYSCALL_MUX_CHK(getpeername)
- _ABI_SYSCALL_MUX_CHK(socketpair)
- _ABI_SYSCALL_MUX_CHK(send)
- _ABI_SYSCALL_MUX_CHK(recv)
- _ABI_SYSCALL_MUX_CHK(sendto)
- _ABI_SYSCALL_MUX_CHK(recvfrom)
- _ABI_SYSCALL_MUX_CHK(shutdown)
- _ABI_SYSCALL_MUX_CHK(setsockopt)
- _ABI_SYSCALL_MUX_CHK(getsockopt)
- _ABI_SYSCALL_MUX_CHK(sendmsg)
- _ABI_SYSCALL_MUX_CHK(recvmsg)
- _ABI_SYSCALL_MUX_CHK(accept4)
- _ABI_SYSCALL_MUX_CHK(recvmmsg)
- _ABI_SYSCALL_MUX_CHK(sendmmsg)
- _ABI_SYSCALL_MUX_CHK(semop)
- _ABI_SYSCALL_MUX_CHK(semget)
- _ABI_SYSCALL_MUX_CHK(semctl)
- _ABI_SYSCALL_MUX_CHK(semtimedop)
- _ABI_SYSCALL_MUX_CHK(msgsnd)
- _ABI_SYSCALL_MUX_CHK(msgrcv)
- _ABI_SYSCALL_MUX_CHK(msgget)
- _ABI_SYSCALL_MUX_CHK(msgctl)
- _ABI_SYSCALL_MUX_CHK(shmat)
- _ABI_SYSCALL_MUX_CHK(shmdt)
- _ABI_SYSCALL_MUX_CHK(shmget)
- _ABI_SYSCALL_MUX_CHK(shmctl)
-
- return __NR_SCMP_ERROR;
-}
-
-/**
- * Rewrite a syscall value to match the architecture
- * @param syscall the syscall number
- *
- * Syscalls can vary across different architectures so this function rewrites
- * the syscall into the correct value for the specified architecture. Returns
- * zero on success, negative values on failure.
- *
- */
-int mips_syscall_rewrite(int *syscall)
-{
- int sys = *syscall;
-
- if (sys <= -100 && sys >= -120)
- *syscall = __mips_NR_socketcall;
- else if (sys <= -200 && sys >= -224)
- *syscall = __mips_NR_ipc;
- else if (sys < 0)
- return -EDOM;
-
- return 0;
-}
-
-/**
- * add a new rule to the mips seccomp filter
- * @param db the seccomp filter db
- * @param rule the filter rule
- *
- * This function adds a new syscall filter to the seccomp filter db, making any
- * necessary adjustments for the mips ABI. Returns zero on success, negative
- * values on failure.
- *
- * It is important to note that in the case of failure the db may be corrupted,
- * the caller must use the transaction mechanism if the db integrity is
- * important.
- *
- */
-int mips_rule_add(struct db_filter *db, struct db_api_rule_list *rule)
-{
- int rc = 0;
- unsigned int iter;
- int sys = rule->syscall;
- int sys_a, sys_b;
- struct db_api_rule_list *rule_a, *rule_b, *rule_dup = NULL;
-
- if (_mips_syscall_socket_test(sys)) {
- /* socket syscalls */
-
- /* strict check for the multiplexed socket syscalls */
- for (iter = 0; iter < ARG_COUNT_MAX; iter++) {
- if ((rule->args[iter].valid != 0) && (rule->strict)) {
- rc = -EINVAL;
- goto add_return;
- }
- }
-
- /* determine both the muxed and direct syscall numbers */
- if (sys > 0) {
- sys_a = _mips_syscall_mux(sys);
- if (sys_a == __NR_SCMP_ERROR) {
- rc = __NR_SCMP_ERROR;
- goto add_return;
- }
- sys_b = sys;
- } else {
- sys_a = sys;
- sys_b = _mips_syscall_demux(sys);
- if (sys_b == __NR_SCMP_ERROR) {
- rc = __NR_SCMP_ERROR;
- goto add_return;
- }
- }
-
- /* use rule_a for the multiplexed syscall and use rule_b for
- * the direct wired syscall */
-
- if (sys_a == __NR_SCMP_UNDEF) {
- rule_a = NULL;
- rule_b = rule;
- } else if (sys_b == __NR_SCMP_UNDEF) {
- rule_a = rule;
- rule_b = NULL;
- } else {
- /* need two rules, dup the first and link together */
- rule_a = rule;
- rule_dup = db_rule_dup(rule_a);
- rule_b = rule_dup;
- if (rule_b == NULL)
- goto add_return;
- rule_b->prev = rule_a;
- rule_b->next = NULL;
- rule_a->next = rule_b;
- }
-
- /* multiplexed socket syscalls */
- if (rule_a != NULL) {
- rule_a->syscall = __mips_NR_socketcall;
- rule_a->args[0].arg = 0;
- rule_a->args[0].op = SCMP_CMP_EQ;
- rule_a->args[0].mask = DATUM_MAX;
- rule_a->args[0].datum = (-sys_a) % 100;
- rule_a->args[0].valid = 1;
- }
-
- /* direct wired socket syscalls */
- if (rule_b != NULL)
- rule_b->syscall = sys_b;
-
- /* we should be protected by a transaction checkpoint */
- if (rule_a != NULL) {
- rc = db_rule_add(db, rule_a);
- if (rc < 0)
- goto add_return;
- }
- if (rule_b != NULL) {
- rc = db_rule_add(db, rule_b);
- if (rc < 0)
- goto add_return;
- }
- } else if (_mips_syscall_ipc_test(sys)) {
- /* ipc syscalls */
-
- /* strict check for the multiplexed socket syscalls */
- for (iter = 0; iter < ARG_COUNT_MAX; iter++) {
- if ((rule->args[iter].valid != 0) && (rule->strict)) {
- rc = -EINVAL;
- goto add_return;
- }
- }
-
- /* determine both the muxed and direct syscall numbers */
- if (sys > 0) {
- sys_a = _mips_syscall_mux(sys);
- if (sys_a == __NR_SCMP_ERROR) {
- rc = __NR_SCMP_ERROR;
- goto add_return;
- }
- sys_b = sys;
- } else {
- sys_a = sys;
- sys_b = _mips_syscall_demux(sys);
- if (sys_b == __NR_SCMP_ERROR) {
- rc = __NR_SCMP_ERROR;
- goto add_return;
- }
- }
-
- /* use rule_a for the multiplexed syscall and use rule_b for
- * the direct wired syscall */
-
- if (sys_a == __NR_SCMP_UNDEF) {
- rule_a = NULL;
- rule_b = rule;
- } else if (sys_b == __NR_SCMP_UNDEF) {
- rule_a = rule;
- rule_b = NULL;
- } else {
- /* need two rules, dup the first and link together */
- rule_a = rule;
- rule_dup = db_rule_dup(rule_a);
- rule_b = rule_dup;
- if (rule_b == NULL)
- goto add_return;
- rule_b->prev = rule_a;
- rule_b->next = NULL;
- rule_a->next = rule_b;
- }
-
- /* multiplexed socket syscalls */
- if (rule_a != NULL) {
- rule_a->syscall = __mips_NR_ipc;
- rule_a->args[0].arg = 0;
- rule_a->args[0].op = SCMP_CMP_EQ;
- rule_a->args[0].mask = DATUM_MAX;
- rule_a->args[0].datum = (-sys_a) % 200;
- rule_a->args[0].valid = 1;
- }
-
- /* direct wired socket syscalls */
- if (rule_b != NULL)
- rule_b->syscall = sys_b;
-
- /* we should be protected by a transaction checkpoint */
- if (rule_a != NULL) {
- rc = db_rule_add(db, rule_a);
- if (rc < 0)
- goto add_return;
- }
- if (rule_b != NULL) {
- rc = db_rule_add(db, rule_b);
- if (rc < 0)
- goto add_return;
- }
- } else if (sys >= 0) {
- /* normal syscall processing */
- rc = db_rule_add(db, rule);
- if (rc < 0)
- goto add_return;
- } else if (rule->strict) {
- rc = -EDOM;
- goto add_return;
- }
-
-add_return:
- if (rule_dup != NULL)
- free(rule_dup);
- return rc;
-}
-
const struct arch_def arch_def_mips = {
.token = SCMP_ARCH_MIPS,
.token_bpf = AUDIT_ARCH_MIPS,
.size = ARCH_SIZE_32,
.endian = ARCH_ENDIAN_BIG,
- .syscall_resolve_name = mips_syscall_resolve_name_munge,
- .syscall_resolve_num = mips_syscall_resolve_num_munge,
- .syscall_rewrite = mips_syscall_rewrite,
- .rule_add = mips_rule_add,
+ .sys_socketcall = __mips_NR_socketcall,
+ .sys_ipc = __mips_NR_ipc,
+ .syscall_resolve_name = abi_syscall_resolve_name_munge,
+ .syscall_resolve_name_raw = mips_syscall_resolve_name,
+ .syscall_resolve_num = abi_syscall_resolve_num_munge,
+ .syscall_resolve_num_raw = mips_syscall_resolve_num,
+ .syscall_rewrite = abi_syscall_rewrite,
+ .rule_add = abi_rule_add,
};
const struct arch_def arch_def_mipsel = {
@@ -566,8 +54,12 @@ const struct arch_def arch_def_mipsel = {
.token_bpf = AUDIT_ARCH_MIPSEL,
.size = ARCH_SIZE_32,
.endian = ARCH_ENDIAN_LITTLE,
- .syscall_resolve_name = mips_syscall_resolve_name_munge,
- .syscall_resolve_num = mips_syscall_resolve_num_munge,
- .syscall_rewrite = mips_syscall_rewrite,
- .rule_add = mips_rule_add,
+ .sys_socketcall = __mips_NR_socketcall,
+ .sys_ipc = __mips_NR_ipc,
+ .syscall_resolve_name = abi_syscall_resolve_name_munge,
+ .syscall_resolve_name_raw = mips_syscall_resolve_name,
+ .syscall_resolve_num = abi_syscall_resolve_num_munge,
+ .syscall_resolve_num_raw = mips_syscall_resolve_num,
+ .syscall_rewrite = abi_syscall_rewrite,
+ .rule_add = abi_rule_add,
};