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: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Link: https://lore.kernel.org/r/7ab0e48b26ba53abf7b703df2dd11a2e99b8efb2.1738268370.git.lorenzo.stoakes@oracle.com
Reviewed-by: Shakeel Butt <shakeel.butt@linux.dev>
Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
Lorenzo Stoakes 2025-01-30 20:40:30 +00:00 committed by Christian Brauner
parent e943271f79
commit 2bbf47f2d3
No known key found for this signature in database
GPG Key ID: 91C61BC06578DCA2
2 changed files with 69 additions and 17 deletions

@ -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;
}

@ -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);
signal(SIGUSR1, set_signal_received_on_sigusr1);
ret = sys_pidfd_send_signal(pidfd, SIGUSR1, NULL, 0);
err = send_signal(pidfd);
if (err)
ksft_exit_fail_msg(
"%s test: Error %d on sending pidfd signal\n",
test_name, err);
close(pidfd);
if (ret < 0)
ksft_exit_fail_msg("%s test: Failed to send signal\n",
test_name);
if (signal_received != 1)
ksft_exit_fail_msg("%s test: Failed to receive signal\n",
test_name);
/* 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);
/*
* 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 (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;
}