summaryrefslogtreecommitdiff
path: root/src/regress/lib/libc/sys/t_msgsnd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/regress/lib/libc/sys/t_msgsnd.c')
-rw-r--r--src/regress/lib/libc/sys/t_msgsnd.c381
1 files changed, 0 insertions, 381 deletions
diff --git a/src/regress/lib/libc/sys/t_msgsnd.c b/src/regress/lib/libc/sys/t_msgsnd.c
deleted file mode 100644
index 4ea2aa485e..0000000000
--- a/src/regress/lib/libc/sys/t_msgsnd.c
+++ /dev/null
@@ -1,381 +0,0 @@
1/* $OpenBSD: t_msgsnd.c,v 1.2 2021/12/13 16:56:48 deraadt Exp $ */
2/* $NetBSD: t_msgsnd.c,v 1.4 2017/10/08 08:31:05 kre Exp $ */
3
4/*-
5 * Copyright (c) 2011 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Jukka Ruohonen.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include "macros.h"
34
35#include <sys/msg.h>
36#include <sys/stat.h>
37#include <sys/sysctl.h>
38#include <sys/wait.h>
39
40#include "atf-c.h"
41#include <errno.h>
42#include <limits.h>
43#include <pwd.h>
44#include <signal.h>
45#include <stdio.h>
46#include <stdlib.h>
47#include <string.h>
48#include <sysexits.h>
49#include <time.h>
50#include <unistd.h>
51
52#define MSG_KEY 1234
53#define MSG_MTYPE_1 0x41
54#define MSG_MTYPE_2 0x42
55#define MSG_MTYPE_3 0x43
56
57struct msg {
58 long mtype;
59 char buf[3];
60};
61
62static void clean(void);
63
64static void
65clean(void)
66{
67 int id;
68
69 if ((id = msgget(MSG_KEY, 0)) != -1)
70 (void)msgctl(id, IPC_RMID, 0);
71}
72
73ATF_TC_WITH_CLEANUP(msgsnd_block);
74ATF_TC_HEAD(msgsnd_block, tc)
75{
76 atf_tc_set_md_var(tc, "descr", "Test that msgsnd(2) blocks");
77 atf_tc_set_md_var(tc, "timeout", "10");
78}
79
80ATF_TC_BODY(msgsnd_block, tc)
81{
82 struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
83 int id, sta;
84 pid_t pid;
85
86 id = msgget(MSG_KEY, IPC_CREAT | 0600);
87 ATF_REQUIRE(id != -1);
88
89 pid = fork();
90 ATF_REQUIRE(pid >= 0);
91
92 if (pid == 0) {
93
94 /*
95 * Enqueue messages until some limit (e.g. the maximum
96 * number of messages in the queue or the maximum number
97 * of bytes in the queue) is reached. After this the call
98 * should block when the IPC_NOWAIT is not set.
99 */
100 for (;;) {
101
102 if (msgsnd(id, &msg, sizeof(struct msg), 0) < 0)
103 _exit(EXIT_FAILURE);
104 }
105 }
106
107 (void)sleep(2);
108 (void)kill(pid, SIGKILL);
109 (void)wait(&sta);
110
111 if (WIFEXITED(sta) != 0 || WIFSIGNALED(sta) == 0)
112 atf_tc_fail("msgsnd(2) did not block");
113
114 ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
115}
116
117ATF_TC_CLEANUP(msgsnd_block, tc)
118{
119 clean();
120}
121
122ATF_TC_WITH_CLEANUP(msgsnd_count);
123ATF_TC_HEAD(msgsnd_count, tc)
124{
125 atf_tc_set_md_var(tc, "descr",
126 "Test that msgsnd(2) increments the amount of "
127 "message in the queue, as given by msgctl(2)");
128 atf_tc_set_md_var(tc, "timeout", "10");
129}
130
131ATF_TC_BODY(msgsnd_count, tc)
132{
133 struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
134 struct msqid_ds ds;
135 size_t i = 0;
136 int id, rv;
137
138 id = msgget(MSG_KEY, IPC_CREAT | 0600);
139 ATF_REQUIRE(id != -1);
140
141 for (;;) {
142
143 errno = 0;
144 rv = msgsnd(id, &msg, sizeof(struct msg), IPC_NOWAIT);
145
146 if (rv == 0) {
147 i++;
148 continue;
149 }
150
151 if (rv == -1 && errno == EAGAIN)
152 break;
153
154 atf_tc_fail("failed to enqueue a message");
155 }
156
157 (void)memset(&ds, 0, sizeof(struct msqid_ds));
158 (void)msgctl(id, IPC_STAT, &ds);
159
160 if (ds.msg_qnum != i)
161 atf_tc_fail("incorrect message count");
162
163 ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
164}
165
166ATF_TC_CLEANUP(msgsnd_count, tc)
167{
168 clean();
169}
170
171ATF_TC_WITH_CLEANUP(msgsnd_err);
172ATF_TC_HEAD(msgsnd_err, tc)
173{
174 atf_tc_set_md_var(tc, "descr", "Test errors from msgsnd(2)");
175}
176
177ATF_TC_BODY(msgsnd_err, tc)
178{
179 struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
180 int id;
181
182 id = msgget(MSG_KEY, IPC_CREAT | 0600);
183 ATF_REQUIRE(id != -1);
184
185 errno = 0;
186
187 ATF_REQUIRE_ERRNO(EFAULT, msgsnd(id, (void *)-1,
188 sizeof(struct msg), IPC_NOWAIT) == -1);
189
190 errno = 0;
191
192 ATF_REQUIRE_ERRNO(EINVAL, msgsnd(-1, &msg,
193 sizeof(struct msg), IPC_NOWAIT) == -1);
194
195 errno = 0;
196
197 ATF_REQUIRE_ERRNO(EINVAL, msgsnd(-1, &msg,
198 SSIZE_MAX, IPC_NOWAIT) == -1);
199
200 errno = 0;
201 msg.mtype = 0;
202
203 ATF_REQUIRE_ERRNO(EINVAL, msgsnd(id, &msg,
204 sizeof(struct msg), IPC_NOWAIT) == -1);
205
206 ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
207}
208
209ATF_TC_CLEANUP(msgsnd_err, tc)
210{
211 clean();
212}
213
214ATF_TC_WITH_CLEANUP(msgsnd_nonblock);
215ATF_TC_HEAD(msgsnd_nonblock, tc)
216{
217 atf_tc_set_md_var(tc, "descr", "Test msgsnd(2) with IPC_NOWAIT");
218 atf_tc_set_md_var(tc, "timeout", "10");
219}
220
221ATF_TC_BODY(msgsnd_nonblock, tc)
222{
223 struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
224 int id, rv, sta;
225 pid_t pid;
226
227 id = msgget(MSG_KEY, IPC_CREAT | 0600);
228 ATF_REQUIRE(id != -1);
229
230 pid = fork();
231 ATF_REQUIRE(pid >= 0);
232
233 if (pid == 0) {
234
235 for (;;) {
236
237 errno = 0;
238 rv = msgsnd(id, &msg, sizeof(struct msg), IPC_NOWAIT);
239
240 if (rv == -1 && errno == EAGAIN)
241 _exit(EXIT_SUCCESS);
242 }
243 }
244
245 (void)sleep(2);
246 (void)kill(pid, SIGKILL);
247 (void)wait(&sta);
248
249 if (WIFEXITED(sta) == 0 || WIFSIGNALED(sta) != 0)
250 atf_tc_fail("msgsnd(2) blocked with IPC_NOWAIT");
251
252 ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
253}
254
255ATF_TC_CLEANUP(msgsnd_nonblock, tc)
256{
257 clean();
258}
259
260ATF_TC_WITH_CLEANUP(msgsnd_perm);
261ATF_TC_HEAD(msgsnd_perm, tc)
262{
263 atf_tc_set_md_var(tc, "descr", "Test permissions with msgsnd(2)");
264 atf_tc_set_md_var(tc, "require.user", "root");
265}
266
267ATF_TC_BODY(msgsnd_perm, tc)
268{
269 struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
270 struct passwd *pw;
271 int id, sta;
272 pid_t pid;
273 uid_t uid;
274
275 pw = getpwnam("nobody");
276 id = msgget(MSG_KEY, IPC_CREAT | 0600);
277
278 ATF_REQUIRE(id != -1);
279 ATF_REQUIRE(pw != NULL);
280
281 uid = pw->pw_uid;
282 ATF_REQUIRE(uid != 0);
283
284 pid = fork();
285 ATF_REQUIRE(pid >= 0);
286
287 if (pid == 0) {
288
289 /*
290 * Try to enqueue a message to the queue
291 * created by root as RW for owner only.
292 */
293 if (setuid(uid) != 0)
294 _exit(EX_OSERR);
295
296 id = msgget(MSG_KEY, 0);
297
298 if (id == -1)
299 _exit(EX_OSERR);
300
301 errno = 0;
302
303 if (msgsnd(id, &msg, sizeof(struct msg), IPC_NOWAIT) == 0)
304 _exit(EXIT_FAILURE);
305
306 if (errno != EACCES)
307 _exit(EXIT_FAILURE);
308
309 _exit(EXIT_SUCCESS);
310 }
311
312 (void)wait(&sta);
313
314 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS) {
315
316 if (errno == EX_OSERR)
317 atf_tc_fail("system call failed");
318
319 atf_tc_fail("UID %u enqueued message to root's queue", uid);
320 }
321
322 ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
323}
324
325ATF_TC_CLEANUP(msgsnd_perm, tc)
326{
327 clean();
328}
329
330static volatile int sig_caught;
331
332static void
333sigsys_handler(int signum)
334{
335
336 sig_caught = signum;
337}
338
339static int
340no_kernel_sysvmsg(void)
341{
342 int id;
343 void (*osig)(int);
344
345 sig_caught = 0;
346 osig = signal(SIGSYS, sigsys_handler);
347 id = msgget(MSG_KEY, IPC_CREAT | 0600);
348 if (sig_caught || id == -1)
349 return 1;
350
351 (void)msgctl(id, IPC_RMID, 0);
352 (void)signal(SIGSYS, osig);
353
354 return 0;
355}
356
357ATF_TC(msgsnd_query);
358ATF_TC_HEAD(msgsnd_query, tc)
359{
360 atf_tc_set_md_var(tc, "descr", "Skip msgsnd_* tests - no SYSVMSG");
361}
362ATF_TC_BODY(msgsnd_query, tc)
363{
364 atf_tc_skip("No SYSVMSG in kernel");
365}
366
367ATF_TP_ADD_TCS(tp)
368{
369
370 if (no_kernel_sysvmsg()) {
371 ATF_TP_ADD_TC(tp, msgsnd_query);
372 } else {
373 ATF_TP_ADD_TC(tp, msgsnd_block);
374 ATF_TP_ADD_TC(tp, msgsnd_count);
375 ATF_TP_ADD_TC(tp, msgsnd_err);
376 ATF_TP_ADD_TC(tp, msgsnd_nonblock);
377 ATF_TP_ADD_TC(tp, msgsnd_perm);
378 }
379
380 return atf_no_error();
381}