Skip to content

Commit 7f1a277

Browse files
committed
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)
2 parents 216532e + 56af94a commit 7f1a277

File tree

3 files changed

+73
-14
lines changed

3 files changed

+73
-14
lines changed

samples/seccomp/user-trap.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ static int send_fd(int sock, int fd)
3333
{
3434
struct msghdr msg = {};
3535
struct cmsghdr *cmsg;
36+
int *fd_ptr;
3637
char buf[CMSG_SPACE(sizeof(int))] = {0}, c = 'c';
3738
struct iovec io = {
3839
.iov_base = &c,
@@ -47,7 +48,8 @@ static int send_fd(int sock, int fd)
4748
cmsg->cmsg_level = SOL_SOCKET;
4849
cmsg->cmsg_type = SCM_RIGHTS;
4950
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
50-
*((int *)CMSG_DATA(cmsg)) = fd;
51+
fd_ptr = (int *)CMSG_DATA(cmsg);
52+
*fd_ptr = fd;
5153
msg.msg_controllen = cmsg->cmsg_len;
5254

5355
if (sendmsg(sock, &msg, 0) < 0) {
@@ -62,6 +64,7 @@ static int recv_fd(int sock)
6264
{
6365
struct msghdr msg = {};
6466
struct cmsghdr *cmsg;
67+
int *fd_ptr;
6568
char buf[CMSG_SPACE(sizeof(int))] = {0}, c = 'c';
6669
struct iovec io = {
6770
.iov_base = &c,
@@ -79,8 +82,9 @@ static int recv_fd(int sock)
7982
}
8083

8184
cmsg = CMSG_FIRSTHDR(&msg);
85+
fd_ptr = (int *)CMSG_DATA(cmsg);
8286

83-
return *((int *)CMSG_DATA(cmsg));
87+
return *fd_ptr;
8488
}
8589

8690
static int user_trap_syscall(int nr, unsigned int flags)

tools/testing/selftests/seccomp/seccomp_benchmark.c

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
*/
55
#define _GNU_SOURCE
66
#include <assert.h>
7+
#include <err.h>
78
#include <limits.h>
9+
#include <sched.h>
810
#include <stdbool.h>
911
#include <stddef.h>
1012
#include <stdio.h>
@@ -76,8 +78,12 @@ unsigned long long calibrate(void)
7678

7779
bool approx(int i_one, int i_two)
7880
{
79-
double one = i_one, one_bump = one * 0.01;
80-
double two = i_two, two_bump = two * 0.01;
81+
/*
82+
* This continues to be a noisy test. Instead of a 1% comparison
83+
* go with 10%.
84+
*/
85+
double one = i_one, one_bump = one * 0.1;
86+
double two = i_two, two_bump = two * 0.1;
8187

8288
one_bump = one + MAX(one_bump, 2.0);
8389
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,
131137
return good ? 0 : 1;
132138
}
133139

140+
/* Pin to a single CPU so the benchmark won't bounce around the system. */
141+
void affinity(void)
142+
{
143+
long cpu;
144+
ulong ncores = sysconf(_SC_NPROCESSORS_CONF);
145+
cpu_set_t *setp = CPU_ALLOC(ncores);
146+
ulong setsz = CPU_ALLOC_SIZE(ncores);
147+
148+
/*
149+
* Totally unscientific way to avoid CPUs that might be busier:
150+
* choose the highest CPU instead of the lowest.
151+
*/
152+
for (cpu = ncores - 1; cpu >= 0; cpu--) {
153+
CPU_ZERO_S(setsz, setp);
154+
CPU_SET_S(cpu, setsz, setp);
155+
if (sched_setaffinity(getpid(), setsz, setp) == -1)
156+
continue;
157+
printf("Pinned to CPU %lu of %lu\n", cpu + 1, ncores);
158+
goto out;
159+
}
160+
fprintf(stderr, "Could not set CPU affinity -- calibration may not work well");
161+
162+
out:
163+
CPU_FREE(setp);
164+
}
165+
134166
int main(int argc, char *argv[])
135167
{
136168
struct sock_filter bitmap_filter[] = {
@@ -172,6 +204,8 @@ int main(int argc, char *argv[])
172204
ksft_print_msg("");
173205
system("grep -H . /proc/sys/net/core/bpf_jit_harden");
174206

207+
affinity();
208+
175209
if (argc > 1)
176210
samples = strtoull(argv[1], NULL, 0);
177211
else

tools/testing/selftests/seccomp/seccomp_bpf.c

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -784,7 +784,7 @@ void *kill_thread(void *data)
784784
bool die = (bool)data;
785785

786786
if (die) {
787-
prctl(PR_GET_SECCOMP, 0, 0, 0, 0);
787+
syscall(__NR_getpid);
788788
return (void *)SIBLING_EXIT_FAILURE;
789789
}
790790

@@ -803,11 +803,11 @@ void kill_thread_or_group(struct __test_metadata *_metadata,
803803
{
804804
pthread_t thread;
805805
void *status;
806-
/* Kill only when calling __NR_prctl. */
806+
/* Kill only when calling __NR_getpid. */
807807
struct sock_filter filter_thread[] = {
808808
BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
809809
offsetof(struct seccomp_data, nr)),
810-
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_prctl, 0, 1),
810+
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 0, 1),
811811
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL_THREAD),
812812
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
813813
};
@@ -819,7 +819,7 @@ void kill_thread_or_group(struct __test_metadata *_metadata,
819819
struct sock_filter filter_process[] = {
820820
BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
821821
offsetof(struct seccomp_data, nr)),
822-
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_prctl, 0, 1),
822+
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 0, 1),
823823
BPF_STMT(BPF_RET|BPF_K, kill),
824824
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
825825
};
@@ -3709,7 +3709,12 @@ TEST(user_notification_sibling_pid_ns)
37093709
ASSERT_GE(pid, 0);
37103710

37113711
if (pid == 0) {
3712-
ASSERT_EQ(unshare(CLONE_NEWPID), 0);
3712+
ASSERT_EQ(unshare(CLONE_NEWPID), 0) {
3713+
if (errno == EPERM)
3714+
SKIP(return, "CLONE_NEWPID requires CAP_SYS_ADMIN");
3715+
else if (errno == EINVAL)
3716+
SKIP(return, "CLONE_NEWPID is invalid (missing CONFIG_PID_NS?)");
3717+
}
37133718

37143719
pid2 = fork();
37153720
ASSERT_GE(pid2, 0);
@@ -3727,6 +3732,8 @@ TEST(user_notification_sibling_pid_ns)
37273732
ASSERT_EQ(unshare(CLONE_NEWPID), 0) {
37283733
if (errno == EPERM)
37293734
SKIP(return, "CLONE_NEWPID requires CAP_SYS_ADMIN");
3735+
else if (errno == EINVAL)
3736+
SKIP(return, "CLONE_NEWPID is invalid (missing CONFIG_PID_NS?)");
37303737
}
37313738
ASSERT_EQ(errno, 0);
37323739

@@ -4037,6 +4044,16 @@ TEST(user_notification_filter_empty_threaded)
40374044
EXPECT_GT((pollfd.revents & POLLHUP) ?: 0, 0);
40384045
}
40394046

4047+
4048+
int get_next_fd(int prev_fd)
4049+
{
4050+
for (int i = prev_fd + 1; i < FD_SETSIZE; ++i) {
4051+
if (fcntl(i, F_GETFD) == -1)
4052+
return i;
4053+
}
4054+
_exit(EXIT_FAILURE);
4055+
}
4056+
40404057
TEST(user_notification_addfd)
40414058
{
40424059
pid_t pid;
@@ -4053,7 +4070,7 @@ TEST(user_notification_addfd)
40534070
/* There may be arbitrary already-open fds at test start. */
40544071
memfd = memfd_create("test", 0);
40554072
ASSERT_GE(memfd, 0);
4056-
nextfd = memfd + 1;
4073+
nextfd = get_next_fd(memfd);
40574074

40584075
ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
40594076
ASSERT_EQ(0, ret) {
@@ -4064,7 +4081,8 @@ TEST(user_notification_addfd)
40644081
/* Check that the basic notification machinery works */
40654082
listener = user_notif_syscall(__NR_getppid,
40664083
SECCOMP_FILTER_FLAG_NEW_LISTENER);
4067-
ASSERT_EQ(listener, nextfd++);
4084+
ASSERT_EQ(listener, nextfd);
4085+
nextfd = get_next_fd(nextfd);
40684086

40694087
pid = fork();
40704088
ASSERT_GE(pid, 0);
@@ -4119,14 +4137,16 @@ TEST(user_notification_addfd)
41194137

41204138
/* Verify we can set an arbitrary remote fd */
41214139
fd = ioctl(listener, SECCOMP_IOCTL_NOTIF_ADDFD, &addfd);
4122-
EXPECT_EQ(fd, nextfd++);
4140+
EXPECT_EQ(fd, nextfd);
4141+
nextfd = get_next_fd(nextfd);
41234142
EXPECT_EQ(filecmp(getpid(), pid, memfd, fd), 0);
41244143

41254144
/* Verify we can set an arbitrary remote fd with large size */
41264145
memset(&big, 0x0, sizeof(big));
41274146
big.addfd = addfd;
41284147
fd = ioctl(listener, SECCOMP_IOCTL_NOTIF_ADDFD_BIG, &big);
4129-
EXPECT_EQ(fd, nextfd++);
4148+
EXPECT_EQ(fd, nextfd);
4149+
nextfd = get_next_fd(nextfd);
41304150

41314151
/* Verify we can set a specific remote fd */
41324152
addfd.newfd = 42;
@@ -4164,7 +4184,8 @@ TEST(user_notification_addfd)
41644184
* Child has earlier "low" fds and now 42, so we expect the next
41654185
* lowest available fd to be assigned here.
41664186
*/
4167-
EXPECT_EQ(fd, nextfd++);
4187+
EXPECT_EQ(fd, nextfd);
4188+
nextfd = get_next_fd(nextfd);
41684189
ASSERT_EQ(filecmp(getpid(), pid, memfd, fd), 0);
41694190

41704191
/*

0 commit comments

Comments
 (0)