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.]
This commit is contained in:
Jonathan Callen 2012-07-24 22:45:22 -04:00 committed by Zbigniew Jędrzejewski-Szmek
parent 25da63b9da
commit 843fc7f7f2
5 changed files with 20 additions and 3 deletions

View file

@ -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 = \

View file

@ -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)
};

View file

@ -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));
}

View file

@ -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;

View file

@ -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);