From 47516603828396f85107ea3e2a254958c2bc3ff5 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Wed, 20 Apr 2016 13:49:04 -0400 Subject: s390: handle multiplexed syscalls correctly It turns out the socket and ipc related syscalls are also multiplexed on s390/s390x much like they are on 32-bit x86. Further making things difficult is that starting with Linux 4.3 the socket syscalls are also available as directly wired versions, much like 32-bit x86. This patch attempts to fix all those problems. Signed-off-by: Paul Moore (imported from commit 66282c31034e2bb442bd9dc862d6d814f0df2f98) --- src/arch-s390-syscalls.c | 84 +++++++++ src/arch-s390.c | 310 +++++++++++++++++++++++++++++++++- src/arch-s390.h | 11 +- src/arch-s390x-syscalls.c | 84 +++++++++ src/arch-s390x.c | 310 +++++++++++++++++++++++++++++++++- src/arch-s390x.h | 13 +- src/arch-x86.c | 2 +- tests/.gitignore | 1 + tests/33-sim-socket_syscalls_be.c | 81 +++++++++ tests/33-sim-socket_syscalls_be.py | 48 ++++++ tests/33-sim-socket_syscalls_be.tests | 39 +++++ tests/Makefile.am | 9 +- 12 files changed, 979 insertions(+), 13 deletions(-) create mode 100644 tests/33-sim-socket_syscalls_be.c create mode 100755 tests/33-sim-socket_syscalls_be.py create mode 100644 tests/33-sim-socket_syscalls_be.tests diff --git a/src/arch-s390-syscalls.c b/src/arch-s390-syscalls.c index a6cf826..a04673a 100644 --- a/src/arch-s390-syscalls.c +++ b/src/arch-s390-syscalls.c @@ -453,6 +453,48 @@ int s390_syscall_resolve_name(const char *name) const struct arch_syscall_def *table = s390_syscall_table; /* XXX - plenty of room for future improvement here */ + + 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, "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; + for (iter = 0; table[iter].name != NULL; iter++) { if (strcmp(name, table[iter].name) == 0) return table[iter].num; @@ -476,6 +518,48 @@ const char *s390_syscall_resolve_num(int num) const struct arch_syscall_def *table = s390_syscall_table; /* XXX - plenty of room for future improvement here */ + + 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"; + for (iter = 0; table[iter].num != __NR_SCMP_ERROR; iter++) { if (num == table[iter].num) return table[iter].name; diff --git a/src/arch-s390.c b/src/arch-s390.c index f509809..fca5fee 100644 --- a/src/arch-s390.c +++ b/src/arch-s390.c @@ -5,11 +5,16 @@ #include #include +#include #include #include "arch.h" #include "arch-s390.h" +/* s390 syscall numbers */ +#define __s390_NR_socketcall 102 +#define __s390_NR_ipc 117 + const struct arch_def arch_def_s390 = { .token = SCMP_ARCH_S390, .token_bpf = AUDIT_ARCH_S390, @@ -17,6 +22,307 @@ const struct arch_def arch_def_s390 = { .endian = ARCH_ENDIAN_BIG, .syscall_resolve_name = s390_syscall_resolve_name, .syscall_resolve_num = s390_syscall_resolve_num, - .syscall_rewrite = NULL, - .rule_add = NULL, + .syscall_rewrite = s390_syscall_rewrite, + .rule_add = s390_rule_add, }; + +/** + * Convert a multiplexed pseudo socket syscall into a direct syscall + * @param socketcall 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. + * + */ +int _s390_sock_demux(int socketcall) +{ + switch (socketcall) { + 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; + } + + 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. + * + */ +int _s390_sock_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; + } + + 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 >= -211) + *syscall = __s390_NR_ipc; + else if (sys < 0) + return -EDOM; + + return 0; +} + +/** + * add a new rule to the s390 seccomp filter + * @param col the filter collection + * @param db the seccomp filter db + * @param strict the strict flag + * @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. + * + */ +int s390_rule_add(struct db_filter_col *col, struct db_filter *db, bool strict, + struct db_api_rule_list *rule) +{ + int rc; + unsigned int iter; + size_t args_size; + int sys = rule->syscall; + int sys_a, sys_b; + struct db_api_rule_list *rule_a, *rule_b; + + 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 < rule->args_cnt; iter++) { + if ((rule->args[iter].valid != 0) && (strict)) + return -EINVAL; + } + + /* determine both the muxed and direct syscall numbers */ + if (sys > 0) { + sys_a = _s390_sock_mux(sys); + if (sys_a == __NR_SCMP_ERROR) + return __NR_SCMP_ERROR; + sys_b = sys; + } else { + sys_a = sys; + sys_b = _s390_sock_demux(sys); + if (sys_b == __NR_SCMP_ERROR) + return __NR_SCMP_ERROR; + } + + /* 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_b = malloc(sizeof(*rule_b)); + if (rule_b == NULL) + return -ENOMEM; + args_size = sizeof(*rule_b->args) * rule_a->args_cnt; + rule_b->args = malloc(args_size); + if (rule_b->args == NULL) { + free(rule_b); + return -ENOMEM; + } + rule_b->action = rule_a->action; + rule_b->syscall = rule_a->syscall; + rule_b->args_cnt = rule_a->args_cnt; + memcpy(rule_b->args, rule_a->args, args_size); + 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; + + /* add the rules as a single transaction */ + rc = db_col_transaction_start(col); + if (rc < 0) + return rc; + if (rule_a != NULL) { + rc = db_rule_add(db, rule_a); + if (rc < 0) + goto fail_transaction; + } + if (rule_b != NULL) { + rc = db_rule_add(db, rule_b); + if (rc < 0) + goto fail_transaction; + } + db_col_transaction_commit(col); + } else if (sys <= -200 && sys >= -211) { + /* multiplexed ipc syscalls */ + for (iter = 0; iter < ARG_COUNT_MAX; iter++) { + if ((rule->args[iter].valid != 0) && (strict)) + return -EINVAL; + } + rule->args[0].arg = 0; + rule->args[0].op = SCMP_CMP_EQ; + rule->args[0].mask = DATUM_MAX; + rule->args[0].datum = abs(sys) % 200; + rule->args[0].valid = 1; + rule->syscall = __s390_NR_ipc; + + rc = db_rule_add(db, rule); + if (rc < 0) + return rc; + } else if (sys >= 0) { + /* normal syscall processing */ + rc = db_rule_add(db, rule); + if (rc < 0) + return rc; + } else if (strict) + return -EDOM; + + return 0; + +fail_transaction: + db_col_transaction_abort(col); + return rc; +} diff --git a/src/arch-s390.h b/src/arch-s390.h index 71ba260..899c952 100644 --- a/src/arch-s390.h +++ b/src/arch-s390.h @@ -3,12 +3,13 @@ * Author: Jan Willeke */ -#ifndef _ARCH_s390_H -#define _ARCH_s390_H +#ifndef _ARCH_S390_H +#define _ARCH_S390_H #include #include "arch.h" +#include "db.h" #include "system.h" #define s390_arg_count_max 6 @@ -18,6 +19,12 @@ extern const struct arch_def arch_def_s390; int s390_syscall_resolve_name(const char *name); const char *s390_syscall_resolve_num(int num); + const char *s390_syscall_iterate_name(unsigned int spot); +int s390_syscall_rewrite(int *syscall); + +int s390_rule_add(struct db_filter_col *col, struct db_filter *db, bool strict, + struct db_api_rule_list *rule); + #endif diff --git a/src/arch-s390x-syscalls.c b/src/arch-s390x-syscalls.c index 25e4c34..9825c63 100644 --- a/src/arch-s390x-syscalls.c +++ b/src/arch-s390x-syscalls.c @@ -453,6 +453,48 @@ int s390x_syscall_resolve_name(const char *name) const struct arch_syscall_def *table = s390x_syscall_table; /* XXX - plenty of room for future improvement here */ + + 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, "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; + for (iter = 0; table[iter].name != NULL; iter++) { if (strcmp(name, table[iter].name) == 0) return table[iter].num; @@ -476,6 +518,48 @@ const char *s390x_syscall_resolve_num(int num) const struct arch_syscall_def *table = s390x_syscall_table; /* XXX - plenty of room for future improvement here */ + + 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"; + for (iter = 0; table[iter].num != __NR_SCMP_ERROR; iter++) { if (num == table[iter].num) return table[iter].name; diff --git a/src/arch-s390x.c b/src/arch-s390x.c index 5471738..d14bdf0 100644 --- a/src/arch-s390x.c +++ b/src/arch-s390x.c @@ -5,11 +5,16 @@ #include #include +#include #include #include "arch.h" #include "arch-s390x.h" +/* s390x syscall numbers */ +#define __s390x_NR_socketcall 102 +#define __s390x_NR_ipc 117 + const struct arch_def arch_def_s390x = { .token = SCMP_ARCH_S390X, .token_bpf = AUDIT_ARCH_S390X, @@ -17,6 +22,307 @@ const struct arch_def arch_def_s390x = { .endian = ARCH_ENDIAN_BIG, .syscall_resolve_name = s390x_syscall_resolve_name, .syscall_resolve_num = s390x_syscall_resolve_num, - .syscall_rewrite = NULL, - .rule_add = NULL, + .syscall_rewrite = s390x_syscall_rewrite, + .rule_add = s390x_rule_add, }; + +/** + * Convert a multiplexed pseudo socket syscall into a direct syscall + * @param socketcall 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. + * + */ +int _s390x_sock_demux(int socketcall) +{ + switch (socketcall) { + 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; + } + + 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. + * + */ +int _s390x_sock_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; + } + + 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 >= -211) + *syscall = __s390x_NR_ipc; + else if (sys < 0) + return -EDOM; + + return 0; +} + +/** + * add a new rule to the s390x seccomp filter + * @param col the filter collection + * @param db the seccomp filter db + * @param strict the strict flag + * @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. + * + */ +int s390x_rule_add(struct db_filter_col *col, struct db_filter *db, bool strict, + struct db_api_rule_list *rule) +{ + int rc; + unsigned int iter; + size_t args_size; + int sys = rule->syscall; + int sys_a, sys_b; + struct db_api_rule_list *rule_a, *rule_b; + + 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 < rule->args_cnt; iter++) { + if ((rule->args[iter].valid != 0) && (strict)) + return -EINVAL; + } + + /* determine both the muxed and direct syscall numbers */ + if (sys > 0) { + sys_a = _s390x_sock_mux(sys); + if (sys_a == __NR_SCMP_ERROR) + return __NR_SCMP_ERROR; + sys_b = sys; + } else { + sys_a = sys; + sys_b = _s390x_sock_demux(sys); + if (sys_b == __NR_SCMP_ERROR) + return __NR_SCMP_ERROR; + } + + /* 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_b = malloc(sizeof(*rule_b)); + if (rule_b == NULL) + return -ENOMEM; + args_size = sizeof(*rule_b->args) * rule_a->args_cnt; + rule_b->args = malloc(args_size); + if (rule_b->args == NULL) { + free(rule_b); + return -ENOMEM; + } + rule_b->action = rule_a->action; + rule_b->syscall = rule_a->syscall; + rule_b->args_cnt = rule_a->args_cnt; + memcpy(rule_b->args, rule_a->args, args_size); + 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; + + /* add the rules as a single transaction */ + rc = db_col_transaction_start(col); + if (rc < 0) + return rc; + if (rule_a != NULL) { + rc = db_rule_add(db, rule_a); + if (rc < 0) + goto fail_transaction; + } + if (rule_b != NULL) { + rc = db_rule_add(db, rule_b); + if (rc < 0) + goto fail_transaction; + } + db_col_transaction_commit(col); + } else if (sys <= -200 && sys >= -211) { + /* multiplexed ipc syscalls */ + for (iter = 0; iter < ARG_COUNT_MAX; iter++) { + if ((rule->args[iter].valid != 0) && (strict)) + return -EINVAL; + } + rule->args[0].arg = 0; + rule->args[0].op = SCMP_CMP_EQ; + rule->args[0].mask = DATUM_MAX; + rule->args[0].datum = abs(sys) % 200; + rule->args[0].valid = 1; + rule->syscall = __s390x_NR_ipc; + + rc = db_rule_add(db, rule); + if (rc < 0) + return rc; + } else if (sys >= 0) { + /* normal syscall processing */ + rc = db_rule_add(db, rule); + if (rc < 0) + return rc; + } else if (strict) + return -EDOM; + + return 0; + +fail_transaction: + db_col_transaction_abort(col); + return rc; +} diff --git a/src/arch-s390x.h b/src/arch-s390x.h index 054044b..2857d7f 100644 --- a/src/arch-s390x.h +++ b/src/arch-s390x.h @@ -3,12 +3,13 @@ * Author: Jan Willeke */ -#ifndef _ARCH_s390x_H -#define _ARCH_s390x_H +#ifndef _ARCH_S390X_H +#define _ARCH_S390X_H #include #include "arch.h" +#include "db.h" #include "system.h" #define s390x_arg_count_max 6 @@ -21,6 +22,12 @@ extern const struct arch_def arch_def_s390x; int s390x_syscall_resolve_name(const char *name); const char *s390x_syscall_resolve_num(int num); + const char *s390x_syscall_iterate_name(unsigned int spot); -const char *s390x_syscall_iterate_name(unsigned int spot); + +int s390x_syscall_rewrite(int *syscall); + +int s390x_rule_add(struct db_filter_col *col, struct db_filter *db, bool strict, + struct db_api_rule_list *rule); + #endif diff --git a/src/arch-x86.c b/src/arch-x86.c index 1bab53f..1bfe926 100644 --- a/src/arch-x86.c +++ b/src/arch-x86.c @@ -232,7 +232,7 @@ int x86_rule_add(struct db_filter_col *col, struct db_filter *db, bool strict, if ((sys <= -100 && sys >= -120) || (sys >= 359 && sys <= 373)) { /* (-100 to -120) : multiplexed socket syscalls - (359 to 373) : direct socket syscalls, Linux 4.4+ */ + (359 to 373) : direct socket syscalls, Linux 4.3+ */ /* strict check for the multiplexed socket syscalls */ for (iter = 0; iter < rule->args_cnt; iter++) { diff --git a/tests/.gitignore b/tests/.gitignore index f6c40ee..b282fa4 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -37,3 +37,4 @@ util.pyc 30-sim-socket_syscalls 31-basic-version_check 32-live-tsync_allow +33-sim-socket_syscalls_be diff --git a/tests/33-sim-socket_syscalls_be.c b/tests/33-sim-socket_syscalls_be.c new file mode 100644 index 0000000..7c4d788 --- /dev/null +++ b/tests/33-sim-socket_syscalls_be.c @@ -0,0 +1,81 @@ +/** + * Seccomp Library test program + * + * Copyright (c) 2016 Red Hat + * Author: Paul Moore + */ + +/* + * This library is free software; you can redistribute it and/or modify it + * under the terms of version 2.1 of the GNU Lesser General Public License as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, see . + */ + +#include +#include + +#include + +#include "util.h" + +int main(int argc, char *argv[]) +{ + int rc; + struct util_options opts; + scmp_filter_ctx ctx = NULL; + + rc = util_getopt(argc, argv, &opts); + if (rc < 0) + goto out; + + ctx = seccomp_init(SCMP_ACT_KILL); + if (ctx == NULL) + return ENOMEM; + + rc = seccomp_arch_remove(ctx, SCMP_ARCH_NATIVE); + if (rc != 0) + goto out; + + rc = seccomp_arch_add(ctx, SCMP_ARCH_S390); + if (rc != 0) + goto out; + rc = seccomp_arch_add(ctx, SCMP_ARCH_S390X); + if (rc != 0) + goto out; + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 0); + if (rc != 0) + goto out; + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(connect), 0); + if (rc != 0) + goto out; + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept), 0); + if (rc != 0) + goto out; + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept4), 0); + if (rc != 0) + goto out; + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(shutdown), 0); + if (rc != 0) + goto out; + + rc = util_filter_output(&opts, ctx); + if (rc) + goto out; + +out: + seccomp_release(ctx); + return (rc < 0 ? -rc : rc); +} diff --git a/tests/33-sim-socket_syscalls_be.py b/tests/33-sim-socket_syscalls_be.py new file mode 100755 index 0000000..416fb33 --- /dev/null +++ b/tests/33-sim-socket_syscalls_be.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python + +# +# Seccomp Library test program +# +# Copyright (c) 2016 Red Hat +# Author: Paul Moore +# + +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of version 2.1 of the GNU Lesser General Public License as +# published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License +# for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library; if not, see . +# + +import argparse +import sys + +import util + +from seccomp import * + +def test(args): + f = SyscallFilter(KILL) + f.remove_arch(Arch()) + f.add_arch(Arch("s390")) + f.add_arch(Arch("s390x")) + f.add_rule(ALLOW, "socket") + f.add_rule(ALLOW, "connect") + f.add_rule(ALLOW, "accept") + f.add_rule(ALLOW, "accept4") + f.add_rule(ALLOW, "shutdown") + return f + +args = util.get_opt() +ctx = test(args) +util.filter_output(args, ctx) + +# kate: syntax python; +# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off; diff --git a/tests/33-sim-socket_syscalls_be.tests b/tests/33-sim-socket_syscalls_be.tests new file mode 100644 index 0000000..b2523af --- /dev/null +++ b/tests/33-sim-socket_syscalls_be.tests @@ -0,0 +1,39 @@ +# +# libseccomp regression test automation data +# +# Copyright (c) 2016 Red Hat +# Author: Paul Moore +# + +test type: bpf-sim + +# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result +33-sim-socket_syscalls_be +s390 socketcall 1 N N N N N ALLOW +33-sim-socket_syscalls_be +s390 socketcall 3 N N N N N ALLOW +33-sim-socket_syscalls_be +s390 socketcall 5 N N N N N ALLOW +33-sim-socket_syscalls_be +s390 socketcall 13 N N N N N ALLOW +33-sim-socket_syscalls_be +s390 359 0 1 2 N N N ALLOW +33-sim-socket_syscalls_be +s390 362 0 1 2 N N N ALLOW +33-sim-socket_syscalls_be +s390 364 0 1 2 N N N ALLOW +33-sim-socket_syscalls_be +s390 373 0 1 2 N N N ALLOW +33-sim-socket_syscalls_be +s390 accept 5 N N N N N ALLOW +33-sim-socket_syscalls_be +s390 accept 0 1 2 N N N KILL +33-sim-socket_syscalls_be +s390 accept4 18 1 2 N N N ALLOW +33-sim-socket_syscalls_be +s390 accept4 0 1 2 N N N KILL +33-sim-socket_syscalls_be +s390x socketcall 1 N N N N N ALLOW +33-sim-socket_syscalls_be +s390x socketcall 3 N N N N N ALLOW +33-sim-socket_syscalls_be +s390x socketcall 5 N N N N N ALLOW +33-sim-socket_syscalls_be +s390x socketcall 13 N N N N N ALLOW +33-sim-socket_syscalls_be +s390x 359 0 1 2 N N N ALLOW +33-sim-socket_syscalls_be +s390x 362 0 1 2 N N N ALLOW +33-sim-socket_syscalls_be +s390x 364 0 1 2 N N N ALLOW +33-sim-socket_syscalls_be +s390x 373 0 1 2 N N N ALLOW +33-sim-socket_syscalls_be +s390x accept 5 N N N N N ALLOW +33-sim-socket_syscalls_be +s390x accept 0 1 2 N N N KILL +33-sim-socket_syscalls_be +s390x accept4 18 1 2 N N N ALLOW +33-sim-socket_syscalls_be +s390x accept4 0 1 2 N N N KILL + +test type: bpf-valgrind + +# Testname +33-sim-socket_syscalls_be diff --git a/tests/Makefile.am b/tests/Makefile.am index 5f17e97..ee4e41b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -60,7 +60,8 @@ check_PROGRAMS = \ 29-sim-pseudo_syscall \ 30-sim-socket_syscalls \ 31-basic-version_check \ - 32-live-tsync_allow + 32-live-tsync_allow \ + 33-sim-socket_syscalls_be EXTRA_DIST_TESTPYTHON = \ util.py \ @@ -95,7 +96,8 @@ EXTRA_DIST_TESTPYTHON = \ 29-sim-pseudo_syscall.py \ 30-sim-socket_syscalls.py \ 31-basic-version_check.py \ - 32-live-tsync_allow.py + 32-live-tsync_allow.py \ + 33-sim-socket_syscalls_be.py EXTRA_DIST_TESTCFGS = \ 01-sim-allow.tests \ @@ -129,7 +131,8 @@ EXTRA_DIST_TESTCFGS = \ 29-sim-pseudo_syscall.tests \ 30-sim-socket_syscalls.tests \ 31-basic-version_check.tests \ - 32-live-tsync_allow.tests + 32-live-tsync_allow.tests \ + 33-sim-socket_syscalls_be.tests EXTRA_DIST_TESTSCRIPTS = regression testdiff testgen -- cgit v1.2.1