Skip to content

Commit adeeec8

Browse files
committed
selftests/seccomp: Refactor to use fixture variants
Now that the selftest harness has variants, use them to eliminate a bunch of copy/paste duplication. Reviewed-by: Jakub Kicinski <[email protected]> Tested-by: Will Deacon <[email protected]> Signed-off-by: Kees Cook <[email protected]>
1 parent 9d1587a commit adeeec8

File tree

1 file changed

+42
-157
lines changed

1 file changed

+42
-157
lines changed

tools/testing/selftests/seccomp/seccomp_bpf.c

Lines changed: 42 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -1510,6 +1510,7 @@ pid_t setup_trace_fixture(struct __test_metadata *_metadata,
15101510

15111511
return tracer_pid;
15121512
}
1513+
15131514
void teardown_trace_fixture(struct __test_metadata *_metadata,
15141515
pid_t tracer)
15151516
{
@@ -1789,7 +1790,7 @@ void change_syscall(struct __test_metadata *_metadata,
17891790
EXPECT_EQ(0, ret);
17901791
}
17911792

1792-
void tracer_syscall(struct __test_metadata *_metadata, pid_t tracee,
1793+
void tracer_seccomp(struct __test_metadata *_metadata, pid_t tracee,
17931794
int status, void *args)
17941795
{
17951796
int ret;
@@ -1866,6 +1867,24 @@ FIXTURE(TRACE_syscall) {
18661867
pid_t tracer, mytid, mypid, parent;
18671868
};
18681869

1870+
FIXTURE_VARIANT(TRACE_syscall) {
1871+
/*
1872+
* All of the SECCOMP_RET_TRACE behaviors can be tested with either
1873+
* SECCOMP_RET_TRACE+PTRACE_CONT or plain ptrace()+PTRACE_SYSCALL.
1874+
* This indicates if we should use SECCOMP_RET_TRACE (false), or
1875+
* ptrace (true).
1876+
*/
1877+
bool use_ptrace;
1878+
};
1879+
1880+
FIXTURE_VARIANT_ADD(TRACE_syscall, ptrace) {
1881+
.use_ptrace = true,
1882+
};
1883+
1884+
FIXTURE_VARIANT_ADD(TRACE_syscall, seccomp) {
1885+
.use_ptrace = false,
1886+
};
1887+
18691888
FIXTURE_SETUP(TRACE_syscall)
18701889
{
18711890
struct sock_filter filter[] = {
@@ -1881,12 +1900,11 @@ FIXTURE_SETUP(TRACE_syscall)
18811900
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1005),
18821901
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
18831902
};
1884-
1885-
memset(&self->prog, 0, sizeof(self->prog));
1886-
self->prog.filter = malloc(sizeof(filter));
1887-
ASSERT_NE(NULL, self->prog.filter);
1888-
memcpy(self->prog.filter, filter, sizeof(filter));
1889-
self->prog.len = (unsigned short)ARRAY_SIZE(filter);
1903+
struct sock_fprog prog = {
1904+
.len = (unsigned short)ARRAY_SIZE(filter),
1905+
.filter = filter,
1906+
};
1907+
long ret;
18901908

18911909
/* Prepare some testable syscall results. */
18921910
self->mytid = syscall(__NR_gettid);
@@ -1904,109 +1922,53 @@ FIXTURE_SETUP(TRACE_syscall)
19041922
ASSERT_NE(self->parent, self->mypid);
19051923

19061924
/* Launch tracer. */
1907-
self->tracer = setup_trace_fixture(_metadata, tracer_syscall, NULL,
1908-
false);
1909-
}
1910-
1911-
FIXTURE_TEARDOWN(TRACE_syscall)
1912-
{
1913-
teardown_trace_fixture(_metadata, self->tracer);
1914-
if (self->prog.filter)
1915-
free(self->prog.filter);
1916-
}
1925+
self->tracer = setup_trace_fixture(_metadata,
1926+
variant->use_ptrace ? tracer_ptrace
1927+
: tracer_seccomp,
1928+
NULL, variant->use_ptrace);
19171929

1918-
TEST_F(TRACE_syscall, ptrace_syscall_redirected)
1919-
{
1920-
/* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
1921-
teardown_trace_fixture(_metadata, self->tracer);
1922-
self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
1923-
true);
1924-
1925-
/* Tracer will redirect getpid to getppid. */
1926-
EXPECT_NE(self->mypid, syscall(__NR_getpid));
1927-
}
1930+
ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1931+
ASSERT_EQ(0, ret);
19281932

1929-
TEST_F(TRACE_syscall, ptrace_syscall_errno)
1930-
{
1931-
/* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
1932-
teardown_trace_fixture(_metadata, self->tracer);
1933-
self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
1934-
true);
1933+
if (variant->use_ptrace)
1934+
return;
19351935

1936-
/* Tracer should skip the open syscall, resulting in ESRCH. */
1937-
EXPECT_SYSCALL_RETURN(-ESRCH, syscall(__NR_openat));
1936+
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
1937+
ASSERT_EQ(0, ret);
19381938
}
19391939

1940-
TEST_F(TRACE_syscall, ptrace_syscall_faked)
1940+
FIXTURE_TEARDOWN(TRACE_syscall)
19411941
{
1942-
/* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
19431942
teardown_trace_fixture(_metadata, self->tracer);
1944-
self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
1945-
true);
1946-
1947-
/* Tracer should skip the gettid syscall, resulting fake pid. */
1948-
EXPECT_SYSCALL_RETURN(45000, syscall(__NR_gettid));
19491943
}
19501944

19511945
TEST_F(TRACE_syscall, syscall_allowed)
19521946
{
1953-
long ret;
1954-
1955-
ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1956-
ASSERT_EQ(0, ret);
1957-
1958-
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
1959-
ASSERT_EQ(0, ret);
1960-
19611947
/* getppid works as expected (no changes). */
19621948
EXPECT_EQ(self->parent, syscall(__NR_getppid));
19631949
EXPECT_NE(self->mypid, syscall(__NR_getppid));
19641950
}
19651951

19661952
TEST_F(TRACE_syscall, syscall_redirected)
19671953
{
1968-
long ret;
1969-
1970-
ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1971-
ASSERT_EQ(0, ret);
1972-
1973-
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
1974-
ASSERT_EQ(0, ret);
1975-
19761954
/* getpid has been redirected to getppid as expected. */
19771955
EXPECT_EQ(self->parent, syscall(__NR_getpid));
19781956
EXPECT_NE(self->mypid, syscall(__NR_getpid));
19791957
}
19801958

19811959
TEST_F(TRACE_syscall, syscall_errno)
19821960
{
1983-
long ret;
1984-
1985-
ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1986-
ASSERT_EQ(0, ret);
1987-
1988-
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
1989-
ASSERT_EQ(0, ret);
1990-
1991-
/* openat has been skipped and an errno return. */
1961+
/* Tracer should skip the open syscall, resulting in ESRCH. */
19921962
EXPECT_SYSCALL_RETURN(-ESRCH, syscall(__NR_openat));
19931963
}
19941964

19951965
TEST_F(TRACE_syscall, syscall_faked)
19961966
{
1997-
long ret;
1998-
1999-
ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
2000-
ASSERT_EQ(0, ret);
2001-
2002-
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
2003-
ASSERT_EQ(0, ret);
2004-
2005-
/* gettid has been skipped and an altered return value stored. */
1967+
/* Tracer skips the gettid syscall and store altered return value. */
20061968
EXPECT_SYSCALL_RETURN(45000, syscall(__NR_gettid));
20071969
}
20081970

2009-
TEST_F(TRACE_syscall, skip_after_RET_TRACE)
1971+
TEST_F(TRACE_syscall, skip_after)
20101972
{
20111973
struct sock_filter filter[] = {
20121974
BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
@@ -2021,14 +1983,7 @@ TEST_F(TRACE_syscall, skip_after_RET_TRACE)
20211983
};
20221984
long ret;
20231985

2024-
ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
2025-
ASSERT_EQ(0, ret);
2026-
2027-
/* Install fixture filter. */
2028-
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
2029-
ASSERT_EQ(0, ret);
2030-
2031-
/* Install "errno on getppid" filter. */
1986+
/* Install additional "errno on getppid" filter. */
20321987
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
20331988
ASSERT_EQ(0, ret);
20341989

@@ -2038,7 +1993,7 @@ TEST_F(TRACE_syscall, skip_after_RET_TRACE)
20381993
EXPECT_EQ(EPERM, errno);
20391994
}
20401995

2041-
TEST_F_SIGNAL(TRACE_syscall, kill_after_RET_TRACE, SIGSYS)
1996+
TEST_F_SIGNAL(TRACE_syscall, kill_after, SIGSYS)
20421997
{
20431998
struct sock_filter filter[] = {
20441999
BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
@@ -2053,77 +2008,7 @@ TEST_F_SIGNAL(TRACE_syscall, kill_after_RET_TRACE, SIGSYS)
20532008
};
20542009
long ret;
20552010

2056-
ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
2057-
ASSERT_EQ(0, ret);
2058-
2059-
/* Install fixture filter. */
2060-
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
2061-
ASSERT_EQ(0, ret);
2062-
2063-
/* Install "death on getppid" filter. */
2064-
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
2065-
ASSERT_EQ(0, ret);
2066-
2067-
/* Tracer will redirect getpid to getppid, and we should die. */
2068-
EXPECT_NE(self->mypid, syscall(__NR_getpid));
2069-
}
2070-
2071-
TEST_F(TRACE_syscall, skip_after_ptrace)
2072-
{
2073-
struct sock_filter filter[] = {
2074-
BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
2075-
offsetof(struct seccomp_data, nr)),
2076-
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1),
2077-
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | EPERM),
2078-
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
2079-
};
2080-
struct sock_fprog prog = {
2081-
.len = (unsigned short)ARRAY_SIZE(filter),
2082-
.filter = filter,
2083-
};
2084-
long ret;
2085-
2086-
/* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
2087-
teardown_trace_fixture(_metadata, self->tracer);
2088-
self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
2089-
true);
2090-
2091-
ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
2092-
ASSERT_EQ(0, ret);
2093-
2094-
/* Install "errno on getppid" filter. */
2095-
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
2096-
ASSERT_EQ(0, ret);
2097-
2098-
/* Tracer will redirect getpid to getppid, and we should see EPERM. */
2099-
EXPECT_EQ(-1, syscall(__NR_getpid));
2100-
EXPECT_EQ(EPERM, errno);
2101-
}
2102-
2103-
TEST_F_SIGNAL(TRACE_syscall, kill_after_ptrace, SIGSYS)
2104-
{
2105-
struct sock_filter filter[] = {
2106-
BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
2107-
offsetof(struct seccomp_data, nr)),
2108-
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1),
2109-
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
2110-
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
2111-
};
2112-
struct sock_fprog prog = {
2113-
.len = (unsigned short)ARRAY_SIZE(filter),
2114-
.filter = filter,
2115-
};
2116-
long ret;
2117-
2118-
/* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
2119-
teardown_trace_fixture(_metadata, self->tracer);
2120-
self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
2121-
true);
2122-
2123-
ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
2124-
ASSERT_EQ(0, ret);
2125-
2126-
/* Install "death on getppid" filter. */
2011+
/* Install additional "death on getppid" filter. */
21272012
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
21282013
ASSERT_EQ(0, ret);
21292014

0 commit comments

Comments
 (0)