1 /*
2 * Check decoding of rt_sigsuspend syscall.
3 *
4 * Copyright (c) 2016 Dmitry V. Levin <ldv@strace.io>
5 * Copyright (c) 2016-2021 The strace developers.
6 * All rights reserved.
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11 #include "tests.h"
12 #include "scno.h"
13
14 #include <assert.h>
15 #include <errno.h>
16 #include <signal.h>
17 #include <stdio.h>
18 #include <stdint.h>
19 #include <string.h>
20 #include <unistd.h>
21
22 static long
23 k_sigsuspend(const sigset_t *const set, const unsigned long size)
24 {
25 return syscall(__NR_rt_sigsuspend, set, size);
26 }
27
28 static void
29 iterate(const char *const text, const int sig,
30 const void *const set, unsigned int size)
31 {
32 for (const void *mask = set;; size >>= 1, mask += size) {
33 raise(sig);
34 assert(k_sigsuspend(mask, size) == -1);
35 if (EINTR == errno) {
36 tprintf("rt_sigsuspend(%s, %u) = ? ERESTARTNOHAND"
37 " (To be restarted if no handler)\n",
38 text, size);
39 } else {
40 if (size < sizeof(long))
41 tprintf("rt_sigsuspend(%p, %u)"
42 " = -1 EINVAL (%m)\n",
43 mask, size);
44 else
45 tprintf("rt_sigsuspend(%s, %u)"
46 " = -1 EINVAL (%m)\n",
47 set == mask ? text : "~[]", size);
48 }
49 if (!size)
50 break;
51 }
52 }
53
54 static void
55 handler(int signo)
56 {
57 }
58
59 int
60 main(void)
61 {
62 tprintf("%s", "");
63
64 const unsigned int big_size = 1024 / 8;
65 void *k_set = tail_alloc(big_size);
66 memset(k_set, 0, big_size);
67
68 TAIL_ALLOC_OBJECT_CONST_PTR(sigset_t, libc_set);
69 sigemptyset(libc_set);
70 sigaddset(libc_set, SIGUSR1);
71 if (sigprocmask(SIG_SETMASK, libc_set, NULL))
72 perror_msg_and_fail("sigprocmask");
73
74 const struct sigaction sa = {
75 .sa_handler = handler
76 };
77 if (sigaction(SIGUSR1, &sa, NULL))
78 perror_msg_and_fail("sigaction");
79
80 raise(SIGUSR1);
81 unsigned int set_size = big_size;
82 for (; set_size; set_size >>= 1, k_set += set_size) {
83 assert(k_sigsuspend(k_set, set_size) == -1);
84 if (EINTR == errno)
85 break;
86 tprintf("rt_sigsuspend(%p, %u) = -1 EINVAL (%m)\n",
87 k_set, set_size);
88 }
89 if (!set_size)
90 perror_msg_and_fail("rt_sigsuspend");
91 tprintf("rt_sigsuspend([], %u) = ? ERESTARTNOHAND"
92 " (To be restarted if no handler)\n", set_size);
93
94 sigemptyset(libc_set);
95 sigaddset(libc_set, SIGUSR2);
96 memcpy(k_set, libc_set, set_size);
97 raise(SIGUSR1);
98 assert(k_sigsuspend(k_set, set_size) == -1);
99 assert(EINTR == errno);
100 tprintf("rt_sigsuspend([USR2], %u) = ? ERESTARTNOHAND"
101 " (To be restarted if no handler)\n", set_size);
102
103 sigaddset(libc_set, SIGHUP);
104 memcpy(k_set, libc_set, set_size);
105 raise(SIGUSR1);
106 assert(k_sigsuspend(k_set, set_size) == -1);
107 assert(EINTR == errno);
108 tprintf("rt_sigsuspend([HUP USR2], %u) = ? ERESTARTNOHAND"
109 " (To be restarted if no handler)\n", set_size);
110
111 sigaddset(libc_set, SIGINT);
112 memcpy(k_set, libc_set, set_size);
113 raise(SIGUSR1);
114 assert(k_sigsuspend(k_set, set_size) == -1);
115 assert(EINTR == errno);
116 tprintf("rt_sigsuspend([HUP INT USR2], %u) = ? ERESTARTNOHAND"
117 " (To be restarted if no handler)\n", set_size);
118
119 memset(libc_set, -1, sizeof(*libc_set));
120 sigdelset(libc_set, SIGUSR1);
121 memcpy(k_set, libc_set, set_size);
122 raise(SIGUSR1);
123 assert(k_sigsuspend(k_set, set_size) == -1);
124 assert(EINTR == errno);
125 tprintf("rt_sigsuspend(~[USR1], %u) = ? ERESTARTNOHAND"
126 " (To be restarted if no handler)\n", set_size);
127
128 assert(k_sigsuspend(k_set - set_size, set_size << 1) == -1);
129 tprintf("rt_sigsuspend(%p, %u) = -1 EINVAL (%m)\n",
130 k_set - set_size, set_size << 1);
131
132 iterate("~[USR1]", SIGUSR1, k_set, set_size >> 1);
133
134 tprintf("+++ exited with 0 +++\n");
135 return 0;
136 }