Unverified Commit f0ece18e authored by Tycho Andersen's avatar Tycho Andersen Committed by Christian Brauner
Browse files

selftests: add ESRCH tests for pidfd_getfd()



Ensure that pidfd_getfd() reports -ESRCH if the task is already exiting.

Signed-off-by: default avatarTycho Andersen <tandersen@netflix.com>
Link: https://lore.kernel.org/r/20240206192357.81942-1-tycho@tycho.pizza


Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
parent 0c9bd6bc
Loading
Loading
Loading
Loading
+30 −1
Original line number Diff line number Diff line
@@ -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)
{