|
51 | 51 | #include <poll.h>
|
52 | 52 |
|
53 | 53 | #include "../kselftest_harness.h"
|
| 54 | +#include "../clone3/clone3_selftests.h" |
54 | 55 |
|
55 | 56 | /* Attempt to de-conflict with the selftests tree. */
|
56 | 57 | #ifndef SKIP
|
@@ -3702,6 +3703,141 @@ TEST(user_notification_continue)
|
3702 | 3703 | }
|
3703 | 3704 | }
|
3704 | 3705 |
|
| 3706 | +TEST(user_notification_filter_empty) |
| 3707 | +{ |
| 3708 | + pid_t pid; |
| 3709 | + long ret; |
| 3710 | + int status; |
| 3711 | + struct pollfd pollfd; |
| 3712 | + struct clone_args args = { |
| 3713 | + .flags = CLONE_FILES, |
| 3714 | + .exit_signal = SIGCHLD, |
| 3715 | + }; |
| 3716 | + |
| 3717 | + ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); |
| 3718 | + ASSERT_EQ(0, ret) { |
| 3719 | + TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!"); |
| 3720 | + } |
| 3721 | + |
| 3722 | + pid = sys_clone3(&args, sizeof(args)); |
| 3723 | + ASSERT_GE(pid, 0); |
| 3724 | + |
| 3725 | + if (pid == 0) { |
| 3726 | + int listener; |
| 3727 | + |
| 3728 | + listener = user_trap_syscall(__NR_mknod, SECCOMP_FILTER_FLAG_NEW_LISTENER); |
| 3729 | + if (listener < 0) |
| 3730 | + _exit(EXIT_FAILURE); |
| 3731 | + |
| 3732 | + if (dup2(listener, 200) != 200) |
| 3733 | + _exit(EXIT_FAILURE); |
| 3734 | + |
| 3735 | + close(listener); |
| 3736 | + |
| 3737 | + _exit(EXIT_SUCCESS); |
| 3738 | + } |
| 3739 | + |
| 3740 | + EXPECT_EQ(waitpid(pid, &status, 0), pid); |
| 3741 | + EXPECT_EQ(true, WIFEXITED(status)); |
| 3742 | + EXPECT_EQ(0, WEXITSTATUS(status)); |
| 3743 | + |
| 3744 | + /* |
| 3745 | + * The seccomp filter has become unused so we should be notified once |
| 3746 | + * the kernel gets around to cleaning up task struct. |
| 3747 | + */ |
| 3748 | + pollfd.fd = 200; |
| 3749 | + pollfd.events = POLLHUP; |
| 3750 | + |
| 3751 | + EXPECT_GT(poll(&pollfd, 1, 2000), 0); |
| 3752 | + EXPECT_GT((pollfd.revents & POLLHUP) ?: 0, 0); |
| 3753 | +} |
| 3754 | + |
| 3755 | +static void *do_thread(void *data) |
| 3756 | +{ |
| 3757 | + return NULL; |
| 3758 | +} |
| 3759 | + |
| 3760 | +TEST(user_notification_filter_empty_threaded) |
| 3761 | +{ |
| 3762 | + pid_t pid; |
| 3763 | + long ret; |
| 3764 | + int status; |
| 3765 | + struct pollfd pollfd; |
| 3766 | + struct clone_args args = { |
| 3767 | + .flags = CLONE_FILES, |
| 3768 | + .exit_signal = SIGCHLD, |
| 3769 | + }; |
| 3770 | + |
| 3771 | + ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); |
| 3772 | + ASSERT_EQ(0, ret) { |
| 3773 | + TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!"); |
| 3774 | + } |
| 3775 | + |
| 3776 | + pid = sys_clone3(&args, sizeof(args)); |
| 3777 | + ASSERT_GE(pid, 0); |
| 3778 | + |
| 3779 | + if (pid == 0) { |
| 3780 | + pid_t pid1, pid2; |
| 3781 | + int listener, status; |
| 3782 | + pthread_t thread; |
| 3783 | + |
| 3784 | + listener = user_trap_syscall(__NR_dup, SECCOMP_FILTER_FLAG_NEW_LISTENER); |
| 3785 | + if (listener < 0) |
| 3786 | + _exit(EXIT_FAILURE); |
| 3787 | + |
| 3788 | + if (dup2(listener, 200) != 200) |
| 3789 | + _exit(EXIT_FAILURE); |
| 3790 | + |
| 3791 | + close(listener); |
| 3792 | + |
| 3793 | + pid1 = fork(); |
| 3794 | + if (pid1 < 0) |
| 3795 | + _exit(EXIT_FAILURE); |
| 3796 | + |
| 3797 | + if (pid1 == 0) |
| 3798 | + _exit(EXIT_SUCCESS); |
| 3799 | + |
| 3800 | + pid2 = fork(); |
| 3801 | + if (pid2 < 0) |
| 3802 | + _exit(EXIT_FAILURE); |
| 3803 | + |
| 3804 | + if (pid2 == 0) |
| 3805 | + _exit(EXIT_SUCCESS); |
| 3806 | + |
| 3807 | + if (pthread_create(&thread, NULL, do_thread, NULL) || |
| 3808 | + pthread_join(thread, NULL)) |
| 3809 | + _exit(EXIT_FAILURE); |
| 3810 | + |
| 3811 | + if (pthread_create(&thread, NULL, do_thread, NULL) || |
| 3812 | + pthread_join(thread, NULL)) |
| 3813 | + _exit(EXIT_FAILURE); |
| 3814 | + |
| 3815 | + if (waitpid(pid1, &status, 0) != pid1 || !WIFEXITED(status) || |
| 3816 | + WEXITSTATUS(status)) |
| 3817 | + _exit(EXIT_FAILURE); |
| 3818 | + |
| 3819 | + if (waitpid(pid2, &status, 0) != pid2 || !WIFEXITED(status) || |
| 3820 | + WEXITSTATUS(status)) |
| 3821 | + _exit(EXIT_FAILURE); |
| 3822 | + |
| 3823 | + exit(EXIT_SUCCESS); |
| 3824 | + } |
| 3825 | + |
| 3826 | + EXPECT_EQ(waitpid(pid, &status, 0), pid); |
| 3827 | + EXPECT_EQ(true, WIFEXITED(status)); |
| 3828 | + EXPECT_EQ(0, WEXITSTATUS(status)); |
| 3829 | + |
| 3830 | + /* |
| 3831 | + * The seccomp filter has become unused so we should be notified once |
| 3832 | + * the kernel gets around to cleaning up task struct. |
| 3833 | + */ |
| 3834 | + pollfd.fd = 200; |
| 3835 | + pollfd.events = POLLHUP; |
| 3836 | + |
| 3837 | + EXPECT_GT(poll(&pollfd, 1, 2000), 0); |
| 3838 | + EXPECT_GT((pollfd.revents & POLLHUP) ?: 0, 0); |
| 3839 | +} |
| 3840 | + |
3705 | 3841 | /*
|
3706 | 3842 | * TODO:
|
3707 | 3843 | * - add microbenchmarks
|
|
0 commit comments