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 /*
8 * This tests the rt_sigqueueinfo() syscall.
9 *
10 * It does so by creating a thread which registers the corresponding
11 * signal handler. After that the main thread sends a signal and data
12 * to the handler thread. If the correct signal and data is received,
13 * the test is successful.
14 */
15
16 #include <signal.h>
17 #include <stdlib.h>
18 #include "config.h"
19 #include "tst_test.h"
20 #include "tst_safe_pthread.h"
21
22 #ifdef HAVE_STRUCT_SIGACTION_SA_SIGACTION
23 #include "rt_sigqueueinfo.h"
24
25 #define SIGNAL SIGUSR1
26 #define DATA 777
27
28 static struct sigaction *sig_action;
29 static int sig_rec;
30 static siginfo_t *uinfo;
31 static pid_t tid;
32
received_signal(int sig,siginfo_t * info,void * ucontext)33 static void received_signal(int sig, siginfo_t *info, void *ucontext)
34 {
35 if (info && ucontext) {
36 if (sig == SIGNAL && info->si_value.sival_int == DATA) {
37 tst_res(TPASS, "Received correct signal and data!");
38 sig_rec = 1;
39 } else
40 tst_res(TFAIL, "Received wrong signal and/or data!");
41 } else
42 tst_res(TFAIL, "Signal handling went wrong!");
43 }
44
handle_thread(void * arg LTP_ATTRIBUTE_UNUSED)45 static void *handle_thread(void *arg LTP_ATTRIBUTE_UNUSED)
46 {
47 int ret;
48
49 tid = tst_syscall(__NR_gettid);
50
51 ret = sigaction(SIGNAL, sig_action, NULL);
52 if (ret)
53 tst_brk(TBROK, "Failed to set sigaction for handler thread!");
54
55 TST_CHECKPOINT_WAKE(0);
56 TST_CHECKPOINT_WAIT(1);
57 return arg;
58 }
59
verify_sigqueueinfo(void)60 static void verify_sigqueueinfo(void)
61 {
62 pthread_t thr;
63
64 SAFE_PTHREAD_CREATE(&thr, NULL, handle_thread, NULL);
65
66 TST_CHECKPOINT_WAIT(0);
67
68 TEST(sys_rt_sigqueueinfo(tid, SIGNAL, uinfo));
69 if (TST_RET != 0) {
70 tst_res(TFAIL | TTERRNO, "rt_sigqueueinfo() failed");
71 return;
72 }
73
74 TST_CHECKPOINT_WAKE(1);
75 SAFE_PTHREAD_JOIN(thr, NULL);
76
77 if (sig_rec)
78 tst_res(TPASS, "rt_sigqueueinfo() was successful!");
79 }
80
setup(void)81 static void setup(void)
82 {
83 sig_action = SAFE_MALLOC(sizeof(struct sigaction));
84
85 memset(sig_action, 0, sizeof(*sig_action));
86 sig_action->sa_sigaction = received_signal;
87 sig_action->sa_flags = SA_SIGINFO;
88
89 uinfo = SAFE_MALLOC(sizeof(siginfo_t));
90
91 memset(uinfo, 0, sizeof(*uinfo));
92 uinfo->si_code = SI_QUEUE;
93 uinfo->si_pid = getpid();
94 uinfo->si_uid = getuid();
95 uinfo->si_value.sival_int = DATA;
96
97 sig_rec = 0;
98 }
99
cleanup(void)100 static void cleanup(void)
101 {
102 free(uinfo);
103 free(sig_action);
104 }
105
106 static struct tst_test test = {
107 .test_all = verify_sigqueueinfo,
108 .setup = setup,
109 .cleanup = cleanup,
110 .needs_checkpoints = 1,
111 .timeout = 20,
112 };
113
114 #else
115 TST_TEST_TCONF(
116 "This system does not support rt_sigqueueinfo().");
117 #endif /* HAVE_STRUCT_SIGACTION_SA_SIGACTION */
118