xref: /minix/minix/tests/test88.c (revision 77e79d33)
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>
13 
14 #include "common.h"
15 
16 #define ITERATIONS	3
17 
18 #define WAIT_USECS	100000		/* time for processes to get ready */
19 
20 #define KEY_A		0x73570001
21 #define KEY_B		(KEY_A + 1)
22 #define KEY_C		(KEY_A + 2)
23 
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 */
28 
29 enum {
30 	DROP_NONE,
31 	DROP_USER,
32 	DROP_ALL,
33 };
34 
35 enum {
36 	SUGID_NONE,
37 	SUGID_ROOT_USER,
38 	SUGID_NONROOT_USER,
39 	SUGID_ROOT_GROUP,
40 	SUGID_NONROOT_GROUP,
41 };
42 
43 struct link {
44 	pid_t pid;
45 	int sndfd;
46 	int rcvfd;
47 };
48 
49 /*
50  * Test semaphore properties.  This is a macro, so that it prints useful line
51  * information if an error occurs.
52  */
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);
59 
60 static int nr_signals = 0;
61 
62 static size_t page_size;
63 static char *page_ptr;
64 static void *bad_ptr;
65 
66 /*
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.
69  */
70 static void
spawn(struct link * link,void (* proc)(struct link *),int drop)71 spawn(struct link * link, void (* proc)(struct link *), int drop)
72 {
73 	struct passwd *pw;
74 	struct group *gr;
75 	int up[2], dn[2];
76 
77 	fflush(stdout);
78 	fflush(stderr);
79 
80 	if (pipe(up) != 0) e(0);
81 	if (pipe(dn) != 0) e(0);
82 
83 	link->pid = fork();
84 
85 	switch (link->pid) {
86 	case 0:
87 		close(up[1]);
88 		close(dn[0]);
89 
90 		link->pid = getppid();
91 		link->rcvfd = up[0];
92 		link->sndfd = dn[1];
93 
94 		errct = 0;
95 
96 		switch (drop) {
97 		case DROP_ALL:
98 			if (setgroups(0, NULL) != 0) e(0);
99 
100 			if ((gr = getgrnam(NONROOT_GROUP)) == NULL) e(0);
101 
102 			if (setgid(gr->gr_gid) != 0) e(0);
103 			if (setegid(gr->gr_gid) != 0) e(0);
104 
105 			/* FALLTHROUGH */
106 		case DROP_USER:
107 			if ((pw = getpwnam(NONROOT_USER)) == NULL) e(0);
108 
109 			if (setuid(pw->pw_uid) != 0) e(0);
110 		}
111 
112 		proc(link);
113 
114 		/* Close our pipe FDs on exit, so that we can make zombies. */
115 		exit(errct);
116 	case -1:
117 		e(0);
118 		break;
119 	}
120 
121 	close(up[0]);
122 	close(dn[1]);
123 
124 	link->sndfd = up[1];
125 	link->rcvfd = dn[0];
126 }
127 
128 /*
129  * Wait for a child process to terminate, and clean up.
130  */
131 static void
collect(struct link * link)132 collect(struct link * link)
133 {
134 	int status;
135 
136 	close(link->sndfd);
137 	close(link->rcvfd);
138 
139 	if (waitpid(link->pid, &status, 0) != link->pid) e(0);
140 
141 	if (!WIFEXITED(status)) e(0);
142 	else errct += WEXITSTATUS(status);
143 }
144 
145 /*
146  * Forcibly terminate a child process, and clean up.
147  */
148 static void
terminate(struct link * link)149 terminate(struct link * link)
150 {
151 	int status;
152 
153 	if (kill(link->pid, SIGKILL) != 0) e(0);
154 
155 	close(link->sndfd);
156 	close(link->rcvfd);
157 
158 	if (waitpid(link->pid, &status, 0) <= 0) e(0);
159 
160 	if (WIFSIGNALED(status)) {
161 		if (WTERMSIG(status) != SIGKILL) e(0);
162 	} else {
163 		if (!WIFEXITED(status)) e(0);
164 		else errct += WEXITSTATUS(status);
165 	}
166 }
167 
168 /*
169  * Send an integer value to the child or parent.
170  */
171 static void
snd(struct link * link,int val)172 snd(struct link * link, int val)
173 {
174 
175 	if (write(link->sndfd, (void *)&val, sizeof(val)) != sizeof(val)) e(0);
176 }
177 
178 /*
179  * Receive an integer value from the child or parent, or -1 on EOF.
180  */
181 static int
rcv(struct link * link)182 rcv(struct link * link)
183 {
184 	int r, val;
185 
186 	if ((r = read(link->rcvfd, (void *)&val, sizeof(val))) == 0)
187 		return -1;
188 
189 	if (r != sizeof(val)) e(0);
190 
191 	return val;
192 }
193 
194 /*
195  * Child procedure that creates semaphore sets.
196  */
197 static void
test_perm_child(struct link * parent)198 test_perm_child(struct link * parent)
199 {
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];
206 
207 	/*
208 	 * Repeatedly create a number of semaphores with the masks provided by
209 	 * the parent process.
210 	 */
211 	while ((mask = rcv(parent)) != -1) {
212 		rmask = rcv(parent);
213 		sugid = rcv(parent);
214 
215 		/*
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).
219 		 */
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);
227 
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;
250 			}
251 
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);
260 		}
261 
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);
270 		}
271 
272 		snd(parent, id[0]);
273 		snd(parent, id[1]);
274 		snd(parent, id[2]);
275 
276 		/* The other child process runs here. */
277 
278 		if (rcv(parent) != 0) e(0);
279 
280 		/*
281 		 * For owner tests, the other child may already have removed
282 		 * the semaphore sets, so ignore return values here.
283 		 */
284 		(void)semctl(id[0], 0, IPC_RMID);
285 		(void)semctl(id[1], 0, IPC_RMID);
286 		(void)semctl(id[2], 0, IPC_RMID);
287 	}
288 }
289 
290 /*
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.
297  */
298 static void
test_perm(void (* proc)(struct link *),int owner_test)299 test_perm(void (* proc)(struct link *), int owner_test)
300 {
301 	struct link child1, child2;
302 	int n, shift, bit, mask, rmask, drop1, drop2, sugid, id[3];
303 
304 	for (n = 0; n < 7; n++) {
305 		/*
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.
314 		 */
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;
359 		}
360 
361 		spawn(&child1, test_perm_child, drop1);
362 		spawn(&child2, proc, drop2);
363 
364 		for (bit = 0; bit <= 7; bit++) {
365 			mask = bit << shift;
366 			rmask = 0777 & ~(7 << shift);
367 
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);
374 
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);
380 
381 			snd(&child1, 0);
382 		}
383 
384 		/* We use a bitmask of -1 to terminate the children. */
385 		snd(&child1, -1);
386 		snd(&child2, -1);
387 
388 		collect(&child1);
389 		collect(&child2);
390 	}
391 }
392 
393 /*
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.
397  */
398 static void
test88a_perm(struct link * parent)399 test88a_perm(struct link * parent)
400 {
401 	int r, tbit, bit, mask, id[3];
402 
403 	while ((tbit = rcv(parent)) != -1) {
404 		id[0] = rcv(parent);
405 		id[1] = rcv(parent);
406 		id[2] = rcv(parent);
407 
408 		/*
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.
412 		 */
413 		for (bit = 0; bit <= 7; bit++) {
414 			mask = bit << 6;
415 
416 			/*
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.
420 			 */
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);
426 
427 			/*
428 			 * Same for semaphore set B, which was created with all
429 			 * irrelevant mode bits inverted.
430 			 */
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);
436 
437 			/*
438 			 * Semaphore set C was created with only irrelevant
439 			 * mode bits set, so opening it must always fail.
440 			 */
441 			if (semget(KEY_C, 0, mask) != -1) e(0);
442 			if (errno != EACCES) e(0);
443 		}
444 
445 		snd(parent, 0);
446 	}
447 }
448 
449 /*
450  * Test the basic semget(2) functionality.
451  */
452 static void
test88a(void)453 test88a(void)
454 {
455 	struct seminfo seminfo;
456 	struct semid_ds semds;
457 	time_t now;
458 	unsigned int i, j;
459 	int id[3], *idp;
460 
461 	subtest = 0;
462 
463 	/*
464 	 * The key IPC_PRIVATE must always yield a new semaphore set identifier
465 	 * regardless of whether IPC_CREAT and IPC_EXCL are supplied.
466 	 */
467 	if ((id[0] = semget(IPC_PRIVATE, 1, IPC_CREAT | 0600)) < 0) e(0);
468 
469 	if ((id[1] = semget(IPC_PRIVATE, 1, IPC_CREAT | IPC_EXCL | 0600)) < 0)
470 		e(0);
471 
472 	if ((id[2] = semget(IPC_PRIVATE, 1, 0600)) < 0) e(0);
473 
474 	if (id[0] == id[1]) e(0);
475 	if (id[1] == id[2]) e(0);
476 	if (id[0] == id[2]) e(0);
477 
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);
481 
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);
487 
488 	/*
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.
492 	 */
493 	if (semget(KEY_A, 1, 0600) != -1) e(0);
494 	if (errno != ENOENT);
495 
496 	if ((id[0] = semget(KEY_A, 1, IPC_CREAT | IPC_EXCL | 0600)) < 0) e(0);
497 
498 	if (semget(KEY_B, 1, 0600) != -1) e(0);
499 	if (errno != ENOENT);
500 
501 	if ((id[1] = semget(KEY_B, 1, IPC_CREAT | 0600)) < 0) e(0);
502 
503 	if (id[0] == id[1]) e(0);
504 
505 	if ((id[2] = semget(KEY_A, 1, 0600)) < 0) e(0);
506 	if (id[2] != id[0]) e(0);
507 
508 	if ((id[2] = semget(KEY_B, 1, IPC_CREAT | 0600)) < 0) e(0);
509 	if (id[2] != id[2]) e(0);
510 
511 	if (semget(KEY_A, 1, IPC_CREAT | IPC_EXCL | 0600) != -1) e(0);
512 	if (errno != EEXIST) e(0);
513 
514 	if (semctl(id[0], 0, IPC_RMID) != 0) e(0);
515 	if (semctl(id[1], 0, IPC_RMID) != 0) e(0);
516 
517 	/*
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.
522 	 */
523 	if (semctl(0, 0, IPC_INFO, &seminfo) == -1) e(0);
524 	if (seminfo.semmni < 3 || seminfo.semmni > USHRT_MAX) e(0);
525 
526 	if ((idp = malloc(sizeof(int) * (seminfo.semmni + 1))) == NULL) e(0);
527 
528 	for (i = 0; i < seminfo.semmni + 1; i++) {
529 		if ((idp[i] = semget(KEY_A + i, 1, IPC_CREAT | 0600)) < 0)
530 			break;
531 
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);
535 	}
536 
537 	if (errno != ENOSPC) e(0);
538 	if (i < 3) e(0);
539 	if (i == seminfo.semmni + 1) e(0);
540 
541 	while (i-- > 0)
542 		if (semctl(idp[i], 0, IPC_RMID) != 0) e(0);
543 
544 	free(idp);
545 
546 	/*
547 	 * The given number of semaphores must be within bounds.
548 	 */
549 	if (semget(KEY_A, -1, IPC_CREAT | 0600) != -1) e(0);
550 	if (errno != EINVAL) e(0);
551 
552 	if (semget(KEY_A, 0, IPC_CREAT | 0600) != -1) e(0);
553 	if (errno != EINVAL) e(0);
554 
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);
558 
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);
562 
563 	if ((id[0] = semget(KEY_A, 2, IPC_CREAT | 0600)) < 0) e(0);
564 
565 	if ((id[1] = semget(KEY_A, 0, 0600)) < 0) e(0);
566 	if (id[0] != id[1]) e(0);
567 
568 	if ((id[1] = semget(KEY_A, 1, 0600)) < 0) e(0);
569 	if (id[0] != id[1]) e(0);
570 
571 	if ((id[1] = semget(KEY_A, 2, 0600)) < 0) e(0);
572 	if (id[0] != id[1]) e(0);
573 
574 	if ((id[1] = semget(KEY_A, 3, 0600)) != -1) e(0);
575 	if (errno != EINVAL) e(0);
576 
577 	if ((id[1] = semget(KEY_A, seminfo.semmsl + 1, 0600)) != -1) e(0);
578 	if (errno != EINVAL) e(0);
579 
580 	if (semctl(id[0], 0, IPC_RMID) != 0) e(0);
581 
582 	/*
583 	 * Verify that the initial values for the semaphore set are as
584 	 * expected.
585 	 */
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);
592 
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);
603 
604 	for (i = 0; i < semds.sem_nsems; i++)
605 		TEST_SEM(id[0], i, 0, 0, 0, 0);
606 
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);
617 
618 	for (i = 0; i < semds.sem_nsems; i++)
619 		TEST_SEM(id[1], i, 0, 0, 0, 0);
620 
621 	if (semctl(id[1], 0, IPC_RMID) != 0) e(0);
622 	if (semctl(id[0], 0, IPC_RMID) != 0) e(0);
623 
624 	/*
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.
628 	 */
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);
631 
632 	if ((id[1] = semget(KEY_A, 0, 0600)) < 0) e(0);
633 	if (id[0] != id[1]) e(0);
634 
635 	if ((id[1] = semget(KEY_A, 0, 0000)) < 0) e(0);
636 	if (id[0] != id[1]) e(0);
637 
638 	if (semctl(id[0], 0, IPC_RMID) != 0) e(0);
639 
640 	/*
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.
644 	 */
645 	test_perm(test88a_perm, 0 /*owner_test*/);
646 }
647 
648 /*
649  * Test semop(2) permission checks.
650  */
651 static void
test88b_perm(struct link * parent)652 test88b_perm(struct link * parent)
653 {
654 	struct sembuf sops[2];
655 	size_t nsops;
656 	int i, r, tbit, bit, id[3];
657 
658 	while ((tbit = rcv(parent)) != -1) {
659 		id[0] = rcv(parent);
660 		id[1] = rcv(parent);
661 		id[2] = rcv(parent);
662 
663 		/*
664 		 * This loop is designed such that failure of any bit-based
665 		 * subset will not result in subsequent operations blocking.
666 		 */
667 		for (i = 0; i < 8; i++) {
668 			memset(sops, 0, sizeof(sops));
669 
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:
702 				/*
703 				 * Two operations on the same semaphore.  As
704 				 * such, this verifies that operations are
705 				 * processed in array order.
706 				 */
707 				sops[0].sem_op = 1;
708 				sops[1].sem_op = -1;
709 				nsops = 2;
710 				bit = 2;
711 				break;
712 			case 7:
713 				/*
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.
719 				 */
720 				sops[0].sem_num = USHRT_MAX;
721 				nsops = 2;
722 				bit = 4;
723 				break;
724 			}
725 
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);
730 
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);
735 
736 			if (semop(id[2], sops, nsops) != -1) e(0);
737 			if (errno != EACCES) e(0);
738 		}
739 
740 		snd(parent, 0);
741 	}
742 }
743 
744 /*
745  * Signal handler.
746  */
747 static void
got_signal(int sig)748 got_signal(int sig)
749 {
750 
751 	if (sig != SIGHUP) e(0);
752 	if (nr_signals != 0) e(0);
753 	nr_signals++;
754 }
755 
756 /*
757  * Child process for semop(2) tests, mainly testing blocking operations.
758  */
759 static void
test88b_child(struct link * parent)760 test88b_child(struct link * parent)
761 {
762 	struct sembuf sops[5];
763 	struct sigaction act;
764 	int id;
765 
766 	id = rcv(parent);
767 
768 	memset(sops, 0, sizeof(sops));
769 	if (semop(id, sops, 1) != 0) e(0);
770 
771 	if (rcv(parent) != 1) e(0);
772 
773 	sops[0].sem_op = -3;
774 	if (semop(id, sops, 1) != 0) e(0);
775 
776 	if (rcv(parent) != 2) e(0);
777 
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);
785 
786 	if (rcv(parent) != 3) e(0);
787 
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);
799 
800 	if (rcv(parent) != 4) e(0);
801 
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);
807 
808 	if (rcv(parent) != 5) e(0);
809 
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);
816 
817 	if (rcv(parent) != 6) e(0);
818 
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);
826 
827 	if (rcv(parent) != 7) e(0);
828 
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);
835 
836 	if (rcv(parent) != 8) e(0);
837 
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);
844 
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);
849 
850 	if (rcv(parent) != 9) e(0);
851 
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);
862 
863 	TEST_SEM(id, 0, 0, parent->pid, 0, 0);
864 	TEST_SEM(id, 1, 1, parent->pid, 0, 0);
865 
866 	if (rcv(parent) != 10) e(0);
867 
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);
872 
873 	id = rcv(parent);
874 
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);
881 
882 	if (rcv(parent) != 11) e(0);
883 
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);
889 
890 	id = rcv(parent);
891 
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);
897 
898 	snd(parent, errct);
899 	if (rcv(parent) != 12) e(0);
900 
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);
907 
908 	e(0);
909 }
910 
911 /*
912  * Test the basic semop(2) functionality.
913  */
914 static void
test88b(void)915 test88b(void)
916 {
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;
925 
926 	subtest = 1;
927 
928 	/* Allocate a buffer for operations. */
929 	if (semctl(0, 0, IPC_INFO, &seminfo) == -1) e(0);
930 
931 	if (seminfo.semopm < 3 || seminfo.semopm > USHRT_MAX) e(0);
932 
933 	size = sizeof(sops[0]) * (seminfo.semopm + 1);
934 	if ((sops = malloc(size)) == NULL) e(0);
935 	memset(sops, 0, size);
936 
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);
939 
940 	/* If no operations are given, the call should succeed. */
941 	if (semop(id, NULL, 0) != 0) e(0);
942 
943 	/*
944 	 * If any operations are given, the pointer must be valid.  Moreover,
945 	 * partially valid buffers must never be processed partially.
946 	 */
947 	if (semop(id, NULL, 1) != -1) e(0);
948 	if (errno != EFAULT) e(0);
949 
950 	if (semop(id, bad_ptr, 1) != -1) e(0);
951 	if (errno != EFAULT) e(0);
952 
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);
958 
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);
962 
963 	/*
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.
966 	 */
967 	time(&now);
968 	if (semop(id, sops, 1) != 0) e(0);
969 
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);
973 
974 	/* Test the limit on the number of operations. */
975 	if (semop(id, sops, seminfo.semopm) != 0) e(0);
976 
977 	if (semop(id, sops, seminfo.semopm + 1) != -1) e(0);
978 	if (errno != E2BIG) e(0);
979 
980 	if (semop(id, sops, SIZE_MAX) != -1) e(0);
981 	if (errno != E2BIG) e(0);
982 
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);
987 
988 	sops[1].sem_num = USHRT_MAX;
989 	if (semop(id, sops, 2) != -1) e(0);
990 	if (errno != EFBIG) e(0);
991 
992 	/*
993 	 * Test nonblocking operations on a single semaphore, starting with
994 	 * value limit and overflow cases.
995 	 */
996 	if (seminfo.semvmx < 3 || seminfo.semvmx > SHRT_MAX) e(0);
997 
998 	sops[0].sem_flg = IPC_NOWAIT;
999 
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);
1006 	}
1007 
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);
1011 
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);
1017 
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);
1022 
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);
1027 
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);
1034 	}
1035 
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);
1039 
1040 	/*
1041 	 * Test basic nonblocking operations on a single semaphore.
1042 	 */
1043 	sops[0].sem_op = 0;
1044 	if (semop(id, sops, 1) != 0) e(0);
1045 
1046 	sops[0].sem_op = 2;
1047 	if (semop(id, sops, 1) != 0) e(0);
1048 	if (semctl(id, 0, GETVAL) != 2) e(0);
1049 
1050 	sops[0].sem_op = 0;
1051 	if (semop(id, sops, 1) != -1) e(0);
1052 	if (errno != EAGAIN) e(0);
1053 
1054 	sops[0].sem_op = -3;
1055 	if (semop(id, sops, 1) != -1) e(0);
1056 	if (errno != EAGAIN) e(0);
1057 
1058 	sops[0].sem_op = 1;
1059 	if (semop(id, sops, 1) != 0) e(0);
1060 	if (semctl(id, 0, GETVAL) != 3) e(0);
1061 
1062 	sops[0].sem_op = -1;
1063 	if (semop(id, sops, 1) != 0) e(0);
1064 	if (semctl(id, 0, GETVAL) != 2) e(0);
1065 
1066 	sops[0].sem_op = 0;
1067 	if (semop(id, sops, 1) != -1) e(0);
1068 	if (errno != EAGAIN) e(0);
1069 
1070 	sops[0].sem_op = -2;
1071 	if (semop(id, sops, 1) != 0) e(0);
1072 	if (semctl(id, 0, GETVAL) != 0) e(0);
1073 
1074 	sops[0].sem_op = 0;
1075 	if (semop(id, sops, 1) != 0) e(0);
1076 
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);
1081 
1082 	/* Even if no operations are given, the identifier must be valid. */
1083 	if (semctl(id, 0, IPC_RMID) != 0) e(0);
1084 
1085 	if (semop(id, NULL, 0) != -1) e(0);
1086 	if (errno != EINVAL) e(0);
1087 
1088 	if (semop(-1, NULL, 0) != -1) e(0);
1089 	if (errno != EINVAL) e(0);
1090 
1091 	if (semop(INT_MIN, NULL, 0) != -1) e(0);
1092 	if (errno != EINVAL) e(0);
1093 
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);
1098 
1099 	/*
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.
1103 	 */
1104 	test_perm(test88b_perm, 0 /*owner_test*/);
1105 
1106 	/*
1107 	 * Test blocking operations, starting with a single blocking operation.
1108 	 */
1109 	if ((id = semget(IPC_PRIVATE, 3, 0600)) == -1) e(0);
1110 
1111 	memset(sops, 0, sizeof(sops[0]));
1112 	sops[0].sem_op = 1;
1113 	if (semop(id, sops, 1) != 0) e(0);
1114 
1115 	TEST_SEM(id, 0, 1, getpid(), 0, 0);
1116 
1117 	spawn(&child, test88b_child, DROP_NONE);
1118 
1119 	snd(&child, id);
1120 
1121 	/*
1122 	 * In various places, we have to sleep in order to allow the child to
1123 	 * get itself blocked in a semop(2) call.
1124 	 */
1125 	usleep(WAIT_USECS);
1126 
1127 	TEST_SEM(id, 0, 1, getpid(), 0, 1);
1128 
1129 	sops[0].sem_op = -1;
1130 	if (semop(id, sops, 1) != 0) e(0);
1131 
1132 	usleep(WAIT_USECS);
1133 
1134 	TEST_SEM(id, 0, 0, child.pid, 0, 0);
1135 
1136 	sops[0].sem_op = 1;
1137 	if (semop(id, sops, 1) != 0) e(0);
1138 
1139 	TEST_SEM(id, 0, 1, getpid(), 0, 0);
1140 
1141 	snd(&child, 1);
1142 
1143 	usleep(WAIT_USECS);
1144 
1145 	TEST_SEM(id, 0, 1, getpid(), 1, 0);
1146 
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);
1150 
1151 	usleep(WAIT_USECS);
1152 
1153 	TEST_SEM(id, 0, 2, getpid(), 1, 0);
1154 
1155 	sops[0].sem_op = 1;
1156 	if (semop(id, sops, 1) != 0) e(0);
1157 
1158 	usleep(WAIT_USECS);
1159 
1160 	TEST_SEM(id, 0, 0, child.pid, 0, 0);
1161 
1162 	/*
1163 	 * Test blocking operations, verifying the correct operation of
1164 	 * multiple (partially) blocking operations and atomicity.
1165 	 */
1166 	memset(sops, 0, sizeof(sops[0]) * 2);
1167 	if (semop(id, sops, 1) != 0) e(0);
1168 
1169 	/* One blocking operation. */
1170 	snd(&child, 2);
1171 
1172 	usleep(WAIT_USECS);
1173 
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);
1177 
1178 	sops[0].sem_num = 1;
1179 	sops[0].sem_op = 1;
1180 	if (semop(id, sops, 1) != 0) e(0);
1181 
1182 	usleep(WAIT_USECS);
1183 
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);
1187 
1188 	/* Two blocking operations in one call, resolved at once. */
1189 	snd(&child, 3);
1190 
1191 	usleep(WAIT_USECS);
1192 
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);
1196 
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);
1202 
1203 	usleep(WAIT_USECS);
1204 
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);
1208 
1209 	/* Two blocking operations in one call, resolved one by one. */
1210 	snd(&child, 4);
1211 
1212 	usleep(WAIT_USECS);
1213 
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);
1217 
1218 	sops[0].sem_num = 1;
1219 	sops[0].sem_op = 1;
1220 	if (semop(id, sops, 1) != 0) e(0);
1221 
1222 	usleep(WAIT_USECS);
1223 
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);
1227 
1228 	sops[0].sem_num = 2;
1229 	sops[0].sem_op = -1;
1230 	if (semop(id, sops, 1) != 0) e(0);
1231 
1232 	usleep(WAIT_USECS);
1233 
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);
1237 
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);
1244 
1245 	snd(&child, 5);
1246 
1247 	usleep(WAIT_USECS);
1248 
1249 	TEST_SEM(id, 0, 0, getpid(), 1, 0);
1250 	TEST_SEM(id, 1, 0, getpid(), 0, 0);
1251 
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);
1257 
1258 	usleep(WAIT_USECS);
1259 
1260 	TEST_SEM(id, 0, 0, child.pid, 0, 0);
1261 	TEST_SEM(id, 1, 0, child.pid, 0, 0);
1262 
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);
1269 
1270 	snd(&child, 6);
1271 
1272 	usleep(WAIT_USECS);
1273 
1274 	TEST_SEM(id, 0, 1, getpid(), 0, 0);
1275 	TEST_SEM(id, 1, 1, getpid(), 0, 1);
1276 
1277 	sops[0].sem_num = 1;
1278 	sops[0].sem_op = -1;
1279 	if (semop(id, sops, 1) != 0) e(0);
1280 
1281 	usleep(WAIT_USECS);
1282 
1283 	TEST_SEM(id, 0, 1, getpid(), 0, 0);
1284 	TEST_SEM(id, 1, 0, getpid(), 0, 0);
1285 
1286 	/*
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.
1293 	 */
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);
1300 
1301 	/*
1302 	 * Ensure that semaphore value overflow is detected properly, at the
1303 	 * moment that the operation is actually processed.
1304 	 */
1305 	sops[0].sem_num = 1;
1306 	sops[0].sem_op = seminfo.semvmx;
1307 	if (semop(id, sops, 1) != 0) e(0);
1308 
1309 	snd(&child, 7);
1310 
1311 	usleep(WAIT_USECS);
1312 
1313 	TEST_SEM(id, 0, 1, getpid(), 0, 1);
1314 	TEST_SEM(id, 1, seminfo.semvmx, getpid(), 0, 0);
1315 
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);
1321 
1322 	TEST_SEM(id, 0, 0, child.pid, 0, 0);
1323 	TEST_SEM(id, 1, seminfo.semvmx, child.pid, 0, 0);
1324 
1325 	sops[0].sem_num = 1;
1326 	sops[0].sem_op = -2;
1327 	if (semop(id, sops, 1) != 0) e(0);
1328 
1329 	snd(&child, 8);
1330 
1331 	usleep(WAIT_USECS);
1332 
1333 	TEST_SEM(id, 0, 0, child.pid, 1, 0);
1334 	TEST_SEM(id, 1, seminfo.semvmx - 2, getpid(), 0, 0);
1335 
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);
1341 
1342 	TEST_SEM(id, 0, 1, getpid(), 0, 0);
1343 	TEST_SEM(id, 1, seminfo.semvmx - 1, getpid(), 0, 0);
1344 
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;
1351 	/*
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.
1355 	 */
1356 	if (semop(id, sops, 3) != -1) e(0);
1357 	if (errno != ERANGE) e(0);
1358 
1359 	TEST_SEM(id, 0, 1, getpid(), 0, 0);
1360 
1361 	/*
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.
1364 	 */
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);
1371 
1372 	TEST_SEM(id, 0, 0, getpid(), 0, 0);
1373 	TEST_SEM(id, 1, 1, getpid(), 0, 0);
1374 
1375 	snd(&child, 9);
1376 
1377 	usleep(WAIT_USECS);
1378 
1379 	TEST_SEM(id, 0, 0, getpid(), 0, 0);
1380 	TEST_SEM(id, 1, 1, getpid(), 0, 1);
1381 
1382 	kill(child.pid, SIGHUP);
1383 	/*
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.
1386 	 */
1387 
1388 	/*
1389 	 * Check that a blocking semop(2) call fails with EIDRM if the
1390 	 * semaphore set is removed after the call has blocked.
1391 	 */
1392 	snd(&child, 10);
1393 
1394 	usleep(WAIT_USECS);
1395 
1396 	if (semctl(id, 0, IPC_RMID) != 0) e(0);
1397 
1398 	/*
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.
1403 	 */
1404 	if ((id = semget(IPC_PRIVATE, 2, 0600)) == -1) e(0);
1405 
1406 	snd(&child, id);
1407 
1408 	usleep(WAIT_USECS);
1409 
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);
1414 
1415 	if (semctl(id, 1, SETVAL, seminfo.semvmx) != 0) e(0);
1416 
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);
1421 
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);
1425 
1426 	if (semctl(id, 0, SETVAL, 0) != 0) e(0);
1427 
1428 	snd(&child, 11);
1429 
1430 	usleep(WAIT_USECS);
1431 
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);
1436 
1437 	if (semctl(id, 1, SETVAL, 0) != 0) e(0);
1438 
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);
1443 
1444 	time(&now);
1445 	if (semctl(id, 0, SETVAL, 2) != 0) e(0);
1446 
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);
1451 
1452 	if (semctl(id, 0, IPC_RMID) != 0) e(0);
1453 
1454 	/*
1455 	 * Perform a similar test for SETALL, ensuring that it causes an
1456 	 * ongoing semop(2) to behave correctly.
1457 	 */
1458 	if ((id = semget(IPC_PRIVATE, 2, 0600)) == -1) e(0);
1459 
1460 	snd(&child, id);
1461 
1462 	usleep(WAIT_USECS);
1463 
1464 	TEST_SEM(id, 0, 0, 0, 1, 0);
1465 	TEST_SEM(id, 1, 0, 0, 0, 0);
1466 
1467 	val[0] = 1;
1468 	val[1] = 1;
1469 	if (semctl(id, 0, SETALL, val) != 0) e(0);
1470 
1471 	TEST_SEM(id, 0, 1, 0, 0, 0);
1472 	TEST_SEM(id, 1, 1, 0, 0, 1);
1473 
1474 	val[0] = 0;
1475 	val[1] = 1;
1476 	if (semctl(id, 0, SETALL, val) != 0) e(0);
1477 
1478 	TEST_SEM(id, 0, 0, 0, 1, 0);
1479 	TEST_SEM(id, 1, 1, 0, 0, 0);
1480 
1481 	val[0] = 1;
1482 	val[1] = 1;
1483 	if (semctl(id, 0, SETALL, val) != 0) e(0);
1484 
1485 	TEST_SEM(id, 0, 1, 0, 0, 0);
1486 	TEST_SEM(id, 1, 1, 0, 0, 1);
1487 
1488 	val[0] = 0;
1489 	val[1] = 0;
1490 	if (semctl(id, 0, SETALL, val) != 0) e(0);
1491 
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);
1496 
1497 	time(&now);
1498 	val[0] = 1;
1499 	val[1] = 0;
1500 	if (semctl(id, 0, SETALL, val) != 0) e(0);
1501 
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);
1506 
1507 	/*
1508 	 * Finally, ensure that if the child is killed, its blocked semop(2)
1509 	 * call is properly cancelled.
1510 	 */
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);
1516 
1517 	TEST_SEM(id, 0, 0, getpid(), 0, 0);
1518 	TEST_SEM(id, 1, 0, getpid(), 0, 0);
1519 
1520 	/* We'll be terminating the child, so let it report its errors now. */
1521 	if (rcv(&child) != 0) e(0);
1522 
1523 	snd(&child, 12);
1524 
1525 	usleep(WAIT_USECS);
1526 
1527 	TEST_SEM(id, 0, 0, getpid(), 0, 0);
1528 	TEST_SEM(id, 1, 0, getpid(), 1, 0);
1529 
1530 	terminate(&child);
1531 
1532 	TEST_SEM(id, 0, 0, getpid(), 0, 0);
1533 	TEST_SEM(id, 1, 0, getpid(), 0, 0);
1534 
1535 	if (semctl(id, 0, IPC_RMID) != 0) e(0);
1536 
1537 	free(sops);
1538 }
1539 
1540 /*
1541  * Test semctl(2) permission checks, part 1: regular commands.
1542  */
1543 static void
test88c_perm1(struct link * parent)1544 test88c_perm1(struct link * parent)
1545 {
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;
1552 
1553 	while ((tbit = rcv(parent)) != -1) {
1554 		id[0] = rcv(parent);
1555 		id[1] = rcv(parent);
1556 		id[2] = rcv(parent);
1557 
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);
1564 
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);
1568 
1569 			if (semctl(id[2], 0, cmds[i]) != -1) e(0);
1570 			if (errno != EACCES) e(0);
1571 		}
1572 
1573 		/*
1574 		 * Then SETVAL, which requires write permission and is the only
1575 		 * one that takes an integer argument.
1576 		 */
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);
1581 
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);
1585 
1586 		if (semctl(id[2], 0, SETVAL, 0) != -1) e(0);
1587 		if (errno != EACCES) e(0);
1588 
1589 		/*
1590 		 * Finally the commands that require read or write permission
1591 		 * and take a pointer as argument.
1592 		 */
1593 		memset(val, 0, sizeof(val));
1594 
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();
1614 			}
1615 
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);
1619 
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);
1623 
1624 			if (semctl(id[2], 0, cmd, ptr) != -1) e(0);
1625 			if (errno != EACCES) e(0);
1626 		}
1627 
1628 		/*
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.
1635 		 */
1636 #ifndef IPCID_TO_IX
1637 #define IPCID_TO_IX(id)		((id) & 0xffff)
1638 #endif
1639 
1640 		bit = 4;
1641 
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);
1645 
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);
1649 
1650 		if (semctl(IPCID_TO_IX(id[2]), 0, SEM_STAT, &semds) != -1)
1651 			e(0);
1652 		if (errno != EACCES) e(0);
1653 
1654 		/*
1655 		 * IPC_INFO and SEM_INFO should always succeed.  They do not
1656 		 * even take a semaphore set identifier.
1657 		 */
1658 		if (semctl(0, 0, IPC_INFO, &seminfo) == -1) e(0);
1659 		if (semctl(0, 0, SEM_INFO, &seminfo) == -1) e(0);
1660 
1661 		snd(parent, 0);
1662 	}
1663 }
1664 
1665 /*
1666  * Test semctl(2) permission checks, part 2: the IPC_SET command.
1667  */
1668 static void
test88c_perm2(struct link * parent)1669 test88c_perm2(struct link * parent)
1670 {
1671 	struct semid_ds semds;
1672 	int r, shift, id[3];
1673 
1674 	while ((shift = rcv(parent)) != -1) {
1675 		id[0] = rcv(parent);
1676 		id[1] = rcv(parent);
1677 		id[2] = rcv(parent);
1678 
1679 		/*
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.
1691 		 */
1692 		memset(&semds, 0, sizeof(semds));
1693 
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);
1697 
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);
1701 
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);
1706 
1707 		snd(parent, 0);
1708 	}
1709 }
1710 
1711 /*
1712  * Test semctl(2) permission checks, part 3: the IPC_RMID command.
1713  */
1714 static void
test88c_perm3(struct link * parent)1715 test88c_perm3(struct link * parent)
1716 {
1717 	int r, shift, id[3];
1718 
1719 	while ((shift = rcv(parent)) != -1) {
1720 		id[0] = rcv(parent);
1721 		id[1] = rcv(parent);
1722 		id[2] = rcv(parent);
1723 
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);
1727 
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);
1731 
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);
1736 
1737 		snd(parent, 0);
1738 	}
1739 }
1740 
1741 /*
1742  * Test the basic semctl(2) functionality.
1743  */
1744 static void
test88c(void)1745 test88c(void)
1746 {
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;
1755 
1756 	subtest = 2;
1757 
1758 	if (semctl(0, 0, IPC_INFO, &seminfo) == -1) e(0);
1759 
1760 	/*
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.
1764 	 */
1765 	test_perm(test88c_perm1, 0 /*owner_test*/);
1766 	test_perm(test88c_perm2, 1 /*owner_test*/);
1767 	test_perm(test88c_perm3, 1 /*owner_test*/);
1768 
1769 	/* Create identifiers known to be invalid. */
1770 	if ((badid1 = semget(IPC_PRIVATE, 1, 0600)) < 0) e(0);
1771 
1772 	if (semctl(badid1, 0, IPC_RMID) != 0) e(0);
1773 
1774 	memset(&semds, 0, sizeof(semds));
1775 	badid2 = IXSEQ_TO_IPCID(seminfo.semmni, semds.sem_perm);
1776 
1777 	if ((id = semget(IPC_PRIVATE, 3, IPC_CREAT | 0600)) < 0) e(0);
1778 
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);
1782 
1783 	/* In this case we can't avoid sleeping for longer periods.. */
1784 	while (time(&now) == semds.sem_ctime)
1785 		usleep(250000);
1786 
1787 	/*
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.
1791 	 */
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);
1795 
1796 		if (semctl(badid1, 0, cmds[i]) != -1) e(0);
1797 		if (errno != EINVAL) e(0);
1798 
1799 		if (semctl(badid2, 0, cmds[i]) != -1) e(0);
1800 		if (errno != EINVAL) e(0);
1801 
1802 		if (semctl(-1, 0, cmds[i]) != -1) e(0);
1803 		if (errno != EINVAL) e(0);
1804 
1805 		if (semctl(INT_MIN, 0, cmds[i]) != -1) e(0);
1806 		if (errno != EINVAL) e(0);
1807 
1808 		if (semctl(id, -1, cmds[i]) != -1) e(0);
1809 		if (errno != EINVAL) e(0);
1810 
1811 		if (semctl(id, 3, cmds[i]) != -1) e(0);
1812 		if (errno != EINVAL) e(0);
1813 
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);
1818 	}
1819 
1820 	/*
1821 	 * Test the GETALL command.
1822 	 */
1823 	/*
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.
1827 	 */
1828 	for (j = 0; j < 5; j++) {
1829 		for (i = 0; i < __arraycount(val); i++)
1830 			val[i] = USHRT_MAX;
1831 
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);
1836 	}
1837 
1838 	for (i = 0; i < __arraycount(val); i++)
1839 		val[i] = USHRT_MAX;
1840 
1841 	if (semctl(badid1, 0, GETALL, val) != -1) e(0);
1842 	if (errno != EINVAL) e(0);
1843 
1844 	if (semctl(badid2, 0, GETALL, val) != -1) e(0);
1845 	if (errno != EINVAL) e(0);
1846 
1847 	if (semctl(-1, 0, GETALL, val) != -1) e(0);
1848 	if (errno != EINVAL) e(0);
1849 
1850 	if (semctl(INT_MIN, 0, GETALL, val) != -1) e(0);
1851 	if (errno != EINVAL) e(0);
1852 
1853 	for (i = 0; i < __arraycount(val); i++)
1854 		if (val[i] != USHRT_MAX) e(0);
1855 
1856 	if (semctl(id, 0, GETALL, NULL) != -1) e(0);
1857 	if (errno != EFAULT) e(0);
1858 
1859 	if (semctl(id, 0, GETALL, bad_ptr) != -1) e(0);
1860 	if (errno != EFAULT) e(0);
1861 
1862 	if (semctl(id, 0, GETALL, ((unsigned short *)bad_ptr) - 2) != -1) e(0);
1863 	if (errno != EFAULT) e(0);
1864 
1865 	if (semctl(id, 0, GETALL, ((unsigned short *)bad_ptr) - 3) != 0) e(0);
1866 
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);
1871 
1872 	/*
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.
1876 	 */
1877 	/*
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.
1881 	 */
1882 	memset(statbuf, 0x5a, sizeof(statbuf));
1883 
1884 	if (semctl(badid1, 0, IPC_STAT, statbuf) != -1) e(0);
1885 	if (errno != EINVAL) e(0);
1886 
1887 	if (semctl(badid2, 0, IPC_STAT, statbuf) != -1) e(0);
1888 	if (errno != EINVAL) e(0);
1889 
1890 	if (semctl(-1, 0, IPC_STAT, statbuf) != -1) e(0);
1891 	if (errno != EINVAL) e(0);
1892 
1893 	if (semctl(INT_MIN, 0, IPC_STAT, statbuf) != -1) e(0);
1894 	if (errno != EINVAL) e(0);
1895 
1896 	for (i = 0; i < sizeof(statbuf); i++)
1897 		if (statbuf[i] != 0x5a) e(0);
1898 
1899 	if (semctl(id, 0, IPC_STAT, statbuf) != 0) e(0);
1900 
1901 	if (statbuf[sizeof(statbuf) - 1] != 0x5a) e(0);
1902 
1903 	if (semctl(id, 0, IPC_STAT, NULL) != -1) e(0);
1904 	if (errno != EFAULT) e(0);
1905 
1906 	if (semctl(id, 0, IPC_STAT, bad_ptr) != -1) e(0);
1907 	if (errno != EFAULT) e(0);
1908 
1909 	if (semctl(id, 0, IPC_STAT, ((struct semid_ds *)bad_ptr) - 1) != 0)
1910 		e(0);
1911 
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);
1915 
1916 	/*
1917 	 * Test SEM_STAT.
1918 	 */
1919 	if ((id2 = semget(KEY_A, seminfo.semmsl, IPC_CREAT | 0642)) < 0) e(0);
1920 
1921 	memset(statbuf, 0x5a, sizeof(statbuf));
1922 
1923 	if (semctl(-1, 0, SEM_STAT, statbuf) != -1) e(0);
1924 	if (errno != EINVAL) e(0);
1925 
1926 	if (semctl(seminfo.semmni, 0, SEM_STAT, statbuf) != -1) e(0);
1927 	if (errno != EINVAL) e(0);
1928 
1929 	for (i = 0; i < sizeof(statbuf); i++)
1930 		if (statbuf[i] != 0x5a) e(0);
1931 
1932 	memset(seen, 0, sizeof(seen));
1933 
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;
1939 		}
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);
1955 
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);
1959 
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);
1971 		}
1972 	}
1973 
1974 	if (seen[0] != 1) e(0);
1975 	if (seen[1] != 1) e(0);
1976 
1977 	if (statbuf[sizeof(statbuf) - 1] != 0x5a) e(0);
1978 
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);
1982 
1983 	/*
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.
1986 	 */
1987 	if (semctl(badid1, 0, SETVAL, 1) != -1) e(0);
1988 	if (errno != EINVAL) e(0);
1989 
1990 	if (semctl(badid2, 0, SETVAL, 1) != -1) e(0);
1991 	if (errno != EINVAL) e(0);
1992 
1993 	if (semctl(-1, 0, SETVAL, 1) != -1) e(0);
1994 	if (errno != EINVAL) e(0);
1995 
1996 	if (semctl(INT_MIN, 0, SETVAL, 1) != -1) e(0);
1997 	if (errno != EINVAL) e(0);
1998 
1999 	if (semctl(id, -1, SETVAL, 1) != -1) e(0);
2000 	if (errno != EINVAL) e(0);
2001 
2002 	if (semctl(id, 3, SETVAL, 1) != -1) e(0);
2003 	if (errno != EINVAL) e(0);
2004 
2005 	if (semctl(id, 0, SETVAL, -1) != -1) e(0);
2006 	if (errno != ERANGE) e(0);
2007 
2008 	if (semctl(id, 0, SETVAL, seminfo.semvmx + 1) != -1) e(0);
2009 	if (errno != ERANGE) e(0);
2010 
2011 	TEST_SEM(id, 0, 0, 0, 0, 0);
2012 
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);
2016 
2017 	/* Alright, there we go.. */
2018 	if (semctl(id, 1, SETVAL, 0) != 0) e(0);
2019 
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);
2023 
2024 	TEST_SEM(id, 1, 0, 0, 0, 0);
2025 
2026 	if (semctl(id, 2, SETVAL, seminfo.semvmx) != 0) e(0);
2027 
2028 	TEST_SEM(id, 2, seminfo.semvmx, 0, 0, 0);
2029 
2030 	if (semctl(id, 0, SETVAL, 1) != 0) e(0);
2031 
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);
2035 
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);
2040 
2041 	if (semctl(id, 0, IPC_STAT, &semds) != 0) e(0);
2042 
2043 	while (time(&now) == semds.sem_ctime)
2044 		usleep(250000);
2045 
2046 	/*
2047 	 * Test SETALL.  Same idea: failure cases first.
2048 	 */
2049 	if (semctl(badid1, 0, SETALL, 1) != -1) e(0);
2050 	if (errno != EINVAL) e(0);
2051 
2052 	if (semctl(badid2, 0, SETALL, 1) != -1) e(0);
2053 	if (errno != EINVAL) e(0);
2054 
2055 	if (semctl(-1, 0, SETALL, 1) != -1) e(0);
2056 	if (errno != EINVAL) e(0);
2057 
2058 	if (semctl(INT_MIN, 0, SETALL, 1) != -1) e(0);
2059 	if (errno != EINVAL) e(0);
2060 
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);
2066 
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);
2072 
2073 	if (semctl(id, 0, SETALL, NULL) != -1) e(0);
2074 	if (errno != EFAULT) e(0);
2075 
2076 	if (semctl(id, 0, SETALL, bad_ptr) != -1) e(0);
2077 	if (errno != EFAULT) e(0);
2078 
2079 	if (semctl(id, 0, SETALL, ((unsigned short *)bad_ptr) - 2) != -1) e(0);
2080 	if (errno != EFAULT) e(0);
2081 
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);
2085 
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);
2089 
2090 	val[0] = seminfo.semvmx;
2091 	val[1] = 0;
2092 	val[2] = 0;
2093 	if (semctl(id, 0, SETALL, val) != 0) e(0);
2094 
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);
2098 
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);
2102 
2103 	val[0] = 0;
2104 	val[1] = 1;
2105 	val[2] = seminfo.semvmx;
2106 	if (semctl(id, INT_MAX, SETALL, val) != 0) e(0);
2107 
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);
2111 
2112 	memset(page_ptr, 0, page_size);
2113 	if (semctl(id, 0, SETALL, ((unsigned short *)bad_ptr) - 3) != 0) e(0);
2114 
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);
2118 
2119 	while (time(&now) == semds.sem_ctime)
2120 		usleep(250000);
2121 
2122 	/*
2123 	 * Test IPC_SET.  Its core functionality has already been tested
2124 	 * thoroughly as part of the permission tests.
2125 	 */
2126 	if (semctl(badid1, 0, IPC_SET, &semds) != -1) e(0);
2127 	if (errno != EINVAL) e(0);
2128 
2129 	if (semctl(badid2, 0, IPC_SET, &semds) != -1) e(0);
2130 	if (errno != EINVAL) e(0);
2131 
2132 	if (semctl(-1, 0, IPC_SET, &semds) != -1) e(0);
2133 	if (errno != EINVAL) e(0);
2134 
2135 	if (semctl(INT_MIN, 0, IPC_SET, &semds) != -1) e(0);
2136 	if (errno != EINVAL) e(0);
2137 
2138 	if (semctl(id, 0, IPC_SET, NULL) != -1) e(0);
2139 	if (errno != EFAULT) e(0);
2140 
2141 	if (semctl(id, 0, IPC_SET, bad_ptr) != -1) e(0);
2142 	if (errno != EFAULT) e(0);
2143 
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);
2147 
2148 	/*
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.
2154 	 */
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);
2160 
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);
2172 
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);
2179 
2180 		if (semctl(id, i / 2 - 2, IPC_STAT, &semds) != 0) e(0);
2181 		if (semds.sem_perm.mode != (SEM_ALLOC | i)) e(0);
2182 
2183 		semds.sem_perm.mode = ~0777 | i;
2184 		if (semctl(id, i / 2 - 3, IPC_SET, &semds) != 0) e(0);
2185 
2186 		if (semctl(id, i / 2 - 4, IPC_STAT, &semds) != 0) e(0);
2187 		if (semds.sem_perm.mode != (SEM_ALLOC | i)) e(0);
2188 	}
2189 	if (semds.sem_perm.uid != osemds.sem_perm.uid) e(0);
2190 	if (semds.sem_perm.gid != osemds.sem_perm.gid) e(0);
2191 
2192 	if (semctl(id, 0, IPC_SET, ((struct semid_ds *)bad_ptr) - 1) != 0)
2193 		e(0);
2194 
2195 	/*
2196 	 * Test IPC_RMID.  Its basic functionality has already been tested
2197 	 * multiple times over, so there is not much left to do here.
2198 	 */
2199 	if (semctl(badid1, 0, IPC_RMID) != -1) e(0);
2200 	if (errno != EINVAL) e(0);
2201 
2202 	if (semctl(badid2, 0, IPC_RMID) != -1) e(0);
2203 	if (errno != EINVAL) e(0);
2204 
2205 	if (semctl(-1, 0, IPC_RMID) != -1) e(0);
2206 	if (errno != EINVAL) e(0);
2207 
2208 	if (semctl(INT_MIN, 0, IPC_RMID) != -1) e(0);
2209 	if (errno != EINVAL) e(0);
2210 
2211 	if (semctl(id, 0, IPC_RMID) != 0) e(0);
2212 
2213 	if (semctl(id, 0, IPC_RMID) != -1) e(0);
2214 	if (errno != EINVAL) e(0);
2215 
2216 	if (semctl(id, 0, IPC_STAT, &semds) != -1) e(0);
2217 	if (errno != EINVAL) e(0);
2218 
2219 	if (semctl(id2, 1, IPC_RMID) != 0) e(0);
2220 
2221 	if (semctl(id2, 1, IPC_RMID) != -1) e(0);
2222 	if (errno != EINVAL) e(0);
2223 
2224 	/*
2225 	 * Test IPC_INFO and SEM_INFO.  Right now, for all practical purposes,
2226 	 * these identifiers behave pretty much the same.
2227 	 */
2228 	if ((id = semget(IPC_PRIVATE, 3, 0600)) == -1) e(0);
2229 	if ((id2 = semget(IPC_PRIVATE, 1, 0600)) == -1) e(0);
2230 
2231 	for (i = 0; i <= 1; i++) {
2232 		cmd = (i == 0) ? IPC_INFO : SEM_INFO;
2233 
2234 		memset(&seminfo, 0xff, sizeof(seminfo));
2235 
2236 		if ((r = semctl(0, 0, cmd, &seminfo)) == -1) e(0);
2237 
2238 		/*
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.
2245 		 */
2246 		if (r < 1 || r >= seminfo.semmni) e(0);
2247 
2248 		/*
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.
2252 		 */
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);
2269 
2270 		if (semctl(INT_MAX, -1, cmd, &seminfo) == -1) e(0);
2271 		if (semctl(-1, INT_MAX, cmd, &seminfo) == -1) e(0);
2272 
2273 		if (semctl(0, 0, cmd, NULL) != -1) e(0);
2274 		if (errno != EFAULT) e(0);
2275 
2276 		if (semctl(0, 0, cmd, bad_ptr) != -1) e(0);
2277 		if (errno != EFAULT) e(0);
2278 
2279 		if (semctl(0, 0, cmd, ((struct seminfo *)bad_ptr) - 1) == -1)
2280 			e(0);
2281 	}
2282 
2283 	if (semctl(id2, 0, IPC_RMID) != 0) e(0);
2284 
2285 	/*
2286 	 * Finally, test invalid commands.  Well, hopefully invalid commands,
2287 	 * anyway.
2288 	 */
2289 	if (semctl(id, 0, INT_MIN) != -1) e(0);
2290 	if (errno != EINVAL) e(0);
2291 
2292 	if (semctl(id, 0, INT_MAX) != -1) e(0);
2293 	if (errno != EINVAL) e(0);
2294 
2295 	if (semctl(id, 0, IPC_RMID) != 0) e(0);
2296 }
2297 
2298 /*
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.
2301  */
2302 static void
test88d(void)2303 test88d(void)
2304 {
2305 	struct sembuf sop;
2306 	int id;
2307 
2308 	subtest = 3;
2309 
2310 	if ((id = semget(IPC_PRIVATE, 1, 0600)) == -1) e(0);
2311 
2312 	/*
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.
2315 	 */
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);
2322 
2323 	if (semctl(id, 0, IPC_RMID) != 0) e(0);
2324 }
2325 
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
2331 };
2332 
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
2341 };
2342 
2343 /*
2344  * Auxiliary child procedure.  The auxiliary children will deadlock until the
2345  * semaphore set is removed.
2346  */
2347 static void
test88e_childaux(struct link * parent)2348 test88e_childaux(struct link * parent)
2349 {
2350 	struct sembuf sops[3];
2351 	struct seminfo seminfo;
2352 	int child, id, num;
2353 
2354 	child = rcv(parent);
2355 	id = rcv(parent);
2356 	num = rcv(parent);
2357 
2358 	memset(sops, 0, sizeof(sops));
2359 
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);
2381 	}
2382 
2383 	snd(parent, 0);
2384 
2385 	if (semop(id, sops, 3) != -1) e(0);
2386 	if (errno != EIDRM) e(0);
2387 }
2388 
2389 /*
2390  * First child procedure.
2391  */
2392 static void
test88e_child1(struct link * parent)2393 test88e_child1(struct link * parent)
2394 {
2395 	struct sembuf sops[3];
2396 	size_t nsops;
2397 	int match, id, expect;
2398 
2399 	match = rcv(parent);
2400 	id = rcv(parent);
2401 
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);
2434 	}
2435 
2436 	snd(parent, 0);
2437 
2438 	if (semop(id, sops, nsops) != expect) e(0);
2439 	if (expect == -1 && errno != EIDRM) e(0);
2440 }
2441 
2442 /*
2443  * Second child procedure.
2444  */
2445 static void
test88e_child2(struct link * parent)2446 test88e_child2(struct link * parent)
2447 {
2448 	struct sembuf sops[2];
2449 	size_t nsops;
2450 	int match, id, expect;
2451 
2452 	match = rcv(parent);
2453 	id = rcv(parent);
2454 
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);
2482 	}
2483 
2484 	snd(parent, 0);
2485 
2486 	if (semop(id, sops, nsops) != expect) e(0);
2487 	if (expect == -1 && errno != EIDRM) e(0);
2488 }
2489 
2490 /*
2491  * Third child procedure.
2492  */
2493 static void
test88e_child3(struct link * parent)2494 test88e_child3(struct link * parent)
2495 {
2496 	struct sembuf sops[1];
2497 	size_t nsops;
2498 	int match, id;
2499 
2500 	match = rcv(parent);
2501 	id = rcv(parent);
2502 
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);
2513 	}
2514 
2515 	snd(parent, 0);
2516 
2517 	if (semop(id, sops, nsops) != 0) e(0);
2518 }
2519 
2520 /*
2521  * Perform one test for operations affecting multiple processes.
2522  */
2523 static void
sub88e(unsigned int match,unsigned int resume,unsigned int aux)2524 sub88e(unsigned int match, unsigned int resume, unsigned int aux)
2525 {
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;
2530 
2531 	/*
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.
2538 	 */
2539 	if ((id = semget(IPC_PRIVATE, __arraycount(val), 0666)) == -1) e(0);
2540 
2541 	aux_zcnt = aux_ncnt = 0;
2542 
2543 	/* Start the first auxiliary child if desired, before all others. */
2544 	if (aux & 1) {
2545 		spawn(&aux1, test88e_childaux, DROP_ALL);
2546 
2547 		snd(&aux1, 1);
2548 		snd(&aux1, id);
2549 		snd(&aux1, (aux & 4) ? 2 : 1);
2550 
2551 		if (rcv(&aux1) != 0) e(0);
2552 
2553 		if (aux & 4)
2554 			aux_zcnt++;
2555 	}
2556 
2557 	/* Start and configure all children for this specific match test. */
2558 	spawn(&child1, test88e_child1, DROP_ALL);
2559 
2560 	snd(&child1, match);
2561 	snd(&child1, id);
2562 
2563 	if (rcv(&child1) != 0) e(0);
2564 
2565 	/*
2566 	 * For fairness tests, we must ensure that the first child blocks on
2567 	 * the semaphore before the second child does.
2568 	 */
2569 	switch (match) {
2570 	case MATCH_FIRST:
2571 	case MATCH_SECOND:
2572 	case MATCH_KILL:
2573 		usleep(WAIT_USECS);
2574 		break;
2575 	}
2576 
2577 	spawn(&child2, test88e_child2, DROP_NONE);
2578 
2579 	snd(&child2, match);
2580 	snd(&child2, id);
2581 
2582 	if (rcv(&child2) != 0) e(0);
2583 
2584 	if (match == MATCH_ALL) {
2585 		spawn(&child3, test88e_child3, DROP_USER);
2586 
2587 		snd(&child3, match);
2588 		snd(&child3, id);
2589 
2590 		if (rcv(&child3) != 0) e(0);
2591 	}
2592 
2593 	/* Start the second auxiliary child if desired, after all others. */
2594 	if (aux & 2) {
2595 		spawn(&aux2, test88e_childaux, DROP_NONE);
2596 
2597 		snd(&aux2, 2);
2598 		snd(&aux2, id);
2599 		snd(&aux2, (aux & 4) ? 2 : 1);
2600 
2601 		if (rcv(&aux2) != 0) e(0);
2602 
2603 		if (aux & 4)
2604 			aux_ncnt++;
2605 	}
2606 
2607 	usleep(WAIT_USECS);
2608 
2609 	/*
2610 	 * Test semaphore values and determine the value with which to increase
2611 	 * the third semaphore.  For MATCH_KILL, also kill the first child.
2612 	 */
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);
2622 
2623 		terminate(&child1);
2624 
2625 		/* As stated before, non-self kills need not be instant. */
2626 		usleep(WAIT_USECS);
2627 
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);
2647 	}
2648 
2649 	TEST_SEM(id, 0, 0, 0, 0, 0);
2650 	TEST_SEM(id, 1, 0, 0, -1, -1);
2651 
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);
2670 	}
2671 
2672 	/*
2673 	 * See if the right children were indeed resumed, and retest the
2674 	 * semaphore values.
2675 	 */
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:
2693 		/*
2694 		 * The children are not ordered in this case, so we do not know
2695 		 * which one gets access to the semaphores last.
2696 		 */
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);
2717 	}
2718 
2719 	TEST_SEM(id, 0, 0, 0, 0, 0);
2720 	TEST_SEM(id, 1, 0, 0, -1, -1);
2721 
2722 	/* Remove the semaphore set.  This should unblock remaining callers. */
2723 	if (semctl(id, 0, IPC_RMID) != 0) e(0);
2724 
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);
2740 	}
2741 
2742 	/* Wait for the auxiliary children as well. */
2743 	if (aux & 1)
2744 		collect(&aux1);
2745 	if (aux & 2)
2746 		collect(&aux2);
2747 }
2748 
2749 /*
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.
2756  */
2757 static void
test88e(void)2758 test88e(void)
2759 {
2760 	unsigned int resume, match, aux;
2761 
2762 	subtest = 4;
2763 
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);
2768 }
2769 
2770 /*
2771  * Verify that non-root processes can use sysctl(2) to see semaphore sets
2772  * created by root.
2773  */
2774 static void
test88f_child(struct link * parent)2775 test88f_child(struct link * parent)
2776 {
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;
2783 
2784 	id[0] = rcv(parent);
2785 	id[1] = rcv(parent);
2786 
2787 	if (sysctl(mib, __arraycount(mib), NULL, &len, NULL, 0) != 0) e(0);
2788 
2789 	if ((semsi = malloc(len)) == NULL) e(0);
2790 
2791 	if (sysctl(mib, __arraycount(mib), semsi, &len, NULL, 0) != 0) e(0);
2792 
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;
2797 
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]++;
2803 	}
2804 
2805 	free(semsi);
2806 
2807 	if (seen[0] != 1) e(0);
2808 	if (seen[1] != 1) e(0);
2809 }
2810 
2811 /*
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.
2814  */
2815 static void
test88f(void)2816 test88f(void)
2817 {
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];
2827 
2828 	/*
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.
2833 	 */
2834 	len = sizeof(seminfo);
2835 	if (sysctl(mib, __arraycount(mib), &seminfo, &len, NULL, 0) != 0) e(0);
2836 	if (len != sizeof(seminfo)) e(0);
2837 
2838 	if (semctl(0, 0, IPC_INFO, &seminfo2) == -1) e(0);
2839 
2840 	if (memcmp(&seminfo, &seminfo2, sizeof(seminfo)) != 0) e(0);
2841 
2842 	/* Verify that the correct size estimation is returned. */
2843 	if (seminfo.semmni <= 0) e(0);
2844 	if (seminfo.semmni > SHRT_MAX) e(0);
2845 
2846 	size = sizeof(*semsi) +
2847 	    sizeof(semsi->semids[0]) * (seminfo.semmni - 1);
2848 
2849 	len = 0;
2850 	if (sysctl(mib, __arraycount(mib), NULL, &len, NULL, 0) != 0) e(0);
2851 	if (len != size) e(0);
2852 
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);
2855 
2856 	if ((id[1] = semget(IPC_PRIVATE, 3, 0650)) < 0) e(0);
2857 
2858 	/*
2859 	 * Retrieve the entire semaphore array, and verify that the general
2860 	 * semaphore information is still correct.
2861 	 */
2862 	if ((semsi = malloc(size)) == NULL) e(0);
2863 
2864 	len = size;
2865 	if (sysctl(mib, __arraycount(mib), semsi, &len, NULL, 0) != 0) e(0);
2866 	if (len != size) e(0);
2867 
2868 	if (sizeof(semsi->seminfo) != sizeof(seminfo)) e(0);
2869 	if (memcmp(&semsi->seminfo, &seminfo, sizeof(semsi->seminfo)) != 0)
2870 	    e(0);
2871 
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;
2877 
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;
2885 		}
2886 	}
2887 
2888 	if (slot[0] < 0) e(0);
2889 	if (slot[1] < 0) e(0);
2890 
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);
2902 
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);
2913 
2914 	/* Make sure that non-root users can see them as well. */
2915 	spawn(&child, test88f_child, DROP_ALL);
2916 
2917 	snd(&child, id[0]);
2918 	snd(&child, id[1]);
2919 
2920 	collect(&child);
2921 
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);
2925 
2926 	len = size;
2927 	if (sysctl(mib, __arraycount(mib), semsi, &len, NULL, 0) != 0) e(0);
2928 	if (len != size) e(0);
2929 
2930 	for (i = 0; i < seminfo.semmni; i++) {
2931 		if (!(semsi->semids[i].sem_perm.mode & SEM_ALLOC))
2932 			continue;
2933 
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);
2937 	}
2938 
2939 	free(semsi);
2940 }
2941 
2942 /*
2943  * Initialize the test.
2944  */
2945 static void
test88_init(void)2946 test88_init(void)
2947 {
2948 	static const int mib[] = { CTL_KERN, KERN_SYSVIPC, KERN_SYSVIPC_SEM };
2949 	struct group *gr;
2950 	size_t len;
2951 	int i;
2952 
2953 	/* Start with full root privileges. */
2954 	setuid(geteuid());
2955 
2956 	if ((gr = getgrnam(ROOT_GROUP)) == NULL) e(0);
2957 
2958 	setgid(gr->gr_gid);
2959 	setegid(gr->gr_gid);
2960 
2961 	/*
2962 	 * Verify that the IPC service is running at all.  If not, there is
2963 	 * obviously no point in running this test.
2964 	 */
2965 	len = sizeof(i);
2966 	if (sysctl(mib, __arraycount(mib), &i, &len, NULL, 0) != 0) e(0);
2967 	if (len != sizeof(i)) e(0);
2968 
2969 	if (i == 0) {
2970 		printf("skipped\n");
2971 		cleanup();
2972 		exit(0);
2973 	}
2974 
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);
2982 }
2983 
2984 /*
2985  * Test program for SysV IPC semaphores.
2986  */
2987 int
main(int argc,char ** argv)2988 main(int argc, char ** argv)
2989 {
2990 	int i, m;
2991 
2992 	start(88);
2993 
2994 	test88_init();
2995 
2996 	if (argc == 2)
2997 		m = atoi(argv[1]);
2998 	else
2999 		m = 0xFF;
3000 
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();
3008 	}
3009 
3010 	quit();
3011 }
3012