Commit d250a3e4 authored by Jann Horn's avatar Jann Horn Committed by Kees Cook
Browse files

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: default avatarJann Horn <jannh@google.com>
Co-developed-by: default avatarKees Cook <keescook@chromium.org>
Signed-off-by: default avatarKees Cook <keescook@chromium.org>
parent 2bfed7d2
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: GPL-2.0
CFLAGS += -Wl,-no-as-needed -Wall -isystem ../../../../usr/include/
LDFLAGS += -lpthread
LDLIBS += -lcap

TEST_GEN_PROGS := seccomp_bpf seccomp_benchmark
include ../lib.mk
+63 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@
#include <sys/ioctl.h>
#include <linux/kcmp.h>
#include <sys/resource.h>
#include <sys/capability.h>

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

/* Make sure PTRACE_O_SUSPEND_SECCOMP requires CAP_SYS_ADMIN. */
FIXTURE(O_SUSPEND_SECCOMP) {
	pid_t pid;
};

FIXTURE_SETUP(O_SUSPEND_SECCOMP)
{
	ERRNO_FILTER(block_read, E2BIG);
	cap_value_t cap_list[] = { CAP_SYS_ADMIN };
	cap_t caps;

	self->pid = 0;

	/* make sure we don't have CAP_SYS_ADMIN */
	caps = cap_get_proc();
	ASSERT_NE(NULL, caps);
	ASSERT_EQ(0, cap_set_flag(caps, CAP_EFFECTIVE, 1, cap_list, CAP_CLEAR));
	ASSERT_EQ(0, cap_set_proc(caps));
	cap_free(caps);

	ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
	ASSERT_EQ(0, prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_block_read));

	self->pid = fork();
	ASSERT_GE(self->pid, 0);

	if (self->pid == 0) {
		while (1)
			pause();
		_exit(127);
	}
}

FIXTURE_TEARDOWN(O_SUSPEND_SECCOMP)
{
	if (self->pid)
		kill(self->pid, SIGKILL);
}

TEST_F(O_SUSPEND_SECCOMP, setoptions)
{
	int wstatus;

	ASSERT_EQ(0, ptrace(PTRACE_ATTACH, self->pid, NULL, 0));
	ASSERT_EQ(self->pid, wait(&wstatus));
	ASSERT_EQ(-1, ptrace(PTRACE_SETOPTIONS, self->pid, NULL, PTRACE_O_SUSPEND_SECCOMP));
	if (errno == EINVAL)
		SKIP(return, "Kernel does not support PTRACE_O_SUSPEND_SECCOMP (missing CONFIG_CHECKPOINT_RESTORE?)");
	ASSERT_EQ(EPERM, errno);
}

TEST_F(O_SUSPEND_SECCOMP, seize)
{
	int ret;

	ret = ptrace(PTRACE_SEIZE, self->pid, NULL, PTRACE_O_SUSPEND_SECCOMP);
	ASSERT_EQ(-1, ret);
	if (errno == EINVAL)
		SKIP(return, "Kernel does not support PTRACE_O_SUSPEND_SECCOMP (missing CONFIG_CHECKPOINT_RESTORE?)");
	ASSERT_EQ(EPERM, errno);
}

/*
 * TODO:
 * - expand NNP testing