Skip to content

Commit d250a3e

Browse files
thejhkees
authored andcommitted
selftests/seccomp: Test PTRACE_O_SUSPEND_SECCOMP without CAP_SYS_ADMIN
Add a test to check that PTRACE_O_SUSPEND_SECCOMP can't be set without CAP_SYS_ADMIN through PTRACE_SEIZE or PTRACE_SETOPTIONS. Signed-off-by: Jann Horn <jannh@google.com> Co-developed-by: Kees Cook <keescook@chromium.org> Signed-off-by: Kees Cook <keescook@chromium.org>
1 parent 2bfed7d commit d250a3e

2 files changed

Lines changed: 64 additions & 0 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# SPDX-License-Identifier: GPL-2.0
22
CFLAGS += -Wl,-no-as-needed -Wall -isystem ../../../../usr/include/
33
LDFLAGS += -lpthread
4+
LDLIBS += -lcap
45

56
TEST_GEN_PROGS := seccomp_bpf seccomp_benchmark
67
include ../lib.mk

tools/testing/selftests/seccomp/seccomp_bpf.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#include <sys/ioctl.h>
4747
#include <linux/kcmp.h>
4848
#include <sys/resource.h>
49+
#include <sys/capability.h>
4950

5051
#include <unistd.h>
5152
#include <sys/syscall.h>
@@ -4231,6 +4232,68 @@ TEST(user_notification_addfd_rlimit)
42314232
close(memfd);
42324233
}
42334234

4235+
/* Make sure PTRACE_O_SUSPEND_SECCOMP requires CAP_SYS_ADMIN. */
4236+
FIXTURE(O_SUSPEND_SECCOMP) {
4237+
pid_t pid;
4238+
};
4239+
4240+
FIXTURE_SETUP(O_SUSPEND_SECCOMP)
4241+
{
4242+
ERRNO_FILTER(block_read, E2BIG);
4243+
cap_value_t cap_list[] = { CAP_SYS_ADMIN };
4244+
cap_t caps;
4245+
4246+
self->pid = 0;
4247+
4248+
/* make sure we don't have CAP_SYS_ADMIN */
4249+
caps = cap_get_proc();
4250+
ASSERT_NE(NULL, caps);
4251+
ASSERT_EQ(0, cap_set_flag(caps, CAP_EFFECTIVE, 1, cap_list, CAP_CLEAR));
4252+
ASSERT_EQ(0, cap_set_proc(caps));
4253+
cap_free(caps);
4254+
4255+
ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
4256+
ASSERT_EQ(0, prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_block_read));
4257+
4258+
self->pid = fork();
4259+
ASSERT_GE(self->pid, 0);
4260+
4261+
if (self->pid == 0) {
4262+
while (1)
4263+
pause();
4264+
_exit(127);
4265+
}
4266+
}
4267+
4268+
FIXTURE_TEARDOWN(O_SUSPEND_SECCOMP)
4269+
{
4270+
if (self->pid)
4271+
kill(self->pid, SIGKILL);
4272+
}
4273+
4274+
TEST_F(O_SUSPEND_SECCOMP, setoptions)
4275+
{
4276+
int wstatus;
4277+
4278+
ASSERT_EQ(0, ptrace(PTRACE_ATTACH, self->pid, NULL, 0));
4279+
ASSERT_EQ(self->pid, wait(&wstatus));
4280+
ASSERT_EQ(-1, ptrace(PTRACE_SETOPTIONS, self->pid, NULL, PTRACE_O_SUSPEND_SECCOMP));
4281+
if (errno == EINVAL)
4282+
SKIP(return, "Kernel does not support PTRACE_O_SUSPEND_SECCOMP (missing CONFIG_CHECKPOINT_RESTORE?)");
4283+
ASSERT_EQ(EPERM, errno);
4284+
}
4285+
4286+
TEST_F(O_SUSPEND_SECCOMP, seize)
4287+
{
4288+
int ret;
4289+
4290+
ret = ptrace(PTRACE_SEIZE, self->pid, NULL, PTRACE_O_SUSPEND_SECCOMP);
4291+
ASSERT_EQ(-1, ret);
4292+
if (errno == EINVAL)
4293+
SKIP(return, "Kernel does not support PTRACE_O_SUSPEND_SECCOMP (missing CONFIG_CHECKPOINT_RESTORE?)");
4294+
ASSERT_EQ(EPERM, errno);
4295+
}
4296+
42344297
/*
42354298
* TODO:
42364299
* - expand NNP testing

0 commit comments

Comments
 (0)