Commit 843fc7f7 authored by Jonathan Callen's avatar Jonathan Callen Committed by Zbigniew Jędrzejewski-Szmek
Browse files

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.]
parent 25da63b9
......@@ -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 = \
......
......@@ -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)
};
......
......@@ -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));
}
......
......@@ -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;
......
......@@ -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);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment