Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion src/codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@
#define SECCOMP_RET_USER_NOTIF 0x7fc00000U
#endif

/* __X32_SYSCALL_BIT from arch/x86/include/uapi/asm/unistd.h */
#define X32_SYSCALL_BIT 0x40000000U

#define CURRENT_LOC (ctxt->buffer.len - 1)
#define LOC_TO_JUMP(loc) (CURRENT_LOC - (loc))

Expand Down Expand Up @@ -686,6 +689,7 @@ static void reverse_instruction_buffer(struct codegen_ctxt *ctxt) {

static int compile_policy_for_archs(struct codegen_ctxt *ctxt,
struct kafel_ctxt *kafel_ctxt,
uint32_t audit_arch,
uint32_t target_archs) {
ASSERT(ctxt != NULL);
ASSERT(kafel_ctxt != NULL);
Expand All @@ -704,6 +708,17 @@ static int compile_policy_for_archs(struct codegen_ctxt *ctxt,
int next = generate_rules(ctxt, rules);
range_rules_destroy(&rules);
if (next > begin) {
if (audit_arch == AUDIT_ARCH_X86_64) {
/*
x32 syscalls also report AUDIT_ARCH_X86_64 and are only told apart by
X32_SYSCALL_BIT in nr, so they would otherwise slip past the x86_64
rules (e.g. a DENY list with DEFAULT ALLOW). Treat them like any other
untargeted architecture, but let nr == -1 through: tracers use it to
skip a syscall and filters are re-run after tracing (see seccomp(2)).
*/
int x32 = add_jump(ctxt, BPF_JEQ, UINT32_MAX, next, -ACTION_KILL);
next = add_jump_ge(ctxt, X32_SYSCALL_BIT, x32, next);
}
begin = next = ADD_INSTR(BPF_LOAD_SYSCALL);
} else {
next = -kafel_ctxt->default_action;
Expand Down Expand Up @@ -759,7 +774,8 @@ static int compile_policy_impl(struct codegen_ctxt *ctxt,
int next = -ACTION_KILL;

for (int i = 0; i < archs_len; ++i) {
int policy = compile_policy_for_archs(ctxt, kafel_ctxt, archs[i].target_archs);
int policy = compile_policy_for_archs(ctxt, kafel_ctxt, archs[i].audit_arch,
archs[i].target_archs);
if (policy != -ACTION_KILL) {
next = add_jump(ctxt, BPF_JEQ, archs[i].audit_arch, policy, next);
}
Expand Down
17 changes: 17 additions & 0 deletions test/basic.c
Original file line number Diff line number Diff line change
Expand Up @@ -259,3 +259,20 @@ TEST_CASE(logic_negation) {
SYSCALL_ERRNO_SPEC(1));
TEST_POLICY_BLOCKS_SYSCALL(SYSCALL_SPEC3(__NR_read, 5, 0, 0));
}

#if defined(__x86_64__)
#define X32_SYSCALL_BIT 0x40000000

TEST_CASE(x32_abi_rejected) {
TEST_POLICY(
"POLICY a {\n"
" ERRNO(1) { getpid }\n"
"} USE a DEFAULT ALLOW");
TEST_POLICY_ALLOWS_SYSCALL(SYSCALL_SPEC0(__NR_getpid),
SYSCALL_ERRNO_SPEC(1));
TEST_POLICY_BLOCKS_SYSCALL(SYSCALL_SPEC0(X32_SYSCALL_BIT | __NR_getpid));
TEST_POLICY_BLOCKS_SYSCALL(SYSCALL_SPEC0(X32_SYSCALL_BIT | __NR_read));
TEST_POLICY_ALLOWS_SYSCALL(SYSCALL_SPEC0(-1),
SYSCALL_EXECUTED_SPEC(-1, ENOSYS));
}
#endif
Loading