1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) International Business Machines Corp., 2002
4 * Copyright (c) Linux Test Project, 2009-2019
5 *
6 * AUTHORS
7 * Paul Larson
8 * Matthias Maennich
9 *
10 * DESCRIPTION
11 * Test 1: Suppress handling SIGUSR1 and SIGUSR1, raise them and assert their
12 * signal pending.
13 * Test 2: Call sigpending(sigset_t*=-1), it should return -1 with errno EFAULT.
14 */
15
16 #include "config.h"
17 #include "tst_test.h"
18 #include "ltp_signal.h"
19 #include "lapi/syscalls.h"
20
sigpending_info(void)21 static void sigpending_info(void)
22 {
23 switch (tst_variant) {
24 case 0:
25 tst_res(TINFO, "Testing libc sigpending()");
26 break;
27 case 1:
28 tst_res(TINFO, "Testing __NR_sigpending syscall");
29 break;
30 case 2:
31 tst_res(TINFO, "Testing __NR_rt_sigpending syscall");
32 break;
33 }
34 }
35
tested_sigpending(sigset_t * sigset)36 static int tested_sigpending(sigset_t *sigset)
37 {
38 switch (tst_variant) {
39 case 0:
40 #ifndef HAVE_SIGPENDING
41 tst_brk(TCONF, "libc sigpending() is not implemented");
42 #else
43 return sigpending(sigset);
44 #endif
45 break;
46 case 1:
47 return tst_syscall(__NR_sigpending, sigset);
48 case 2:
49 return tst_syscall(__NR_rt_sigpending, sigset, SIGSETSIZE);
50 }
51 return -1;
52 }
53
54 static int sighandler_counter;
sighandler(int signum LTP_ATTRIBUTE_UNUSED)55 static void sighandler(int signum LTP_ATTRIBUTE_UNUSED)
56 {
57 ++sighandler_counter;
58 }
59
test_sigpending(void)60 static void test_sigpending(void)
61 {
62 int SIGMAX = MIN(sizeof(sigset_t) * 8, (size_t)_NSIG);
63
64 int i; /* loop index */
65
66 sighandler_counter = 0;
67
68 /* set up signal mask and handler */
69 sigset_t only_SIGUSR, old_mask;
70 sighandler_t old_sighandler1, old_sighandler2;
71 sigemptyset(&only_SIGUSR);
72 sigaddset(&only_SIGUSR, SIGUSR1);
73 sigaddset(&only_SIGUSR, SIGUSR2);
74 if (sigprocmask(SIG_SETMASK, &only_SIGUSR, &old_mask))
75 tst_brk(TBROK, "sigprocmask failed");
76 old_sighandler1 = SAFE_SIGNAL(SIGUSR1, sighandler);
77 old_sighandler2 = SAFE_SIGNAL(SIGUSR2, sighandler);
78
79 /* Initially no signal should be pending */
80 sigset_t pending;
81 sigemptyset(&pending);
82 TEST(tested_sigpending(&pending));
83
84 for (i = 1; i < SIGMAX; ++i)
85 if (sigismember(&pending, i))
86 tst_brk(TFAIL,
87 "initialization failed: no signal should be pending by now");
88
89 /* raise a signal */
90 if (raise(SIGUSR1))
91 tst_brk(TBROK, "raising SIGUSR1 failed");
92 if (sighandler_counter > 0)
93 tst_brk(TFAIL,
94 "signal handler is not (yet) supposed to be called");
95
96 /* now we should have exactly one pending signal (SIGUSR1) */
97 sigemptyset(&pending);
98 TEST(tested_sigpending(&pending));
99 for (i = 1; i < SIGMAX; ++i)
100 if ((i == SIGUSR1) != sigismember(&pending, i))
101 tst_brk(TFAIL, "only SIGUSR1 should be pending by now");
102
103 /* raise another signal */
104 if (raise(SIGUSR2))
105 tst_brk(TBROK, "raising SIGUSR2 failed");
106 if (sighandler_counter > 0)
107 tst_brk(TFAIL,
108 "signal handler is not (yet) supposed to be called");
109
110 /* now we should have exactly two pending signals (SIGUSR1, SIGUSR2) */
111 sigemptyset(&pending);
112 TEST(tested_sigpending(&pending));
113 for (i = 1; i < SIGMAX; ++i)
114 if ((i == SIGUSR1 || i == SIGUSR2) != sigismember(&pending, i))
115 tst_brk(TFAIL,
116 "only SIGUSR1, SIGUSR2 should be pending by now");
117
118 tst_res(TPASS, "basic sigpending test successful");
119
120 /* reinstate old mask */
121 if (sigprocmask(SIG_SETMASK, &old_mask, NULL))
122 tst_brk(TBROK, "sigprocmask failed");
123
124 /* at this time the signal handler has been called, once for each signal */
125 if (sighandler_counter != 2)
126 tst_brk(TFAIL,
127 "signal handler has not been called for each signal");
128
129 /* reinstate the original signal handlers */
130 SAFE_SIGNAL(SIGUSR1, old_sighandler1);
131 SAFE_SIGNAL(SIGUSR2, old_sighandler2);
132 }
133
test_efault_on_invalid_sigset(void)134 static void test_efault_on_invalid_sigset(void)
135 {
136 /* set sigset to point to an invalid location */
137 sigset_t *sigset = tst_get_bad_addr(NULL);
138
139 TEST(tested_sigpending(sigset));
140
141 /* check return code */
142 if (TST_RET == -1) {
143 if (TST_ERR != EFAULT) {
144 tst_res(TFAIL | TTERRNO,
145 "syscall failed with wrong errno, expected errno=%d, got %d",
146 EFAULT, TST_ERR);
147 } else {
148 tst_res(TPASS | TTERRNO, "expected failure");
149 }
150 } else {
151 tst_res(TFAIL,
152 "syscall failed, expected return value=-1, got %ld",
153 TST_RET);
154 }
155 }
156
run(void)157 static void run(void)
158 {
159 sigpending_info();
160 test_sigpending();
161 test_efault_on_invalid_sigset();
162 }
163
164 static struct tst_test test = {
165 .test_all = run,
166 .test_variants = 3,
167 };
168