]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
selftests: add ESRCH tests for pidfd_getfd()
authorTycho Andersen <tandersen@netflix.com>
Wed, 7 Feb 2024 09:19:44 +0000 (10:19 +0100)
committerChristian Brauner <brauner@kernel.org>
Wed, 7 Feb 2024 14:48:31 +0000 (15:48 +0100)
Ensure that pidfd_getfd() reports -ESRCH if the task is already exiting.

Signed-off-by: Tycho Andersen <tandersen@netflix.com>
Link: https://lore.kernel.org/r/20240206192357.81942-1-tycho@tycho.pizza
Signed-off-by: Christian Brauner <brauner@kernel.org>
tools/testing/selftests/pidfd/pidfd_getfd_test.c

index 0930e2411dfb9a1337988e4cb815e14bfa4464b5..cd51d547b751db39547d4e25b8db44f25dd23780 100644 (file)
@@ -5,6 +5,7 @@
 #include <fcntl.h>
 #include <limits.h>
 #include <linux/types.h>
+#include <poll.h>
 #include <sched.h>
 #include <signal.h>
 #include <stdio.h>
@@ -129,6 +130,7 @@ FIXTURE(child)
         * When it is closed, the child will exit.
         */
        int sk;
+       bool ignore_child_result;
 };
 
 FIXTURE_SETUP(child)
@@ -165,10 +167,14 @@ FIXTURE_SETUP(child)
 
 FIXTURE_TEARDOWN(child)
 {
+       int ret;
+
        EXPECT_EQ(0, close(self->pidfd));
        EXPECT_EQ(0, close(self->sk));
 
-       EXPECT_EQ(0, wait_for_pid(self->pid));
+       ret = wait_for_pid(self->pid);
+       if (!self->ignore_child_result)
+               EXPECT_EQ(0, ret);
 }
 
 TEST_F(child, disable_ptrace)
@@ -235,6 +241,29 @@ TEST(flags_set)
        EXPECT_EQ(errno, EINVAL);
 }
 
+TEST_F(child, no_strange_EBADF)
+{
+       struct pollfd fds;
+
+       self->ignore_child_result = true;
+
+       fds.fd = self->pidfd;
+       fds.events = POLLIN;
+
+       ASSERT_EQ(kill(self->pid, SIGKILL), 0);
+       ASSERT_EQ(poll(&fds, 1, 5000), 1);
+
+       /*
+        * It used to be that pidfd_getfd() could race with the exiting thread
+        * between exit_files() and release_task(), and get a non-null task
+        * with a NULL files struct, and you'd get EBADF, which was slightly
+        * confusing.
+        */
+       errno = 0;
+       EXPECT_EQ(sys_pidfd_getfd(self->pidfd, self->remote_fd, 0), -1);
+       EXPECT_EQ(errno, ESRCH);
+}
+
 #if __NR_pidfd_getfd == -1
 int main(void)
 {