1 /*
2  * Copyright (c) Jiri Palecek<jpalecek@web.de>, 2009
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of version 2 of the GNU General Public License as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it would be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  *
12  * Further, this software is distributed without any warranty that it is
13  * free of the rightful claim of any third person regarding infringement
14  * or the like.  Any license provided herein, whether implied or
15  * otherwise, applies only to this software file.  Patent licenses, if
16  * any, provided herein do not apply to combinations of this program with
17  * other software, or any other product whatsoever.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 #include "test.h"
24 #include <errno.h>
25 #include <signal.h>
26 #include "../utils/include_j_h.h"
27 #include "../utils/common_j_h.c"
28 #include <limits.h>
29 #include "lapi/syscalls.h"
30 
31 #define SUCCEED_OR_DIE(syscall, message, ...)				 \
32 	(errno = 0,							 \
33 		({int ret=syscall(__VA_ARGS__);				 \
34 			if (ret==-1)					 \
35 				tst_brkm(TBROK|TERRNO, cleanup, message);\
36 			ret;}))
37 
38 /* Report success iff TEST_RETURN and TEST_ERRNO are equal to
39 	 exp_return and exp_errno, resp., and cond is true. If cond is not
40 	 true, report condition_errmsg
41 */
report_success_cond(const char * func,const char * file,int line,long exp_return,int exp_errno,int condition,char * condition_errmsg)42 static void report_success_cond(const char *func, const char *file, int line,
43 				long exp_return, int exp_errno, int condition,
44 				char *condition_errmsg)
45 {
46 	if (exp_return == TEST_RETURN
47 	    && (exp_return != -1 || exp_errno == TEST_ERRNO))
48 		if (condition)
49 			tst_resm(TPASS, "Test passed");
50 		else
51 			tst_resm(TFAIL, "%s (%s: %d): %s", func, file, line,
52 				 condition_errmsg);
53 	else if (TEST_RETURN != -1)
54 		tst_resm(TFAIL,
55 			 "%s (%s: %d): Unexpected return value; expected %ld, got %ld",
56 			 func, file, line, exp_return, TEST_RETURN);
57 	else
58 		tst_resm(TFAIL | TTERRNO, "%s (%s: %d): Unexpected failure",
59 			 func, file, line);
60 }
61 
62 #define REPORT_SUCCESS_COND(exp_return, exp_errno, condition, condition_errmsg)	\
63 	report_success_cond(__FUNCTION__, __FILE__, __LINE__, exp_return, exp_errno, condition, condition_errmsg);
64 
65 /* Report success iff TEST_RETURN and TEST_ERRNO are equal to
66 	 exp_return and exp_errno, resp.
67 */
68 #define REPORT_SUCCESS(exp_return, exp_errno)					\
69 	REPORT_SUCCESS_COND(exp_return, exp_errno, 1, "");
70 
71 static void cleanup(void);
72 
empty_handler(int sig)73 static void empty_handler(int sig)
74 {
75 }
76 
setup(void)77 static void setup(void)
78 {
79 	tst_sig(FORK, DEF_HANDLER, cleanup);
80 	signal(SIGUSR1, empty_handler);
81 	signal(SIGALRM, empty_handler);
82 	signal(SIGUSR2, SIG_IGN);
83 
84 	TEST_PAUSE;
85 }
86 
cleanup(void)87 static void cleanup(void)
88 {
89 }
90 
91 typedef int (*swi_func) (const sigset_t * set, siginfo_t * info,
92 			 struct timespec * timeout);
93 typedef void (*test_func) (swi_func, int);
94 
95 #ifdef TEST_SIGWAIT
my_sigwait(const sigset_t * set,siginfo_t * info,struct timespec * timeout)96 static int my_sigwait(const sigset_t * set, siginfo_t * info,
97 		      struct timespec *timeout)
98 {
99 	int ret;
100 	int err = sigwait(set, &ret);
101 
102 	if (err == 0)
103 		return ret;
104 	errno = err;
105 	return -1;
106 }
107 #endif
108 
109 #ifdef TEST_SIGWAITINFO
my_sigwaitinfo(const sigset_t * set,siginfo_t * info,struct timespec * timeout)110 static int my_sigwaitinfo(const sigset_t * set, siginfo_t * info,
111 			  struct timespec *timeout)
112 {
113 
114 	return sigwaitinfo(set, info);
115 }
116 #endif
117 
118 #ifdef TEST_SIGTIMEDWAIT
my_sigtimedwait(const sigset_t * set,siginfo_t * info,struct timespec * timeout)119 static int my_sigtimedwait(const sigset_t * set, siginfo_t * info,
120 			   struct timespec *timeout)
121 {
122 
123 	return sigtimedwait(set, info, timeout);
124 }
125 #endif
126 
127 #ifdef TEST_RT_SIGTIMEDWAIT
my_rt_sigtimedwait(const sigset_t * set,siginfo_t * info,struct timespec * timeout)128 static int my_rt_sigtimedwait(const sigset_t * set, siginfo_t * info,
129 			      struct timespec *timeout)
130 {
131 	/* _NSIG is always the right number of bits of signal map for all arches */
132 	return ltp_syscall(__NR_rt_sigtimedwait, set, info, timeout, _NSIG/8);
133 }
134 #endif
135 
test_empty_set(swi_func sigwaitinfo,int signo)136 void test_empty_set(swi_func sigwaitinfo, int signo)
137 {
138 	sigset_t sigs;
139 	siginfo_t si;
140 	pid_t child;
141 
142 	SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
143 	/* Run a child that will wake us up */
144 	child = create_sig_proc(100000, signo, UINT_MAX);
145 
146 	TEST(sigwaitinfo(&sigs, &si, NULL));
147 	REPORT_SUCCESS(-1, EINTR);
148 
149 	kill(child, SIGTERM);
150 }
151 
test_timeout(swi_func sigwaitinfo,int signo)152 void test_timeout(swi_func sigwaitinfo, int signo)
153 {
154 	sigset_t sigs;
155 	siginfo_t si;
156 	pid_t child;
157 	struct timespec ts = {.tv_sec = 1 };
158 
159 	SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
160 
161 	/* Run a child that will wake us up */
162 	child = create_sig_proc(100000, signo, UINT_MAX);
163 
164 	TEST(sigwaitinfo(&sigs, &si, &ts));
165 	REPORT_SUCCESS(-1, EAGAIN);
166 
167 	kill(child, SIGTERM);
168 }
169 
170 /* Note: sigwait-ing for a signal that is not blocked is unspecified
171  * by POSIX; but works for non-ignored signals under Linux
172  */
test_unmasked_matching(swi_func sigwaitinfo,int signo)173 void test_unmasked_matching(swi_func sigwaitinfo, int signo)
174 {
175 	sigset_t sigs;
176 	siginfo_t si;
177 	pid_t child;
178 
179 	SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
180 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo);
181 
182 	/* Run a child that will wake us up */
183 	child = create_sig_proc(100000, signo, UINT_MAX);
184 
185 	TEST(sigwaitinfo(&sigs, &si, NULL));
186 	REPORT_SUCCESS_COND(signo, 0, si.si_pid == child
187 			    && si.si_code == SI_USER
188 			    && si.si_signo == signo, "Struct siginfo mismatch");
189 
190 	kill(child, SIGTERM);
191 }
192 
test_unmasked_matching_noinfo(swi_func sigwaitinfo,int signo)193 void test_unmasked_matching_noinfo(swi_func sigwaitinfo, int signo)
194 {
195 	sigset_t sigs;
196 	pid_t child;
197 
198 	SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
199 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo);
200 	/* Run a child that will wake us up */
201 	child = create_sig_proc(100000, signo, UINT_MAX);
202 
203 	TEST(sigwaitinfo(&sigs, NULL, NULL));
204 	REPORT_SUCCESS(signo, 0);
205 
206 	kill(child, SIGTERM);
207 }
208 
test_masked_matching(swi_func sigwaitinfo,int signo)209 void test_masked_matching(swi_func sigwaitinfo, int signo)
210 {
211 	sigset_t sigs, oldmask;
212 	siginfo_t si;
213 	pid_t child;
214 
215 	SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
216 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo);
217 	/* let's not get interrupted by our dying child */
218 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, SIGCHLD);
219 
220 	SUCCEED_OR_DIE(sigprocmask, "sigprocmask failed", SIG_SETMASK, &sigs,
221 		       &oldmask);
222 
223 	/* don't wait on a SIGCHLD */
224 	SUCCEED_OR_DIE(sigdelset, "sigaddset failed", &sigs, SIGCHLD);
225 
226 	/* Run a child that will wake us up */
227 	child = create_sig_proc(0, signo, 1);
228 
229 	TEST(sigwaitinfo(&sigs, &si, NULL));
230 	REPORT_SUCCESS_COND(signo, 0, si.si_pid == child
231 			    && si.si_code == SI_USER
232 			    && si.si_signo == signo, "Struct siginfo mismatch");
233 
234 	SUCCEED_OR_DIE(sigprocmask, "restoring original signal mask failed",
235 		       SIG_SETMASK, &oldmask, &oldmask);
236 
237 	tst_count--;
238 
239 	if (sigismember(&oldmask, signo))
240 		tst_resm(TPASS, "sigwaitinfo restored the original mask");
241 	else
242 		tst_resm(TFAIL,
243 			 "sigwaitinfo failed to restore the original mask");
244 }
245 
test_masked_matching_rt(swi_func sigwaitinfo,int signo)246 void test_masked_matching_rt(swi_func sigwaitinfo, int signo)
247 {
248 	sigset_t sigs, oldmask;
249 	siginfo_t si;
250 	pid_t child[2];
251 	int status;
252 
253 	signo = SIGRTMIN + 1;
254 
255 	SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
256 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo);
257 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo + 1);
258 	/* let's not get interrupted by our dying child */
259 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, SIGCHLD);
260 
261 	SUCCEED_OR_DIE(sigprocmask, "sigprocmask failed", SIG_SETMASK, &sigs,
262 		       &oldmask);
263 
264 	/* don't wait on a SIGCHLD */
265 	SUCCEED_OR_DIE(sigdelset, "sigdelset failed", &sigs, SIGCHLD);
266 
267 	/* Run a child that will wake us up */
268 	child[0] = create_sig_proc(0, signo, 1);
269 	child[1] = create_sig_proc(0, signo + 1, 1);
270 
271 	/* Ensure that the signals have been sent */
272 	waitpid(child[0], &status, 0);
273 	waitpid(child[1], &status, 0);
274 
275 	TEST(sigwaitinfo(&sigs, &si, NULL));
276 	REPORT_SUCCESS_COND(signo, 0, si.si_pid == child[0]
277 			    && si.si_code == SI_USER
278 			    && si.si_signo == signo, "Struct siginfo mismatch");
279 
280 	/* eat the other signal */
281 	tst_count--;
282 	TEST(sigwaitinfo(&sigs, &si, NULL));
283 	REPORT_SUCCESS_COND(signo + 1, 0, si.si_pid == child[1]
284 			    && si.si_code == SI_USER
285 			    && si.si_signo == signo + 1,
286 			    "Struct siginfo mismatch");
287 
288 	SUCCEED_OR_DIE(sigprocmask, "restoring original signal mask failed",
289 		       SIG_SETMASK, &oldmask, &oldmask);
290 
291 	tst_count--;
292 
293 	if (sigismember(&oldmask, signo))
294 		tst_resm(TPASS, "sigwaitinfo restored the original mask");
295 	else
296 		tst_resm(TFAIL,
297 			 "sigwaitinfo failed to restore the original mask");
298 }
299 
test_masked_matching_noinfo(swi_func sigwaitinfo,int signo)300 void test_masked_matching_noinfo(swi_func sigwaitinfo, int signo)
301 {
302 	sigset_t sigs, oldmask;
303 	pid_t child;
304 
305 	SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
306 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo);
307 	/* let's not get interrupted by our dying child */
308 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, SIGCHLD);
309 
310 	SUCCEED_OR_DIE(sigprocmask, "sigprocmask failed", SIG_SETMASK, &sigs,
311 		       &oldmask);
312 
313 	/* don't wait on a SIGCHLD */
314 	SUCCEED_OR_DIE(sigdelset, "sigaddset failed", &sigs, SIGCHLD);
315 
316 	/* Run a child that will wake us up */
317 	child = create_sig_proc(0, signo, 1);
318 
319 	TEST(sigwaitinfo(&sigs, NULL, NULL));
320 	REPORT_SUCCESS(signo, 0);
321 
322 	SUCCEED_OR_DIE(sigprocmask, "restoring original signal mask failed",
323 		       SIG_SETMASK, &oldmask, &oldmask);
324 
325 	tst_count--;
326 
327 	if (sigismember(&oldmask, signo))
328 		tst_resm(TPASS, "sigwaitinfo restored the original mask");
329 	else
330 		tst_resm(TFAIL,
331 			 "sigwaitinfo failed to restore the original mask");
332 
333 }
334 
test_bad_address(swi_func sigwaitinfo,int signo)335 void test_bad_address(swi_func sigwaitinfo, int signo)
336 {
337 	sigset_t sigs, oldmask;
338 	pid_t child;
339 
340 	SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
341 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo);
342 	/* let's not get interrupted by our dying child */
343 	SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, SIGCHLD);
344 
345 	SUCCEED_OR_DIE(sigprocmask, "sigprocmask failed", SIG_SETMASK, &sigs,
346 		       &oldmask);
347 
348 	/* don't wait on a SIGCHLD */
349 	SUCCEED_OR_DIE(sigdelset, "sigaddset failed", &sigs, SIGCHLD);
350 
351 	/* Run a child that will wake us up */
352 	child = create_sig_proc(0, signo, 1);
353 
354 	TEST(sigwaitinfo(&sigs, (void *)1, NULL));
355 	REPORT_SUCCESS(-1, EFAULT);
356 
357 	SUCCEED_OR_DIE(sigprocmask, "sigprocmask failed", SIG_SETMASK, &oldmask,
358 		       &oldmask);
359 
360 	kill(child, SIGTERM);
361 }
362 
test_bad_address2(swi_func sigwaitinfo,int signo)363 void test_bad_address2(swi_func sigwaitinfo, int signo)
364 {
365 	pid_t pid;
366 	int status;
367 
368 	switch (pid = fork()) {
369 	case -1:
370 		tst_brkm(TBROK | TERRNO, NULL, "fork() failed");
371 	case 0:
372 		signal(SIGSEGV, SIG_DFL);
373 
374 		/*
375 		 * depending on glibc implementation we should
376 		 * either crash or get EFAULT
377 		 */
378 		TEST(sigwaitinfo((void *)1, NULL, NULL));
379 
380 		if (TEST_RETURN == -1 && TEST_ERRNO == EFAULT)
381 			_exit(0);
382 
383 		tst_resm(TINFO | TTERRNO, "swi_func returned: %ld",
384 			TEST_RETURN);
385 		_exit(1);
386 		break;
387 	default:
388 		break;
389 	}
390 
391 	SUCCEED_OR_DIE(waitpid, "waitpid failed", pid, &status, 0);
392 
393 	if ((WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV)
394 		|| (WIFEXITED(status) && WEXITSTATUS(status) == 0)) {
395 		tst_resm(TPASS, "Test passed");
396 		return;
397 	}
398 
399 	if (WIFEXITED(status)) {
400 		tst_resm(TFAIL, "Unrecognised child exit code: %d",
401 			WEXITSTATUS(status));
402 	}
403 	if (WIFSIGNALED(status)) {
404 		tst_resm(TFAIL, "Unrecognised child termsig: %d",
405 			WTERMSIG(status));
406 	}
407 }
408 
test_bad_address3(swi_func sigwaitinfo,int signo)409 void test_bad_address3(swi_func sigwaitinfo, int signo)
410 {
411 	sigset_t sigs;
412 	SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
413 
414 	TEST(sigwaitinfo(&sigs, NULL, (void *)1));
415 	REPORT_SUCCESS(-1, EFAULT);
416 }
417 
418 struct test_desc {
419 	test_func tf;
420 	swi_func swi;
421 	int signo;
422 } tests[] = {
423 #ifdef TEST_RT_SIGTIMEDWAIT
424 	{
425 	test_empty_set, my_rt_sigtimedwait, SIGUSR1}, {
426 	test_unmasked_matching, my_rt_sigtimedwait, SIGUSR1}, {
427 	test_masked_matching, my_rt_sigtimedwait, SIGUSR1}, {
428 	test_unmasked_matching_noinfo, my_rt_sigtimedwait, SIGUSR1}, {
429 	test_masked_matching_noinfo, my_rt_sigtimedwait, SIGUSR1}, {
430 	test_bad_address, my_rt_sigtimedwait, SIGUSR1}, {
431 	test_bad_address2, my_rt_sigtimedwait, SIGUSR1}, {
432 	test_bad_address3, my_rt_sigtimedwait, SIGUSR1}, {
433 	test_timeout, my_rt_sigtimedwait, 0},
434 	    /* Special cases */
435 	    /* 1: sigwaitinfo does respond to ignored signal */
436 	{
437 	test_masked_matching, my_rt_sigtimedwait, SIGUSR2},
438 	    /* 2: An ignored signal doesn't cause sigwaitinfo to return EINTR */
439 	{
440 	test_timeout, my_rt_sigtimedwait, SIGUSR2},
441 	    /* 3: The handler is not called when the signal is waited for by sigwaitinfo */
442 	{
443 	test_masked_matching, my_rt_sigtimedwait, SIGTERM},
444 	    /* 4: Simultaneous realtime signals are delivered in the order of increasing signal number */
445 #if !(defined(ANDROID) && !defined(__LP64__))
446 	{
447 	test_masked_matching_rt, my_rt_sigtimedwait, -1},
448 #endif
449 #endif
450 #if defined TEST_SIGWAIT
451 	{
452 	test_unmasked_matching_noinfo, my_sigwait, SIGUSR1}, {
453 	test_masked_matching_noinfo, my_sigwait, SIGUSR1},
454 #endif
455 #if defined TEST_SIGWAITINFO
456 	{
457 	test_empty_set, my_sigwaitinfo, SIGUSR1}, {
458 	test_unmasked_matching, my_sigwaitinfo, SIGUSR1}, {
459 	test_masked_matching, my_sigwaitinfo, SIGUSR1}, {
460 	test_unmasked_matching_noinfo, my_sigwaitinfo, SIGUSR1}, {
461 	test_masked_matching_noinfo, my_sigwaitinfo, SIGUSR1}, {
462 	test_bad_address, my_sigwaitinfo, SIGUSR1}, {
463 	test_bad_address2, my_sigwaitinfo, SIGUSR1},
464 #endif
465 #if defined TEST_SIGTIMEDWAIT
466 	{
467 	test_empty_set, my_sigtimedwait, SIGUSR1}, {
468 	test_unmasked_matching, my_sigtimedwait, SIGUSR1}, {
469 	test_masked_matching, my_sigtimedwait, SIGUSR1}, {
470 	test_unmasked_matching_noinfo, my_sigtimedwait, SIGUSR1}, {
471 	test_masked_matching_noinfo, my_sigtimedwait, SIGUSR1}, {
472 	test_bad_address, my_sigtimedwait, SIGUSR1}, {
473 	test_bad_address2, my_sigtimedwait, SIGUSR1}, {
474 	test_bad_address3, my_sigtimedwait, SIGUSR1}, {
475 	test_timeout, my_sigtimedwait, 0},
476 #endif
477 };
478 
479 #if defined TEST_SIGWAITINFO
480 const char *TCID = "sigwaitinfo01";
481 #elif defined TEST_RT_SIGTIMEDWAIT
482 const char *TCID = "rt_sigtimedwait01";
483 #elif defined TEST_SIGTIMEDWAIT
484 const char *TCID = "sigtimedwait01";
485 #elif defined TEST_SIGWAIT
486 const char *TCID = "sigwait01";
487 #endif
488 
489 int TST_TOTAL = ARRAY_SIZE(tests);
490 
main(int argc,char ** argv)491 int main(int argc, char **argv)
492 {
493 	unsigned i;
494 	int lc;
495 
496 	tst_parse_opts(argc, argv, NULL, NULL);
497 
498 	setup();
499 
500 	for (lc = 0; TEST_LOOPING(lc); ++lc) {
501 		tst_count = 0;
502 
503 		for (i = 0; i < ARRAY_SIZE(tests); i++) {
504 			alarm(10);	/* arrange a 10 second timeout */
505 			tst_resm(TINFO, "%p, %d", tests[i].swi, tests[i].signo);
506 			tests[i].tf(tests[i].swi, tests[i].signo);
507 		}
508 		alarm(0);
509 	}
510 
511 	cleanup();
512 	tst_exit();
513 }
514