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