Drop main() prototype. Syncs with NetBSD-8
[minix.git] / minix / tests / test88.c
blob865682769569c2517ecbbbc024702538ec9502ec
1 /* Tests for System V IPC semaphores - by D.C. van Moolenbroek */
2 /* This test must be run as root, as it includes permission checking tests. */
3 #include <stdlib.h>
4 #include <limits.h>
5 #include <pwd.h>
6 #include <grp.h>
7 #include <sys/ipc.h>
8 #include <sys/sem.h>
9 #include <sys/wait.h>
10 #include <sys/mman.h>
11 #include <sys/sysctl.h>
12 #include <signal.h>
14 #include "common.h"
16 #define ITERATIONS 3
18 #define WAIT_USECS 100000 /* time for processes to get ready */
20 #define KEY_A 0x73570001
21 #define KEY_B (KEY_A + 1)
22 #define KEY_C (KEY_A + 2)
24 #define ROOT_USER "root" /* name of root */
25 #define ROOT_GROUP "wheel" /* name of root's group */
26 #define NONROOT_USER "bin" /* name of any unprivileged user */
27 #define NONROOT_GROUP "bin" /* name of any unprivileged group */
29 enum {
30 DROP_NONE,
31 DROP_USER,
32 DROP_ALL,
35 enum {
36 SUGID_NONE,
37 SUGID_ROOT_USER,
38 SUGID_NONROOT_USER,
39 SUGID_ROOT_GROUP,
40 SUGID_NONROOT_GROUP,
43 struct link {
44 pid_t pid;
45 int sndfd;
46 int rcvfd;
50 * Test semaphore properties. This is a macro, so that it prints useful line
51 * information if an error occurs.
53 #define TEST_SEM(id, num, val, pid, ncnt, zcnt) do { \
54 if (semctl(id, num, GETVAL) != val) e(0); \
55 if (pid != -1 && semctl(id, num, GETPID) != pid) e(1); \
56 if (ncnt != -1 && semctl(id, num, GETNCNT) != ncnt) e(2); \
57 if (zcnt != -1 && semctl(id, num, GETZCNT) != zcnt) e(3); \
58 } while (0);
60 static int nr_signals = 0;
62 static size_t page_size;
63 static char *page_ptr;
64 static void *bad_ptr;
67 * Spawn a child process, with a pair of pipes to talk to it bidirectionally.
68 * Drop user and group privileges in the child process if requested.
70 static void
71 spawn(struct link * link, void (* proc)(struct link *), int drop)
73 struct passwd *pw;
74 struct group *gr;
75 int up[2], dn[2];
77 fflush(stdout);
78 fflush(stderr);
80 if (pipe(up) != 0) e(0);
81 if (pipe(dn) != 0) e(0);
83 link->pid = fork();
85 switch (link->pid) {
86 case 0:
87 close(up[1]);
88 close(dn[0]);
90 link->pid = getppid();
91 link->rcvfd = up[0];
92 link->sndfd = dn[1];
94 errct = 0;
96 switch (drop) {
97 case DROP_ALL:
98 if (setgroups(0, NULL) != 0) e(0);
100 if ((gr = getgrnam(NONROOT_GROUP)) == NULL) e(0);
102 if (setgid(gr->gr_gid) != 0) e(0);
103 if (setegid(gr->gr_gid) != 0) e(0);
105 /* FALLTHROUGH */
106 case DROP_USER:
107 if ((pw = getpwnam(NONROOT_USER)) == NULL) e(0);
109 if (setuid(pw->pw_uid) != 0) e(0);
112 proc(link);
114 /* Close our pipe FDs on exit, so that we can make zombies. */
115 exit(errct);
116 case -1:
117 e(0);
118 break;
121 close(up[0]);
122 close(dn[1]);
124 link->sndfd = up[1];
125 link->rcvfd = dn[0];
129 * Wait for a child process to terminate, and clean up.
131 static void
132 collect(struct link * link)
134 int status;
136 close(link->sndfd);
137 close(link->rcvfd);
139 if (waitpid(link->pid, &status, 0) != link->pid) e(0);
141 if (!WIFEXITED(status)) e(0);
142 else errct += WEXITSTATUS(status);
146 * Forcibly terminate a child process, and clean up.
148 static void
149 terminate(struct link * link)
151 int status;
153 if (kill(link->pid, SIGKILL) != 0) e(0);
155 close(link->sndfd);
156 close(link->rcvfd);
158 if (waitpid(link->pid, &status, 0) <= 0) e(0);
160 if (WIFSIGNALED(status)) {
161 if (WTERMSIG(status) != SIGKILL) e(0);
162 } else {
163 if (!WIFEXITED(status)) e(0);
164 else errct += WEXITSTATUS(status);
169 * Send an integer value to the child or parent.
171 static void
172 snd(struct link * link, int val)
175 if (write(link->sndfd, (void *)&val, sizeof(val)) != sizeof(val)) e(0);
179 * Receive an integer value from the child or parent, or -1 on EOF.
181 static int
182 rcv(struct link * link)
184 int r, val;
186 if ((r = read(link->rcvfd, (void *)&val, sizeof(val))) == 0)
187 return -1;
189 if (r != sizeof(val)) e(0);
191 return val;
195 * Child procedure that creates semaphore sets.
197 static void
198 test_perm_child(struct link * parent)
200 struct passwd *pw;
201 struct group *gr;
202 struct semid_ds semds;
203 uid_t uid;
204 gid_t gid;
205 int mask, rmask, sugid, id[3];
208 * Repeatedly create a number of semaphores with the masks provided by
209 * the parent process.
211 while ((mask = rcv(parent)) != -1) {
212 rmask = rcv(parent);
213 sugid = rcv(parent);
216 * Create the semaphores. For KEY_A, if we are going to set
217 * the mode through IPC_SET anyway, start with a zero mask to
218 * check that the replaced mode is used (thus testing IPC_SET).
220 if ((id[0] = semget(KEY_A, 3,
221 IPC_CREAT | IPC_EXCL |
222 ((sugid == SUGID_NONE) ? mask : 0))) == -1) e(0);
223 if ((id[1] = semget(KEY_B, 3,
224 IPC_CREAT | IPC_EXCL | mask | rmask)) == -1) e(0);
225 if ((id[2] = semget(KEY_C, 3,
226 IPC_CREAT | IPC_EXCL | rmask)) == -1) e(0);
228 uid = geteuid();
229 gid = getegid();
230 if (sugid != SUGID_NONE) {
231 switch (sugid) {
232 case SUGID_ROOT_USER:
233 if ((pw = getpwnam(ROOT_USER)) == NULL) e(0);
234 uid = pw->pw_uid;
235 break;
236 case SUGID_NONROOT_USER:
237 if ((pw = getpwnam(NONROOT_USER)) == NULL)
238 e(0);
239 uid = pw->pw_uid;
240 break;
241 case SUGID_ROOT_GROUP:
242 if ((gr = getgrnam(ROOT_GROUP)) == NULL) e(0);
243 gid = gr->gr_gid;
244 break;
245 case SUGID_NONROOT_GROUP:
246 if ((gr = getgrnam(NONROOT_GROUP)) == NULL)
247 e(0);
248 gid = gr->gr_gid;
249 break;
252 semds.sem_perm.uid = uid;
253 semds.sem_perm.gid = gid;
254 semds.sem_perm.mode = mask;
255 if (semctl(id[0], 0, IPC_SET, &semds) != 0) e(0);
256 semds.sem_perm.mode = mask | rmask;
257 if (semctl(id[1], 0, IPC_SET, &semds) != 0) e(0);
258 semds.sem_perm.mode = rmask;
259 if (semctl(id[2], 0, IPC_SET, &semds) != 0) e(0);
262 /* Do a quick test to confirm the right privileges. */
263 if (mask & IPC_R) {
264 if (semctl(id[0], 0, IPC_STAT, &semds) != 0) e(0);
265 if (semds.sem_perm.mode != (SEM_ALLOC | mask)) e(0);
266 if (semds.sem_perm.uid != uid) e(0);
267 if (semds.sem_perm.gid != gid) e(0);
268 if (semds.sem_perm.cuid != geteuid()) e(0);
269 if (semds.sem_perm.cgid != getegid()) e(0);
272 snd(parent, id[0]);
273 snd(parent, id[1]);
274 snd(parent, id[2]);
276 /* The other child process runs here. */
278 if (rcv(parent) != 0) e(0);
281 * For owner tests, the other child may already have removed
282 * the semaphore sets, so ignore return values here.
284 (void)semctl(id[0], 0, IPC_RMID);
285 (void)semctl(id[1], 0, IPC_RMID);
286 (void)semctl(id[2], 0, IPC_RMID);
291 * Perform a permission test. The given procedure will be called for various
292 * access masks, which it can use to determine whether operations on three
293 * created semaphore sets should succeed or fail. The first two semaphore sets
294 * are created with appropriate privileges, the third one is not. If the
295 * 'owner_test' variable is set, the test will change slightly so as to allow
296 * testing of operations that require a matching uid/cuid.
298 static void
299 test_perm(void (* proc)(struct link *), int owner_test)
301 struct link child1, child2;
302 int n, shift, bit, mask, rmask, drop1, drop2, sugid, id[3];
304 for (n = 0; n < 7; n++) {
306 * Child 1 creates the semaphores, and child 2 opens them.
307 * For shift 6 (0700), child 1 drops its privileges to match
308 * child 2's (n=0). For shift 3 (0070), child 2 drops its user
309 * privileges (n=3). For shift 0 (0007), child 2 drops its
310 * group in addition to its user privileges (n=6). Also try
311 * with differing uid/cuid (n=1,2) and gid/cgid (n=4,5), where
312 * the current ownership (n=1,4) or the creator's ownership
313 * (n=2,5) is tested.
315 switch (n) {
316 case 0:
317 shift = 6;
318 drop1 = DROP_ALL;
319 drop2 = DROP_ALL;
320 sugid = SUGID_NONE;
321 break;
322 case 1:
323 shift = 6;
324 drop1 = DROP_NONE;
325 drop2 = DROP_ALL;
326 sugid = SUGID_NONROOT_USER;
327 break;
328 case 2:
329 shift = 6;
330 drop1 = DROP_USER;
331 drop2 = DROP_ALL;
332 sugid = SUGID_ROOT_USER;
333 break;
334 case 3:
335 shift = 3;
336 drop1 = DROP_NONE;
337 drop2 = DROP_USER;
338 sugid = SUGID_NONE;
339 break;
340 case 4:
341 shift = 3;
342 drop1 = DROP_NONE;
343 drop2 = DROP_ALL;
344 sugid = SUGID_NONROOT_GROUP;
345 break;
346 case 5:
347 /* The root group has no special privileges. */
348 shift = 3;
349 drop1 = DROP_NONE;
350 drop2 = DROP_USER;
351 sugid = SUGID_NONROOT_GROUP;
352 break;
353 case 6:
354 shift = 0;
355 drop1 = DROP_NONE;
356 drop2 = DROP_ALL;
357 sugid = SUGID_NONE;
358 break;
361 spawn(&child1, test_perm_child, drop1);
362 spawn(&child2, proc, drop2);
364 for (bit = 0; bit <= 7; bit++) {
365 mask = bit << shift;
366 rmask = 0777 & ~(7 << shift);
368 snd(&child1, mask);
369 snd(&child1, rmask);
370 snd(&child1, sugid);
371 id[0] = rcv(&child1);
372 id[1] = rcv(&child1);
373 id[2] = rcv(&child1);
375 snd(&child2, (owner_test) ? shift : bit);
376 snd(&child2, id[0]);
377 snd(&child2, id[1]);
378 snd(&child2, id[2]);
379 if (rcv(&child2) != 0) e(0);
381 snd(&child1, 0);
384 /* We use a bitmask of -1 to terminate the children. */
385 snd(&child1, -1);
386 snd(&child2, -1);
388 collect(&child1);
389 collect(&child2);
394 * Test semget(2) permission checks. Please note that the checks are advisory:
395 * nothing keeps a process from opening a semaphore set with fewer privileges
396 * than required by the operations the process subsequently issues on the set.
398 static void
399 test88a_perm(struct link * parent)
401 int r, tbit, bit, mask, id[3];
403 while ((tbit = rcv(parent)) != -1) {
404 id[0] = rcv(parent);
405 id[1] = rcv(parent);
406 id[2] = rcv(parent);
409 * We skip setting lower bits, as it is not clear what effect
410 * that should have. We assume that zero bits should result in
411 * failure.
413 for (bit = 0; bit <= 7; bit++) {
414 mask = bit << 6;
417 * Opening semaphore set A must succeed iff the given
418 * bits are all set in the relevant three-bit section
419 * of the creation mask.
421 r = semget(KEY_A, 0, mask);
422 if (r < 0 && (r != -1 || errno != EACCES)) e(0);
423 if ((bit != 0 && (bit & tbit) == bit) != (r != -1))
424 e(0);
425 if (r != -1 && r != id[0]) e(0);
428 * Same for semaphore set B, which was created with all
429 * irrelevant mode bits inverted.
431 r = semget(KEY_B, 0, mask);
432 if (r < 0 && (r != -1 || errno != EACCES)) e(0);
433 if ((bit != 0 && (bit & tbit) == bit) != (r != -1))
434 e(0);
435 if (r != -1 && r != id[1]) e(0);
438 * Semaphore set C was created with only irrelevant
439 * mode bits set, so opening it must always fail.
441 if (semget(KEY_C, 0, mask) != -1) e(0);
442 if (errno != EACCES) e(0);
445 snd(parent, 0);
450 * Test the basic semget(2) functionality.
452 static void
453 test88a(void)
455 struct seminfo seminfo;
456 struct semid_ds semds;
457 time_t now;
458 unsigned int i, j;
459 int id[3], *idp;
461 subtest = 0;
464 * The key IPC_PRIVATE must always yield a new semaphore set identifier
465 * regardless of whether IPC_CREAT and IPC_EXCL are supplied.
467 if ((id[0] = semget(IPC_PRIVATE, 1, IPC_CREAT | 0600)) < 0) e(0);
469 if ((id[1] = semget(IPC_PRIVATE, 1, IPC_CREAT | IPC_EXCL | 0600)) < 0)
470 e(0);
472 if ((id[2] = semget(IPC_PRIVATE, 1, 0600)) < 0) e(0);
474 if (id[0] == id[1]) e(0);
475 if (id[1] == id[2]) e(0);
476 if (id[0] == id[2]) e(0);
478 if (semctl(id[0], 0, IPC_RMID) != 0) e(0);
479 if (semctl(id[1], 0, IPC_RMID) != 0) e(0);
480 if (semctl(id[2], 0, IPC_RMID) != 0) e(0);
482 /* Remove any leftovers from previous test runs. */
483 if ((id[0] = semget(KEY_A, 0, 0600)) >= 0 &&
484 semctl(id[0], 0, IPC_RMID) == -1) e(0);
485 if ((id[0] = semget(KEY_B, 0, 0600)) >= 0 &&
486 semctl(id[0], 0, IPC_RMID) == -1) e(0);
489 * For non-IPC_PRIVATE keys, open(2)-like semantics apply with respect
490 * to IPC_CREAT and IPC_EXCL flags. The behavior of supplying IPC_EXCL
491 * without IPC_CREAT is undefined, so we do not test for that here.
493 if (semget(KEY_A, 1, 0600) != -1) e(0);
494 if (errno != ENOENT);
496 if ((id[0] = semget(KEY_A, 1, IPC_CREAT | IPC_EXCL | 0600)) < 0) e(0);
498 if (semget(KEY_B, 1, 0600) != -1) e(0);
499 if (errno != ENOENT);
501 if ((id[1] = semget(KEY_B, 1, IPC_CREAT | 0600)) < 0) e(0);
503 if (id[0] == id[1]) e(0);
505 if ((id[2] = semget(KEY_A, 1, 0600)) < 0) e(0);
506 if (id[2] != id[0]) e(0);
508 if ((id[2] = semget(KEY_B, 1, IPC_CREAT | 0600)) < 0) e(0);
509 if (id[2] != id[2]) e(0);
511 if (semget(KEY_A, 1, IPC_CREAT | IPC_EXCL | 0600) != -1) e(0);
512 if (errno != EEXIST) e(0);
514 if (semctl(id[0], 0, IPC_RMID) != 0) e(0);
515 if (semctl(id[1], 0, IPC_RMID) != 0) e(0);
518 * Check that we get the right error when we run out of semaphore sets.
519 * It is possible that other processes in the system are using sets
520 * right now, so see if we can anywhere from three (the number we had
521 * already) to SEMMNI semaphore sets, and check for ENOSPC after that.
523 if (semctl(0, 0, IPC_INFO, &seminfo) == -1) e(0);
524 if (seminfo.semmni < 3 || seminfo.semmni > USHRT_MAX) e(0);
526 if ((idp = malloc(sizeof(int) * (seminfo.semmni + 1))) == NULL) e(0);
528 for (i = 0; i < seminfo.semmni + 1; i++) {
529 if ((idp[i] = semget(KEY_A + i, 1, IPC_CREAT | 0600)) < 0)
530 break;
532 /* Ensure that there are no ID collisions. O(n**2). */
533 for (j = 0; j < i; j++)
534 if (idp[i] == idp[j]) e(0);
537 if (errno != ENOSPC) e(0);
538 if (i < 3) e(0);
539 if (i == seminfo.semmni + 1) e(0);
541 while (i-- > 0)
542 if (semctl(idp[i], 0, IPC_RMID) != 0) e(0);
544 free(idp);
547 * The given number of semaphores must be within bounds.
549 if (semget(KEY_A, -1, IPC_CREAT | 0600) != -1) e(0);
550 if (errno != EINVAL) e(0);
552 if (semget(KEY_A, 0, IPC_CREAT | 0600) != -1) e(0);
553 if (errno != EINVAL) e(0);
555 if (seminfo.semmsl < 3 || seminfo.semmsl > USHRT_MAX) e(0);
556 if (semget(KEY_A, seminfo.semmsl + 1, IPC_CREAT | 0600) != -1) e(0);
557 if (errno != EINVAL) e(0);
559 if ((id[0] = semget(KEY_A, seminfo.semmsl, IPC_CREAT | 0600)) < 0)
560 e(0);
561 if (semctl(id[0], 0, IPC_RMID) != 0) e(0);
563 if ((id[0] = semget(KEY_A, 2, IPC_CREAT | 0600)) < 0) e(0);
565 if ((id[1] = semget(KEY_A, 0, 0600)) < 0) e(0);
566 if (id[0] != id[1]) e(0);
568 if ((id[1] = semget(KEY_A, 1, 0600)) < 0) e(0);
569 if (id[0] != id[1]) e(0);
571 if ((id[1] = semget(KEY_A, 2, 0600)) < 0) e(0);
572 if (id[0] != id[1]) e(0);
574 if ((id[1] = semget(KEY_A, 3, 0600)) != -1) e(0);
575 if (errno != EINVAL) e(0);
577 if ((id[1] = semget(KEY_A, seminfo.semmsl + 1, 0600)) != -1) e(0);
578 if (errno != EINVAL) e(0);
580 if (semctl(id[0], 0, IPC_RMID) != 0) e(0);
583 * Verify that the initial values for the semaphore set are as
584 * expected.
586 time(&now);
587 if (seminfo.semmns < 3 + seminfo.semmsl) e(0);
588 if ((id[0] = semget(IPC_PRIVATE, 3, IPC_CREAT | IPC_EXCL | 0642)) < 0)
589 e(0);
590 if ((id[1] = semget(KEY_A, seminfo.semmsl, IPC_CREAT | 0613)) < 0)
591 e(0);
593 if (semctl(id[0], 0, IPC_STAT, &semds) != 0) e(0);
594 if (semds.sem_perm.uid != geteuid()) e(0);
595 if (semds.sem_perm.gid != getegid()) e(0);
596 if (semds.sem_perm.cuid != geteuid()) e(0);
597 if (semds.sem_perm.cgid != getegid()) e(0);
598 if (semds.sem_perm.mode != (SEM_ALLOC | 0642)) e(0);
599 if (semds.sem_perm._key != IPC_PRIVATE) e(0);
600 if (semds.sem_nsems != 3) e(0);
601 if (semds.sem_otime != 0) e(0);
602 if (semds.sem_ctime < now || semds.sem_ctime >= now + 10) e(0);
604 for (i = 0; i < semds.sem_nsems; i++)
605 TEST_SEM(id[0], i, 0, 0, 0, 0);
607 if (semctl(id[1], 0, IPC_STAT, &semds) != 0) e(0);
608 if (semds.sem_perm.uid != geteuid()) e(0);
609 if (semds.sem_perm.gid != getegid()) e(0);
610 if (semds.sem_perm.cuid != geteuid()) e(0);
611 if (semds.sem_perm.cgid != getegid()) e(0);
612 if (semds.sem_perm.mode != (SEM_ALLOC | 0613)) e(0);
613 if (semds.sem_perm._key != KEY_A) e(0);
614 if (semds.sem_nsems != seminfo.semmsl) e(0);
615 if (semds.sem_otime != 0) e(0);
616 if (semds.sem_ctime < now || semds.sem_ctime >= now + 10) e(0);
618 for (i = 0; i < semds.sem_nsems; i++)
619 TEST_SEM(id[1], i, 0, 0, 0, 0);
621 if (semctl(id[1], 0, IPC_RMID) != 0) e(0);
622 if (semctl(id[0], 0, IPC_RMID) != 0) e(0);
625 * Finally, perform a number of permission-related checks. Since the
626 * main test program is running with superuser privileges, most of the
627 * permission tests use an unprivileged child process.
629 /* The superuser can always open and destroy a semaphore set. */
630 if ((id[0] = semget(KEY_A, 1, IPC_CREAT | IPC_EXCL | 0000)) < 0) e(0);
632 if ((id[1] = semget(KEY_A, 0, 0600)) < 0) e(0);
633 if (id[0] != id[1]) e(0);
635 if ((id[1] = semget(KEY_A, 0, 0000)) < 0) e(0);
636 if (id[0] != id[1]) e(0);
638 if (semctl(id[0], 0, IPC_RMID) != 0) e(0);
641 * When an unprivileged process tries to open a semaphore set, the
642 * given upper three permission bits from the mode (0700) are tested
643 * against the appropriate permission bits from the semaphore set.
645 test_perm(test88a_perm, 0 /*owner_test*/);
649 * Test semop(2) permission checks.
651 static void
652 test88b_perm(struct link * parent)
654 struct sembuf sops[2];
655 size_t nsops;
656 int i, r, tbit, bit, id[3];
658 while ((tbit = rcv(parent)) != -1) {
659 id[0] = rcv(parent);
660 id[1] = rcv(parent);
661 id[2] = rcv(parent);
664 * This loop is designed such that failure of any bit-based
665 * subset will not result in subsequent operations blocking.
667 for (i = 0; i < 8; i++) {
668 memset(sops, 0, sizeof(sops));
670 switch (i) {
671 case 0:
672 nsops = 1;
673 bit = 4;
674 break;
675 case 1:
676 sops[0].sem_op = 1;
677 nsops = 1;
678 bit = 2;
679 break;
680 case 2:
681 sops[0].sem_op = -1;
682 nsops = 1;
683 bit = 2;
684 break;
685 case 3:
686 sops[1].sem_op = 1;
687 nsops = 2;
688 bit = 6;
689 break;
690 case 4:
691 sops[0].sem_num = 1;
692 sops[1].sem_op = -1;
693 nsops = 2;
694 bit = 6;
695 break;
696 case 5:
697 sops[1].sem_num = 1;
698 nsops = 2;
699 bit = 4;
700 break;
701 case 6:
703 * Two operations on the same semaphore. As
704 * such, this verifies that operations are
705 * processed in array order.
707 sops[0].sem_op = 1;
708 sops[1].sem_op = -1;
709 nsops = 2;
710 bit = 2;
711 break;
712 case 7:
714 * Test the order of checks. Since IPC_STAT
715 * requires read permission, it is reasonable
716 * that the check against sem_nsems be done
717 * only after the permission check as well.
718 * For this test we rewrite EFBIG to OK below.
720 sops[0].sem_num = USHRT_MAX;
721 nsops = 2;
722 bit = 4;
723 break;
726 r = semop(id[0], sops, nsops);
727 if (i == 7 && r == -1 && errno == EFBIG) r = 0;
728 if (r < 0 && (r != -1 || errno != EACCES)) e(0);
729 if (((bit & tbit) == bit) != (r != -1)) e(0);
731 r = semop(id[1], sops, nsops);
732 if (i == 7 && r == -1 && errno == EFBIG) r = 0;
733 if (r < 0 && (r != -1 || errno != EACCES)) e(0);
734 if (((bit & tbit) == bit) != (r != -1)) e(0);
736 if (semop(id[2], sops, nsops) != -1) e(0);
737 if (errno != EACCES) e(0);
740 snd(parent, 0);
745 * Signal handler.
747 static void
748 got_signal(int sig)
751 if (sig != SIGHUP) e(0);
752 if (nr_signals != 0) e(0);
753 nr_signals++;
757 * Child process for semop(2) tests, mainly testing blocking operations.
759 static void
760 test88b_child(struct link * parent)
762 struct sembuf sops[5];
763 struct sigaction act;
764 int id;
766 id = rcv(parent);
768 memset(sops, 0, sizeof(sops));
769 if (semop(id, sops, 1) != 0) e(0);
771 if (rcv(parent) != 1) e(0);
773 sops[0].sem_op = -3;
774 if (semop(id, sops, 1) != 0) e(0);
776 if (rcv(parent) != 2) e(0);
778 sops[0].sem_num = 2;
779 sops[0].sem_op = 2;
780 sops[1].sem_num = 1;
781 sops[1].sem_op = -1;
782 sops[2].sem_num = 0;
783 sops[2].sem_op = 1;
784 if (semop(id, sops, 3) != 0) e(0);
786 if (rcv(parent) != 3) e(0);
788 sops[0].sem_num = 1;
789 sops[0].sem_op = 0;
790 sops[1].sem_num = 1;
791 sops[1].sem_op = 1;
792 sops[2].sem_num = 0;
793 sops[2].sem_op = 0;
794 sops[3].sem_num = 2;
795 sops[3].sem_op = 0;
796 sops[4].sem_num = 2;
797 sops[4].sem_op = 1;
798 if (semop(id, sops, 5) != 0) e(0);
800 if (rcv(parent) != 4) e(0);
802 sops[0].sem_num = 1;
803 sops[0].sem_op = -2;
804 sops[1].sem_num = 2;
805 sops[1].sem_op = 0;
806 if (semop(id, sops, 2) != 0) e(0);
808 if (rcv(parent) != 5) e(0);
810 sops[0].sem_num = 0;
811 sops[0].sem_op = -1;
812 sops[1].sem_num = 1;
813 sops[1].sem_op = -1;
814 sops[1].sem_flg = IPC_NOWAIT;
815 if (semop(id, sops, 2) != 0) e(0);
817 if (rcv(parent) != 6) e(0);
819 sops[0].sem_num = 1;
820 sops[0].sem_op = 0;
821 sops[1].sem_num = 0;
822 sops[1].sem_op = 0;
823 sops[1].sem_flg = IPC_NOWAIT;
824 if (semop(id, sops, 2) != -1) e(0);
825 if (errno != EAGAIN) e(0);
827 if (rcv(parent) != 7) e(0);
829 sops[0].sem_num = 0;
830 sops[0].sem_op = 0;
831 sops[1].sem_num = 1;
832 sops[1].sem_op = 1;
833 sops[1].sem_flg = 0;
834 if (semop(id, sops, 2) != 0) e(0);
836 if (rcv(parent) != 8) e(0);
838 sops[0].sem_num = 0;
839 sops[0].sem_op = -1;
840 sops[1].sem_num = 1;
841 sops[1].sem_op = 2;
842 if (semop(id, sops, 2) != -1) e(0);
843 if (errno != ERANGE) e(0);
845 memset(&act, 0, sizeof(act));
846 act.sa_handler = got_signal;
847 sigfillset(&act.sa_mask);
848 if (sigaction(SIGHUP, &act, NULL) != 0) e(0);
850 if (rcv(parent) != 9) e(0);
852 memset(sops, 0, sizeof(sops));
853 sops[0].sem_num = 0;
854 sops[0].sem_op = 0;
855 sops[1].sem_num = 0;
856 sops[1].sem_op = 1;
857 sops[2].sem_num = 1;
858 sops[2].sem_op = 0;
859 if (semop(id, sops, 3) != -1)
860 if (errno != EINTR) e(0);
861 if (nr_signals != 1) e(0);
863 TEST_SEM(id, 0, 0, parent->pid, 0, 0);
864 TEST_SEM(id, 1, 1, parent->pid, 0, 0);
866 if (rcv(parent) != 10) e(0);
868 memset(sops, 0, sizeof(sops));
869 sops[0].sem_op = -3;
870 if (semop(id, sops, 1) != -1) e(0);
871 if (errno != EIDRM) e(0);
873 id = rcv(parent);
875 sops[0].sem_num = 0;
876 sops[0].sem_op = -1;
877 sops[1].sem_num = 1;
878 sops[1].sem_op = 1;
879 if (semop(id, sops, 2) != -1) e(0);
880 if (errno != ERANGE) e(0);
882 if (rcv(parent) != 11) e(0);
884 sops[0].sem_num = 1;
885 sops[0].sem_op = 0;
886 sops[1].sem_num = 0;
887 sops[1].sem_op = -1;
888 if (semop(id, sops, 2) != 0) e(0);
890 id = rcv(parent);
892 sops[0].sem_num = 0;
893 sops[0].sem_op = -1;
894 sops[1].sem_num = 1;
895 sops[1].sem_op = 0;
896 if (semop(id, sops, 2) != 0) e(0);
898 snd(parent, errct);
899 if (rcv(parent) != 12) e(0);
901 /* The child will be killed during this call. It should not return. */
902 sops[0].sem_num = 1;
903 sops[0].sem_op = -1;
904 sops[1].sem_num = 0;
905 sops[1].sem_op = 3;
906 (void)semop(id, sops, 2);
908 e(0);
912 * Test the basic semop(2) functionality.
914 static void
915 test88b(void)
917 struct seminfo seminfo;
918 struct semid_ds semds;
919 struct sembuf *sops, *sops2;
920 size_t size;
921 struct link child;
922 time_t now;
923 unsigned short val[2];
924 int id;
926 subtest = 1;
928 /* Allocate a buffer for operations. */
929 if (semctl(0, 0, IPC_INFO, &seminfo) == -1) e(0);
931 if (seminfo.semopm < 3 || seminfo.semopm > USHRT_MAX) e(0);
933 size = sizeof(sops[0]) * (seminfo.semopm + 1);
934 if ((sops = malloc(size)) == NULL) e(0);
935 memset(sops, 0, size);
937 /* Do a few first tests with a set containing one semaphore. */
938 if ((id = semget(IPC_PRIVATE, 1, IPC_CREAT | 0600)) == -1) e(0);
940 /* If no operations are given, the call should succeed. */
941 if (semop(id, NULL, 0) != 0) e(0);
944 * If any operations are given, the pointer must be valid. Moreover,
945 * partially valid buffers must never be processed partially.
947 if (semop(id, NULL, 1) != -1) e(0);
948 if (errno != EFAULT) e(0);
950 if (semop(id, bad_ptr, 1) != -1) e(0);
951 if (errno != EFAULT) e(0);
953 memset(page_ptr, 0, page_size);
954 sops2 = ((struct sembuf *)bad_ptr) - 1;
955 sops2->sem_op = 1;
956 if (semop(id, sops2, 2) != -1) e(0);
957 if (errno != EFAULT) e(0);
959 TEST_SEM(id, 0, 0, 0, 0, 0);
960 if (semctl(id, 0, IPC_STAT, &semds) != 0) e(0);
961 if (semds.sem_otime != 0) e(0);
964 * A new semaphore set is initialized to an all-zeroes state, and a
965 * zeroed operation tests for a zeroed semaphore. This should pass.
967 time(&now);
968 if (semop(id, sops, 1) != 0) e(0);
970 TEST_SEM(id, 0, 0, getpid(), 0, 0);
971 if (semctl(id, 0, IPC_STAT, &semds) != 0) e(0);
972 if (semds.sem_otime < now || semds.sem_otime >= now + 10) e(0);
974 /* Test the limit on the number of operations. */
975 if (semop(id, sops, seminfo.semopm) != 0) e(0);
977 if (semop(id, sops, seminfo.semopm + 1) != -1) e(0);
978 if (errno != E2BIG) e(0);
980 if (semop(id, sops, SIZE_MAX) != -1) e(0);
981 if (errno != E2BIG) e(0);
983 /* Test the range check on the semaphore numbers. */
984 sops[1].sem_num = 1;
985 if (semop(id, sops, 2) != -1) e(0);
986 if (errno != EFBIG) e(0);
988 sops[1].sem_num = USHRT_MAX;
989 if (semop(id, sops, 2) != -1) e(0);
990 if (errno != EFBIG) e(0);
993 * Test nonblocking operations on a single semaphore, starting with
994 * value limit and overflow cases.
996 if (seminfo.semvmx < 3 || seminfo.semvmx > SHRT_MAX) e(0);
998 sops[0].sem_flg = IPC_NOWAIT;
1000 /* This block does not trigger on MINIX3. */
1001 if (seminfo.semvmx < SHRT_MAX) {
1002 sops[0].sem_op = seminfo.semvmx + 1;
1003 if (semop(id, sops, 1) != -1) e(0);
1004 if (errno != ERANGE) e(0);
1005 if (semctl(id, 0, GETVAL) != 0) e(0);
1008 sops[0].sem_op = seminfo.semvmx;
1009 if (semop(id, sops, 1) != 0) e(0);
1010 if (semctl(id, 0, GETVAL) != seminfo.semvmx) e(0);
1012 /* As of writing, the proper checks for this is missing on NetBSD. */
1013 sops[0].sem_op = 1;
1014 if (semop(id, sops, 1) != -1) e(0);
1015 if (errno != ERANGE) e(0);
1016 if (semctl(id, 0, GETVAL) != seminfo.semvmx) e(0);
1018 sops[0].sem_op = seminfo.semvmx;
1019 if (semop(id, sops, 1) != -1) e(0);
1020 if (errno != ERANGE) e(0);
1021 if (semctl(id, 0, GETVAL) != seminfo.semvmx) e(0);
1023 sops[0].sem_op = SHRT_MAX;
1024 if (semop(id, sops, 1) != -1) e(0);
1025 if (errno != ERANGE) e(0);
1026 if (semctl(id, 0, GETVAL) != seminfo.semvmx) e(0);
1028 /* This block does trigger on MINIX3. */
1029 if (seminfo.semvmx < -(int)SHRT_MIN) {
1030 sops[0].sem_op = -seminfo.semvmx - 1;
1031 if (semop(id, sops, 1) != -1) e(0);
1032 if (errno != EAGAIN) e(0);
1033 if (semctl(id, 0, GETVAL) != seminfo.semvmx) e(0);
1036 sops[0].sem_op = -seminfo.semvmx;
1037 if (semop(id, sops, 1) != 0) e(0);
1038 if (semctl(id, 0, GETVAL) != 0) e(0);
1041 * Test basic nonblocking operations on a single semaphore.
1043 sops[0].sem_op = 0;
1044 if (semop(id, sops, 1) != 0) e(0);
1046 sops[0].sem_op = 2;
1047 if (semop(id, sops, 1) != 0) e(0);
1048 if (semctl(id, 0, GETVAL) != 2) e(0);
1050 sops[0].sem_op = 0;
1051 if (semop(id, sops, 1) != -1) e(0);
1052 if (errno != EAGAIN) e(0);
1054 sops[0].sem_op = -3;
1055 if (semop(id, sops, 1) != -1) e(0);
1056 if (errno != EAGAIN) e(0);
1058 sops[0].sem_op = 1;
1059 if (semop(id, sops, 1) != 0) e(0);
1060 if (semctl(id, 0, GETVAL) != 3) e(0);
1062 sops[0].sem_op = -1;
1063 if (semop(id, sops, 1) != 0) e(0);
1064 if (semctl(id, 0, GETVAL) != 2) e(0);
1066 sops[0].sem_op = 0;
1067 if (semop(id, sops, 1) != -1) e(0);
1068 if (errno != EAGAIN) e(0);
1070 sops[0].sem_op = -2;
1071 if (semop(id, sops, 1) != 0) e(0);
1072 if (semctl(id, 0, GETVAL) != 0) e(0);
1074 sops[0].sem_op = 0;
1075 if (semop(id, sops, 1) != 0) e(0);
1077 /* Make sure that not too much data is being read in. */
1078 sops2->sem_op = 0;
1079 sops2--;
1080 if (semop(id, sops2, 2) != 0) e(0);
1082 /* Even if no operations are given, the identifier must be valid. */
1083 if (semctl(id, 0, IPC_RMID) != 0) e(0);
1085 if (semop(id, NULL, 0) != -1) e(0);
1086 if (errno != EINVAL) e(0);
1088 if (semop(-1, NULL, 0) != -1) e(0);
1089 if (errno != EINVAL) e(0);
1091 if (semop(INT_MIN, NULL, 0) != -1) e(0);
1092 if (errno != EINVAL) e(0);
1094 memset(&semds, 0, sizeof(semds));
1095 id = IXSEQ_TO_IPCID(seminfo.semmni, semds.sem_perm);
1096 if (semop(id, NULL, 0) != -1) e(0);
1097 if (errno != EINVAL) e(0);
1100 * Test permission checks. As part of this, test basic nonblocking
1101 * multi-operation calls, including operation processing in array order
1102 * and the order of (permission vs other) checks.
1104 test_perm(test88b_perm, 0 /*owner_test*/);
1107 * Test blocking operations, starting with a single blocking operation.
1109 if ((id = semget(IPC_PRIVATE, 3, 0600)) == -1) e(0);
1111 memset(sops, 0, sizeof(sops[0]));
1112 sops[0].sem_op = 1;
1113 if (semop(id, sops, 1) != 0) e(0);
1115 TEST_SEM(id, 0, 1, getpid(), 0, 0);
1117 spawn(&child, test88b_child, DROP_NONE);
1119 snd(&child, id);
1122 * In various places, we have to sleep in order to allow the child to
1123 * get itself blocked in a semop(2) call.
1125 usleep(WAIT_USECS);
1127 TEST_SEM(id, 0, 1, getpid(), 0, 1);
1129 sops[0].sem_op = -1;
1130 if (semop(id, sops, 1) != 0) e(0);
1132 usleep(WAIT_USECS);
1134 TEST_SEM(id, 0, 0, child.pid, 0, 0);
1136 sops[0].sem_op = 1;
1137 if (semop(id, sops, 1) != 0) e(0);
1139 TEST_SEM(id, 0, 1, getpid(), 0, 0);
1141 snd(&child, 1);
1143 usleep(WAIT_USECS);
1145 TEST_SEM(id, 0, 1, getpid(), 1, 0);
1147 /* This should cause a (fruitless) retry of the blocking operation. */
1148 sops[0].sem_op = 1;
1149 if (semop(id, sops, 1) != 0) e(0);
1151 usleep(WAIT_USECS);
1153 TEST_SEM(id, 0, 2, getpid(), 1, 0);
1155 sops[0].sem_op = 1;
1156 if (semop(id, sops, 1) != 0) e(0);
1158 usleep(WAIT_USECS);
1160 TEST_SEM(id, 0, 0, child.pid, 0, 0);
1163 * Test blocking operations, verifying the correct operation of
1164 * multiple (partially) blocking operations and atomicity.
1166 memset(sops, 0, sizeof(sops[0]) * 2);
1167 if (semop(id, sops, 1) != 0) e(0);
1169 /* One blocking operation. */
1170 snd(&child, 2);
1172 usleep(WAIT_USECS);
1174 TEST_SEM(id, 0, 0, getpid(), 0, 0);
1175 TEST_SEM(id, 1, 0, 0, 1, 0);
1176 TEST_SEM(id, 2, 0, 0, 0, 0);
1178 sops[0].sem_num = 1;
1179 sops[0].sem_op = 1;
1180 if (semop(id, sops, 1) != 0) e(0);
1182 usleep(WAIT_USECS);
1184 TEST_SEM(id, 0, 1, child.pid, 0, 0);
1185 TEST_SEM(id, 1, 0, child.pid, 0, 0);
1186 TEST_SEM(id, 2, 2, child.pid, 0, 0);
1188 /* Two blocking operations in one call, resolved at once. */
1189 snd(&child, 3);
1191 usleep(WAIT_USECS);
1193 TEST_SEM(id, 0, 1, child.pid, 0, 1);
1194 TEST_SEM(id, 1, 0, child.pid, 0, 0);
1195 TEST_SEM(id, 2, 2, child.pid, 0, 0);
1197 sops[0].sem_num = 0;
1198 sops[0].sem_op = -1;
1199 sops[1].sem_num = 2;
1200 sops[1].sem_op = -2;
1201 if (semop(id, sops, 2) != 0) e(0);
1203 usleep(WAIT_USECS);
1205 TEST_SEM(id, 0, 0, child.pid, 0, 0);
1206 TEST_SEM(id, 1, 1, child.pid, 0, 0);
1207 TEST_SEM(id, 2, 1, child.pid, 0, 0);
1209 /* Two blocking operations in one call, resolved one by one. */
1210 snd(&child, 4);
1212 usleep(WAIT_USECS);
1214 TEST_SEM(id, 0, 0, child.pid, 0, 0);
1215 TEST_SEM(id, 1, 1, child.pid, 1, 0);
1216 TEST_SEM(id, 2, 1, child.pid, 0, 0);
1218 sops[0].sem_num = 1;
1219 sops[0].sem_op = 1;
1220 if (semop(id, sops, 1) != 0) e(0);
1222 usleep(WAIT_USECS);
1224 TEST_SEM(id, 0, 0, child.pid, 0, 0);
1225 TEST_SEM(id, 1, 2, getpid(), 0, 0);
1226 TEST_SEM(id, 2, 1, child.pid, 0, 1);
1228 sops[0].sem_num = 2;
1229 sops[0].sem_op = -1;
1230 if (semop(id, sops, 1) != 0) e(0);
1232 usleep(WAIT_USECS);
1234 TEST_SEM(id, 0, 0, child.pid, 0, 0);
1235 TEST_SEM(id, 1, 0, child.pid, 0, 0);
1236 TEST_SEM(id, 2, 0, child.pid, 0, 0);
1238 /* One blocking op followed by a nonblocking one, cleared at once. */
1239 sops[0].sem_num = 0;
1240 sops[0].sem_op = 0;
1241 sops[1].sem_num = 1;
1242 sops[1].sem_op = 0;
1243 if (semop(id, sops, 2) != 0) e(0);
1245 snd(&child, 5);
1247 usleep(WAIT_USECS);
1249 TEST_SEM(id, 0, 0, getpid(), 1, 0);
1250 TEST_SEM(id, 1, 0, getpid(), 0, 0);
1252 sops[0].sem_num = 0;
1253 sops[0].sem_op = 1;
1254 sops[1].sem_num = 1;
1255 sops[1].sem_op = 1;
1256 if (semop(id, sops, 2) != 0) e(0);
1258 usleep(WAIT_USECS);
1260 TEST_SEM(id, 0, 0, child.pid, 0, 0);
1261 TEST_SEM(id, 1, 0, child.pid, 0, 0);
1263 /* One blocking op followed by a nonblocking one, only one cleared. */
1264 sops[0].sem_num = 0;
1265 sops[0].sem_op = 1;
1266 sops[1].sem_num = 1;
1267 sops[1].sem_op = 1;
1268 if (semop(id, sops, 2) != 0) e(0);
1270 snd(&child, 6);
1272 usleep(WAIT_USECS);
1274 TEST_SEM(id, 0, 1, getpid(), 0, 0);
1275 TEST_SEM(id, 1, 1, getpid(), 0, 1);
1277 sops[0].sem_num = 1;
1278 sops[0].sem_op = -1;
1279 if (semop(id, sops, 1) != 0) e(0);
1281 usleep(WAIT_USECS);
1283 TEST_SEM(id, 0, 1, getpid(), 0, 0);
1284 TEST_SEM(id, 1, 0, getpid(), 0, 0);
1287 * Ensure that all semaphore numbers are checked immediately, which
1288 * given the earlier test results also implies that permissions are
1289 * checked immediately (so we don't have to recheck that too). We do
1290 * not check whether permissions are rechecked after a blocking
1291 * operation, because the specification does not describe the intended
1292 * behavior on this point.
1294 sops[0].sem_num = 0;
1295 sops[0].sem_op = 0;
1296 sops[1].sem_num = 4;
1297 sops[1].sem_op = 0;
1298 if (semop(id, sops, 2) != -1) e(0);
1299 if (errno != EFBIG) e(0);
1302 * Ensure that semaphore value overflow is detected properly, at the
1303 * moment that the operation is actually processed.
1305 sops[0].sem_num = 1;
1306 sops[0].sem_op = seminfo.semvmx;
1307 if (semop(id, sops, 1) != 0) e(0);
1309 snd(&child, 7);
1311 usleep(WAIT_USECS);
1313 TEST_SEM(id, 0, 1, getpid(), 0, 1);
1314 TEST_SEM(id, 1, seminfo.semvmx, getpid(), 0, 0);
1316 sops[0].sem_num = 0;
1317 sops[0].sem_op = -1;
1318 sops[1].sem_num = 1;
1319 sops[1].sem_op = -1;
1320 if (semop(id, sops, 2) != 0) e(0);
1322 TEST_SEM(id, 0, 0, child.pid, 0, 0);
1323 TEST_SEM(id, 1, seminfo.semvmx, child.pid, 0, 0);
1325 sops[0].sem_num = 1;
1326 sops[0].sem_op = -2;
1327 if (semop(id, sops, 1) != 0) e(0);
1329 snd(&child, 8);
1331 usleep(WAIT_USECS);
1333 TEST_SEM(id, 0, 0, child.pid, 1, 0);
1334 TEST_SEM(id, 1, seminfo.semvmx - 2, getpid(), 0, 0);
1336 sops[0].sem_num = 0;
1337 sops[0].sem_op = 1;
1338 sops[1].sem_num = 1;
1339 sops[1].sem_op = 1;
1340 if (semop(id, sops, 2) != 0) e(0);
1342 TEST_SEM(id, 0, 1, getpid(), 0, 0);
1343 TEST_SEM(id, 1, seminfo.semvmx - 1, getpid(), 0, 0);
1345 sops[0].sem_num = 0;
1346 sops[0].sem_op = seminfo.semvmx - 1;
1347 sops[1].sem_num = 0;
1348 sops[1].sem_op = seminfo.semvmx - 1;
1349 sops[2].sem_num = 0;
1350 sops[2].sem_op = 2;
1352 * With the current SEMVMX, the sum of the values is now USHRT_MAX-1,
1353 * which if processed could result in a zero semaphore value. That
1354 * should not happen. Looking at you, NetBSD.
1356 if (semop(id, sops, 3) != -1) e(0);
1357 if (errno != ERANGE) e(0);
1359 TEST_SEM(id, 0, 1, getpid(), 0, 0);
1362 * Check that a blocking semop(2) call fails with EINTR if a signal is
1363 * caught by the process after the call has blocked.
1365 if (semctl(id, 1, SETVAL, 0) != 0) e(0);
1366 sops[0].sem_num = 0;
1367 sops[0].sem_op = -1;
1368 sops[1].sem_num = 1;
1369 sops[1].sem_op = 1;
1370 if (semop(id, sops, 2) != 0) e(0);
1372 TEST_SEM(id, 0, 0, getpid(), 0, 0);
1373 TEST_SEM(id, 1, 1, getpid(), 0, 0);
1375 snd(&child, 9);
1377 usleep(WAIT_USECS);
1379 TEST_SEM(id, 0, 0, getpid(), 0, 0);
1380 TEST_SEM(id, 1, 1, getpid(), 0, 1);
1382 kill(child.pid, SIGHUP);
1384 * Kills are not guaranteed to be delivered immediately to processes
1385 * other than the caller of kill(2), so let the child perform checks.
1389 * Check that a blocking semop(2) call fails with EIDRM if the
1390 * semaphore set is removed after the call has blocked.
1392 snd(&child, 10);
1394 usleep(WAIT_USECS);
1396 if (semctl(id, 0, IPC_RMID) != 0) e(0);
1399 * Check if sem_otime is updated correctly. Instead of sleeping for
1400 * whole seconds so as to be able to detect differences, use SETVAL,
1401 * which does not update sem_otime at all. This doubles as a first
1402 * test to see if SETVAL correctly wakes up a blocked semop(2) call.
1404 if ((id = semget(IPC_PRIVATE, 2, 0600)) == -1) e(0);
1406 snd(&child, id);
1408 usleep(WAIT_USECS);
1410 TEST_SEM(id, 0, 0, 0, 1, 0);
1411 TEST_SEM(id, 1, 0, 0, 0, 0);
1412 if (semctl(id, 0, IPC_STAT, &semds) != 0) e(0);
1413 if (semds.sem_otime != 0) e(0);
1415 if (semctl(id, 1, SETVAL, seminfo.semvmx) != 0) e(0);
1417 TEST_SEM(id, 0, 0, 0, 1, 0);
1418 TEST_SEM(id, 1, seminfo.semvmx, 0, 0, 0);
1419 if (semctl(id, 0, IPC_STAT, &semds) != 0) e(0);
1420 if (semds.sem_otime != 0) e(0);
1422 if (semctl(id, 0, SETVAL, 1) != 0) e(0);
1423 TEST_SEM(id, 0, 1, 0, 0, 0);
1424 TEST_SEM(id, 1, seminfo.semvmx, 0, 0, 0);
1426 if (semctl(id, 0, SETVAL, 0) != 0) e(0);
1428 snd(&child, 11);
1430 usleep(WAIT_USECS);
1432 TEST_SEM(id, 0, 0, 0, 0, 0);
1433 TEST_SEM(id, 1, seminfo.semvmx, 0, 0, 1);
1434 if (semctl(id, 0, IPC_STAT, &semds) != 0) e(0);
1435 if (semds.sem_otime != 0) e(0);
1437 if (semctl(id, 1, SETVAL, 0) != 0) e(0);
1439 TEST_SEM(id, 0, 0, 0, 1, 0);
1440 TEST_SEM(id, 1, 0, 0, 0, 0);
1441 if (semctl(id, 0, IPC_STAT, &semds) != 0) e(0);
1442 if (semds.sem_otime != 0) e(0);
1444 time(&now);
1445 if (semctl(id, 0, SETVAL, 2) != 0) e(0);
1447 TEST_SEM(id, 0, 1, child.pid, 0, 0);
1448 TEST_SEM(id, 1, 0, child.pid, 0, 0);
1449 if (semctl(id, 0, IPC_STAT, &semds) != 0) e(0);
1450 if (semds.sem_otime < now || semds.sem_otime >= now + 10) e(0);
1452 if (semctl(id, 0, IPC_RMID) != 0) e(0);
1455 * Perform a similar test for SETALL, ensuring that it causes an
1456 * ongoing semop(2) to behave correctly.
1458 if ((id = semget(IPC_PRIVATE, 2, 0600)) == -1) e(0);
1460 snd(&child, id);
1462 usleep(WAIT_USECS);
1464 TEST_SEM(id, 0, 0, 0, 1, 0);
1465 TEST_SEM(id, 1, 0, 0, 0, 0);
1467 val[0] = 1;
1468 val[1] = 1;
1469 if (semctl(id, 0, SETALL, val) != 0) e(0);
1471 TEST_SEM(id, 0, 1, 0, 0, 0);
1472 TEST_SEM(id, 1, 1, 0, 0, 1);
1474 val[0] = 0;
1475 val[1] = 1;
1476 if (semctl(id, 0, SETALL, val) != 0) e(0);
1478 TEST_SEM(id, 0, 0, 0, 1, 0);
1479 TEST_SEM(id, 1, 1, 0, 0, 0);
1481 val[0] = 1;
1482 val[1] = 1;
1483 if (semctl(id, 0, SETALL, val) != 0) e(0);
1485 TEST_SEM(id, 0, 1, 0, 0, 0);
1486 TEST_SEM(id, 1, 1, 0, 0, 1);
1488 val[0] = 0;
1489 val[1] = 0;
1490 if (semctl(id, 0, SETALL, val) != 0) e(0);
1492 TEST_SEM(id, 0, 0, 0, 1, 0);
1493 TEST_SEM(id, 1, 0, 0, 0, 0);
1494 if (semctl(id, 0, IPC_STAT, &semds) != 0) e(0);
1495 if (semds.sem_otime != 0) e(0);
1497 time(&now);
1498 val[0] = 1;
1499 val[1] = 0;
1500 if (semctl(id, 0, SETALL, val) != 0) e(0);
1502 TEST_SEM(id, 0, 0, child.pid, 0, 0);
1503 TEST_SEM(id, 1, 0, child.pid, 0, 0);
1504 if (semctl(id, 0, IPC_STAT, &semds) != 0) e(0);
1505 if (semds.sem_otime < now || semds.sem_otime >= now + 10) e(0);
1508 * Finally, ensure that if the child is killed, its blocked semop(2)
1509 * call is properly cancelled.
1511 sops[0].sem_num = 0;
1512 sops[0].sem_op = 0;
1513 sops[1].sem_num = 1;
1514 sops[1].sem_op = 0;
1515 if (semop(id, sops, 2) != 0) e(0);
1517 TEST_SEM(id, 0, 0, getpid(), 0, 0);
1518 TEST_SEM(id, 1, 0, getpid(), 0, 0);
1520 /* We'll be terminating the child, so let it report its errors now. */
1521 if (rcv(&child) != 0) e(0);
1523 snd(&child, 12);
1525 usleep(WAIT_USECS);
1527 TEST_SEM(id, 0, 0, getpid(), 0, 0);
1528 TEST_SEM(id, 1, 0, getpid(), 1, 0);
1530 terminate(&child);
1532 TEST_SEM(id, 0, 0, getpid(), 0, 0);
1533 TEST_SEM(id, 1, 0, getpid(), 0, 0);
1535 if (semctl(id, 0, IPC_RMID) != 0) e(0);
1537 free(sops);
1541 * Test semctl(2) permission checks, part 1: regular commands.
1543 static void
1544 test88c_perm1(struct link * parent)
1546 static const int cmds[] = { GETVAL, GETPID, GETNCNT, GETZCNT };
1547 struct semid_ds semds;
1548 struct seminfo seminfo;
1549 unsigned short val[3];
1550 int i, r, tbit, bit, id[3], cmd;
1551 void *ptr;
1553 while ((tbit = rcv(parent)) != -1) {
1554 id[0] = rcv(parent);
1555 id[1] = rcv(parent);
1556 id[2] = rcv(parent);
1558 /* First the read-only, no-argument cases. */
1559 bit = 4;
1560 for (i = 0; i < __arraycount(cmds); i++) {
1561 r = semctl(id[0], 0, cmds[i]);
1562 if (r < 0 && (r != -1 || errno != EACCES)) e(0);
1563 if (((bit & tbit) == bit) != (r != -1)) e(0);
1565 r = semctl(id[1], 0, cmds[i]);
1566 if (r < 0 && (r != -1 || errno != EACCES)) e(0);
1567 if (((bit & tbit) == bit) != (r != -1)) e(0);
1569 if (semctl(id[2], 0, cmds[i]) != -1) e(0);
1570 if (errno != EACCES) e(0);
1574 * Then SETVAL, which requires write permission and is the only
1575 * one that takes an integer argument.
1577 bit = 2;
1578 r = semctl(id[0], 0, SETVAL, 0);
1579 if (r < 0 && (r != -1 || errno != EACCES)) e(0);
1580 if (((bit & tbit) == bit) != (r != -1)) e(0);
1582 r = semctl(id[1], 0, SETVAL, 0);
1583 if (r < 0 && (r != -1 || errno != EACCES)) e(0);
1584 if (((bit & tbit) == bit) != (r != -1)) e(0);
1586 if (semctl(id[2], 0, SETVAL, 0) != -1) e(0);
1587 if (errno != EACCES) e(0);
1590 * Finally the commands that require read or write permission
1591 * and take a pointer as argument.
1593 memset(val, 0, sizeof(val));
1595 for (i = 0; i < 3; i++) {
1596 switch (i) {
1597 case 0:
1598 cmd = GETALL;
1599 ptr = val;
1600 bit = 4;
1601 break;
1602 case 1:
1603 cmd = SETALL;
1604 ptr = val;
1605 bit = 2;
1606 break;
1607 case 2:
1608 cmd = IPC_STAT;
1609 ptr = &semds;
1610 bit = 4;
1611 break;
1612 default:
1613 abort();
1616 r = semctl(id[0], 0, cmd, ptr);
1617 if (r < 0 && (r != -1 || errno != EACCES)) e(0);
1618 if (((bit & tbit) == bit) != (r != -1)) e(0);
1620 r = semctl(id[1], 0, cmd, ptr);
1621 if (r < 0 && (r != -1 || errno != EACCES)) e(0);
1622 if (((bit & tbit) == bit) != (r != -1)) e(0);
1624 if (semctl(id[2], 0, cmd, ptr) != -1) e(0);
1625 if (errno != EACCES) e(0);
1629 * I was hoping to avoid this, but otherwise we have to make
1630 * the other child iterate through all semaphore sets to find
1631 * the right index for each of the identifiers. As noted in
1632 * the IPC server itself as well, duplicating these macros is
1633 * not a big deal since the split is firmly hardcoded through
1634 * the exposure of IXSEQ_TO_IPCID to userland.
1636 #ifndef IPCID_TO_IX
1637 #define IPCID_TO_IX(id) ((id) & 0xffff)
1638 #endif
1640 bit = 4;
1642 r = semctl(IPCID_TO_IX(id[0]), 0, SEM_STAT, &semds);
1643 if (r < 0 && (r != -1 || errno != EACCES)) e(0);
1644 if (((bit & tbit) == bit) != (r != -1)) e(0);
1646 r = semctl(IPCID_TO_IX(id[1]), 0, SEM_STAT, &semds);
1647 if (r < 0 && (r != -1 || errno != EACCES)) e(0);
1648 if (((bit & tbit) == bit) != (r != -1)) e(0);
1650 if (semctl(IPCID_TO_IX(id[2]), 0, SEM_STAT, &semds) != -1)
1651 e(0);
1652 if (errno != EACCES) e(0);
1655 * IPC_INFO and SEM_INFO should always succeed. They do not
1656 * even take a semaphore set identifier.
1658 if (semctl(0, 0, IPC_INFO, &seminfo) == -1) e(0);
1659 if (semctl(0, 0, SEM_INFO, &seminfo) == -1) e(0);
1661 snd(parent, 0);
1666 * Test semctl(2) permission checks, part 2: the IPC_SET command.
1668 static void
1669 test88c_perm2(struct link * parent)
1671 struct semid_ds semds;
1672 int r, shift, id[3];
1674 while ((shift = rcv(parent)) != -1) {
1675 id[0] = rcv(parent);
1676 id[1] = rcv(parent);
1677 id[2] = rcv(parent);
1680 * Test IPC_SET. Ideally, we would set the permissions to what
1681 * they currently are, but we do not actually know what they
1682 * are, and IPC_STAT requires read permission which we may not
1683 * have! However, no matter what we do, we cannot prevent the
1684 * other child from being able to remove the semaphore sets
1685 * afterwards. So, we just set the permissions to all-zeroes;
1686 * even though those values are meaningful (mode 0000, uid 0,
1687 * gid 0) they could be anything: the API will accept anything.
1688 * This does mean we need to test IPC_RMID permissions from
1689 * another procedure, because we may now be locking ourselves
1690 * out. The System V IPC interface is pretty strange that way.
1692 memset(&semds, 0, sizeof(semds));
1694 r = semctl(id[0], 0, IPC_SET, &semds);
1695 if (r < 0 && (r != -1 || errno != EPERM)) e(0);
1696 if ((shift == 6) != (r != -1)) e(0);
1698 r = semctl(id[1], 0, IPC_SET, &semds);
1699 if (r < 0 && (r != -1 || errno != EPERM)) e(0);
1700 if ((shift == 6) != (r != -1)) e(0);
1702 /* For once, this too should succeed. */
1703 r = semctl(id[2], 0, IPC_SET, &semds);
1704 if (r < 0 && (r != -1 || errno != EPERM)) e(0);
1705 if ((shift == 6) != (r != -1)) e(0);
1707 snd(parent, 0);
1712 * Test semctl(2) permission checks, part 3: the IPC_RMID command.
1714 static void
1715 test88c_perm3(struct link * parent)
1717 int r, shift, id[3];
1719 while ((shift = rcv(parent)) != -1) {
1720 id[0] = rcv(parent);
1721 id[1] = rcv(parent);
1722 id[2] = rcv(parent);
1724 r = semctl(id[0], 0, IPC_RMID);
1725 if (r < 0 && (r != -1 || errno != EPERM)) e(0);
1726 if ((shift == 6) != (r != -1)) e(0);
1728 r = semctl(id[1], 0, IPC_RMID);
1729 if (r < 0 && (r != -1 || errno != EPERM)) e(0);
1730 if ((shift == 6) != (r != -1)) e(0);
1732 /* Okay, twice then. */
1733 r = semctl(id[2], 0, IPC_RMID);
1734 if (r < 0 && (r != -1 || errno != EPERM)) e(0);
1735 if ((shift == 6) != (r != -1)) e(0);
1737 snd(parent, 0);
1742 * Test the basic semctl(2) functionality.
1744 static void
1745 test88c(void)
1747 static const int cmds[] = { GETVAL, GETPID, GETNCNT, GETZCNT };
1748 struct seminfo seminfo;
1749 struct semid_ds semds, osemds;
1750 unsigned short val[4], seen[2];
1751 char statbuf[sizeof(struct semid_ds) + 1];
1752 unsigned int i, j;
1753 time_t now;
1754 int r, id, id2, badid1, badid2, cmd;
1756 subtest = 2;
1758 if (semctl(0, 0, IPC_INFO, &seminfo) == -1) e(0);
1761 * Start with permission checks on the commands. IPC_SET and IPC_RMID
1762 * are special: they check for ownership (uid/cuid) and return EPERM
1763 * rather than EACCES on permission failure.
1765 test_perm(test88c_perm1, 0 /*owner_test*/);
1766 test_perm(test88c_perm2, 1 /*owner_test*/);
1767 test_perm(test88c_perm3, 1 /*owner_test*/);
1769 /* Create identifiers known to be invalid. */
1770 if ((badid1 = semget(IPC_PRIVATE, 1, 0600)) < 0) e(0);
1772 if (semctl(badid1, 0, IPC_RMID) != 0) e(0);
1774 memset(&semds, 0, sizeof(semds));
1775 badid2 = IXSEQ_TO_IPCID(seminfo.semmni, semds.sem_perm);
1777 if ((id = semget(IPC_PRIVATE, 3, IPC_CREAT | 0600)) < 0) e(0);
1779 if (semctl(id, 0, IPC_STAT, &semds) != 0) e(0);
1780 if (semds.sem_otime != 0) e(0);
1781 if (semds.sem_ctime == 0) e(0);
1783 /* In this case we can't avoid sleeping for longer periods.. */
1784 while (time(&now) == semds.sem_ctime)
1785 usleep(250000);
1788 * Test the simple GET commands. The actual functionality of these
1789 * commands have already been tested thoroughly as part of the
1790 * semop(2) part of the test set, so we do not repeat that here.
1792 for (i = 0; i < __arraycount(cmds); i++) {
1793 for (j = 0; j < 3; j++)
1794 if (semctl(id, j, cmds[i]) != 0) e(0);
1796 if (semctl(badid1, 0, cmds[i]) != -1) e(0);
1797 if (errno != EINVAL) e(0);
1799 if (semctl(badid2, 0, cmds[i]) != -1) e(0);
1800 if (errno != EINVAL) e(0);
1802 if (semctl(-1, 0, cmds[i]) != -1) e(0);
1803 if (errno != EINVAL) e(0);
1805 if (semctl(INT_MIN, 0, cmds[i]) != -1) e(0);
1806 if (errno != EINVAL) e(0);
1808 if (semctl(id, -1, cmds[i]) != -1) e(0);
1809 if (errno != EINVAL) e(0);
1811 if (semctl(id, 3, cmds[i]) != -1) e(0);
1812 if (errno != EINVAL) e(0);
1814 /* These commands should not update ctime or otime. */
1815 if (semctl(id, 0, IPC_STAT, &semds) != 0) e(0);
1816 if (semds.sem_otime != 0) e(0);
1817 if (semds.sem_ctime >= now) e(0);
1821 * Test the GETALL command.
1824 * Contrary to what the Open Group specification suggests, actual
1825 * implementations agree that the semnum parameter is to be ignored for
1826 * calls not involving a specific semaphore in the set.
1828 for (j = 0; j < 5; j++) {
1829 for (i = 0; i < __arraycount(val); i++)
1830 val[i] = USHRT_MAX;
1832 if (semctl(id, (int)j - 1, GETALL, val) != 0) e(0);
1833 for (i = 0; i < 3; i++)
1834 if (val[i] != 0) e(0);
1835 if (val[i] != USHRT_MAX) e(0);
1838 for (i = 0; i < __arraycount(val); i++)
1839 val[i] = USHRT_MAX;
1841 if (semctl(badid1, 0, GETALL, val) != -1) e(0);
1842 if (errno != EINVAL) e(0);
1844 if (semctl(badid2, 0, GETALL, val) != -1) e(0);
1845 if (errno != EINVAL) e(0);
1847 if (semctl(-1, 0, GETALL, val) != -1) e(0);
1848 if (errno != EINVAL) e(0);
1850 if (semctl(INT_MIN, 0, GETALL, val) != -1) e(0);
1851 if (errno != EINVAL) e(0);
1853 for (i = 0; i < __arraycount(val); i++)
1854 if (val[i] != USHRT_MAX) e(0);
1856 if (semctl(id, 0, GETALL, NULL) != -1) e(0);
1857 if (errno != EFAULT) e(0);
1859 if (semctl(id, 0, GETALL, bad_ptr) != -1) e(0);
1860 if (errno != EFAULT) e(0);
1862 if (semctl(id, 0, GETALL, ((unsigned short *)bad_ptr) - 2) != -1) e(0);
1863 if (errno != EFAULT) e(0);
1865 if (semctl(id, 0, GETALL, ((unsigned short *)bad_ptr) - 3) != 0) e(0);
1867 /* Still no change in either otime or ctime. */
1868 if (semctl(id, 0, IPC_STAT, &semds) != 0) e(0);
1869 if (semds.sem_otime != 0) e(0);
1870 if (semds.sem_ctime >= now) e(0);
1873 * Test the IPC_STAT command. This is the last command we are testing
1874 * here that does not affect sem_ctime, so in order to avoid extra
1875 * sleep times, we test this command first now.
1878 * The basic IPC_STAT functionality has already been tested heavily as
1879 * part of the semget(2) and permission tests, so we do not repeat that
1880 * here.
1882 memset(statbuf, 0x5a, sizeof(statbuf));
1884 if (semctl(badid1, 0, IPC_STAT, statbuf) != -1) e(0);
1885 if (errno != EINVAL) e(0);
1887 if (semctl(badid2, 0, IPC_STAT, statbuf) != -1) e(0);
1888 if (errno != EINVAL) e(0);
1890 if (semctl(-1, 0, IPC_STAT, statbuf) != -1) e(0);
1891 if (errno != EINVAL) e(0);
1893 if (semctl(INT_MIN, 0, IPC_STAT, statbuf) != -1) e(0);
1894 if (errno != EINVAL) e(0);
1896 for (i = 0; i < sizeof(statbuf); i++)
1897 if (statbuf[i] != 0x5a) e(0);
1899 if (semctl(id, 0, IPC_STAT, statbuf) != 0) e(0);
1901 if (statbuf[sizeof(statbuf) - 1] != 0x5a) e(0);
1903 if (semctl(id, 0, IPC_STAT, NULL) != -1) e(0);
1904 if (errno != EFAULT) e(0);
1906 if (semctl(id, 0, IPC_STAT, bad_ptr) != -1) e(0);
1907 if (errno != EFAULT) e(0);
1909 if (semctl(id, 0, IPC_STAT, ((struct semid_ds *)bad_ptr) - 1) != 0)
1910 e(0);
1912 if (semctl(id, -1, IPC_STAT, &semds) != 0) e(0);
1913 if (semds.sem_otime != 0) e(0);
1914 if (semds.sem_ctime >= now) e(0);
1917 * Test SEM_STAT.
1919 if ((id2 = semget(KEY_A, seminfo.semmsl, IPC_CREAT | 0642)) < 0) e(0);
1921 memset(statbuf, 0x5a, sizeof(statbuf));
1923 if (semctl(-1, 0, SEM_STAT, statbuf) != -1) e(0);
1924 if (errno != EINVAL) e(0);
1926 if (semctl(seminfo.semmni, 0, SEM_STAT, statbuf) != -1) e(0);
1927 if (errno != EINVAL) e(0);
1929 for (i = 0; i < sizeof(statbuf); i++)
1930 if (statbuf[i] != 0x5a) e(0);
1932 memset(seen, 0, sizeof(seen));
1934 for (i = 0; i < seminfo.semmni; i++) {
1935 errno = 0;
1936 if ((r = semctl(i, i / 2 - 1, SEM_STAT, statbuf)) == -1) {
1937 if (errno != EINVAL) e(0);
1938 continue;
1940 if (r < 0) e(0);
1941 memcpy(&semds, statbuf, sizeof(semds));
1942 if (!(semds.sem_perm.mode & SEM_ALLOC)) e(0);
1943 if (semds.sem_ctime == 0) e(0);
1944 if (IXSEQ_TO_IPCID(i, semds.sem_perm) != r) e(0);
1945 if (r == id) {
1946 seen[0]++;
1947 if (semds.sem_perm.mode != (SEM_ALLOC | 0600)) e(0);
1948 if (semds.sem_perm.uid != geteuid()) e(0);
1949 if (semds.sem_perm.gid != getegid()) e(0);
1950 if (semds.sem_perm.cuid != semds.sem_perm.uid) e(0);
1951 if (semds.sem_perm.cgid != semds.sem_perm.gid) e(0);
1952 if (semds.sem_perm._key != IPC_PRIVATE) e(0);
1953 if (semds.sem_nsems != 3) e(0);
1954 if (semds.sem_otime != 0) e(0);
1956 /* This is here because we need a valid index. */
1957 if (semctl(i, 0, SEM_STAT, NULL) != -1) e(0);
1958 if (errno != EFAULT) e(0);
1960 if (semctl(i, 0, SEM_STAT, bad_ptr) != -1) e(0);
1961 if (errno != EFAULT) e(0);
1962 } else if (r == id2) {
1963 seen[1]++;
1964 if (semds.sem_perm.mode != (SEM_ALLOC | 0642)) e(0);
1965 if (semds.sem_perm.uid != geteuid()) e(0);
1966 if (semds.sem_perm.gid != getegid()) e(0);
1967 if (semds.sem_perm.cuid != semds.sem_perm.uid) e(0);
1968 if (semds.sem_perm.cgid != semds.sem_perm.gid) e(0);
1969 if (semds.sem_perm._key != KEY_A) e(0);
1970 if (semds.sem_nsems != seminfo.semmsl) e(0);
1974 if (seen[0] != 1) e(0);
1975 if (seen[1] != 1) e(0);
1977 if (statbuf[sizeof(statbuf) - 1] != 0x5a) e(0);
1979 if (semctl(id, 5, IPC_STAT, &semds) != 0) e(0);
1980 if (semds.sem_otime != 0) e(0);
1981 if (semds.sem_ctime >= now) e(0);
1984 * Test SETVAL. We start with all the failure cases, so as to be able
1985 * to check that sem_ctime is not changed in those cases.
1987 if (semctl(badid1, 0, SETVAL, 1) != -1) e(0);
1988 if (errno != EINVAL) e(0);
1990 if (semctl(badid2, 0, SETVAL, 1) != -1) e(0);
1991 if (errno != EINVAL) e(0);
1993 if (semctl(-1, 0, SETVAL, 1) != -1) e(0);
1994 if (errno != EINVAL) e(0);
1996 if (semctl(INT_MIN, 0, SETVAL, 1) != -1) e(0);
1997 if (errno != EINVAL) e(0);
1999 if (semctl(id, -1, SETVAL, 1) != -1) e(0);
2000 if (errno != EINVAL) e(0);
2002 if (semctl(id, 3, SETVAL, 1) != -1) e(0);
2003 if (errno != EINVAL) e(0);
2005 if (semctl(id, 0, SETVAL, -1) != -1) e(0);
2006 if (errno != ERANGE) e(0);
2008 if (semctl(id, 0, SETVAL, seminfo.semvmx + 1) != -1) e(0);
2009 if (errno != ERANGE) e(0);
2011 TEST_SEM(id, 0, 0, 0, 0, 0);
2013 if (semctl(id, 0, IPC_STAT, &semds) != 0) e(0);
2014 if (semds.sem_otime != 0) e(0);
2015 if (semds.sem_ctime >= now) e(0);
2017 /* Alright, there we go.. */
2018 if (semctl(id, 1, SETVAL, 0) != 0) e(0);
2020 if (semctl(id, 0, IPC_STAT, &semds) != 0) e(0);
2021 if (semds.sem_otime != 0) e(0);
2022 if (semds.sem_ctime < now || semds.sem_ctime >= now + 10) e(0);
2024 TEST_SEM(id, 1, 0, 0, 0, 0);
2026 if (semctl(id, 2, SETVAL, seminfo.semvmx) != 0) e(0);
2028 TEST_SEM(id, 2, seminfo.semvmx, 0, 0, 0);
2030 if (semctl(id, 0, SETVAL, 1) != 0) e(0);
2032 TEST_SEM(id, 0, 1, 0, 0, 0);
2033 TEST_SEM(id, 1, 0, 0, 0, 0);
2034 TEST_SEM(id, 2, seminfo.semvmx, 0, 0, 0);
2036 if (semctl(id, 0, GETALL, val) != 0) e(0);
2037 if (val[0] != 1) e(0);
2038 if (val[1] != 0) e(0);
2039 if (val[2] != seminfo.semvmx) e(0);
2041 if (semctl(id, 0, IPC_STAT, &semds) != 0) e(0);
2043 while (time(&now) == semds.sem_ctime)
2044 usleep(250000);
2047 * Test SETALL. Same idea: failure cases first.
2049 if (semctl(badid1, 0, SETALL, 1) != -1) e(0);
2050 if (errno != EINVAL) e(0);
2052 if (semctl(badid2, 0, SETALL, 1) != -1) e(0);
2053 if (errno != EINVAL) e(0);
2055 if (semctl(-1, 0, SETALL, 1) != -1) e(0);
2056 if (errno != EINVAL) e(0);
2058 if (semctl(INT_MIN, 0, SETALL, 1) != -1) e(0);
2059 if (errno != EINVAL) e(0);
2061 val[0] = seminfo.semvmx + 1;
2062 val[1] = 0;
2063 val[2] = 0;
2064 if (semctl(id, 0, SETALL, val) != -1) e(0);
2065 if (errno != ERANGE) e(0);
2067 val[0] = 0;
2068 val[1] = 1;
2069 val[2] = seminfo.semvmx + 1;
2070 if (semctl(id, 0, SETALL, val) != -1) e(0);
2071 if (errno != ERANGE) e(0);
2073 if (semctl(id, 0, SETALL, NULL) != -1) e(0);
2074 if (errno != EFAULT) e(0);
2076 if (semctl(id, 0, SETALL, bad_ptr) != -1) e(0);
2077 if (errno != EFAULT) e(0);
2079 if (semctl(id, 0, SETALL, ((unsigned short *)bad_ptr) - 2) != -1) e(0);
2080 if (errno != EFAULT) e(0);
2082 TEST_SEM(id, 0, 1, 0, 0, 0);
2083 TEST_SEM(id, 1, 0, 0, 0, 0);
2084 TEST_SEM(id, 2, seminfo.semvmx, 0, 0, 0);
2086 if (semctl(id, 0, IPC_STAT, &semds) != 0) e(0);
2087 if (semds.sem_otime != 0) e(0);
2088 if (semds.sem_ctime >= now) e(0);
2090 val[0] = seminfo.semvmx;
2091 val[1] = 0;
2092 val[2] = 0;
2093 if (semctl(id, 0, SETALL, val) != 0) e(0);
2095 if (semctl(id, 0, IPC_STAT, &semds) != 0) e(0);
2096 if (semds.sem_otime != 0) e(0);
2097 if (semds.sem_ctime < now || semds.sem_ctime >= now + 10) e(0);
2099 TEST_SEM(id, 0, seminfo.semvmx, 0, 0, 0);
2100 TEST_SEM(id, 1, 0, 0, 0, 0);
2101 TEST_SEM(id, 2, 0, 0, 0, 0);
2103 val[0] = 0;
2104 val[1] = 1;
2105 val[2] = seminfo.semvmx;
2106 if (semctl(id, INT_MAX, SETALL, val) != 0) e(0);
2108 TEST_SEM(id, 0, 0, 0, 0, 0);
2109 TEST_SEM(id, 1, 1, 0, 0, 0);
2110 TEST_SEM(id, 2, seminfo.semvmx, 0, 0, 0);
2112 memset(page_ptr, 0, page_size);
2113 if (semctl(id, 0, SETALL, ((unsigned short *)bad_ptr) - 3) != 0) e(0);
2115 TEST_SEM(id, 0, 0, 0, 0, 0);
2116 TEST_SEM(id, 1, 0, 0, 0, 0);
2117 TEST_SEM(id, 2, 0, 0, 0, 0);
2119 while (time(&now) == semds.sem_ctime)
2120 usleep(250000);
2123 * Test IPC_SET. Its core functionality has already been tested
2124 * thoroughly as part of the permission tests.
2126 if (semctl(badid1, 0, IPC_SET, &semds) != -1) e(0);
2127 if (errno != EINVAL) e(0);
2129 if (semctl(badid2, 0, IPC_SET, &semds) != -1) e(0);
2130 if (errno != EINVAL) e(0);
2132 if (semctl(-1, 0, IPC_SET, &semds) != -1) e(0);
2133 if (errno != EINVAL) e(0);
2135 if (semctl(INT_MIN, 0, IPC_SET, &semds) != -1) e(0);
2136 if (errno != EINVAL) e(0);
2138 if (semctl(id, 0, IPC_SET, NULL) != -1) e(0);
2139 if (errno != EFAULT) e(0);
2141 if (semctl(id, 0, IPC_SET, bad_ptr) != -1) e(0);
2142 if (errno != EFAULT) e(0);
2144 if (semctl(id, 0, IPC_STAT, &osemds) != 0) e(0);
2145 if (osemds.sem_otime != 0) e(0);
2146 if (osemds.sem_ctime >= now) e(0);
2149 * Only mode, uid, gid may be set. While the given mode is sanitized
2150 * in our implementation (see below; the open group specification
2151 * leaves this undefined), the uid and gid are not (we do not test this
2152 * exhaustively). The other given fields must be ignored. The ctime
2153 * field will be updated.
2155 memset(&semds, 0x5b, sizeof(semds));
2156 semds.sem_perm.mode = 0712;
2157 semds.sem_perm.uid = UID_MAX;
2158 semds.sem_perm.gid = GID_MAX - 1;
2159 if (semctl(id, 0, IPC_SET, &semds) != 0) e(0);
2161 if (semctl(id, 0, IPC_STAT, &semds) != 0) e(0);
2162 if (semds.sem_perm.mode != (SEM_ALLOC | 0712)) e(0);
2163 if (semds.sem_perm.uid != UID_MAX) e(0);
2164 if (semds.sem_perm.gid != GID_MAX - 1) e(0);
2165 if (semds.sem_perm.cuid != osemds.sem_perm.cuid) e(0);
2166 if (semds.sem_perm.cgid != osemds.sem_perm.cgid) e(0);
2167 if (semds.sem_perm._seq != osemds.sem_perm._seq) e(0);
2168 if (semds.sem_perm._key != osemds.sem_perm._key) e(0);
2169 if (semds.sem_nsems != osemds.sem_nsems) e(0);
2170 if (semds.sem_otime != osemds.sem_otime) e(0);
2171 if (semds.sem_ctime < now || semds.sem_ctime >= now + 10) e(0);
2173 /* It should be possible to set any mode, but mask 0777 is applied. */
2174 semds.sem_perm.uid = osemds.sem_perm.uid;
2175 semds.sem_perm.gid = osemds.sem_perm.gid;
2176 for (i = 0; i < 0777; i++) {
2177 semds.sem_perm.mode = i;
2178 if (semctl(id, i / 2 - 1, IPC_SET, &semds) != 0) e(0);
2180 if (semctl(id, i / 2 - 2, IPC_STAT, &semds) != 0) e(0);
2181 if (semds.sem_perm.mode != (SEM_ALLOC | i)) e(0);
2183 semds.sem_perm.mode = ~0777 | i;
2184 if (semctl(id, i / 2 - 3, IPC_SET, &semds) != 0) e(0);
2186 if (semctl(id, i / 2 - 4, IPC_STAT, &semds) != 0) e(0);
2187 if (semds.sem_perm.mode != (SEM_ALLOC | i)) e(0);
2189 if (semds.sem_perm.uid != osemds.sem_perm.uid) e(0);
2190 if (semds.sem_perm.gid != osemds.sem_perm.gid) e(0);
2192 if (semctl(id, 0, IPC_SET, ((struct semid_ds *)bad_ptr) - 1) != 0)
2193 e(0);
2196 * Test IPC_RMID. Its basic functionality has already been tested
2197 * multiple times over, so there is not much left to do here.
2199 if (semctl(badid1, 0, IPC_RMID) != -1) e(0);
2200 if (errno != EINVAL) e(0);
2202 if (semctl(badid2, 0, IPC_RMID) != -1) e(0);
2203 if (errno != EINVAL) e(0);
2205 if (semctl(-1, 0, IPC_RMID) != -1) e(0);
2206 if (errno != EINVAL) e(0);
2208 if (semctl(INT_MIN, 0, IPC_RMID) != -1) e(0);
2209 if (errno != EINVAL) e(0);
2211 if (semctl(id, 0, IPC_RMID) != 0) e(0);
2213 if (semctl(id, 0, IPC_RMID) != -1) e(0);
2214 if (errno != EINVAL) e(0);
2216 if (semctl(id, 0, IPC_STAT, &semds) != -1) e(0);
2217 if (errno != EINVAL) e(0);
2219 if (semctl(id2, 1, IPC_RMID) != 0) e(0);
2221 if (semctl(id2, 1, IPC_RMID) != -1) e(0);
2222 if (errno != EINVAL) e(0);
2225 * Test IPC_INFO and SEM_INFO. Right now, for all practical purposes,
2226 * these identifiers behave pretty much the same.
2228 if ((id = semget(IPC_PRIVATE, 3, 0600)) == -1) e(0);
2229 if ((id2 = semget(IPC_PRIVATE, 1, 0600)) == -1) e(0);
2231 for (i = 0; i <= 1; i++) {
2232 cmd = (i == 0) ? IPC_INFO : SEM_INFO;
2234 memset(&seminfo, 0xff, sizeof(seminfo));
2236 if ((r = semctl(0, 0, cmd, &seminfo)) == -1) e(0);
2239 * These commands return the index of the highest in-use slot
2240 * in the semaphore set table. Bad idea of course, because
2241 * that means the value 0 has two potential meanings. Since we
2242 * cannot guarantee that no other running application is using
2243 * semaphores, we settle for "at least" tests based on the two
2244 * semaphore sets we just created.
2246 if (r < 1 || r >= seminfo.semmni) e(0);
2249 * Many of these checks are rather basic because of missing
2250 * SEM_UNDO support. The only difference between IPC_INFO and
2251 * SEM_INFO is the meaning of the semusz and semaem fields.
2253 if (seminfo.semmap < 0) e(0);
2254 if (seminfo.semmni < 3 || seminfo.semmni > USHRT_MAX) e(0);
2255 if (seminfo.semmns < 3 || seminfo.semmns > USHRT_MAX) e(0);
2256 if (seminfo.semmnu < 0) e(0);
2257 if (seminfo.semmsl < 3 || seminfo.semmsl > USHRT_MAX) e(0);
2258 if (seminfo.semopm < 3 || seminfo.semopm > USHRT_MAX) e(0);
2259 if (seminfo.semume < 0) e(0);
2260 if (cmd == SEM_INFO) {
2261 if (seminfo.semusz < 2) e(0);
2262 } else
2263 if (seminfo.semusz < 0) e(0);
2264 if (seminfo.semvmx < 3 || seminfo.semvmx > SHRT_MAX) e(0);
2265 if (cmd == SEM_INFO) {
2266 if (seminfo.semaem < 4) e(0);
2267 } else
2268 if (seminfo.semaem < 0) e(0);
2270 if (semctl(INT_MAX, -1, cmd, &seminfo) == -1) e(0);
2271 if (semctl(-1, INT_MAX, cmd, &seminfo) == -1) e(0);
2273 if (semctl(0, 0, cmd, NULL) != -1) e(0);
2274 if (errno != EFAULT) e(0);
2276 if (semctl(0, 0, cmd, bad_ptr) != -1) e(0);
2277 if (errno != EFAULT) e(0);
2279 if (semctl(0, 0, cmd, ((struct seminfo *)bad_ptr) - 1) == -1)
2280 e(0);
2283 if (semctl(id2, 0, IPC_RMID) != 0) e(0);
2286 * Finally, test invalid commands. Well, hopefully invalid commands,
2287 * anyway.
2289 if (semctl(id, 0, INT_MIN) != -1) e(0);
2290 if (errno != EINVAL) e(0);
2292 if (semctl(id, 0, INT_MAX) != -1) e(0);
2293 if (errno != EINVAL) e(0);
2295 if (semctl(id, 0, IPC_RMID) != 0) e(0);
2299 * Test SEM_UNDO support. Right now this functionality is missing altogether.
2300 * For now, we test that any attempt to use SEM_UNDO fails.
2302 static void
2303 test88d(void)
2305 struct sembuf sop;
2306 int id;
2308 subtest = 3;
2310 if ((id = semget(IPC_PRIVATE, 1, 0600)) == -1) e(0);
2313 * Use an all-ones (but positive) flag field. This will include
2314 * SEM_UNDO, but also tell the IPC server to report no warning.
2316 if (!(SHRT_MAX & SEM_UNDO)) e(0);
2317 sop.sem_num = 0;
2318 sop.sem_op = 1;
2319 sop.sem_flg = SHRT_MAX;
2320 if (semop(id, &sop, 1) != -1) e(0);
2321 if (errno != EINVAL) e(0);
2323 if (semctl(id, 0, IPC_RMID) != 0) e(0);
2326 enum {
2327 RESUME_SEMOP, /* use semop() to resume blocked parties */
2328 RESUME_SETVAL, /* use semctl(SETVAL) to resume blocked parties */
2329 RESUME_SETALL, /* use semctl(SETALL) to resume blocked parties */
2330 NR_RESUMES
2333 enum {
2334 MATCH_FIRST, /* first match completes, blocks second match */
2335 MATCH_SECOND, /* first match does not complete, second match does */
2336 MATCH_KILL, /* second match completes after first is aborted */
2337 MATCH_BOTH, /* first and second match both complete */
2338 MATCH_CASCADE, /* completed match in turn causes another match */
2339 MATCH_ALL, /* a combination of the last two */
2340 NR_MATCHES
2344 * Auxiliary child procedure. The auxiliary children will deadlock until the
2345 * semaphore set is removed.
2347 static void
2348 test88e_childaux(struct link * parent)
2350 struct sembuf sops[3];
2351 struct seminfo seminfo;
2352 int child, id, num;
2354 child = rcv(parent);
2355 id = rcv(parent);
2356 num = rcv(parent);
2358 memset(sops, 0, sizeof(sops));
2360 /* These operations are guaranteed to never return successfully. */
2361 switch (child) {
2362 case 1:
2363 sops[0].sem_num = num;
2364 sops[0].sem_op = 1;
2365 sops[1].sem_num = num;
2366 sops[1].sem_op = 0;
2367 sops[2].sem_num = 0;
2368 sops[2].sem_op = 1;
2369 break;
2370 case 2:
2371 if (semctl(0, 0, IPC_INFO, &seminfo) == -1) e(0);
2372 sops[0].sem_num = num;
2373 sops[0].sem_op = -seminfo.semvmx;
2374 sops[1].sem_num = num;
2375 sops[1].sem_op = -seminfo.semvmx;
2376 sops[2].sem_num = 0;
2377 sops[2].sem_op = 1;
2378 break;
2379 default:
2380 e(0);
2383 snd(parent, 0);
2385 if (semop(id, sops, 3) != -1) e(0);
2386 if (errno != EIDRM) e(0);
2390 * First child procedure.
2392 static void
2393 test88e_child1(struct link * parent)
2395 struct sembuf sops[3];
2396 size_t nsops;
2397 int match, id, expect;
2399 match = rcv(parent);
2400 id = rcv(parent);
2402 /* Start off with some defaults, then refine by match type. */
2403 memset(sops, 0, sizeof(sops));
2404 sops[0].sem_num = 2;
2405 sops[0].sem_op = -1;
2406 nsops = 2;
2407 expect = 0;
2408 switch (match) {
2409 case MATCH_FIRST:
2410 sops[1].sem_num = 3;
2411 sops[1].sem_op = 1;
2412 break;
2413 case MATCH_SECOND:
2414 sops[1].sem_num = 3;
2415 sops[1].sem_op = -1;
2416 sops[2].sem_num = 0;
2417 sops[2].sem_op = 1;
2418 nsops = 3;
2419 expect = -1;
2420 break;
2421 case MATCH_KILL:
2422 sops[1].sem_num = 0;
2423 sops[1].sem_op = 1;
2424 expect = INT_MIN;
2425 break;
2426 case MATCH_BOTH:
2427 case MATCH_CASCADE:
2428 case MATCH_ALL:
2429 sops[1].sem_num = 3;
2430 sops[1].sem_op = 1;
2431 break;
2432 default:
2433 e(0);
2436 snd(parent, 0);
2438 if (semop(id, sops, nsops) != expect) e(0);
2439 if (expect == -1 && errno != EIDRM) e(0);
2443 * Second child procedure.
2445 static void
2446 test88e_child2(struct link * parent)
2448 struct sembuf sops[2];
2449 size_t nsops;
2450 int match, id, expect;
2452 match = rcv(parent);
2453 id = rcv(parent);
2455 /* Start off with some defaults, then refine by match type. */
2456 memset(sops, 0, sizeof(sops));
2457 sops[0].sem_num = 2;
2458 sops[0].sem_op = -1;
2459 nsops = 2;
2460 expect = 0;
2461 switch (match) {
2462 case MATCH_FIRST:
2463 sops[1].sem_num = 0;
2464 sops[1].sem_op = 1;
2465 expect = -1;
2466 break;
2467 case MATCH_SECOND:
2468 case MATCH_KILL:
2469 nsops = 1;
2470 break;
2471 case MATCH_BOTH:
2472 case MATCH_ALL:
2473 sops[1].sem_num = 3;
2474 sops[1].sem_op = 1;
2475 break;
2476 case MATCH_CASCADE:
2477 sops[0].sem_num = 3;
2478 nsops = 1;
2479 break;
2480 default:
2481 e(0);
2484 snd(parent, 0);
2486 if (semop(id, sops, nsops) != expect) e(0);
2487 if (expect == -1 && errno != EIDRM) e(0);
2491 * Third child procedure.
2493 static void
2494 test88e_child3(struct link * parent)
2496 struct sembuf sops[1];
2497 size_t nsops;
2498 int match, id;
2500 match = rcv(parent);
2501 id = rcv(parent);
2503 /* Things are a bit simpler here. */
2504 memset(sops, 0, sizeof(sops));
2505 nsops = 1;
2506 switch (match) {
2507 case MATCH_ALL:
2508 sops[0].sem_num = 3;
2509 sops[0].sem_op = -2;
2510 break;
2511 default:
2512 e(0);
2515 snd(parent, 0);
2517 if (semop(id, sops, nsops) != 0) e(0);
2521 * Perform one test for operations affecting multiple processes.
2523 static void
2524 sub88e(unsigned int match, unsigned int resume, unsigned int aux)
2526 struct link aux1, aux2, child1, child2, child3;
2527 struct sembuf sop;
2528 unsigned short val[4];
2529 int id, inc, aux_zcnt, aux_ncnt;
2532 * For this test we use one single semaphore set, with four semaphores.
2533 * The first semaphore is increased in the case that an operation that
2534 * should never complete does complete, and thus should stay zero.
2535 * Depending on 'aux', the second or third semaphore is used by the
2536 * auxiliary children (if any, also depending on 'aux') to deadlock on.
2537 * The third and higher semaphores are used in the main operations.
2539 if ((id = semget(IPC_PRIVATE, __arraycount(val), 0666)) == -1) e(0);
2541 aux_zcnt = aux_ncnt = 0;
2543 /* Start the first auxiliary child if desired, before all others. */
2544 if (aux & 1) {
2545 spawn(&aux1, test88e_childaux, DROP_ALL);
2547 snd(&aux1, 1);
2548 snd(&aux1, id);
2549 snd(&aux1, (aux & 4) ? 2 : 1);
2551 if (rcv(&aux1) != 0) e(0);
2553 if (aux & 4)
2554 aux_zcnt++;
2557 /* Start and configure all children for this specific match test. */
2558 spawn(&child1, test88e_child1, DROP_ALL);
2560 snd(&child1, match);
2561 snd(&child1, id);
2563 if (rcv(&child1) != 0) e(0);
2566 * For fairness tests, we must ensure that the first child blocks on
2567 * the semaphore before the second child does.
2569 switch (match) {
2570 case MATCH_FIRST:
2571 case MATCH_SECOND:
2572 case MATCH_KILL:
2573 usleep(WAIT_USECS);
2574 break;
2577 spawn(&child2, test88e_child2, DROP_NONE);
2579 snd(&child2, match);
2580 snd(&child2, id);
2582 if (rcv(&child2) != 0) e(0);
2584 if (match == MATCH_ALL) {
2585 spawn(&child3, test88e_child3, DROP_USER);
2587 snd(&child3, match);
2588 snd(&child3, id);
2590 if (rcv(&child3) != 0) e(0);
2593 /* Start the second auxiliary child if desired, after all others. */
2594 if (aux & 2) {
2595 spawn(&aux2, test88e_childaux, DROP_NONE);
2597 snd(&aux2, 2);
2598 snd(&aux2, id);
2599 snd(&aux2, (aux & 4) ? 2 : 1);
2601 if (rcv(&aux2) != 0) e(0);
2603 if (aux & 4)
2604 aux_ncnt++;
2607 usleep(WAIT_USECS);
2610 * Test semaphore values and determine the value with which to increase
2611 * the third semaphore. For MATCH_KILL, also kill the first child.
2613 inc = 1;
2614 switch (match) {
2615 case MATCH_FIRST:
2616 case MATCH_SECOND:
2617 TEST_SEM(id, 2, 0, 0, 2 + aux_ncnt, aux_zcnt);
2618 TEST_SEM(id, 3, 0, 0, 0, 0);
2619 break;
2620 case MATCH_KILL:
2621 TEST_SEM(id, 2, 0, 0, 2 + aux_ncnt, aux_zcnt);
2623 terminate(&child1);
2625 /* As stated before, non-self kills need not be instant. */
2626 usleep(WAIT_USECS);
2628 TEST_SEM(id, 2, 0, 0, 1 + aux_ncnt, aux_zcnt);
2629 TEST_SEM(id, 3, 0, 0, 0, 0);
2630 break;
2631 case MATCH_BOTH:
2632 TEST_SEM(id, 2, 0, 0, 2 + aux_ncnt, aux_zcnt);
2633 TEST_SEM(id, 3, 0, 0, 0, 0);
2634 inc = 2;
2635 break;
2636 case MATCH_CASCADE:
2637 TEST_SEM(id, 2, 0, 0, 1 + aux_ncnt, aux_zcnt);
2638 TEST_SEM(id, 3, 0, 0, 1, 0);
2639 break;
2640 case MATCH_ALL:
2641 TEST_SEM(id, 2, 0, 0, 2 + aux_ncnt, aux_zcnt);
2642 TEST_SEM(id, 3, 0, 0, 1, 0);
2643 inc = 2;
2644 break;
2645 default:
2646 e(0);
2649 TEST_SEM(id, 0, 0, 0, 0, 0);
2650 TEST_SEM(id, 1, 0, 0, -1, -1);
2652 /* Resume the appropriate set of children. */
2653 switch (resume) {
2654 case RESUME_SEMOP:
2655 memset(&sop, 0, sizeof(sop));
2656 sop.sem_num = 2;
2657 sop.sem_op = inc;
2658 if (semop(id, &sop, 1) != 0) e(0);
2659 break;
2660 case RESUME_SETVAL:
2661 if (semctl(id, 2, SETVAL, inc) != 0) e(0);
2662 break;
2663 case RESUME_SETALL:
2664 memset(val, 0, sizeof(val));
2665 val[2] = inc;
2666 if (semctl(id, 0, SETALL, val) != 0) e(0);
2667 break;
2668 default:
2669 e(0);
2673 * See if the right children were indeed resumed, and retest the
2674 * semaphore values.
2676 switch (match) {
2677 case MATCH_FIRST:
2678 TEST_SEM(id, 2, 0, child1.pid, 1 + aux_ncnt, aux_zcnt);
2679 TEST_SEM(id, 3, 1, child1.pid, 0, 0);
2680 collect(&child1);
2681 break;
2682 case MATCH_SECOND:
2683 TEST_SEM(id, 2, 0, child2.pid, 1 + aux_ncnt, aux_zcnt);
2684 TEST_SEM(id, 3, 0, 0, 0, 0);
2685 collect(&child2);
2686 break;
2687 case MATCH_KILL:
2688 TEST_SEM(id, 2, 0, child2.pid, aux_ncnt, aux_zcnt);
2689 TEST_SEM(id, 3, 0, 0, 0, 0);
2690 collect(&child2);
2691 break;
2692 case MATCH_BOTH:
2694 * The children are not ordered in this case, so we do not know
2695 * which one gets access to the semaphores last.
2697 TEST_SEM(id, 2, 0, -1, aux_ncnt, aux_zcnt);
2698 TEST_SEM(id, 3, 2, -1, 0, 0);
2699 collect(&child1);
2700 collect(&child2);
2701 break;
2702 case MATCH_CASCADE:
2703 TEST_SEM(id, 2, 0, child1.pid, aux_ncnt, aux_zcnt);
2704 TEST_SEM(id, 3, 0, child2.pid, 0, 0);
2705 collect(&child1);
2706 collect(&child2);
2707 break;
2708 case MATCH_ALL:
2709 TEST_SEM(id, 2, 0, -1, aux_ncnt, aux_zcnt);
2710 TEST_SEM(id, 3, 0, child3.pid, 0, 0);
2711 collect(&child1);
2712 collect(&child2);
2713 collect(&child3);
2714 break;
2715 default:
2716 e(0);
2719 TEST_SEM(id, 0, 0, 0, 0, 0);
2720 TEST_SEM(id, 1, 0, 0, -1, -1);
2722 /* Remove the semaphore set. This should unblock remaining callers. */
2723 if (semctl(id, 0, IPC_RMID) != 0) e(0);
2725 /* Wait for the children that were not resumed, but should be now. */
2726 switch (match) {
2727 case MATCH_FIRST:
2728 collect(&child2);
2729 break;
2730 case MATCH_SECOND:
2731 collect(&child1);
2732 break;
2733 case MATCH_KILL:
2734 case MATCH_BOTH:
2735 case MATCH_CASCADE:
2736 case MATCH_ALL:
2737 break;
2738 default:
2739 e(0);
2742 /* Wait for the auxiliary children as well. */
2743 if (aux & 1)
2744 collect(&aux1);
2745 if (aux & 2)
2746 collect(&aux2);
2750 * Test operations affecting multiple processes, ensuring the following points:
2751 * 1) an operation resumes all possible waiters; 2) a resumed operation in turn
2752 * correctly resumes other now-unblocked operations; 3) a basic level of FIFO
2753 * fairness is provided between blocked parties; 4) all the previous points are
2754 * unaffected by additional waiters that are not being resumed; 5) identifier
2755 * removal properly resumes all affected waiters.
2757 static void
2758 test88e(void)
2760 unsigned int resume, match, aux;
2762 subtest = 4;
2764 for (match = 0; match < NR_MATCHES; match++)
2765 for (resume = 0; resume < NR_RESUMES; resume++)
2766 for (aux = 1; aux <= 8; aux++) /* 0 and 4 are equal */
2767 sub88e(match, resume, aux);
2771 * Verify that non-root processes can use sysctl(2) to see semaphore sets
2772 * created by root.
2774 static void
2775 test88f_child(struct link * parent)
2777 static const int mib[] = { CTL_KERN, KERN_SYSVIPC, KERN_SYSVIPC_INFO,
2778 KERN_SYSVIPC_SEM_INFO };
2779 struct sem_sysctl_info *semsi;
2780 size_t len;
2781 int id[2], id2, seen[2];
2782 int32_t i;
2784 id[0] = rcv(parent);
2785 id[1] = rcv(parent);
2787 if (sysctl(mib, __arraycount(mib), NULL, &len, NULL, 0) != 0) e(0);
2789 if ((semsi = malloc(len)) == NULL) e(0);
2791 if (sysctl(mib, __arraycount(mib), semsi, &len, NULL, 0) != 0) e(0);
2793 seen[0] = seen[1] = 0;
2794 for (i = 0; i < semsi->seminfo.semmni; i++) {
2795 if (!(semsi->semids[i].sem_perm.mode & SEM_ALLOC))
2796 continue;
2798 id2 = IXSEQ_TO_IPCID(i, semsi->semids[i].sem_perm);
2799 if (id2 == id[0])
2800 seen[0]++;
2801 else if (id2 == id[1])
2802 seen[1]++;
2805 free(semsi);
2807 if (seen[0] != 1) e(0);
2808 if (seen[1] != 1) e(0);
2812 * Test sysctl(2) based information retrieval. This test aims to ensure that
2813 * in particular ipcs(1) and ipcrm(1) will be able to do their jobs.
2815 static void
2816 test88f(void)
2818 static const int mib[] = { CTL_KERN, KERN_SYSVIPC, KERN_SYSVIPC_INFO,
2819 KERN_SYSVIPC_SEM_INFO };
2820 struct seminfo seminfo, seminfo2;
2821 struct sem_sysctl_info *semsi;
2822 struct semid_ds_sysctl *semds;
2823 struct link child;
2824 size_t len, size;
2825 int id[2], id2;
2826 int32_t i, slot[2];
2829 * Verify that we can retrieve only the general semaphore information,
2830 * without any actual semaphore set entries. This is actually a dirty
2831 * sysctl-level hack, as sysctl requests should not behave differently
2832 * based on the requested length. However, ipcs(1) relies on this.
2834 len = sizeof(seminfo);
2835 if (sysctl(mib, __arraycount(mib), &seminfo, &len, NULL, 0) != 0) e(0);
2836 if (len != sizeof(seminfo)) e(0);
2838 if (semctl(0, 0, IPC_INFO, &seminfo2) == -1) e(0);
2840 if (memcmp(&seminfo, &seminfo2, sizeof(seminfo)) != 0) e(0);
2842 /* Verify that the correct size estimation is returned. */
2843 if (seminfo.semmni <= 0) e(0);
2844 if (seminfo.semmni > SHRT_MAX) e(0);
2846 size = sizeof(*semsi) +
2847 sizeof(semsi->semids[0]) * (seminfo.semmni - 1);
2849 len = 0;
2850 if (sysctl(mib, __arraycount(mib), NULL, &len, NULL, 0) != 0) e(0);
2851 if (len != size) e(0);
2853 /* Create two semaphore sets that should show up in the listing. */
2854 if ((id[0] = semget(KEY_A, 5, IPC_CREAT | 0612)) < 0) e(0);
2856 if ((id[1] = semget(IPC_PRIVATE, 3, 0650)) < 0) e(0);
2859 * Retrieve the entire semaphore array, and verify that the general
2860 * semaphore information is still correct.
2862 if ((semsi = malloc(size)) == NULL) e(0);
2864 len = size;
2865 if (sysctl(mib, __arraycount(mib), semsi, &len, NULL, 0) != 0) e(0);
2866 if (len != size) e(0);
2868 if (sizeof(semsi->seminfo) != sizeof(seminfo)) e(0);
2869 if (memcmp(&semsi->seminfo, &seminfo, sizeof(semsi->seminfo)) != 0)
2870 e(0);
2872 /* Verify that our semaphore sets are each in the array once. */
2873 slot[0] = slot[1] = -1;
2874 for (i = 0; i < seminfo.semmni; i++) {
2875 if (!(semsi->semids[i].sem_perm.mode & SEM_ALLOC))
2876 continue;
2878 id2 = IXSEQ_TO_IPCID(i, semsi->semids[i].sem_perm);
2879 if (id2 == id[0]) {
2880 if (slot[0] != -1) e(0);
2881 slot[0] = i;
2882 } else if (id2 == id[1]) {
2883 if (slot[1] != -1) e(0);
2884 slot[1] = i;
2888 if (slot[0] < 0) e(0);
2889 if (slot[1] < 0) e(0);
2891 /* Check that the semaphore sets have the expected properties. */
2892 semds = &semsi->semids[slot[0]];
2893 if (semds->sem_perm.uid != geteuid()) e(0);
2894 if (semds->sem_perm.gid != getegid()) e(0);
2895 if (semds->sem_perm.cuid != geteuid()) e(0);
2896 if (semds->sem_perm.cgid != getegid()) e(0);
2897 if (semds->sem_perm.mode != (SEM_ALLOC | 0612)) e(0);
2898 if (semds->sem_perm._key != KEY_A) e(0);
2899 if (semds->sem_nsems != 5) e(0);
2900 if (semds->sem_otime != 0) e(0);
2901 if (semds->sem_ctime == 0) e(0);
2903 semds = &semsi->semids[slot[1]];
2904 if (semds->sem_perm.uid != geteuid()) e(0);
2905 if (semds->sem_perm.gid != getegid()) e(0);
2906 if (semds->sem_perm.cuid != geteuid()) e(0);
2907 if (semds->sem_perm.cgid != getegid()) e(0);
2908 if (semds->sem_perm.mode != (SEM_ALLOC | 0650)) e(0);
2909 if (semds->sem_perm._key != IPC_PRIVATE) e(0);
2910 if (semds->sem_nsems != 3) e(0);
2911 if (semds->sem_otime != 0) e(0);
2912 if (semds->sem_ctime == 0) e(0);
2914 /* Make sure that non-root users can see them as well. */
2915 spawn(&child, test88f_child, DROP_ALL);
2917 snd(&child, id[0]);
2918 snd(&child, id[1]);
2920 collect(&child);
2922 /* Clean up, and verify that the sets are no longer in the listing. */
2923 if (semctl(id[0], 0, IPC_RMID) != 0) e(0);
2924 if (semctl(id[1], 0, IPC_RMID) != 0) e(0);
2926 len = size;
2927 if (sysctl(mib, __arraycount(mib), semsi, &len, NULL, 0) != 0) e(0);
2928 if (len != size) e(0);
2930 for (i = 0; i < seminfo.semmni; i++) {
2931 if (!(semsi->semids[i].sem_perm.mode & SEM_ALLOC))
2932 continue;
2934 id2 = IXSEQ_TO_IPCID(i, semsi->semids[i].sem_perm);
2935 if (id2 == id[0]) e(0);
2936 if (id2 == id[1]) e(0);
2939 free(semsi);
2943 * Initialize the test.
2945 static void
2946 test88_init(void)
2948 static const int mib[] = { CTL_KERN, KERN_SYSVIPC, KERN_SYSVIPC_SEM };
2949 struct group *gr;
2950 size_t len;
2951 int i;
2953 /* Start with full root privileges. */
2954 setuid(geteuid());
2956 if ((gr = getgrnam(ROOT_GROUP)) == NULL) e(0);
2958 setgid(gr->gr_gid);
2959 setegid(gr->gr_gid);
2962 * Verify that the IPC service is running at all. If not, there is
2963 * obviously no point in running this test.
2965 len = sizeof(i);
2966 if (sysctl(mib, __arraycount(mib), &i, &len, NULL, 0) != 0) e(0);
2967 if (len != sizeof(i)) e(0);
2969 if (i == 0) {
2970 printf("skipped\n");
2971 cleanup();
2972 exit(0);
2975 /* Allocate a memory page followed by an unmapped page. */
2976 page_size = getpagesize();
2977 page_ptr = mmap(NULL, page_size * 2, PROT_READ | PROT_WRITE,
2978 MAP_ANON | MAP_PRIVATE, -1, 0);
2979 if (page_ptr == MAP_FAILED) e(0);
2980 bad_ptr = page_ptr + page_size;
2981 if (munmap(bad_ptr, page_size) != 0) e(0);
2985 * Test program for SysV IPC semaphores.
2988 main(int argc, char ** argv)
2990 int i, m;
2992 start(88);
2994 test88_init();
2996 if (argc == 2)
2997 m = atoi(argv[1]);
2998 else
2999 m = 0xFF;
3001 for (i = 0; i < ITERATIONS; i++) {
3002 if (m & 0x01) test88a();
3003 if (m & 0x02) test88b();
3004 if (m & 0x04) test88c();
3005 if (m & 0x08) test88d();
3006 if (m & 0x10) test88e();
3007 if (m & 0x20) test88f();
3010 quit();