diff options
author | Jonathan Callen <abcd@gentoo.org> | 2012-07-24 22:45:22 -0400 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2013-01-19 12:03:06 -0500 |
commit | 843fc7f7f26a6507fe896a79ed1b474c35c4300f (patch) | |
tree | bd465b18a828d0abbc5505f2d63fc7ccb5817208 | |
parent | 25da63b9dac8f166ebf390ca92d1de18fbfc9d11 (diff) |
execute: Fix seccomp support on x32
In the x32 ABI, syscall numbers start at 0x40000000. Mask that bit on
x32 for lookups in the syscall_names array and syscall_filter and ensure
that syscall.h is parsed correctly.
[zj: added SYSCALL_TO_INDEX, INDEX_TO_SYSCALL macros.]
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | src/core/execute.c | 2 | ||||
-rw-r--r-- | src/core/load-fragment.c | 2 | ||||
-rw-r--r-- | src/core/syscall-list.c | 1 | ||||
-rw-r--r-- | src/core/syscall-list.h | 14 |
5 files changed, 20 insertions, 3 deletions
diff --git a/Makefile.am b/Makefile.am index ba93db0d82..2631748f61 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1099,7 +1099,7 @@ BUILT_SOURCES += \ src/core/syscall-list.txt: Makefile $(AM_V_at)$(MKDIR_P) $(dir $@) - $(AM_V_GEN)$(CPP) $(CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) -dM -include sys/syscall.h - < /dev/null | $(AWK) '/^#define[ \t]+__NR_[^ ]+[ \t]+\(?.*[0-9]+.*\)?/ { sub(/__NR_/, "", $$2); print $$2; }' > $@ + $(AM_V_GEN)$(CPP) $(CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) -dM -include sys/syscall.h - < /dev/null | $(AWK) '/^#define[ \t]+__NR_[^ ]+[ \t]+[0-9(]/ { sub(/__NR_/, "", $$2); print $$2; }' > $@ src/core/syscall-from-name.gperf: src/core/syscall-list.txt Makefile $(AM_V_at)$(MKDIR_P) $(dir $@) @@ -1111,7 +1111,7 @@ src/core/syscall-from-name.h: src/core/syscall-from-name.gperf Makefile src/core/syscall-to-name.h: src/core/syscall-list.txt Makefile $(AM_V_at)$(MKDIR_P) $(dir $@) - $(AM_V_GEN)$(AWK) 'BEGIN{ print "const char* const syscall_names[] = { "} { printf "[__NR_%s] = \"%s\",\n", $$1, $$1 } END{print "};"}' < $< > $@ + $(AM_V_GEN)$(AWK) 'BEGIN{ print "const char* const syscall_names[] = { "} { printf "[SYSCALL_TO_INDEX(__NR_%s)] = \"%s\",\n", $$1, $$1 } END{print "};"}' < $< > $@ # ------------------------------------------------------------------------------ systemd_SOURCES = \ diff --git a/src/core/execute.c b/src/core/execute.c index 65a10af3b0..1413c9110e 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -957,7 +957,7 @@ static int apply_seccomp(uint32_t *syscall_filter) { for (i = 0, n = 0; i < syscall_max(); i++) if (syscall_filter[i >> 4] & (1 << (i & 31))) { struct sock_filter item[] = { - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, i, 0, 1), + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, INDEX_TO_SYSCALL(i), 0, 1), BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) }; diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index f82ddd530c..8436d4f95e 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -2120,10 +2120,12 @@ int config_parse_documentation( } static void syscall_set(uint32_t *p, int nr) { + nr = SYSCALL_TO_INDEX(nr); p[nr >> 4] |= 1 << (nr & 31); } static void syscall_unset(uint32_t *p, int nr) { + nr = SYSCALL_TO_INDEX(nr); p[nr >> 4] &= ~(1 << (nr & 31)); } diff --git a/src/core/syscall-list.c b/src/core/syscall-list.c index 05fad3e158..b608e8582f 100644 --- a/src/core/syscall-list.c +++ b/src/core/syscall-list.c @@ -32,6 +32,7 @@ const struct syscall_name *lookup_syscall(register const char *str, register uns #include "syscall-from-name.h" const char *syscall_to_name(int id) { + id = SYSCALL_TO_INDEX(id); if (id < 0 || id >= (int) ELEMENTSOF(syscall_names)) return NULL; diff --git a/src/core/syscall-list.h b/src/core/syscall-list.h index 0fc6859605..503838b7fb 100644 --- a/src/core/syscall-list.h +++ b/src/core/syscall-list.h @@ -22,6 +22,20 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#if defined __x86_64__ && defined __ILP32__ +/* The x32 ABI defines all of its syscalls with bit 30 set, which causes + issues when attempting to use syscalls as simple indicies into an array. + Instead, use the syscall id & ~SYSCALL_MASK as the index, and | the + internal id with the syscall mask as needed. +*/ +#include <asm/unistd.h> +#define SYSCALL_TO_INDEX(x) ((x) & ~__X32_SYSCALL_BIT) +#define INDEX_TO_SYSCALL(x) ((x) | __X32_SYSCALL_BIT) +#else +#define SYSCALL_TO_INDEX(x) (x) +#define INDEX_TO_SYSCALL(x) (x) +#endif + const char *syscall_to_name(int id); int syscall_from_name(const char *name); |