Skip to content

Commit 1e6d69c

Browse files
committed
selftests/seccomp: Report event mismatches more clearly
When running under tracer, more explicitly report the status and event mismatches to help with debugging. Additionally add an "immediate kill" test when under tracing to verify that fatal SIGSYS behaves the same under ptrace or seccomp tracing. Cc: Andy Lutomirski <[email protected]> Cc: Will Drewry <[email protected]> Cc: [email protected] Signed-off-by: Kees Cook <[email protected]> Acked-by: "Eric W. Biederman" <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 48d5fd0 commit 1e6d69c

File tree

1 file changed

+49
-5
lines changed

1 file changed

+49
-5
lines changed

tools/testing/selftests/seccomp/seccomp_bpf.c

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1487,7 +1487,7 @@ TEST_F(precedence, log_is_fifth_in_any_order)
14871487
#define PTRACE_EVENT_SECCOMP 7
14881488
#endif
14891489

1490-
#define IS_SECCOMP_EVENT(status) ((status >> 16) == PTRACE_EVENT_SECCOMP)
1490+
#define PTRACE_EVENT_MASK(status) ((status) >> 16)
14911491
bool tracer_running;
14921492
void tracer_stop(int sig)
14931493
{
@@ -1539,12 +1539,22 @@ void start_tracer(struct __test_metadata *_metadata, int fd, pid_t tracee,
15391539

15401540
if (wait(&status) != tracee)
15411541
continue;
1542-
if (WIFSIGNALED(status) || WIFEXITED(status))
1543-
/* Child is dead. Time to go. */
1542+
1543+
if (WIFSIGNALED(status)) {
1544+
/* Child caught a fatal signal. */
1545+
return;
1546+
}
1547+
if (WIFEXITED(status)) {
1548+
/* Child exited with code. */
15441549
return;
1550+
}
15451551

1546-
/* Check if this is a seccomp event. */
1547-
ASSERT_EQ(!ptrace_syscall, IS_SECCOMP_EVENT(status));
1552+
/* Check if we got an expected event. */
1553+
ASSERT_EQ(WIFCONTINUED(status), false);
1554+
ASSERT_EQ(WIFSTOPPED(status), true);
1555+
ASSERT_EQ(WSTOPSIG(status) & SIGTRAP, SIGTRAP) {
1556+
TH_LOG("Unexpected WSTOPSIG: %d", WSTOPSIG(status));
1557+
}
15481558

15491559
tracer_func(_metadata, tracee, status, args);
15501560

@@ -1961,6 +1971,11 @@ void tracer_seccomp(struct __test_metadata *_metadata, pid_t tracee,
19611971
int ret;
19621972
unsigned long msg;
19631973

1974+
EXPECT_EQ(PTRACE_EVENT_MASK(status), PTRACE_EVENT_SECCOMP) {
1975+
TH_LOG("Unexpected ptrace event: %d", PTRACE_EVENT_MASK(status));
1976+
return;
1977+
}
1978+
19641979
/* Make sure we got the right message. */
19651980
ret = ptrace(PTRACE_GETEVENTMSG, tracee, NULL, &msg);
19661981
EXPECT_EQ(0, ret);
@@ -2011,6 +2026,11 @@ void tracer_ptrace(struct __test_metadata *_metadata, pid_t tracee,
20112026
long *syscall_nr = NULL, *syscall_ret = NULL;
20122027
FIXTURE_DATA(TRACE_syscall) *self = args;
20132028

2029+
EXPECT_EQ(WSTOPSIG(status) & 0x80, 0x80) {
2030+
TH_LOG("Unexpected WSTOPSIG: %d", WSTOPSIG(status));
2031+
return;
2032+
}
2033+
20142034
/*
20152035
* The traditional way to tell PTRACE_SYSCALL entry/exit
20162036
* is by counting.
@@ -2128,6 +2148,7 @@ FIXTURE_SETUP(TRACE_syscall)
21282148
ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
21292149
ASSERT_EQ(0, ret);
21302150

2151+
/* Do not install seccomp rewrite filters, as we'll use ptrace instead. */
21312152
if (variant->use_ptrace)
21322153
return;
21332154

@@ -2186,6 +2207,29 @@ TEST_F(TRACE_syscall, syscall_faked)
21862207
EXPECT_SYSCALL_RETURN(45000, syscall(__NR_gettid));
21872208
}
21882209

2210+
TEST_F_SIGNAL(TRACE_syscall, kill_immediate, SIGSYS)
2211+
{
2212+
struct sock_filter filter[] = {
2213+
BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
2214+
offsetof(struct seccomp_data, nr)),
2215+
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_mknodat, 0, 1),
2216+
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL_THREAD),
2217+
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
2218+
};
2219+
struct sock_fprog prog = {
2220+
.len = (unsigned short)ARRAY_SIZE(filter),
2221+
.filter = filter,
2222+
};
2223+
long ret;
2224+
2225+
/* Install "kill on mknodat" filter. */
2226+
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
2227+
ASSERT_EQ(0, ret);
2228+
2229+
/* This should immediately die with SIGSYS, regardless of tracer. */
2230+
EXPECT_EQ(-1, syscall(__NR_mknodat, -1, NULL, 0, 0));
2231+
}
2232+
21892233
TEST_F(TRACE_syscall, skip_after)
21902234
{
21912235
struct sock_filter filter[] = {

0 commit comments

Comments
 (0)