1 /*
2  * Copyright (c) 2023 Meta
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <errno.h>
8 #include <pthread.h>
9 #include <signal.h>
10 #include <stdio.h>
11 
12 #include <zephyr/sys/util.h>
13 #include <zephyr/ztest.h>
14 
ZTEST(posix_signals,test_sigemptyset)15 ZTEST(posix_signals, test_sigemptyset)
16 {
17 	sigset_t set;
18 
19 	for (int i = 0; i < ARRAY_SIZE(set.sig); i++) {
20 		set.sig[i] = -1;
21 	}
22 
23 	zassert_ok(sigemptyset(&set));
24 
25 	for (int i = 0; i < ARRAY_SIZE(set.sig); i++) {
26 		zassert_equal(set.sig[i], 0u, "set.sig[%d] is not empty: 0x%lx", i, set.sig[i]);
27 	}
28 }
29 
ZTEST(posix_signals,test_sigfillset)30 ZTEST(posix_signals, test_sigfillset)
31 {
32 	sigset_t set = (sigset_t){0};
33 
34 	zassert_ok(sigfillset(&set));
35 
36 	for (int i = 0; i < ARRAY_SIZE(set.sig); i++) {
37 		zassert_equal(set.sig[i], -1, "set.sig[%d] is not filled: 0x%lx", i, set.sig[i]);
38 	}
39 }
40 
ZTEST(posix_signals,test_sigaddset_oor)41 ZTEST(posix_signals, test_sigaddset_oor)
42 {
43 	sigset_t set = (sigset_t){0};
44 
45 	zassert_equal(sigaddset(&set, -1), -1, "rc should be -1");
46 	zassert_equal(errno, EINVAL, "errno should be %s", "EINVAL");
47 
48 	zassert_equal(sigaddset(&set, 0), -1, "rc should be -1");
49 	zassert_equal(errno, EINVAL, "errno should be %s", "EINVAL");
50 
51 	zassert_equal(sigaddset(&set, _NSIG), -1, "rc should be -1");
52 	zassert_equal(errno, EINVAL, "errno should be %s", "EINVAL");
53 }
54 
ZTEST(posix_signals,test_sigaddset)55 ZTEST(posix_signals, test_sigaddset)
56 {
57 	int signo;
58 	sigset_t set = (sigset_t){0};
59 	sigset_t target = (sigset_t){0};
60 
61 	signo = SIGHUP;
62 	zassert_ok(sigaddset(&set, signo));
63 	WRITE_BIT(target.sig[0], signo, 1);
64 	for (int i = 0; i < ARRAY_SIZE(set.sig); i++) {
65 		zassert_equal(set.sig[i], target.sig[i],
66 			      "set.sig[%d of %d] has content: %lx, expected %lx", i,
67 			      ARRAY_SIZE(set.sig) - 1, set.sig[i], target.sig[i]);
68 	}
69 
70 	signo = SIGSYS;
71 	zassert_ok(sigaddset(&set, signo));
72 	WRITE_BIT(target.sig[0], signo, 1);
73 	for (int i = 0; i < ARRAY_SIZE(set.sig); i++) {
74 		zassert_equal(set.sig[i], target.sig[i],
75 			      "set.sig[%d of %d] has content: %lx, expected %lx", i,
76 			      ARRAY_SIZE(set.sig) - 1, set.sig[i], target.sig[i]);
77 	}
78 
79 	signo = SIGRTMIN; /* >=32, will be in the second sig set for 32bit */
80 	zassert_ok(sigaddset(&set, signo));
81 #ifdef CONFIG_64BIT
82 	WRITE_BIT(target.sig[0], signo, 1);
83 #else /* 32BIT */
84 	WRITE_BIT(target.sig[1], (signo)-BITS_PER_LONG, 1);
85 #endif
86 	for (int i = 0; i < ARRAY_SIZE(set.sig); i++) {
87 		zassert_equal(set.sig[i], target.sig[i],
88 			      "set.sig[%d of %d] has content: %lx, expected %lx", i,
89 			      ARRAY_SIZE(set.sig) - 1, set.sig[i], target.sig[i]);
90 	}
91 
92 	signo = SIGRTMAX;
93 	zassert_ok(sigaddset(&set, signo));
94 	WRITE_BIT(target.sig[signo / BITS_PER_LONG], signo % BITS_PER_LONG, 1);
95 	for (int i = 0; i < ARRAY_SIZE(set.sig); i++) {
96 		zassert_equal(set.sig[i], target.sig[i],
97 			      "set.sig[%d of %d] has content: %lx, expected %lx", i,
98 			      ARRAY_SIZE(set.sig) - 1, set.sig[i], target.sig[i]);
99 	}
100 }
101 
ZTEST(posix_signals,test_sigdelset_oor)102 ZTEST(posix_signals, test_sigdelset_oor)
103 {
104 	sigset_t set = (sigset_t){0};
105 
106 	zassert_equal(sigdelset(&set, -1), -1, "rc should be -1");
107 	zassert_equal(errno, EINVAL, "errno should be %s", "EINVAL");
108 
109 	zassert_equal(sigdelset(&set, 0), -1, "rc should be -1");
110 	zassert_equal(errno, EINVAL, "errno should be %s", "EINVAL");
111 
112 	zassert_equal(sigdelset(&set, _NSIG), -1, "rc should be -1");
113 	zassert_equal(errno, EINVAL, "errno should be %s", "EINVAL");
114 }
115 
ZTEST(posix_signals,test_sigdelset)116 ZTEST(posix_signals, test_sigdelset)
117 {
118 	int signo;
119 	sigset_t set = (sigset_t){0};
120 	sigset_t target = (sigset_t){0};
121 
122 	signo = SIGHUP;
123 	zassert_ok(sigdelset(&set, signo));
124 	WRITE_BIT(target.sig[0], signo, 0);
125 	for (int i = 0; i < ARRAY_SIZE(set.sig); i++) {
126 		zassert_equal(set.sig[i], target.sig[i],
127 			      "set.sig[%d of %d] has content: %lx, expected %lx", i,
128 			      ARRAY_SIZE(set.sig) - 1, set.sig[i], target.sig[i]);
129 	}
130 
131 	signo = SIGSYS;
132 	zassert_ok(sigdelset(&set, signo));
133 	WRITE_BIT(target.sig[0], signo, 0);
134 	for (int i = 0; i < ARRAY_SIZE(set.sig); i++) {
135 		zassert_equal(set.sig[i], target.sig[i],
136 			      "set.sig[%d of %d] has content: %lx, expected %lx", i,
137 			      ARRAY_SIZE(set.sig) - 1, set.sig[i], target.sig[i]);
138 	}
139 
140 	signo = SIGRTMIN; /* >=32, will be in the second sig set for 32bit */
141 	zassert_ok(sigdelset(&set, signo));
142 #ifdef CONFIG_64BIT
143 	WRITE_BIT(target.sig[0], signo, 0);
144 #else /* 32BIT */
145 	WRITE_BIT(target.sig[1], (signo)-BITS_PER_LONG, 0);
146 #endif
147 	for (int i = 0; i < ARRAY_SIZE(set.sig); i++) {
148 		zassert_equal(set.sig[i], target.sig[i],
149 			      "set.sig[%d of %d] has content: %lx, expected %lx", i,
150 			      ARRAY_SIZE(set.sig) - 1, set.sig[i], target.sig[i]);
151 	}
152 
153 	signo = SIGRTMAX;
154 	zassert_ok(sigdelset(&set, signo));
155 	WRITE_BIT(target.sig[signo / BITS_PER_LONG], signo % BITS_PER_LONG, 0);
156 	for (int i = 0; i < ARRAY_SIZE(set.sig); i++) {
157 		zassert_equal(set.sig[i], target.sig[i],
158 			      "set.sig[%d of %d] has content: %lx, expected %lx", i,
159 			      ARRAY_SIZE(set.sig) - 1, set.sig[i], target.sig[i]);
160 	}
161 }
162 
ZTEST(posix_signals,test_sigismember_oor)163 ZTEST(posix_signals, test_sigismember_oor)
164 {
165 	sigset_t set = {0};
166 
167 	zassert_equal(sigismember(&set, -1), -1, "rc should be -1");
168 	zassert_equal(errno, EINVAL, "errno should be %s", "EINVAL");
169 
170 	zassert_equal(sigismember(&set, 0), -1, "rc should be -1");
171 	zassert_equal(errno, EINVAL, "errno should be %s", "EINVAL");
172 
173 	zassert_equal(sigismember(&set, _NSIG), -1, "rc should be -1");
174 	zassert_equal(errno, EINVAL, "errno should be %s", "EINVAL");
175 }
176 
ZTEST(posix_signals,test_sigismember)177 ZTEST(posix_signals, test_sigismember)
178 {
179 	sigset_t set = (sigset_t){0};
180 
181 #ifdef CONFIG_64BIT
182 	set.sig[0] = BIT(SIGHUP) | BIT(SIGSYS) | BIT(SIGRTMIN);
183 #else /* 32BIT */
184 	set.sig[0] = BIT(SIGHUP) | BIT(SIGSYS);
185 	set.sig[1] = BIT((SIGRTMIN)-BITS_PER_LONG);
186 #endif
187 	WRITE_BIT(set.sig[SIGRTMAX / BITS_PER_LONG], SIGRTMAX % BITS_PER_LONG, 1);
188 
189 	zassert_equal(sigismember(&set, SIGHUP), 1, "%s expected to be member", "SIGHUP");
190 	zassert_equal(sigismember(&set, SIGSYS), 1, "%s expected to be member", "SIGSYS");
191 	zassert_equal(sigismember(&set, SIGRTMIN), 1, "%s expected to be member", "SIGRTMIN");
192 	zassert_equal(sigismember(&set, SIGRTMAX), 1, "%s expected to be member", "SIGRTMAX");
193 
194 	zassert_equal(sigismember(&set, SIGKILL), 0, "%s not expected to be member", "SIGKILL");
195 	zassert_equal(sigismember(&set, SIGTERM), 0, "%s not expected to be member", "SIGTERM");
196 }
197 
ZTEST(posix_signals,test_signal_strsignal)198 ZTEST(posix_signals, test_signal_strsignal)
199 {
200 	/* Using -INT_MAX here because compiler resolves INT_MIN to (-2147483647 - 1) */
201 	char buf[sizeof("RT signal -" STRINGIFY(INT_MAX))] = {0};
202 
203 	zassert_mem_equal(strsignal(-1), "Invalid signal", sizeof("Invalid signal"));
204 	zassert_mem_equal(strsignal(0), "Invalid signal", sizeof("Invalid signal"));
205 	zassert_mem_equal(strsignal(_NSIG), "Invalid signal", sizeof("Invalid signal"));
206 
207 	zassert_mem_equal(strsignal(30), "Signal 30", sizeof("Signal 30"));
208 	snprintf(buf, sizeof(buf), "RT signal %d", SIGRTMIN - SIGRTMIN);
209 	zassert_mem_equal(strsignal(SIGRTMIN), buf, strlen(buf));
210 	snprintf(buf, sizeof(buf), "RT signal %d", SIGRTMAX - SIGRTMIN);
211 	zassert_mem_equal(strsignal(SIGRTMAX), buf, strlen(buf));
212 
213 #ifdef CONFIG_POSIX_SIGNAL_STRING_DESC
214 	zassert_mem_equal(strsignal(SIGHUP), "Hangup", sizeof("Hangup"));
215 	zassert_mem_equal(strsignal(SIGSYS), "Bad system call", sizeof("Bad system call"));
216 #else
217 	zassert_mem_equal(strsignal(SIGHUP), "Signal 1", sizeof("Signal 1"));
218 	zassert_mem_equal(strsignal(SIGSYS), "Signal 31", sizeof("Signal 31"));
219 #endif
220 }
221 
222 typedef int (*sigmask_fn)(int how, const sigset_t *set, sigset_t *oset);
test_sigmask_entry(void * arg)223 static void *test_sigmask_entry(void *arg)
224 {
225 /* for clarity */
226 #define SIG_GETMASK SIG_SETMASK
227 
228 	enum {
229 		NEW,
230 		OLD,
231 	};
232 	static sigset_t set[2];
233 	const int invalid_how = 0x9a2ba9e;
234 	sigmask_fn sigmask = arg;
235 
236 	/* invalid how results in EINVAL */
237 	zassert_equal(sigmask(invalid_how, NULL, NULL), EINVAL);
238 	zassert_equal(sigmask(invalid_how, &set[NEW], &set[OLD]), EINVAL);
239 
240 	/* verify setting / getting masks */
241 	zassert_ok(sigemptyset(&set[NEW]));
242 	zassert_ok(sigmask(SIG_SETMASK, &set[NEW], NULL));
243 	zassert_ok(sigfillset(&set[OLD]));
244 	zassert_ok(sigmask(SIG_GETMASK, NULL, &set[OLD]));
245 	zassert_mem_equal(&set[OLD], &set[NEW], sizeof(set[OLD]));
246 
247 	zassert_ok(sigfillset(&set[NEW]));
248 	zassert_ok(sigmask(SIG_SETMASK, &set[NEW], NULL));
249 	zassert_ok(sigemptyset(&set[OLD]));
250 	zassert_ok(sigmask(SIG_GETMASK, NULL, &set[OLD]));
251 	zassert_mem_equal(&set[OLD], &set[NEW], sizeof(set[OLD]));
252 
253 	/* start with an empty mask */
254 	zassert_ok(sigemptyset(&set[NEW]));
255 	zassert_ok(sigmask(SIG_SETMASK, &set[NEW], NULL));
256 
257 	/* verify SIG_BLOCK: expect (SIGUSR1 | SIGUSR2 | SIGHUP) */
258 	zassert_ok(sigemptyset(&set[NEW]));
259 	zassert_ok(sigaddset(&set[NEW], SIGUSR1));
260 	zassert_ok(sigmask(SIG_BLOCK, &set[NEW], NULL));
261 
262 	zassert_ok(sigemptyset(&set[NEW]));
263 	zassert_ok(sigaddset(&set[NEW], SIGUSR2));
264 	zassert_ok(sigaddset(&set[NEW], SIGHUP));
265 	zassert_ok(sigmask(SIG_BLOCK, &set[NEW], NULL));
266 
267 	zassert_ok(sigemptyset(&set[OLD]));
268 	zassert_ok(sigaddset(&set[OLD], SIGUSR1));
269 	zassert_ok(sigaddset(&set[OLD], SIGUSR2));
270 	zassert_ok(sigaddset(&set[OLD], SIGHUP));
271 
272 	zassert_ok(sigmask(SIG_GETMASK, NULL, &set[NEW]));
273 	zassert_mem_equal(&set[NEW], &set[OLD], sizeof(set[NEW]));
274 
275 	/* start with full mask */
276 	zassert_ok(sigfillset(&set[NEW]));
277 	zassert_ok(sigmask(SIG_SETMASK, &set[NEW], NULL));
278 
279 	/* verify SIG_UNBLOCK: expect ~(SIGUSR1 | SIGUSR2 | SIGHUP) */
280 	zassert_ok(sigemptyset(&set[NEW]));
281 	zassert_ok(sigaddset(&set[NEW], SIGUSR1));
282 	zassert_ok(sigmask(SIG_UNBLOCK, &set[NEW], NULL));
283 
284 	zassert_ok(sigemptyset(&set[NEW]));
285 	zassert_ok(sigaddset(&set[NEW], SIGUSR2));
286 	zassert_ok(sigaddset(&set[NEW], SIGHUP));
287 	zassert_ok(sigmask(SIG_UNBLOCK, &set[NEW], NULL));
288 
289 	zassert_ok(sigfillset(&set[OLD]));
290 	zassert_ok(sigdelset(&set[OLD], SIGUSR1));
291 	zassert_ok(sigdelset(&set[OLD], SIGUSR2));
292 	zassert_ok(sigdelset(&set[OLD], SIGHUP));
293 
294 	zassert_ok(sigmask(SIG_GETMASK, NULL, &set[NEW]));
295 	zassert_mem_equal(&set[NEW], &set[OLD], sizeof(set[NEW]));
296 
297 	return NULL;
298 }
299 
ZTEST(posix_signals,test_pthread_sigmask)300 ZTEST(posix_signals, test_pthread_sigmask)
301 {
302 	pthread_t th;
303 
304 	zassert_ok(pthread_create(&th, NULL, test_sigmask_entry, pthread_sigmask));
305 	zassert_ok(pthread_join(th, NULL));
306 }
307 
ZTEST(posix_signals,test_sigprocmask)308 ZTEST(posix_signals, test_sigprocmask)
309 {
310 	if (IS_ENABLED(CONFIG_MULTITHREADING)) {
311 		if (!IS_ENABLED(CONFIG_ASSERT)) {
312 			zassert_not_ok(sigprocmask(SIG_SETMASK, NULL, NULL));
313 			zassert_equal(errno, ENOSYS);
314 		}
315 	} else {
316 		pthread_t th;
317 
318 		zassert_ok(pthread_create(&th, NULL, test_sigmask_entry, sigprocmask));
319 		zassert_ok(pthread_join(th, NULL));
320 	}
321 }
322 
before(void * arg)323 static void before(void *arg)
324 {
325 	ARG_UNUSED(arg);
326 
327 	if (!IS_ENABLED(CONFIG_DYNAMIC_THREAD)) {
328 		/* skip redundant testing if there is no thread pool / heap allocation */
329 		ztest_test_skip();
330 	}
331 }
332 
333 ZTEST_SUITE(posix_signals, NULL, NULL, before, NULL, NULL);
334