summaryrefslogtreecommitdiff
path: root/src/regress/lib/libc/sys/t_msgctl.c
diff options
context:
space:
mode:
authorbluhm <>2019-11-19 19:57:04 +0000
committerbluhm <>2019-11-19 19:57:04 +0000
commit9185f840eda265016178aeb0dcdba964f8f6f3e2 (patch)
treeda100b3712514c566fe948116f7926ad7f725401 /src/regress/lib/libc/sys/t_msgctl.c
parent6a6fe688152b422f3d65c970dad56e7d9d28b1ee (diff)
downloadopenbsd-9185f840eda265016178aeb0dcdba964f8f6f3e2.tar.gz
openbsd-9185f840eda265016178aeb0dcdba964f8f6f3e2.tar.bz2
openbsd-9185f840eda265016178aeb0dcdba964f8f6f3e2.zip
Import NetBSD system call regression tests. They were written with
ATF (Automated Testing Framework), so we use a small wrapper to map it to our bsd.regress.mk framework. Only half of the 80 NetBSD tests have been taken, the others need more work to adapt. Of them 34 syscall tests pass. Moritz Buhl ported the tests to OpenBSD.
Diffstat (limited to 'src/regress/lib/libc/sys/t_msgctl.c')
-rw-r--r--src/regress/lib/libc/sys/t_msgctl.c405
1 files changed, 405 insertions, 0 deletions
diff --git a/src/regress/lib/libc/sys/t_msgctl.c b/src/regress/lib/libc/sys/t_msgctl.c
new file mode 100644
index 0000000000..980f11ee0b
--- /dev/null
+++ b/src/regress/lib/libc/sys/t_msgctl.c
@@ -0,0 +1,405 @@
1/* $OpenBSD: t_msgctl.c,v 1.1.1.1 2019/11/19 19:57:04 bluhm Exp $ */
2/* $NetBSD: t_msgctl.c,v 1.7 2017/10/07 17:15:44 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/cdefs.h>
36__RCSID("$NetBSD: t_msgctl.c,v 1.7 2017/10/07 17:15:44 kre Exp $");
37
38#include <sys/msg.h>
39#include <sys/stat.h>
40#include <sys/sysctl.h>
41#include <sys/wait.h>
42
43#include "atf-c.h"
44#include <errno.h>
45#include <limits.h>
46#include <pwd.h>
47#include <signal.h>
48#include <stdio.h>
49#include <stdlib.h>
50#include <string.h>
51#include <sysexits.h>
52#include <time.h>
53#include <unistd.h>
54
55#define MSG_KEY 12345689
56#define MSG_MTYPE_1 0x41
57
58struct msg {
59 long mtype;
60 char buf[3];
61};
62
63static void clean(void);
64
65static void
66clean(void)
67{
68 int id;
69
70 if ((id = msgget(MSG_KEY, 0)) != -1)
71 (void)msgctl(id, IPC_RMID, 0);
72}
73
74ATF_TC_WITH_CLEANUP(msgctl_err);
75ATF_TC_HEAD(msgctl_err, tc)
76{
77 atf_tc_set_md_var(tc, "descr", "Test errors from msgctl(2)");
78}
79
80ATF_TC_BODY(msgctl_err, tc)
81{
82 const int cmd[] = { IPC_STAT, IPC_SET, IPC_RMID };
83 struct msqid_ds msgds;
84 size_t i;
85 int id;
86
87 (void)memset(&msgds, 0, sizeof(struct msqid_ds));
88
89 id = msgget(MSG_KEY, IPC_CREAT | 0600);
90 ATF_REQUIRE(id != -1);
91
92 errno = 0;
93 ATF_REQUIRE_ERRNO(EINVAL, msgctl(id, INT_MAX, &msgds) == -1);
94
95 errno = 0;
96 ATF_REQUIRE_ERRNO(EFAULT, msgctl(id, IPC_STAT, (void *)-1) == -1);
97
98 for (i = 0; i < __arraycount(cmd); i++) {
99 errno = 0;
100 ATF_REQUIRE_ERRNO(EINVAL, msgctl(-1, cmd[i], &msgds) == -1);
101 }
102
103 ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
104}
105
106ATF_TC_CLEANUP(msgctl_err, tc)
107{
108 clean();
109}
110
111ATF_TC_WITH_CLEANUP(msgctl_perm);
112ATF_TC_HEAD(msgctl_perm, tc)
113{
114 atf_tc_set_md_var(tc, "descr", "Test permissions with msgctl(2)");
115 atf_tc_set_md_var(tc, "require.user", "root");
116}
117
118ATF_TC_BODY(msgctl_perm, tc)
119{
120 struct msqid_ds msgds;
121 struct passwd *pw;
122 pid_t pid;
123 int sta;
124 int id;
125
126 (void)memset(&msgds, 0, sizeof(struct msqid_ds));
127
128 pw = getpwnam("nobody");
129 id = msgget(MSG_KEY, IPC_CREAT | 0600);
130
131 ATF_REQUIRE(id != -1);
132 ATF_REQUIRE(pw != NULL);
133 ATF_REQUIRE(msgctl(id, IPC_STAT, &msgds) == 0);
134
135 pid = fork();
136 ATF_REQUIRE(pid >= 0);
137
138 if (pid == 0) {
139
140 if (setuid(pw->pw_uid) != 0)
141 _exit(EX_OSERR);
142
143 msgds.msg_perm.uid = getuid();
144 msgds.msg_perm.gid = getgid();
145
146 errno = 0;
147
148 if (msgctl(id, IPC_SET, &msgds) == 0)
149 _exit(EXIT_FAILURE);
150
151 if (errno != EPERM)
152 _exit(EXIT_FAILURE);
153
154 (void)memset(&msgds, 0, sizeof(struct msqid_ds));
155
156 if (msgctl(id, IPC_STAT, &msgds) != 0)
157 _exit(EX_OSERR);
158
159 msgds.msg_qbytes = 1;
160
161 if (msgctl(id, IPC_SET, &msgds) == 0)
162 _exit(EXIT_FAILURE);
163
164 if (errno != EPERM)
165 _exit(EXIT_FAILURE);
166
167 _exit(EXIT_SUCCESS);
168 }
169
170 (void)wait(&sta);
171
172 if (WIFEXITED(sta) == 0) {
173
174 if (WEXITSTATUS(sta) == EX_OSERR)
175 atf_tc_fail("system call failed");
176
177 if (WEXITSTATUS(sta) == EXIT_FAILURE)
178 atf_tc_fail("UID %u manipulated root's "
179 "message queue", pw->pw_uid);
180 }
181
182 ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
183}
184
185ATF_TC_CLEANUP(msgctl_perm, tc)
186{
187 clean();
188}
189
190ATF_TC_WITH_CLEANUP(msgctl_pid);
191ATF_TC_HEAD(msgctl_pid, tc)
192{
193 atf_tc_set_md_var(tc, "descr", "Test that PIDs are updated");
194}
195
196ATF_TC_BODY(msgctl_pid, tc)
197{
198 struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
199 struct msqid_ds msgds;
200 int id, sta;
201 pid_t pid;
202
203 id = msgget(MSG_KEY, IPC_CREAT | 0600);
204 ATF_REQUIRE(id != -1);
205
206 pid = fork();
207 ATF_REQUIRE(pid >= 0);
208
209 if (pid == 0) {
210
211 (void)msgsnd(id, &msg, sizeof(struct msg), IPC_NOWAIT);
212
213 _exit(EXIT_SUCCESS);
214 }
215
216 (void)sleep(1);
217 (void)wait(&sta);
218 (void)memset(&msgds, 0, sizeof(struct msqid_ds));
219
220 ATF_REQUIRE(msgctl(id, IPC_STAT, &msgds) == 0);
221
222 if (pid != msgds.msg_lspid)
223 atf_tc_fail("the PID of last msgsnd(2) was not updated");
224
225 pid = fork();
226 ATF_REQUIRE(pid >= 0);
227
228 if (pid == 0) {
229
230 (void)msgrcv(id, &msg,
231 sizeof(struct msg), MSG_MTYPE_1, IPC_NOWAIT);
232
233 _exit(EXIT_SUCCESS);
234 }
235
236 (void)sleep(1);
237 (void)wait(&sta);
238 (void)memset(&msgds, 0, sizeof(struct msqid_ds));
239
240 ATF_REQUIRE(msgctl(id, IPC_STAT, &msgds) == 0);
241
242 if (pid != msgds.msg_lrpid)
243 atf_tc_fail("the PID of last msgrcv(2) was not updated");
244
245 ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
246}
247
248ATF_TC_CLEANUP(msgctl_pid, tc)
249{
250 clean();
251}
252
253ATF_TC_WITH_CLEANUP(msgctl_set);
254ATF_TC_HEAD(msgctl_set, tc)
255{
256 atf_tc_set_md_var(tc, "descr", "Test msgctl(2) with IPC_SET");
257 atf_tc_set_md_var(tc, "require.user", "root");
258}
259
260ATF_TC_BODY(msgctl_set, tc)
261{
262 struct msqid_ds msgds;
263 struct passwd *pw;
264 int id;
265
266 (void)memset(&msgds, 0, sizeof(struct msqid_ds));
267
268 pw = getpwnam("nobody");
269 id = msgget(MSG_KEY, IPC_CREAT | 0600);
270
271 ATF_REQUIRE(id != -1);
272 ATF_REQUIRE(pw != NULL);
273 ATF_REQUIRE(msgctl(id, IPC_STAT, &msgds) == 0);
274
275 msgds.msg_perm.uid = pw->pw_uid;
276
277 if (msgctl(id, IPC_SET, &msgds) != 0)
278 atf_tc_fail("root failed to change the UID of message queue");
279
280 msgds.msg_perm.uid = getuid();
281 msgds.msg_perm.gid = pw->pw_gid;
282
283 if (msgctl(id, IPC_SET, &msgds) != 0)
284 atf_tc_fail("root failed to change the GID of message queue");
285
286 /*
287 * Note: setting the qbytes to zero fails even as root.
288 */
289 msgds.msg_qbytes = 1;
290 msgds.msg_perm.gid = getgid();
291
292 if (msgctl(id, IPC_SET, &msgds) != 0)
293 atf_tc_fail("root failed to change qbytes of message queue");
294
295 ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
296}
297
298ATF_TC_CLEANUP(msgctl_set, tc)
299{
300 clean();
301}
302
303ATF_TC_WITH_CLEANUP(msgctl_time);
304ATF_TC_HEAD(msgctl_time, tc)
305{
306 atf_tc_set_md_var(tc, "descr", "Test that access times are updated");
307}
308
309ATF_TC_BODY(msgctl_time, tc)
310{
311 struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
312 struct msqid_ds msgds;
313 time_t t;
314 int id;
315
316 id = msgget(MSG_KEY, IPC_CREAT | 0600);
317 ATF_REQUIRE(id != -1);
318
319 t = time(NULL);
320
321 (void)memset(&msgds, 0, sizeof(struct msqid_ds));
322 (void)msgsnd(id, &msg, sizeof(struct msg), IPC_NOWAIT);
323 (void)msgctl(id, IPC_STAT, &msgds);
324
325 if (llabs(t - msgds.msg_stime) > 1)
326 atf_tc_fail("time of last msgsnd(2) was not updated");
327
328 if (msgds.msg_rtime != 0)
329 atf_tc_fail("time of last msgrcv(2) was updated incorrectly");
330
331 t = time(NULL);
332
333 (void)memset(&msgds, 0, sizeof(struct msqid_ds));
334 (void)msgrcv(id, &msg, sizeof(struct msg), MSG_MTYPE_1, IPC_NOWAIT);
335 (void)msgctl(id, IPC_STAT, &msgds);
336
337 if (llabs(t - msgds.msg_rtime) > 1)
338 atf_tc_fail("time of last msgrcv(2) was not updated");
339
340 /*
341 * Note: this is non-zero even after the memset(3).
342 */
343 if (msgds.msg_stime == 0)
344 atf_tc_fail("time of last msgsnd(2) was updated incorrectly");
345
346 ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
347}
348
349ATF_TC_CLEANUP(msgctl_time, tc)
350{
351 clean();
352}
353
354static volatile int sig_caught;
355
356static void
357sigsys_handler(int signum)
358{
359
360 sig_caught = signum;
361}
362
363static int
364no_kernel_sysvmsg(void)
365{
366 int id;
367 void (*osig)(int);
368
369 sig_caught = 0;
370 osig = signal(SIGSYS, sigsys_handler);
371 id = msgget(MSG_KEY, IPC_CREAT | 0600);
372 if (sig_caught || id == -1)
373 return 1;
374
375 (void)msgctl(id, IPC_RMID, 0);
376 (void)signal(SIGSYS, osig);
377
378 return 0;
379}
380
381ATF_TC(msgctl_query);
382ATF_TC_HEAD(msgctl_query, tc)
383{
384 atf_tc_set_md_var(tc, "descr", "Skip msgctl_* tests - no SYSVMSG");
385}
386ATF_TC_BODY(msgctl_query, tc)
387{
388 atf_tc_skip("No SYSVMSG in kernel");
389}
390
391ATF_TP_ADD_TCS(tp)
392{
393
394 if (no_kernel_sysvmsg()) {
395 ATF_TP_ADD_TC(tp, msgctl_query);
396 } else {
397 ATF_TP_ADD_TC(tp, msgctl_err);
398 ATF_TP_ADD_TC(tp, msgctl_perm);
399 ATF_TP_ADD_TC(tp, msgctl_pid);
400 ATF_TP_ADD_TC(tp, msgctl_set);
401 ATF_TP_ADD_TC(tp, msgctl_time);
402 }
403
404 return atf_no_error();
405}