|
44 | 44 | #include <sys/times.h>
|
45 | 45 | #include <sys/socket.h>
|
46 | 46 | #include <sys/ioctl.h>
|
| 47 | +#include <linux/kcmp.h> |
47 | 48 |
|
48 | 49 | #include <unistd.h>
|
49 | 50 | #include <sys/syscall.h>
|
@@ -167,6 +168,10 @@ struct seccomp_metadata {
|
167 | 168 |
|
168 | 169 | #define SECCOMP_RET_USER_NOTIF 0x7fc00000U
|
169 | 170 |
|
| 171 | +#ifndef SECCOMP_USER_NOTIF_FLAG_CONTINUE |
| 172 | +#define SECCOMP_USER_NOTIF_FLAG_CONTINUE 0x00000001 |
| 173 | +#endif |
| 174 | + |
170 | 175 | #define SECCOMP_IOC_MAGIC '!'
|
171 | 176 | #define SECCOMP_IO(nr) _IO(SECCOMP_IOC_MAGIC, nr)
|
172 | 177 | #define SECCOMP_IOR(nr, type) _IOR(SECCOMP_IOC_MAGIC, nr, type)
|
@@ -3486,6 +3491,108 @@ TEST(seccomp_get_notif_sizes)
|
3486 | 3491 | EXPECT_EQ(sizes.seccomp_notif_resp, sizeof(struct seccomp_notif_resp));
|
3487 | 3492 | }
|
3488 | 3493 |
|
| 3494 | +static int filecmp(pid_t pid1, pid_t pid2, int fd1, int fd2) |
| 3495 | +{ |
| 3496 | +#ifdef __NR_kcmp |
| 3497 | + return syscall(__NR_kcmp, pid1, pid2, KCMP_FILE, fd1, fd2); |
| 3498 | +#else |
| 3499 | + errno = ENOSYS; |
| 3500 | + return -1; |
| 3501 | +#endif |
| 3502 | +} |
| 3503 | + |
| 3504 | +TEST(user_notification_continue) |
| 3505 | +{ |
| 3506 | + pid_t pid; |
| 3507 | + long ret; |
| 3508 | + int status, listener; |
| 3509 | + struct seccomp_notif req = {}; |
| 3510 | + struct seccomp_notif_resp resp = {}; |
| 3511 | + struct pollfd pollfd; |
| 3512 | + |
| 3513 | + ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); |
| 3514 | + ASSERT_EQ(0, ret) { |
| 3515 | + TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!"); |
| 3516 | + } |
| 3517 | + |
| 3518 | + listener = user_trap_syscall(__NR_dup, SECCOMP_FILTER_FLAG_NEW_LISTENER); |
| 3519 | + ASSERT_GE(listener, 0); |
| 3520 | + |
| 3521 | + pid = fork(); |
| 3522 | + ASSERT_GE(pid, 0); |
| 3523 | + |
| 3524 | + if (pid == 0) { |
| 3525 | + int dup_fd, pipe_fds[2]; |
| 3526 | + pid_t self; |
| 3527 | + |
| 3528 | + ret = pipe(pipe_fds); |
| 3529 | + if (ret < 0) |
| 3530 | + exit(1); |
| 3531 | + |
| 3532 | + dup_fd = dup(pipe_fds[0]); |
| 3533 | + if (dup_fd < 0) |
| 3534 | + exit(1); |
| 3535 | + |
| 3536 | + self = getpid(); |
| 3537 | + |
| 3538 | + ret = filecmp(self, self, pipe_fds[0], dup_fd); |
| 3539 | + if (ret) |
| 3540 | + exit(2); |
| 3541 | + |
| 3542 | + exit(0); |
| 3543 | + } |
| 3544 | + |
| 3545 | + pollfd.fd = listener; |
| 3546 | + pollfd.events = POLLIN | POLLOUT; |
| 3547 | + |
| 3548 | + EXPECT_GT(poll(&pollfd, 1, -1), 0); |
| 3549 | + EXPECT_EQ(pollfd.revents, POLLIN); |
| 3550 | + |
| 3551 | + EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req), 0); |
| 3552 | + |
| 3553 | + pollfd.fd = listener; |
| 3554 | + pollfd.events = POLLIN | POLLOUT; |
| 3555 | + |
| 3556 | + EXPECT_GT(poll(&pollfd, 1, -1), 0); |
| 3557 | + EXPECT_EQ(pollfd.revents, POLLOUT); |
| 3558 | + |
| 3559 | + EXPECT_EQ(req.data.nr, __NR_dup); |
| 3560 | + |
| 3561 | + resp.id = req.id; |
| 3562 | + resp.flags = SECCOMP_USER_NOTIF_FLAG_CONTINUE; |
| 3563 | + |
| 3564 | + /* |
| 3565 | + * Verify that setting SECCOMP_USER_NOTIF_FLAG_CONTINUE enforces other |
| 3566 | + * args be set to 0. |
| 3567 | + */ |
| 3568 | + resp.error = 0; |
| 3569 | + resp.val = USER_NOTIF_MAGIC; |
| 3570 | + EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp), -1); |
| 3571 | + EXPECT_EQ(errno, EINVAL); |
| 3572 | + |
| 3573 | + resp.error = USER_NOTIF_MAGIC; |
| 3574 | + resp.val = 0; |
| 3575 | + EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp), -1); |
| 3576 | + EXPECT_EQ(errno, EINVAL); |
| 3577 | + |
| 3578 | + resp.error = 0; |
| 3579 | + resp.val = 0; |
| 3580 | + EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp), 0) { |
| 3581 | + if (errno == EINVAL) |
| 3582 | + XFAIL(goto skip, "Kernel does not support SECCOMP_USER_NOTIF_FLAG_CONTINUE"); |
| 3583 | + } |
| 3584 | + |
| 3585 | +skip: |
| 3586 | + EXPECT_EQ(waitpid(pid, &status, 0), pid); |
| 3587 | + EXPECT_EQ(true, WIFEXITED(status)); |
| 3588 | + EXPECT_EQ(0, WEXITSTATUS(status)) { |
| 3589 | + if (WEXITSTATUS(status) == 2) { |
| 3590 | + XFAIL(return, "Kernel does not support kcmp() syscall"); |
| 3591 | + return; |
| 3592 | + } |
| 3593 | + } |
| 3594 | +} |
| 3595 | + |
3489 | 3596 | /*
|
3490 | 3597 | * TODO:
|
3491 | 3598 | * - add microbenchmarks
|
|
0 commit comments