1 /* $NetBSD: t_sysv.c,v 1.4 2014/03/02 20:13:12 jmmv Exp $ */ 2 3 /*- 4 * Copyright (c) 1999, 2007 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center, and by Andrew Doran. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * Test the SVID-compatible Message Queue facility. 35 */ 36 37 #include <atf-c.h> 38 39 #include <err.h> 40 #include <errno.h> 41 #include <fcntl.h> 42 #include <signal.h> 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <time.h> 47 #include <unistd.h> 48 49 #include <sys/ipc.h> 50 #include <sys/mman.h> 51 #include <sys/msg.h> 52 #include <sys/param.h> 53 #include <sys/sem.h> 54 #include <sys/shm.h> 55 #include <sys/wait.h> 56 57 volatile int did_sigsys; 58 59 void sigsys_handler(int); 60 61 key_t get_ftok(int); 62 63 void print_msqid_ds(struct msqid_ds *, mode_t); 64 void receiver(void); 65 66 void print_semid_ds(struct semid_ds *, mode_t); 67 void waiter(void); 68 69 void print_shmid_ds(struct shmid_ds *, mode_t); 70 void sharer(void); 71 72 #define MESSAGE_TEXT_LEN 256 73 74 struct testmsg { 75 long mtype; 76 char mtext[MESSAGE_TEXT_LEN]; 77 }; 78 79 const char *m1_str = "California is overrated."; 80 const char *m2_str = "The quick brown fox jumped over the lazy dog."; 81 82 size_t pgsize; 83 84 #define MTYPE_1 1 85 #define MTYPE_1_ACK 2 86 87 #define MTYPE_2 3 88 #define MTYPE_2_ACK 4 89 90 pid_t child_pid; 91 92 key_t msgkey, semkey, shmkey; 93 94 int maxloop = 1; 95 96 union semun { 97 int val; /* value for SETVAL */ 98 struct semid_ds *buf; /* buffer for IPC_{STAT,SET} */ 99 u_short *array; /* array for GETALL & SETALL */ 100 }; 101 102 103 /* Writes an integer to a file. To be used from the body of the test 104 * cases below to pass any global identifiers to the cleanup routine. */ 105 static void 106 write_int(const char *path, const int value) 107 { 108 int output; 109 110 output = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600); 111 ATF_REQUIRE_MSG(output != -1, "Failed to create %s", path); 112 write(output, &value, sizeof(value)); 113 close(output); 114 } 115 116 117 /* Reads an integer from a file. To be used from the cleanup routines 118 * of the test cases below. */ 119 static int 120 read_int(const char *path) 121 { 122 int input; 123 124 input = open(path, O_RDONLY); 125 if (input == -1) 126 return -1; 127 else { 128 int value; 129 ATF_REQUIRE_EQ(read(input, &value, sizeof(value)), sizeof(value)); 130 close(input); 131 return value; 132 } 133 } 134 135 136 void 137 sigsys_handler(int signo) 138 { 139 140 did_sigsys = 1; 141 } 142 143 key_t get_ftok(int id) 144 { 145 int fd; 146 char token_key[64], token_dir[64]; 147 char *tmpdir; 148 key_t key; 149 150 strlcpy(token_key, "/tmp/t_sysv.XXXXXX", sizeof(token_key)); 151 tmpdir = mkdtemp(token_key); 152 ATF_REQUIRE_MSG(tmpdir != NULL, "mkdtemp() failed: %d", errno); 153 154 strlcpy(token_dir, tmpdir, sizeof(token_dir)); 155 strlcpy(token_key, tmpdir, sizeof(token_key)); 156 strlcat(token_key, "/token_key", sizeof(token_key)); 157 158 /* Create the file, since ftok() requires it to exist! */ 159 160 fd = open(token_key, O_RDWR | O_CREAT | O_EXCL, 0600); 161 if (fd == -1) { 162 rmdir(tmpdir); 163 atf_tc_fail("open() of temp file failed: %d", errno); 164 return (key_t)-1; 165 } else 166 close(fd); 167 168 key = ftok(token_key, id); 169 170 ATF_REQUIRE_MSG(unlink(token_key) != -1, "unlink() failed: %d", errno); 171 ATF_REQUIRE_MSG(rmdir(token_dir) != -1, "rmdir() failed: %d", errno); 172 173 return key; 174 } 175 176 ATF_TC_WITH_CLEANUP(msg); 177 ATF_TC_HEAD(msg, tc) 178 { 179 180 atf_tc_set_md_var(tc, "timeout", "3"); 181 atf_tc_set_md_var(tc, "descr", "Checks sysvmsg passing"); 182 } 183 184 ATF_TC_BODY(msg, tc) 185 { 186 struct sigaction sa; 187 struct msqid_ds m_ds; 188 struct testmsg m; 189 int sender_msqid; 190 int loop; 191 int c_status; 192 pid_t wait_result; 193 194 /* 195 * Install a SIGSYS handler so that we can exit gracefully if 196 * System V Message Queue support isn't in the kernel. 197 */ 198 did_sigsys = 0; 199 sa.sa_handler = sigsys_handler; 200 sigemptyset(&sa.sa_mask); 201 sa.sa_flags = 0; 202 ATF_REQUIRE_MSG(sigaction(SIGSYS, &sa, NULL) != -1, 203 "sigaction SIGSYS: %d", errno); 204 205 msgkey = get_ftok(4160); 206 ATF_REQUIRE_MSG(msgkey != (key_t)-1, "get_ftok failed"); 207 208 sender_msqid = msgget(msgkey, IPC_CREAT | 0640); 209 ATF_REQUIRE_MSG(sender_msqid != -1, "msgget: %d", errno); 210 write_int("sender_msqid", sender_msqid); 211 212 if (did_sigsys) { 213 atf_tc_skip("SYSV Message Queue not supported"); 214 return; 215 } 216 217 ATF_REQUIRE_MSG(msgctl(sender_msqid, IPC_STAT, &m_ds) != -1, 218 "msgctl IPC_STAT 1: %d", errno); 219 220 print_msqid_ds(&m_ds, 0640); 221 222 m_ds.msg_perm.mode = (m_ds.msg_perm.mode & ~0777) | 0600; 223 224 ATF_REQUIRE_MSG(msgctl(sender_msqid, IPC_SET, &m_ds) != -1, 225 "msgctl IPC_SET: %d", errno); 226 227 memset(&m_ds, 0, sizeof(m_ds)); 228 229 ATF_REQUIRE_MSG(msgctl(sender_msqid, IPC_STAT, &m_ds) != -1, 230 "msgctl IPC_STAT 2: %d", errno); 231 232 ATF_REQUIRE_MSG((m_ds.msg_perm.mode & 0777) == 0600, 233 "IPC_SET of mode didn't hold"); 234 235 print_msqid_ds(&m_ds, 0600); 236 237 fflush(stdout); 238 239 switch ((child_pid = fork())) { 240 case -1: 241 atf_tc_fail("fork: %d", errno); 242 return; 243 244 case 0: 245 receiver(); 246 break; 247 248 default: 249 break; 250 } 251 252 for (loop = 0; loop < maxloop; loop++) { 253 /* 254 * Send the first message to the receiver and wait for the ACK. 255 */ 256 m.mtype = MTYPE_1; 257 strlcpy(m.mtext, m1_str, sizeof(m.mtext)); 258 ATF_REQUIRE_MSG(msgsnd(sender_msqid, &m, MESSAGE_TEXT_LEN, 259 0) != -1, "sender: msgsnd 1: %d", errno); 260 261 ATF_REQUIRE_MSG(msgrcv(sender_msqid, &m, MESSAGE_TEXT_LEN, 262 MTYPE_1_ACK, 0) == MESSAGE_TEXT_LEN, 263 "sender: msgrcv 1 ack: %d", errno); 264 265 print_msqid_ds(&m_ds, 0600); 266 267 /* 268 * Send the second message to the receiver and wait for the ACK. 269 */ 270 m.mtype = MTYPE_2; 271 strlcpy(m.mtext, m2_str, sizeof(m.mtext)); 272 ATF_REQUIRE_MSG(msgsnd(sender_msqid, &m, MESSAGE_TEXT_LEN, 0) != -1, 273 "sender: msgsnd 2: %d", errno); 274 275 ATF_REQUIRE_MSG(msgrcv(sender_msqid, &m, MESSAGE_TEXT_LEN, 276 MTYPE_2_ACK, 0) == MESSAGE_TEXT_LEN, 277 "sender: msgrcv 2 ack: %d", errno); 278 } 279 280 /* 281 * Wait for child to finish 282 */ 283 wait_result = wait(&c_status); 284 ATF_REQUIRE_EQ_MSG(wait_result, child_pid, "wait returned %d (%s)", 285 wait_result, wait_result == -1 ? strerror(errno) : ""); 286 ATF_REQUIRE_MSG(WIFEXITED(c_status), "child abnormal exit: %d (sig %d)", 287 c_status, WTERMSIG(c_status)); 288 ATF_REQUIRE_EQ_MSG(WEXITSTATUS(c_status), 0, "child status: %d", 289 WEXITSTATUS(c_status)); 290 291 ATF_REQUIRE_MSG(msgctl(sender_msqid, IPC_STAT, &m_ds) != -1, 292 "msgctl IPC_STAT: %d", errno); 293 294 print_msqid_ds(&m_ds, 0600); 295 } 296 297 ATF_TC_CLEANUP(msg, tc) 298 { 299 int sender_msqid; 300 301 /* 302 * Remove the message queue if it exists. 303 */ 304 sender_msqid = read_int("sender_msqid"); 305 if (sender_msqid != -1) 306 if (msgctl(sender_msqid, IPC_RMID, NULL) == -1) 307 err(1, "msgctl IPC_RMID"); 308 } 309 310 void 311 print_msqid_ds(struct msqid_ds *mp, mode_t mode) 312 { 313 uid_t uid = geteuid(); 314 gid_t gid = getegid(); 315 316 printf("PERM: uid %d, gid %d, cuid %d, cgid %d, mode 0%o\n", 317 mp->msg_perm.uid, mp->msg_perm.gid, 318 mp->msg_perm.cuid, mp->msg_perm.cgid, 319 mp->msg_perm.mode & 0777); 320 321 printf("qnum %lu, qbytes %lu, lspid %d, lrpid %d\n", 322 mp->msg_qnum, (u_long)mp->msg_qbytes, mp->msg_lspid, 323 mp->msg_lrpid); 324 325 printf("stime: %s", ctime(&mp->msg_stime)); 326 printf("rtime: %s", ctime(&mp->msg_rtime)); 327 printf("ctime: %s", ctime(&mp->msg_ctime)); 328 329 /* 330 * Sanity check a few things. 331 */ 332 333 ATF_REQUIRE_MSG(mp->msg_perm.uid == uid && mp->msg_perm.cuid == uid, 334 "uid mismatch"); 335 336 ATF_REQUIRE_MSG(mp->msg_perm.gid == gid && mp->msg_perm.cgid == gid, 337 "gid mismatch"); 338 339 ATF_REQUIRE_MSG((mp->msg_perm.mode & 0777) == mode, "mode mismatch"); 340 } 341 342 void 343 receiver(void) 344 { 345 struct testmsg m; 346 int msqid, loop; 347 348 if ((msqid = msgget(msgkey, 0)) == -1) 349 err(1, "receiver: msgget"); 350 351 for (loop = 0; loop < maxloop; loop++) { 352 /* 353 * Receive the first message, print it, and send an ACK. 354 */ 355 if (msgrcv(msqid, &m, MESSAGE_TEXT_LEN, MTYPE_1, 0) != MESSAGE_TEXT_LEN) 356 err(1, "receiver: msgrcv 1"); 357 358 printf("%s\n", m.mtext); 359 if (strcmp(m.mtext, m1_str) != 0) 360 errx(1, "receiver: message 1 data isn't correct"); 361 362 m.mtype = MTYPE_1_ACK; 363 364 if (msgsnd(msqid, &m, MESSAGE_TEXT_LEN, 0) == -1) 365 err(1, "receiver: msgsnd ack 1"); 366 367 /* 368 * Receive the second message, print it, and send an ACK. 369 */ 370 371 if (msgrcv(msqid, &m, MESSAGE_TEXT_LEN, MTYPE_2, 0) != MESSAGE_TEXT_LEN) 372 err(1, "receiver: msgrcv 2"); 373 374 printf("%s\n", m.mtext); 375 if (strcmp(m.mtext, m2_str) != 0) 376 errx(1, "receiver: message 2 data isn't correct"); 377 378 m.mtype = MTYPE_2_ACK; 379 380 if (msgsnd(msqid, &m, MESSAGE_TEXT_LEN, 0) == -1) 381 err(1, "receiver: msgsnd ack 2"); 382 } 383 384 exit(0); 385 } 386 387 /* 388 * Test the SVID-compatible Semaphore facility. 389 */ 390 391 ATF_TC_WITH_CLEANUP(sem); 392 ATF_TC_HEAD(sem, tc) 393 { 394 395 atf_tc_set_md_var(tc, "timeout", "3"); 396 atf_tc_set_md_var(tc, "descr", "Checks sysvmsg passing"); 397 } 398 399 ATF_TC_BODY(sem, tc) 400 { 401 struct sigaction sa; 402 union semun sun; 403 struct semid_ds s_ds; 404 int sender_semid; 405 int i; 406 int c_status; 407 int child_count; 408 pid_t wait_result; 409 410 /* 411 * Install a SIGSYS handler so that we can exit gracefully if 412 * System V Semaphore support isn't in the kernel. 413 */ 414 did_sigsys = 0; 415 sa.sa_handler = sigsys_handler; 416 sigemptyset(&sa.sa_mask); 417 sa.sa_flags = 0; 418 ATF_REQUIRE_MSG(sigaction(SIGSYS, &sa, NULL) != -1, 419 "sigaction SIGSYS: %d", errno); 420 421 semkey = get_ftok(4160); 422 ATF_REQUIRE_MSG(semkey != (key_t)-1, "get_ftok failed"); 423 424 sender_semid = semget(semkey, 1, IPC_CREAT | 0640); 425 ATF_REQUIRE_MSG(sender_semid != -1, "semget: %d", errno); 426 write_int("sender_semid", sender_semid); 427 428 if (did_sigsys) { 429 atf_tc_skip("SYSV Semaphore not supported"); 430 return; 431 } 432 433 sun.buf = &s_ds; 434 ATF_REQUIRE_MSG(semctl(sender_semid, 0, IPC_STAT, sun) != -1, 435 "semctl IPC_STAT: %d", errno); 436 437 print_semid_ds(&s_ds, 0640); 438 439 s_ds.sem_perm.mode = (s_ds.sem_perm.mode & ~0777) | 0600; 440 441 sun.buf = &s_ds; 442 ATF_REQUIRE_MSG(semctl(sender_semid, 0, IPC_SET, sun) != -1, 443 "semctl IPC_SET: %d", errno); 444 445 memset(&s_ds, 0, sizeof(s_ds)); 446 447 sun.buf = &s_ds; 448 ATF_REQUIRE_MSG(semctl(sender_semid, 0, IPC_STAT, sun) != -1, 449 "semctl IPC_STAT: %d", errno); 450 451 ATF_REQUIRE_MSG((s_ds.sem_perm.mode & 0777) == 0600, 452 "IPC_SET of mode didn't hold"); 453 454 print_semid_ds(&s_ds, 0600); 455 456 fflush(stdout); 457 458 for (child_count = 0; child_count < 5; child_count++) { 459 switch ((child_pid = fork())) { 460 case -1: 461 atf_tc_fail("fork: %d", errno); 462 return; 463 464 case 0: 465 waiter(); 466 break; 467 468 default: 469 break; 470 } 471 } 472 473 /* 474 * Wait for all of the waiters to be attempting to acquire the 475 * semaphore. 476 */ 477 for (;;) { 478 i = semctl(sender_semid, 0, GETNCNT); 479 if (i == -1) 480 atf_tc_fail("semctl GETNCNT: %d", i); 481 if (i == 5) 482 break; 483 } 484 485 /* 486 * Now set the thundering herd in motion by initializing the 487 * semaphore to the value 1. 488 */ 489 sun.val = 1; 490 ATF_REQUIRE_MSG(semctl(sender_semid, 0, SETVAL, sun) != -1, 491 "sender: semctl SETVAL to 1: %d", errno); 492 493 /* 494 * Wait for all children to finish 495 */ 496 while (child_count-- > 0) { 497 wait_result = wait(&c_status); 498 ATF_REQUIRE_MSG(wait_result != -1, "wait failed: %s", 499 strerror(errno)); 500 ATF_REQUIRE_MSG(WIFEXITED(c_status), 501 "child abnormal exit: %d (sig %d)", 502 c_status, WTERMSIG(c_status)); 503 ATF_REQUIRE_EQ_MSG(WEXITSTATUS(c_status), 0, "child status: %d", 504 WEXITSTATUS(c_status)); 505 506 sun.buf = &s_ds; 507 ATF_REQUIRE_MSG(semctl(sender_semid, 0, IPC_STAT, sun) != -1, 508 "semctl IPC_STAT: %d", errno); 509 510 print_semid_ds(&s_ds, 0600); 511 } 512 } 513 514 ATF_TC_CLEANUP(sem, tc) 515 { 516 int sender_semid; 517 518 /* 519 * Remove the semaphore if it exists 520 */ 521 sender_semid = read_int("sender_semid"); 522 if (sender_semid != -1) 523 if (semctl(sender_semid, 0, IPC_RMID) == -1) 524 err(1, "semctl IPC_RMID"); 525 } 526 527 void 528 print_semid_ds(struct semid_ds *sp, mode_t mode) 529 { 530 uid_t uid = geteuid(); 531 gid_t gid = getegid(); 532 533 printf("PERM: uid %d, gid %d, cuid %d, cgid %d, mode 0%o\n", 534 sp->sem_perm.uid, sp->sem_perm.gid, 535 sp->sem_perm.cuid, sp->sem_perm.cgid, 536 sp->sem_perm.mode & 0777); 537 538 printf("nsems %u\n", sp->sem_nsems); 539 540 printf("otime: %s", ctime(&sp->sem_otime)); 541 printf("ctime: %s", ctime(&sp->sem_ctime)); 542 543 /* 544 * Sanity check a few things. 545 */ 546 547 ATF_REQUIRE_MSG(sp->sem_perm.uid == uid && sp->sem_perm.cuid == uid, 548 "uid mismatch"); 549 550 ATF_REQUIRE_MSG(sp->sem_perm.gid == gid && sp->sem_perm.cgid == gid, 551 "gid mismatch"); 552 553 ATF_REQUIRE_MSG((sp->sem_perm.mode & 0777) == mode, 554 "mode mismatch %o != %o", (sp->sem_perm.mode & 0777), mode); 555 } 556 557 void 558 waiter(void) 559 { 560 struct sembuf s; 561 int semid; 562 563 if ((semid = semget(semkey, 1, 0)) == -1) 564 err(1, "waiter: semget"); 565 566 /* 567 * Attempt to acquire the semaphore. 568 */ 569 s.sem_num = 0; 570 s.sem_op = -1; 571 s.sem_flg = SEM_UNDO; 572 573 if (semop(semid, &s, 1) == -1) 574 err(1, "waiter: semop -1"); 575 576 printf("WOO! GOT THE SEMAPHORE!\n"); 577 usleep(10000); 578 579 /* 580 * Release the semaphore and exit. 581 */ 582 s.sem_num = 0; 583 s.sem_op = 1; 584 s.sem_flg = SEM_UNDO; 585 586 if (semop(semid, &s, 1) == -1) 587 err(1, "waiter: semop +1"); 588 589 exit(0); 590 } 591 592 /* 593 * Test the SVID-compatible Shared Memory facility. 594 */ 595 596 ATF_TC_WITH_CLEANUP(shm); 597 ATF_TC_HEAD(shm, tc) 598 { 599 600 atf_tc_set_md_var(tc, "timeout", "3"); 601 atf_tc_set_md_var(tc, "descr", "Checks sysv shared memory"); 602 } 603 604 ATF_TC_BODY(shm, tc) 605 { 606 struct sigaction sa; 607 struct shmid_ds s_ds; 608 char *shm_buf; 609 int sender_shmid; 610 int c_status; 611 pid_t wait_result; 612 613 /* 614 * Install a SIGSYS handler so that we can exit gracefully if 615 * System V Shared Memory support isn't in the kernel. 616 */ 617 did_sigsys = 0; 618 sa.sa_handler = sigsys_handler; 619 sigemptyset(&sa.sa_mask); 620 sa.sa_flags = 0; 621 ATF_REQUIRE_MSG(sigaction(SIGSYS, &sa, NULL) != -1, 622 "sigaction SIGSYS: %d", errno); 623 624 pgsize = sysconf(_SC_PAGESIZE); 625 626 shmkey = get_ftok(4160); 627 ATF_REQUIRE_MSG(shmkey != (key_t)-1, "get_ftok failed"); 628 629 ATF_REQUIRE_MSG((sender_shmid = shmget(shmkey, pgsize, 630 IPC_CREAT | 0640)) != -1, 631 "shmget: %d", errno); 632 write_int("sender_shmid", sender_shmid); 633 634 ATF_REQUIRE_MSG(shmctl(sender_shmid, IPC_STAT, &s_ds) != -1, 635 "shmctl IPC_STAT: %d", errno); 636 637 print_shmid_ds(&s_ds, 0640); 638 639 s_ds.shm_perm.mode = (s_ds.shm_perm.mode & ~0777) | 0600; 640 641 ATF_REQUIRE_MSG(shmctl(sender_shmid, IPC_SET, &s_ds) != -1, 642 "shmctl IPC_SET: %d", errno); 643 644 memset(&s_ds, 0, sizeof(s_ds)); 645 646 ATF_REQUIRE_MSG(shmctl(sender_shmid, IPC_STAT, &s_ds) != -1, 647 "shmctl IPC_STAT: %d", errno); 648 649 ATF_REQUIRE_MSG((s_ds.shm_perm.mode & 0777) == 0600, 650 "IPC_SET of mode didn't hold"); 651 652 print_shmid_ds(&s_ds, 0600); 653 654 shm_buf = shmat(sender_shmid, NULL, 0); 655 ATF_REQUIRE_MSG(shm_buf != (void *) -1, "sender: shmat: %d", errno); 656 657 /* 658 * Write the test pattern into the shared memory buffer. 659 */ 660 strcpy(shm_buf, m2_str); 661 662 fflush(stdout); 663 664 switch ((child_pid = fork())) { 665 case -1: 666 atf_tc_fail("fork: %d", errno); 667 return; 668 669 case 0: 670 sharer(); 671 break; 672 673 default: 674 break; 675 } 676 677 /* 678 * Wait for child to finish 679 */ 680 wait_result = wait(&c_status); 681 ATF_REQUIRE_EQ_MSG(wait_result, child_pid, "wait returned %d (%s)", 682 wait_result, wait_result == -1 ? strerror(errno) : ""); 683 ATF_REQUIRE_MSG(WIFEXITED(c_status), "child abnormal exit: %d (sig %d)", 684 c_status, WTERMSIG(c_status)); 685 ATF_REQUIRE_EQ_MSG(WEXITSTATUS(c_status), 0, "child status: %d", 686 WEXITSTATUS(c_status)); 687 688 ATF_REQUIRE_MSG(shmctl(sender_shmid, IPC_STAT, &s_ds) != -1, 689 "shmctl IPC_STAT: %d", errno); 690 691 print_shmid_ds(&s_ds, 0600); 692 } 693 694 static void 695 shmid_cleanup(const char *name) 696 { 697 int shmid; 698 699 /* 700 * Remove the shared memory area if it exists. 701 */ 702 shmid = read_int(name); 703 if (shmid != -1) { 704 if (shmctl(shmid, IPC_RMID, NULL) == -1) 705 err(1, "shmctl IPC_RMID"); 706 } 707 } 708 709 ATF_TC_CLEANUP(shm, tc) 710 { 711 712 shmid_cleanup("sender_shmid"); 713 } 714 715 void 716 print_shmid_ds(struct shmid_ds *sp, mode_t mode) 717 { 718 uid_t uid = geteuid(); 719 gid_t gid = getegid(); 720 721 printf("PERM: uid %d, gid %d, cuid %d, cgid %d, mode 0%o\n", 722 sp->shm_perm.uid, sp->shm_perm.gid, 723 sp->shm_perm.cuid, sp->shm_perm.cgid, 724 sp->shm_perm.mode & 0777); 725 726 printf("segsz %lu, lpid %d, cpid %d, nattch %u\n", 727 (u_long)sp->shm_segsz, sp->shm_lpid, sp->shm_cpid, 728 sp->shm_nattch); 729 730 printf("atime: %s", ctime(&sp->shm_atime)); 731 printf("dtime: %s", ctime(&sp->shm_dtime)); 732 printf("ctime: %s", ctime(&sp->shm_ctime)); 733 734 /* 735 * Sanity check a few things. 736 */ 737 738 ATF_REQUIRE_MSG(sp->shm_perm.uid == uid && sp->shm_perm.cuid == uid, 739 "uid mismatch"); 740 741 ATF_REQUIRE_MSG(sp->shm_perm.gid == gid && sp->shm_perm.cgid == gid, 742 "gid mismatch"); 743 744 ATF_REQUIRE_MSG((sp->shm_perm.mode & 0777) == mode, "mode mismatch"); 745 } 746 747 void 748 sharer(void) 749 { 750 int shmid; 751 void *shm_buf; 752 753 shmid = shmget(shmkey, pgsize, 0); 754 if (shmid == -1) 755 err(1, "receiver: shmget"); 756 757 shm_buf = shmat(shmid, NULL, 0); 758 if (shm_buf == (void *) -1) 759 err(1, "receiver: shmat"); 760 761 printf("%s\n", (const char *)shm_buf); 762 763 if (strcmp((const char *)shm_buf, m2_str) != 0) 764 errx(1, "receiver: data isn't correct"); 765 766 exit(0); 767 } 768 769 #ifdef SHM_REMAP 770 ATF_TC_WITH_CLEANUP(shm_remap); 771 ATF_TC_HEAD(shm_remap, tc) 772 { 773 774 atf_tc_set_md_var(tc, "descr", "Checks SHM_REMAP"); 775 } 776 777 ATF_TC_BODY(shm_remap, tc) 778 { 779 char *shm_buf; 780 int shmid_remap; 781 782 pgsize = sysconf(_SC_PAGESIZE); 783 784 shmkey = get_ftok(4160); 785 ATF_REQUIRE_MSG(shmkey != (key_t)-1, "get_ftok failed"); 786 787 ATF_REQUIRE_MSG((shmid_remap = shmget(shmkey, pgsize, 788 IPC_CREAT | 0640)) != -1, "shmget: %d", errno); 789 write_int("shmid_remap", shmid_remap); 790 791 ATF_REQUIRE_MSG((shm_buf = mmap(NULL, pgsize, PROT_READ | PROT_WRITE, 792 MAP_ANON | MAP_PRIVATE, -1, 0)) != MAP_FAILED, "mmap: %d", errno); 793 794 ATF_REQUIRE_MSG(shmat(shmid_remap, shm_buf, 0) == (void *)-1, 795 "shmat without MAP_REMAP succeeded"); 796 ATF_REQUIRE_MSG(shmat(shmid_remap, shm_buf, SHM_REMAP) == shm_buf, 797 "shmat(SHM_REMAP): %d", errno); 798 } 799 800 ATF_TC_CLEANUP(shm_remap, tc) 801 { 802 803 shmid_cleanup("shmid_remap"); 804 } 805 #endif /* SHM_REMAP */ 806 807 ATF_TP_ADD_TCS(tp) 808 { 809 810 ATF_TP_ADD_TC(tp, msg); 811 ATF_TP_ADD_TC(tp, sem); 812 ATF_TP_ADD_TC(tp, shm); 813 #ifdef SHM_REMAP 814 ATF_TP_ADD_TC(tp, shm_remap); 815 #endif 816 817 return atf_no_error(); 818 } 819 820