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