1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2019 SUSE LLC
4 * Author: Christian Amann <camann@suse.com>
5 */
6 /*
7 * Tests if the pidfd_send_signal syscall behaves
8 * like rt_sigqueueinfo when a pointer to a siginfo_t
9 * struct is passed.
10 */
11
12 #define _GNU_SOURCE
13 #include <signal.h>
14 #include <stdlib.h>
15 #include "lapi/pidfd_send_signal.h"
16 #include "tst_safe_pthread.h"
17
18 #define SIGNAL SIGUSR1
19 #define DATA 777
20
21 static struct sigaction *sig_action;
22 static int sig_rec;
23 static siginfo_t *uinfo;
24 static int pidfd;
25
received_signal(int sig,siginfo_t * info,void * ucontext)26 static void received_signal(int sig, siginfo_t *info, void *ucontext)
27 {
28 if (info && ucontext) {
29 if (sig == SIGNAL && info->si_value.sival_int == DATA) {
30 tst_res(TPASS, "Received correct signal and data!");
31 sig_rec = 1;
32 } else {
33 tst_res(TFAIL, "Received wrong signal and/or data!");
34 }
35 } else {
36 tst_res(TFAIL, "Signal handling went wrong!");
37 }
38 }
39
handle_thread(void * arg)40 static void *handle_thread(void *arg)
41 {
42 SAFE_SIGACTION(SIGNAL, sig_action, NULL);
43 TST_CHECKPOINT_WAKE_AND_WAIT(0);
44 return arg;
45 }
46
verify_pidfd_send_signal(void)47 static void verify_pidfd_send_signal(void)
48 {
49 pthread_t thr;
50
51 SAFE_PTHREAD_CREATE(&thr, NULL, handle_thread, NULL);
52
53 TST_CHECKPOINT_WAIT(0);
54
55 TEST(pidfd_send_signal(pidfd, SIGNAL, uinfo, 0));
56 if (TST_RET != 0) {
57 tst_res(TFAIL | TTERRNO, "pidfd_send_signal() failed");
58 return;
59 }
60
61 TST_CHECKPOINT_WAKE(0);
62 SAFE_PTHREAD_JOIN(thr, NULL);
63
64 if (sig_rec) {
65 tst_res(TPASS,
66 "pidfd_send_signal() behaved like rt_sigqueueinfo()");
67 }
68 }
69
setup(void)70 static void setup(void)
71 {
72 pidfd_send_signal_supported();
73
74 pidfd = SAFE_OPEN("/proc/self", O_DIRECTORY | O_CLOEXEC);
75
76 sig_action = SAFE_MALLOC(sizeof(struct sigaction));
77
78 memset(sig_action, 0, sizeof(*sig_action));
79 sig_action->sa_sigaction = received_signal;
80 sig_action->sa_flags = SA_SIGINFO;
81
82 uinfo = SAFE_MALLOC(sizeof(siginfo_t));
83
84 memset(uinfo, 0, sizeof(*uinfo));
85 uinfo->si_signo = SIGNAL;
86 uinfo->si_code = SI_QUEUE;
87 uinfo->si_pid = getpid();
88 uinfo->si_uid = getuid();
89 uinfo->si_value.sival_int = DATA;
90 }
91
cleanup(void)92 static void cleanup(void)
93 {
94 free(uinfo);
95 free(sig_action);
96 if (pidfd > 0)
97 SAFE_CLOSE(pidfd);
98 }
99
100 static struct tst_test test = {
101 .test_all = verify_pidfd_send_signal,
102 .setup = setup,
103 .cleanup = cleanup,
104 .needs_checkpoints = 1,
105 };
106