Unverified Commit 2bbf47f2 authored by Lorenzo Stoakes's avatar Lorenzo Stoakes Committed by Christian Brauner
Browse files

selftests/pidfd: add tests for PIDFD_SELF_*



Add tests to assert that PIDFD_SELF* correctly refers to the current
thread and process.

We explicitly test pidfd_send_signal(), however We defer testing of
mm-specific functionality which uses pidfd, namely process_madvise() and
process_mrelease() to mm testing (though note the latter can not be
sensibly tested as it would require the testing process to be dying).

We also correct the pidfd_open_test.c fields which refer to .request_mask
whereas the UAPI header refers to .mask, which otherwise break the import
of the UAPI header.

Signed-off-by: default avatarLorenzo Stoakes <lorenzo.stoakes@oracle.com>
Link: https://lore.kernel.org/r/7ab0e48b26ba53abf7b703df2dd11a2e99b8efb2.1738268370.git.lorenzo.stoakes@oracle.com


Reviewed-by: default avatarShakeel Butt <shakeel.butt@linux.dev>
Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
parent e943271f
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@
#define PIDFD_INFO_CGROUPID		(1UL << 0)

struct pidfd_info {
	__u64 request_mask;
	__u64 mask;
	__u64 cgroupid;
	__u32 pid;
	__u32 tgid;
@@ -148,7 +148,7 @@ static pid_t get_pid_from_fdinfo_file(int pidfd, const char *key, size_t keylen)
int main(int argc, char **argv)
{
	struct pidfd_info info = {
		.request_mask = PIDFD_INFO_CGROUPID,
		.mask = PIDFD_INFO_CGROUPID,
	};
	int pidfd = -1, ret = 1;
	pid_t pid;
@@ -227,7 +227,7 @@ int main(int argc, char **argv)
			       getegid(), info.sgid);
		goto on_error;
	}
	if ((info.request_mask & PIDFD_INFO_CGROUPID) && info.cgroupid == 0) {
	if ((info.mask & PIDFD_INFO_CGROUPID) && info.cgroupid == 0) {
		ksft_print_msg("cgroupid should not be 0 when PIDFD_INFO_CGROUPID is set\n");
		goto on_error;
	}
+64 −12
Original line number Diff line number Diff line
@@ -42,12 +42,41 @@ static pid_t pidfd_clone(int flags, int *pidfd, int (*fn)(void *))
#endif
}

static int signal_received;
static pthread_t signal_received;

static void set_signal_received_on_sigusr1(int sig)
{
	if (sig == SIGUSR1)
		signal_received = 1;
		signal_received = pthread_self();
}

static int send_signal(int pidfd)
{
	int ret = 0;

	if (sys_pidfd_send_signal(pidfd, SIGUSR1, NULL, 0) < 0) {
		ret = -EINVAL;
		goto exit;
	}

	if (signal_received != pthread_self()) {
		ret = -EINVAL;
		goto exit;
	}

exit:
	signal_received = 0;
	return ret;
}

static void *send_signal_worker(void *arg)
{
	int pidfd = (int)(intptr_t)arg;
	int ret;

	/* We forward any errors for the caller to handle. */
	ret = send_signal(pidfd);
	return (void *)(intptr_t)ret;
}

/*
@@ -56,8 +85,11 @@ static void set_signal_received_on_sigusr1(int sig)
 */
static int test_pidfd_send_signal_simple_success(void)
{
	int pidfd, ret;
	int pidfd;
	const char *test_name = "pidfd_send_signal send SIGUSR1";
	pthread_t thread;
	void *thread_res;
	int err;

	if (!have_pidfd_send_signal) {
		ksft_test_result_skip(
@@ -66,25 +98,45 @@ static int test_pidfd_send_signal_simple_success(void)
		return 0;
	}

	signal(SIGUSR1, set_signal_received_on_sigusr1);

	/* Try sending a signal to ourselves via /proc/self. */
	pidfd = open("/proc/self", O_DIRECTORY | O_CLOEXEC);
	if (pidfd < 0)
		ksft_exit_fail_msg(
			"%s test: Failed to open process file descriptor\n",
			test_name);
	err = send_signal(pidfd);
	if (err)
		ksft_exit_fail_msg(
			"%s test: Error %d on sending pidfd signal\n",
			test_name, err);
	close(pidfd);

	signal(SIGUSR1, set_signal_received_on_sigusr1);
	/* Now try the same thing only using PIDFD_SELF_THREAD_GROUP. */
	err = send_signal(PIDFD_SELF_THREAD_GROUP);
	if (err)
		ksft_exit_fail_msg(
			"%s test: Error %d on PIDFD_SELF_THREAD_GROUP signal\n",
			test_name, err);

	ret = sys_pidfd_send_signal(pidfd, SIGUSR1, NULL, 0);
	close(pidfd);
	if (ret < 0)
		ksft_exit_fail_msg("%s test: Failed to send signal\n",
	/*
	 * Now try the same thing in a thread and assert thread ID is equal to
	 * worker thread ID.
	 */
	if (pthread_create(&thread, NULL, send_signal_worker,
			   (void *)(intptr_t)PIDFD_SELF_THREAD))
		ksft_exit_fail_msg("%s test: Failed to create thread\n",
				   test_name);

	if (signal_received != 1)
		ksft_exit_fail_msg("%s test: Failed to receive signal\n",
	if (pthread_join(thread, &thread_res))
		ksft_exit_fail_msg("%s test: Failed to join thread\n",
				   test_name);
	err = (int)(intptr_t)thread_res;
	if (err)
		ksft_exit_fail_msg(
			"%s test: Error %d on PIDFD_SELF_THREAD signal\n",
			test_name, err);

	signal_received = 0;
	ksft_test_result_pass("%s test: Sent signal\n", test_name);
	return 0;
}