Commit 7f1a2774 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'seccomp-v6.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux

Pull seccomp updates from Kees Cook:
 "There are no core kernel changes here; it's entirely selftests and
  samples:

   - Improve reliability of selftests (Terry Tritton, Kees Cook)

   - Fix strict-aliasing warning in samples (Arnd Bergmann)"

* tag 'seccomp-v6.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
  samples: user-trap: fix strict-aliasing warning
  selftests/seccomp: Pin benchmark to single CPU
  selftests/seccomp: user_notification_addfd check nextfd is available
  selftests/seccomp: Change the syscall used in KILL_THREAD test
  selftests/seccomp: Handle EINVAL on unshare(CLONE_NEWPID)
parents 216532e1 56af94aa
...@@ -33,6 +33,7 @@ static int send_fd(int sock, int fd) ...@@ -33,6 +33,7 @@ static int send_fd(int sock, int fd)
{ {
struct msghdr msg = {}; struct msghdr msg = {};
struct cmsghdr *cmsg; struct cmsghdr *cmsg;
int *fd_ptr;
char buf[CMSG_SPACE(sizeof(int))] = {0}, c = 'c'; char buf[CMSG_SPACE(sizeof(int))] = {0}, c = 'c';
struct iovec io = { struct iovec io = {
.iov_base = &c, .iov_base = &c,
...@@ -47,7 +48,8 @@ static int send_fd(int sock, int fd) ...@@ -47,7 +48,8 @@ static int send_fd(int sock, int fd)
cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int)); cmsg->cmsg_len = CMSG_LEN(sizeof(int));
*((int *)CMSG_DATA(cmsg)) = fd; fd_ptr = (int *)CMSG_DATA(cmsg);
*fd_ptr = fd;
msg.msg_controllen = cmsg->cmsg_len; msg.msg_controllen = cmsg->cmsg_len;
if (sendmsg(sock, &msg, 0) < 0) { if (sendmsg(sock, &msg, 0) < 0) {
...@@ -62,6 +64,7 @@ static int recv_fd(int sock) ...@@ -62,6 +64,7 @@ static int recv_fd(int sock)
{ {
struct msghdr msg = {}; struct msghdr msg = {};
struct cmsghdr *cmsg; struct cmsghdr *cmsg;
int *fd_ptr;
char buf[CMSG_SPACE(sizeof(int))] = {0}, c = 'c'; char buf[CMSG_SPACE(sizeof(int))] = {0}, c = 'c';
struct iovec io = { struct iovec io = {
.iov_base = &c, .iov_base = &c,
...@@ -79,8 +82,9 @@ static int recv_fd(int sock) ...@@ -79,8 +82,9 @@ static int recv_fd(int sock)
} }
cmsg = CMSG_FIRSTHDR(&msg); cmsg = CMSG_FIRSTHDR(&msg);
fd_ptr = (int *)CMSG_DATA(cmsg);
return *((int *)CMSG_DATA(cmsg)); return *fd_ptr;
} }
static int user_trap_syscall(int nr, unsigned int flags) static int user_trap_syscall(int nr, unsigned int flags)
......
...@@ -4,7 +4,9 @@ ...@@ -4,7 +4,9 @@
*/ */
#define _GNU_SOURCE #define _GNU_SOURCE
#include <assert.h> #include <assert.h>
#include <err.h>
#include <limits.h> #include <limits.h>
#include <sched.h>
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include <stdio.h> #include <stdio.h>
...@@ -76,8 +78,12 @@ unsigned long long calibrate(void) ...@@ -76,8 +78,12 @@ unsigned long long calibrate(void)
bool approx(int i_one, int i_two) bool approx(int i_one, int i_two)
{ {
double one = i_one, one_bump = one * 0.01; /*
double two = i_two, two_bump = two * 0.01; * This continues to be a noisy test. Instead of a 1% comparison
* go with 10%.
*/
double one = i_one, one_bump = one * 0.1;
double two = i_two, two_bump = two * 0.1;
one_bump = one + MAX(one_bump, 2.0); one_bump = one + MAX(one_bump, 2.0);
two_bump = two + MAX(two_bump, 2.0); two_bump = two + MAX(two_bump, 2.0);
...@@ -131,6 +137,32 @@ long compare(const char *name_one, const char *name_eval, const char *name_two, ...@@ -131,6 +137,32 @@ long compare(const char *name_one, const char *name_eval, const char *name_two,
return good ? 0 : 1; return good ? 0 : 1;
} }
/* Pin to a single CPU so the benchmark won't bounce around the system. */
void affinity(void)
{
long cpu;
ulong ncores = sysconf(_SC_NPROCESSORS_CONF);
cpu_set_t *setp = CPU_ALLOC(ncores);
ulong setsz = CPU_ALLOC_SIZE(ncores);
/*
* Totally unscientific way to avoid CPUs that might be busier:
* choose the highest CPU instead of the lowest.
*/
for (cpu = ncores - 1; cpu >= 0; cpu--) {
CPU_ZERO_S(setsz, setp);
CPU_SET_S(cpu, setsz, setp);
if (sched_setaffinity(getpid(), setsz, setp) == -1)
continue;
printf("Pinned to CPU %lu of %lu\n", cpu + 1, ncores);
goto out;
}
fprintf(stderr, "Could not set CPU affinity -- calibration may not work well");
out:
CPU_FREE(setp);
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
struct sock_filter bitmap_filter[] = { struct sock_filter bitmap_filter[] = {
...@@ -172,6 +204,8 @@ int main(int argc, char *argv[]) ...@@ -172,6 +204,8 @@ int main(int argc, char *argv[])
ksft_print_msg(""); ksft_print_msg("");
system("grep -H . /proc/sys/net/core/bpf_jit_harden"); system("grep -H . /proc/sys/net/core/bpf_jit_harden");
affinity();
if (argc > 1) if (argc > 1)
samples = strtoull(argv[1], NULL, 0); samples = strtoull(argv[1], NULL, 0);
else else
......
...@@ -784,7 +784,7 @@ void *kill_thread(void *data) ...@@ -784,7 +784,7 @@ void *kill_thread(void *data)
bool die = (bool)data; bool die = (bool)data;
if (die) { if (die) {
prctl(PR_GET_SECCOMP, 0, 0, 0, 0); syscall(__NR_getpid);
return (void *)SIBLING_EXIT_FAILURE; return (void *)SIBLING_EXIT_FAILURE;
} }
...@@ -803,11 +803,11 @@ void kill_thread_or_group(struct __test_metadata *_metadata, ...@@ -803,11 +803,11 @@ void kill_thread_or_group(struct __test_metadata *_metadata,
{ {
pthread_t thread; pthread_t thread;
void *status; void *status;
/* Kill only when calling __NR_prctl. */ /* Kill only when calling __NR_getpid. */
struct sock_filter filter_thread[] = { struct sock_filter filter_thread[] = {
BPF_STMT(BPF_LD|BPF_W|BPF_ABS, BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
offsetof(struct seccomp_data, nr)), offsetof(struct seccomp_data, nr)),
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_prctl, 0, 1), BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 0, 1),
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL_THREAD), BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL_THREAD),
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW), BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
}; };
...@@ -819,7 +819,7 @@ void kill_thread_or_group(struct __test_metadata *_metadata, ...@@ -819,7 +819,7 @@ void kill_thread_or_group(struct __test_metadata *_metadata,
struct sock_filter filter_process[] = { struct sock_filter filter_process[] = {
BPF_STMT(BPF_LD|BPF_W|BPF_ABS, BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
offsetof(struct seccomp_data, nr)), offsetof(struct seccomp_data, nr)),
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_prctl, 0, 1), BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 0, 1),
BPF_STMT(BPF_RET|BPF_K, kill), BPF_STMT(BPF_RET|BPF_K, kill),
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW), BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
}; };
...@@ -3709,7 +3709,12 @@ TEST(user_notification_sibling_pid_ns) ...@@ -3709,7 +3709,12 @@ TEST(user_notification_sibling_pid_ns)
ASSERT_GE(pid, 0); ASSERT_GE(pid, 0);
if (pid == 0) { if (pid == 0) {
ASSERT_EQ(unshare(CLONE_NEWPID), 0); ASSERT_EQ(unshare(CLONE_NEWPID), 0) {
if (errno == EPERM)
SKIP(return, "CLONE_NEWPID requires CAP_SYS_ADMIN");
else if (errno == EINVAL)
SKIP(return, "CLONE_NEWPID is invalid (missing CONFIG_PID_NS?)");
}
pid2 = fork(); pid2 = fork();
ASSERT_GE(pid2, 0); ASSERT_GE(pid2, 0);
...@@ -3727,6 +3732,8 @@ TEST(user_notification_sibling_pid_ns) ...@@ -3727,6 +3732,8 @@ TEST(user_notification_sibling_pid_ns)
ASSERT_EQ(unshare(CLONE_NEWPID), 0) { ASSERT_EQ(unshare(CLONE_NEWPID), 0) {
if (errno == EPERM) if (errno == EPERM)
SKIP(return, "CLONE_NEWPID requires CAP_SYS_ADMIN"); SKIP(return, "CLONE_NEWPID requires CAP_SYS_ADMIN");
else if (errno == EINVAL)
SKIP(return, "CLONE_NEWPID is invalid (missing CONFIG_PID_NS?)");
} }
ASSERT_EQ(errno, 0); ASSERT_EQ(errno, 0);
...@@ -4037,6 +4044,16 @@ TEST(user_notification_filter_empty_threaded) ...@@ -4037,6 +4044,16 @@ TEST(user_notification_filter_empty_threaded)
EXPECT_GT((pollfd.revents & POLLHUP) ?: 0, 0); EXPECT_GT((pollfd.revents & POLLHUP) ?: 0, 0);
} }
int get_next_fd(int prev_fd)
{
for (int i = prev_fd + 1; i < FD_SETSIZE; ++i) {
if (fcntl(i, F_GETFD) == -1)
return i;
}
_exit(EXIT_FAILURE);
}
TEST(user_notification_addfd) TEST(user_notification_addfd)
{ {
pid_t pid; pid_t pid;
...@@ -4053,7 +4070,7 @@ TEST(user_notification_addfd) ...@@ -4053,7 +4070,7 @@ TEST(user_notification_addfd)
/* There may be arbitrary already-open fds at test start. */ /* There may be arbitrary already-open fds at test start. */
memfd = memfd_create("test", 0); memfd = memfd_create("test", 0);
ASSERT_GE(memfd, 0); ASSERT_GE(memfd, 0);
nextfd = memfd + 1; nextfd = get_next_fd(memfd);
ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
ASSERT_EQ(0, ret) { ASSERT_EQ(0, ret) {
...@@ -4064,7 +4081,8 @@ TEST(user_notification_addfd) ...@@ -4064,7 +4081,8 @@ TEST(user_notification_addfd)
/* Check that the basic notification machinery works */ /* Check that the basic notification machinery works */
listener = user_notif_syscall(__NR_getppid, listener = user_notif_syscall(__NR_getppid,
SECCOMP_FILTER_FLAG_NEW_LISTENER); SECCOMP_FILTER_FLAG_NEW_LISTENER);
ASSERT_EQ(listener, nextfd++); ASSERT_EQ(listener, nextfd);
nextfd = get_next_fd(nextfd);
pid = fork(); pid = fork();
ASSERT_GE(pid, 0); ASSERT_GE(pid, 0);
...@@ -4119,14 +4137,16 @@ TEST(user_notification_addfd) ...@@ -4119,14 +4137,16 @@ TEST(user_notification_addfd)
/* Verify we can set an arbitrary remote fd */ /* Verify we can set an arbitrary remote fd */
fd = ioctl(listener, SECCOMP_IOCTL_NOTIF_ADDFD, &addfd); fd = ioctl(listener, SECCOMP_IOCTL_NOTIF_ADDFD, &addfd);
EXPECT_EQ(fd, nextfd++); EXPECT_EQ(fd, nextfd);
nextfd = get_next_fd(nextfd);
EXPECT_EQ(filecmp(getpid(), pid, memfd, fd), 0); EXPECT_EQ(filecmp(getpid(), pid, memfd, fd), 0);
/* Verify we can set an arbitrary remote fd with large size */ /* Verify we can set an arbitrary remote fd with large size */
memset(&big, 0x0, sizeof(big)); memset(&big, 0x0, sizeof(big));
big.addfd = addfd; big.addfd = addfd;
fd = ioctl(listener, SECCOMP_IOCTL_NOTIF_ADDFD_BIG, &big); fd = ioctl(listener, SECCOMP_IOCTL_NOTIF_ADDFD_BIG, &big);
EXPECT_EQ(fd, nextfd++); EXPECT_EQ(fd, nextfd);
nextfd = get_next_fd(nextfd);
/* Verify we can set a specific remote fd */ /* Verify we can set a specific remote fd */
addfd.newfd = 42; addfd.newfd = 42;
...@@ -4164,7 +4184,8 @@ TEST(user_notification_addfd) ...@@ -4164,7 +4184,8 @@ TEST(user_notification_addfd)
* Child has earlier "low" fds and now 42, so we expect the next * Child has earlier "low" fds and now 42, so we expect the next
* lowest available fd to be assigned here. * lowest available fd to be assigned here.
*/ */
EXPECT_EQ(fd, nextfd++); EXPECT_EQ(fd, nextfd);
nextfd = get_next_fd(nextfd);
ASSERT_EQ(filecmp(getpid(), pid, memfd, fd), 0); ASSERT_EQ(filecmp(getpid(), pid, memfd, fd), 0);
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment