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