selftests: add ESRCH tests for pidfd_getfd()

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>
This commit is contained in:
Tycho Andersen 2024-02-07 10:19:44 +01:00 committed by Christian Brauner
parent 0c9bd6bc4b
commit f0ece18e99
No known key found for this signature in database
GPG Key ID: 91C61BC06578DCA2

View 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)
{