• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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