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, did_sigchild; 58 volatile int child_status, child_count; 59 60 void sigsys_handler(int); 61 void sigchld_handler(int); 62 63 key_t get_ftok(int); 64 65 void print_msqid_ds(struct msqid_ds *, mode_t); 66 void receiver(void); 67 68 void print_semid_ds(struct semid_ds *, mode_t); 69 void waiter(void); 70 71 void print_shmid_ds(struct shmid_ds *, mode_t); 72 void sharer(void); 73 74 #define MESSAGE_TEXT_LEN 256 75 76 struct testmsg { 77 long mtype; 78 char mtext[MESSAGE_TEXT_LEN]; 79 }; 80 81 const char *m1_str = "California is overrated."; 82 const char *m2_str = "The quick brown fox jumped over the lazy dog."; 83 84 size_t pgsize; 85 86 #define MTYPE_1 1 87 #define MTYPE_1_ACK 2 88 89 #define MTYPE_2 3 90 #define MTYPE_2_ACK 4 91 92 pid_t child_pid; 93 94 key_t msgkey, semkey, shmkey; 95 96 int maxloop = 1; 97 98 union semun { 99 int val; /* value for SETVAL */ 100 struct semid_ds *buf; /* buffer for IPC_{STAT,SET} */ 101 u_short *array; /* array for GETALL & SETALL */ 102 }; 103 104 105 /* Writes an integer to a file. To be used from the body of the test 106 * cases below to pass any global identifiers to the cleanup routine. */ 107 static void 108 write_int(const char *path, const int value) 109 { 110 int output; 111 112 output = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600); 113 ATF_REQUIRE_MSG(output != -1, "Failed to create %s", path); 114 write(output, &value, sizeof(value)); 115 close(output); 116 } 117 118 119 /* Reads an integer from a file. To be used from the cleanup routines 120 * of the test cases below. */ 121 static int 122 read_int(const char *path) 123 { 124 int input; 125 126 input = open(path, O_RDONLY); 127 if (input == -1) 128 return -1; 129 else { 130 int value; 131 ATF_REQUIRE_EQ(read(input, &value, sizeof(value)), sizeof(value)); 132 close(input); 133 return value; 134 } 135 } 136 137 138 void 139 sigsys_handler(int signo) 140 { 141 142 did_sigsys = 1; 143 } 144 145 void 146 sigchld_handler(int signo) 147 { 148 int c_status; 149 150 did_sigchild = 1; 151 /* 152 * Reap the child and return its status 153 */ 154 if (wait(&c_status) == -1) 155 child_status = -errno; 156 else 157 child_status = c_status; 158 159 child_count--; 160 } 161 162 key_t get_ftok(int id) 163 { 164 int fd; 165 char token_key[64], token_dir[64]; 166 char *tmpdir; 167 key_t key; 168 169 strlcpy(token_key, "/tmp/t_sysv.XXXXXX", sizeof(token_key)); 170 tmpdir = mkdtemp(token_key); 171 ATF_REQUIRE_MSG(tmpdir != NULL, "mkdtemp() failed: %d", errno); 172 173 strlcpy(token_dir, tmpdir, sizeof(token_dir)); 174 strlcpy(token_key, tmpdir, sizeof(token_key)); 175 strlcat(token_key, "/token_key", sizeof(token_key)); 176 177 /* Create the file, since ftok() requires it to exist! */ 178 179 fd = open(token_key, O_RDWR | O_CREAT | O_EXCL, 0600); 180 if (fd == -1) { 181 rmdir(tmpdir); 182 atf_tc_fail("open() of temp file failed: %d", errno); 183 return (key_t)-1; 184 } else 185 close(fd); 186 187 key = ftok(token_key, id); 188 189 ATF_REQUIRE_MSG(unlink(token_key) != -1, "unlink() failed: %d", errno); 190 ATF_REQUIRE_MSG(rmdir(token_dir) != -1, "rmdir() failed: %d", errno); 191 192 return key; 193 } 194 195 ATF_TC_WITH_CLEANUP(msg); 196 ATF_TC_HEAD(msg, tc) 197 { 198 199 atf_tc_set_md_var(tc, "timeout", "3"); 200 atf_tc_set_md_var(tc, "descr", "Checks sysvmsg passing"); 201 } 202 203 ATF_TC_BODY(msg, tc) 204 { 205 struct sigaction sa; 206 struct msqid_ds m_ds; 207 struct testmsg m; 208 sigset_t sigmask; 209 int sender_msqid; 210 int loop; 211 int c_status; 212 213 /* 214 * Install a SIGSYS handler so that we can exit gracefully if 215 * System V Message Queue support isn't in the kernel. 216 */ 217 did_sigsys = 0; 218 sa.sa_handler = sigsys_handler; 219 sigemptyset(&sa.sa_mask); 220 sa.sa_flags = 0; 221 ATF_REQUIRE_MSG(sigaction(SIGSYS, &sa, NULL) != -1, 222 "sigaction SIGSYS: %d", errno); 223 224 /* 225 * Install a SIGCHLD handler to deal with all possible exit 226 * conditions of the receiver. 227 */ 228 did_sigchild = 0; 229 child_count = 0; 230 sa.sa_handler = sigchld_handler; 231 sigemptyset(&sa.sa_mask); 232 sa.sa_flags = 0; 233 ATF_REQUIRE_MSG(sigaction(SIGCHLD, &sa, NULL) != -1, 234 "sigaction SIGCHLD: %d", errno); 235 236 msgkey = get_ftok(4160); 237 ATF_REQUIRE_MSG(msgkey != (key_t)-1, "get_ftok failed"); 238 239 sender_msqid = msgget(msgkey, IPC_CREAT | 0640); 240 ATF_REQUIRE_MSG(sender_msqid != -1, "msgget: %d", errno); 241 write_int("sender_msqid", sender_msqid); 242 243 if (did_sigsys) { 244 atf_tc_skip("SYSV Message Queue not supported"); 245 return; 246 } 247 248 ATF_REQUIRE_MSG(msgctl(sender_msqid, IPC_STAT, &m_ds) != -1, 249 "msgctl IPC_STAT 1: %d", errno); 250 251 print_msqid_ds(&m_ds, 0640); 252 253 m_ds.msg_perm.mode = (m_ds.msg_perm.mode & ~0777) | 0600; 254 255 ATF_REQUIRE_MSG(msgctl(sender_msqid, IPC_SET, &m_ds) != -1, 256 "msgctl IPC_SET: %d", errno); 257 258 memset(&m_ds, 0, sizeof(m_ds)); 259 260 ATF_REQUIRE_MSG(msgctl(sender_msqid, IPC_STAT, &m_ds) != -1, 261 "msgctl IPC_STAT 2: %d", errno); 262 263 ATF_REQUIRE_MSG((m_ds.msg_perm.mode & 0777) == 0600, 264 "IPC_SET of mode didn't hold"); 265 266 print_msqid_ds(&m_ds, 0600); 267 268 switch ((child_pid = fork())) { 269 case -1: 270 atf_tc_fail("fork: %d", errno); 271 return; 272 273 case 0: 274 child_count++; 275 receiver(); 276 break; 277 278 default: 279 break; 280 } 281 282 for (loop = 0; loop < maxloop; loop++) { 283 /* 284 * Send the first message to the receiver and wait for the ACK. 285 */ 286 m.mtype = MTYPE_1; 287 strlcpy(m.mtext, m1_str, sizeof(m.mtext)); 288 ATF_REQUIRE_MSG(msgsnd(sender_msqid, &m, MESSAGE_TEXT_LEN, 289 0) != -1, "sender: msgsnd 1: %d", errno); 290 291 ATF_REQUIRE_MSG(msgrcv(sender_msqid, &m, MESSAGE_TEXT_LEN, 292 MTYPE_1_ACK, 0) == MESSAGE_TEXT_LEN, 293 "sender: msgrcv 1 ack: %d", errno); 294 295 print_msqid_ds(&m_ds, 0600); 296 297 /* 298 * Send the second message to the receiver and wait for the ACK. 299 */ 300 m.mtype = MTYPE_2; 301 strlcpy(m.mtext, m2_str, sizeof(m.mtext)); 302 ATF_REQUIRE_MSG(msgsnd(sender_msqid, &m, MESSAGE_TEXT_LEN, 0) != -1, 303 "sender: msgsnd 2: %d", errno); 304 305 ATF_REQUIRE_MSG(msgrcv(sender_msqid, &m, MESSAGE_TEXT_LEN, 306 MTYPE_2_ACK, 0) == MESSAGE_TEXT_LEN, 307 "sender: msgrcv 2 ack: %d", errno); 308 } 309 310 /* 311 * Wait for child to finish 312 */ 313 sigemptyset(&sigmask); 314 (void) sigsuspend(&sigmask); 315 316 /* 317 * ...and any other signal is an unexpected error. 318 */ 319 if (did_sigchild) { 320 c_status = child_status; 321 if (c_status < 0) 322 atf_tc_fail("waitpid: %d", -c_status); 323 else if (WIFEXITED(c_status) == 0) 324 atf_tc_fail("child abnormal exit: %d", c_status); 325 else if (WEXITSTATUS(c_status) != 0) 326 atf_tc_fail("c status: %d", WEXITSTATUS(c_status)); 327 else { 328 ATF_REQUIRE_MSG(msgctl(sender_msqid, IPC_STAT, &m_ds) 329 != -1, "msgctl IPC_STAT: %d", errno); 330 331 print_msqid_ds(&m_ds, 0600); 332 atf_tc_pass(); 333 } 334 } else 335 atf_tc_fail("sender: received unexpected signal"); 336 } 337 338 ATF_TC_CLEANUP(msg, tc) 339 { 340 int sender_msqid; 341 342 /* 343 * Remove the message queue if it exists. 344 */ 345 sender_msqid = read_int("sender_msqid"); 346 if (sender_msqid != -1) 347 if (msgctl(sender_msqid, IPC_RMID, NULL) == -1) 348 err(1, "msgctl IPC_RMID"); 349 } 350 351 void 352 print_msqid_ds(struct msqid_ds *mp, 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(void) 385 { 386 struct testmsg 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(struct semid_ds *sp, mode_t mode) 592 { 593 uid_t uid = geteuid(); 594 gid_t gid = getegid(); 595 596 printf("PERM: uid %d, gid %d, cuid %d, cgid %d, mode 0%o\n", 597 sp->sem_perm.uid, sp->sem_perm.gid, 598 sp->sem_perm.cuid, sp->sem_perm.cgid, 599 sp->sem_perm.mode & 0777); 600 601 printf("nsems %u\n", sp->sem_nsems); 602 603 printf("otime: %s", ctime(&sp->sem_otime)); 604 printf("ctime: %s", ctime(&sp->sem_ctime)); 605 606 /* 607 * Sanity check a few things. 608 */ 609 610 ATF_REQUIRE_MSG(sp->sem_perm.uid == uid && sp->sem_perm.cuid == uid, 611 "uid mismatch"); 612 613 ATF_REQUIRE_MSG(sp->sem_perm.gid == gid && sp->sem_perm.cgid == gid, 614 "gid mismatch"); 615 616 ATF_REQUIRE_MSG((sp->sem_perm.mode & 0777) == mode, 617 "mode mismatch %o != %o", (sp->sem_perm.mode & 0777), mode); 618 } 619 620 void 621 waiter(void) 622 { 623 struct sembuf s; 624 int semid; 625 626 if ((semid = semget(semkey, 1, 0)) == -1) 627 err(1, "waiter: semget"); 628 629 /* 630 * Attempt to acquire the semaphore. 631 */ 632 s.sem_num = 0; 633 s.sem_op = -1; 634 s.sem_flg = SEM_UNDO; 635 636 if (semop(semid, &s, 1) == -1) 637 err(1, "waiter: semop -1"); 638 639 printf("WOO! GOT THE SEMAPHORE!\n"); 640 sleep(1); 641 642 /* 643 * Release the semaphore and exit. 644 */ 645 s.sem_num = 0; 646 s.sem_op = 1; 647 s.sem_flg = SEM_UNDO; 648 649 if (semop(semid, &s, 1) == -1) 650 err(1, "waiter: semop +1"); 651 652 exit(0); 653 } 654 655 /* 656 * Test the SVID-compatible Shared Memory facility. 657 */ 658 659 ATF_TC_WITH_CLEANUP(shm); 660 ATF_TC_HEAD(shm, tc) 661 { 662 663 atf_tc_set_md_var(tc, "timeout", "3"); 664 atf_tc_set_md_var(tc, "descr", "Checks sysv shared memory"); 665 } 666 667 ATF_TC_BODY(shm, tc) 668 { 669 struct sigaction sa; 670 struct shmid_ds s_ds; 671 sigset_t sigmask; 672 char *shm_buf; 673 int sender_shmid; 674 int c_status; 675 676 /* 677 * Install a SIGSYS handler so that we can exit gracefully if 678 * System V Shared Memory support isn't in the kernel. 679 */ 680 did_sigsys = 0; 681 sa.sa_handler = sigsys_handler; 682 sigemptyset(&sa.sa_mask); 683 sa.sa_flags = 0; 684 ATF_REQUIRE_MSG(sigaction(SIGSYS, &sa, NULL) != -1, 685 "sigaction SIGSYS: %d", errno); 686 687 /* 688 * Install a SIGCHLD handler to deal with all possible exit 689 * conditions of the sharer. 690 */ 691 did_sigchild = 0; 692 child_count = 0; 693 sa.sa_handler = sigchld_handler; 694 sigemptyset(&sa.sa_mask); 695 sa.sa_flags = 0; 696 ATF_REQUIRE_MSG(sigaction(SIGCHLD, &sa, NULL) != -1, 697 "sigaction SIGCHLD: %d", errno); 698 699 pgsize = sysconf(_SC_PAGESIZE); 700 701 shmkey = get_ftok(4160); 702 ATF_REQUIRE_MSG(shmkey != (key_t)-1, "get_ftok failed"); 703 704 ATF_REQUIRE_MSG((sender_shmid = shmget(shmkey, pgsize, 705 IPC_CREAT | 0640)) != -1, 706 "shmget: %d", errno); 707 write_int("sender_shmid", sender_shmid); 708 709 ATF_REQUIRE_MSG(shmctl(sender_shmid, IPC_STAT, &s_ds) != -1, 710 "shmctl IPC_STAT: %d", errno); 711 712 print_shmid_ds(&s_ds, 0640); 713 714 s_ds.shm_perm.mode = (s_ds.shm_perm.mode & ~0777) | 0600; 715 716 ATF_REQUIRE_MSG(shmctl(sender_shmid, IPC_SET, &s_ds) != -1, 717 "shmctl IPC_SET: %d", errno); 718 719 memset(&s_ds, 0, sizeof(s_ds)); 720 721 ATF_REQUIRE_MSG(shmctl(sender_shmid, IPC_STAT, &s_ds) != -1, 722 "shmctl IPC_STAT: %d", errno); 723 724 ATF_REQUIRE_MSG((s_ds.shm_perm.mode & 0777) == 0600, 725 "IPC_SET of mode didn't hold"); 726 727 print_shmid_ds(&s_ds, 0600); 728 729 shm_buf = shmat(sender_shmid, NULL, 0); 730 ATF_REQUIRE_MSG(shm_buf != (void *) -1, "sender: shmat: %d", errno); 731 732 /* 733 * Write the test pattern into the shared memory buffer. 734 */ 735 strcpy(shm_buf, m2_str); 736 737 switch ((child_pid = fork())) { 738 case -1: 739 atf_tc_fail("fork: %d", errno); 740 return; 741 742 case 0: 743 sharer(); 744 break; 745 746 default: 747 break; 748 } 749 750 /* 751 * Wait for child to finish 752 */ 753 sigemptyset(&sigmask); 754 (void) sigsuspend(&sigmask); 755 756 if (did_sigchild) { 757 c_status = child_status; 758 if (c_status < 0) 759 atf_tc_fail("waitpid: %d", -c_status); 760 else if (WIFEXITED(c_status) == 0) 761 atf_tc_fail("c abnormal exit: %d", c_status); 762 else if (WEXITSTATUS(c_status) != 0) 763 atf_tc_fail("c status: %d", WEXITSTATUS(c_status)); 764 else { 765 ATF_REQUIRE_MSG(shmctl(sender_shmid, IPC_STAT, 766 &s_ds) != -1, 767 "shmctl IPC_STAT: %d", errno); 768 769 print_shmid_ds(&s_ds, 0600); 770 atf_tc_pass(); 771 } 772 } else 773 atf_tc_fail("sender: received unexpected signal"); 774 } 775 776 static void 777 shmid_cleanup(const char *name) 778 { 779 int shmid; 780 781 /* 782 * Remove the shared memory area if it exists. 783 */ 784 shmid = read_int(name); 785 if (shmid != -1) { 786 if (shmctl(shmid, IPC_RMID, NULL) == -1) 787 err(1, "shmctl IPC_RMID"); 788 } 789 } 790 791 ATF_TC_CLEANUP(shm, tc) 792 { 793 794 shmid_cleanup("sender_shmid"); 795 } 796 797 void 798 print_shmid_ds(struct shmid_ds *sp, mode_t mode) 799 { 800 uid_t uid = geteuid(); 801 gid_t gid = getegid(); 802 803 printf("PERM: uid %d, gid %d, cuid %d, cgid %d, mode 0%o\n", 804 sp->shm_perm.uid, sp->shm_perm.gid, 805 sp->shm_perm.cuid, sp->shm_perm.cgid, 806 sp->shm_perm.mode & 0777); 807 808 printf("segsz %lu, lpid %d, cpid %d, nattch %u\n", 809 (u_long)sp->shm_segsz, sp->shm_lpid, sp->shm_cpid, 810 sp->shm_nattch); 811 812 printf("atime: %s", ctime(&sp->shm_atime)); 813 printf("dtime: %s", ctime(&sp->shm_dtime)); 814 printf("ctime: %s", ctime(&sp->shm_ctime)); 815 816 /* 817 * Sanity check a few things. 818 */ 819 820 ATF_REQUIRE_MSG(sp->shm_perm.uid == uid && sp->shm_perm.cuid == uid, 821 "uid mismatch"); 822 823 ATF_REQUIRE_MSG(sp->shm_perm.gid == gid && sp->shm_perm.cgid == gid, 824 "gid mismatch"); 825 826 ATF_REQUIRE_MSG((sp->shm_perm.mode & 0777) == mode, "mode mismatch"); 827 } 828 829 void 830 sharer(void) 831 { 832 int shmid; 833 void *shm_buf; 834 835 shmid = shmget(shmkey, pgsize, 0); 836 ATF_REQUIRE_MSG(shmid != -1, "receiver: shmget:%d", errno); 837 838 shm_buf = shmat(shmid, NULL, 0); 839 ATF_REQUIRE_MSG(shm_buf != (void *) -1, "receiver: shmat: %d", errno); 840 841 printf("%s\n", (const char *)shm_buf); 842 843 ATF_REQUIRE_MSG(strcmp((const char *)shm_buf, m2_str) == 0, 844 "receiver: data isn't correct"); 845 846 exit(0); 847 } 848 849 #ifdef SHM_REMAP 850 ATF_TC_WITH_CLEANUP(shm_remap); 851 ATF_TC_HEAD(shm_remap, tc) 852 { 853 854 atf_tc_set_md_var(tc, "descr", "Checks SHM_REMAP"); 855 } 856 857 ATF_TC_BODY(shm_remap, tc) 858 { 859 char *shm_buf; 860 int shmid_remap; 861 862 pgsize = sysconf(_SC_PAGESIZE); 863 864 shmkey = get_ftok(4160); 865 ATF_REQUIRE_MSG(shmkey != (key_t)-1, "get_ftok failed"); 866 867 ATF_REQUIRE_MSG((shmid_remap = shmget(shmkey, pgsize, 868 IPC_CREAT | 0640)) != -1, "shmget: %d", errno); 869 write_int("shmid_remap", shmid_remap); 870 871 ATF_REQUIRE_MSG((shm_buf = mmap(NULL, pgsize, PROT_READ | PROT_WRITE, 872 MAP_ANON | MAP_PRIVATE, -1, 0)) != MAP_FAILED, "mmap: %d", errno); 873 874 ATF_REQUIRE_MSG(shmat(shmid_remap, shm_buf, 0) == (void *)-1, 875 "shmat without MAP_REMAP succeeded"); 876 ATF_REQUIRE_MSG(shmat(shmid_remap, shm_buf, SHM_REMAP) == shm_buf, 877 "shmat(SHM_REMAP): %d", errno); 878 } 879 880 ATF_TC_CLEANUP(shm_remap, tc) 881 { 882 883 shmid_cleanup("shmid_remap"); 884 } 885 #endif /* SHM_REMAP */ 886 887 ATF_TP_ADD_TCS(tp) 888 { 889 890 ATF_TP_ADD_TC(tp, msg); 891 ATF_TP_ADD_TC(tp, sem); 892 ATF_TP_ADD_TC(tp, shm); 893 #ifdef SHM_REMAP 894 ATF_TP_ADD_TC(tp, shm_remap); 895 #endif 896 897 return atf_no_error(); 898 } 899 900