mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-19 23:02:31 +00:00
seccomp updates for v6.9-rc1
- Improve reliability of selftests (Terry Tritton, Kees Cook) - Fix strict-aliasing warning in samples (Arnd Bergmann) -----BEGIN PGP SIGNATURE----- iQJKBAABCgA0FiEEpcP2jyKd1g9yPm4TiXL039xtwCYFAmXvlj8WHGtlZXNjb29r QGNocm9taXVtLm9yZwAKCRCJcvTf3G3AJs6fD/9jcb5/9RNObVjSb19XSDfmlm6t +0u+aHKBZCuIu8WgrlU2rtMUJ8BiiWKVQIOViIJJJ6xz4uXIo+cRV3o5oRNKRrbj TDBoX3aiaFN8AcJL8TXHRMWpjOod99VLAazMD5ZbMI97/kWS1eFyZiyewea24NpS uMSBQFbfZUs44nvYLv+6zIVsBZ1AOhUJwnjgY/3cV2MleVPyb81EJRtJBiOlmTBY i2Vhk61Vgb4Ab/NruMmsBMCEMZzGNKeO1HaatmFBPhEZYh9vkeynCQC9MciBgVBB jzdhsxWVbBhkYc1GJUzXNGDavGuay/OIuuihA58JDQGHFUxJGR3hkDXSaXLCmGxt dPln+WFItfQHCJStfa+9m/muuoCJkKCZu6TkCVZC+n8fbaCPNSvvEjGfi2b7jL/x QKYto9AgWA/FJU+Z572davaMcCk84gcm8FNpQzm0KoMkfRVqz6XCSoYQ8sxNXrQp 9+XzwAkLrqsVRZQK8rTzfGJ7G+7yMShBlyCgM8BhvUmGE6KS2c1J3AEe+ejumK1V a3jlmj6cO4IXVDZdE585NYTO6dMKxQ659VMErqYt0tzvmyPh6BqNyJkga9l/CHTA LHpYGImmQLtWx5uuh5jM+YLFSNktBhDeVMaqJOmalUfqdD8NeMuub7GciPxF6qAz u13iYmRsw4KZ66tE/w== =lqxR -----END PGP SIGNATURE----- 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)
This commit is contained in:
commit
7f1a277409
@ -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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 @@
|
|||||||
*/
|
*/
|
||||||
#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)
|
|||||||
|
|
||||||
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 @@ out:
|
|||||||
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[])
|
|||||||
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)
|
|||||||
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,
|
|||||||
{
|
{
|
||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
/* 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)
|
|||||||
/* 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)
|
|||||||
|
|
||||||
/* 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)
|
|||||||
* 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);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user