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 if (atf_tc_get_config_var_as_bool_wd(tc, "ci", false)) 214 atf_tc_skip("https://bugs.freebsd.org/233649"); 215 216 /* 217 * Install a SIGSYS handler so that we can exit gracefully if 218 * System V Message Queue support isn't in the kernel. 219 */ 220 did_sigsys = 0; 221 sa.sa_handler = sigsys_handler; 222 sigemptyset(&sa.sa_mask); 223 sa.sa_flags = 0; 224 ATF_REQUIRE_MSG(sigaction(SIGSYS, &sa, NULL) != -1, 225 "sigaction SIGSYS: %d", errno); 226 227 /* 228 * Install a SIGCHLD handler to deal with all possible exit 229 * conditions of the receiver. 230 */ 231 did_sigchild = 0; 232 child_count = 0; 233 sa.sa_handler = sigchld_handler; 234 sigemptyset(&sa.sa_mask); 235 sa.sa_flags = 0; 236 ATF_REQUIRE_MSG(sigaction(SIGCHLD, &sa, NULL) != -1, 237 "sigaction SIGCHLD: %d", errno); 238 239 msgkey = get_ftok(4160); 240 ATF_REQUIRE_MSG(msgkey != (key_t)-1, "get_ftok failed"); 241 242 sender_msqid = msgget(msgkey, IPC_CREAT | 0640); 243 ATF_REQUIRE_MSG(sender_msqid != -1, "msgget: %d", errno); 244 write_int("sender_msqid", sender_msqid); 245 246 if (did_sigsys) { 247 atf_tc_skip("SYSV Message Queue not supported"); 248 return; 249 } 250 251 ATF_REQUIRE_MSG(msgctl(sender_msqid, IPC_STAT, &m_ds) != -1, 252 "msgctl IPC_STAT 1: %d", errno); 253 254 print_msqid_ds(&m_ds, 0640); 255 256 m_ds.msg_perm.mode = (m_ds.msg_perm.mode & ~0777) | 0600; 257 258 ATF_REQUIRE_MSG(msgctl(sender_msqid, IPC_SET, &m_ds) != -1, 259 "msgctl IPC_SET: %d", errno); 260 261 memset(&m_ds, 0, sizeof(m_ds)); 262 263 ATF_REQUIRE_MSG(msgctl(sender_msqid, IPC_STAT, &m_ds) != -1, 264 "msgctl IPC_STAT 2: %d", errno); 265 266 ATF_REQUIRE_MSG((m_ds.msg_perm.mode & 0777) == 0600, 267 "IPC_SET of mode didn't hold"); 268 269 print_msqid_ds(&m_ds, 0600); 270 271 switch ((child_pid = fork())) { 272 case -1: 273 atf_tc_fail("fork: %d", errno); 274 return; 275 276 case 0: 277 child_count++; 278 receiver(); 279 break; 280 281 default: 282 break; 283 } 284 285 for (loop = 0; loop < maxloop; loop++) { 286 /* 287 * Send the first message to the receiver and wait for the ACK. 288 */ 289 m.mtype = MTYPE_1; 290 strlcpy(m.mtext, m1_str, sizeof(m.mtext)); 291 ATF_REQUIRE_MSG(msgsnd(sender_msqid, &m, MESSAGE_TEXT_LEN, 292 0) != -1, "sender: msgsnd 1: %d", errno); 293 294 ATF_REQUIRE_MSG(msgrcv(sender_msqid, &m, MESSAGE_TEXT_LEN, 295 MTYPE_1_ACK, 0) == MESSAGE_TEXT_LEN, 296 "sender: msgrcv 1 ack: %d", errno); 297 298 print_msqid_ds(&m_ds, 0600); 299 300 /* 301 * Send the second message to the receiver and wait for the ACK. 302 */ 303 m.mtype = MTYPE_2; 304 strlcpy(m.mtext, m2_str, sizeof(m.mtext)); 305 ATF_REQUIRE_MSG(msgsnd(sender_msqid, &m, MESSAGE_TEXT_LEN, 0) != -1, 306 "sender: msgsnd 2: %d", errno); 307 308 ATF_REQUIRE_MSG(msgrcv(sender_msqid, &m, MESSAGE_TEXT_LEN, 309 MTYPE_2_ACK, 0) == MESSAGE_TEXT_LEN, 310 "sender: msgrcv 2 ack: %d", errno); 311 } 312 313 /* 314 * Wait for child to finish 315 */ 316 sigemptyset(&sigmask); 317 (void) sigsuspend(&sigmask); 318 319 /* 320 * ...and any other signal is an unexpected error. 321 */ 322 if (did_sigchild) { 323 c_status = child_status; 324 if (c_status < 0) 325 atf_tc_fail("waitpid: %d", -c_status); 326 else if (WIFEXITED(c_status) == 0) 327 atf_tc_fail("child abnormal exit: %d", c_status); 328 else if (WEXITSTATUS(c_status) != 0) 329 atf_tc_fail("c status: %d", WEXITSTATUS(c_status)); 330 else { 331 ATF_REQUIRE_MSG(msgctl(sender_msqid, IPC_STAT, &m_ds) 332 != -1, "msgctl IPC_STAT: %d", errno); 333 334 print_msqid_ds(&m_ds, 0600); 335 atf_tc_pass(); 336 } 337 } else 338 atf_tc_fail("sender: received unexpected signal"); 339 } 340 341 ATF_TC_CLEANUP(msg, tc) 342 { 343 int sender_msqid; 344 345 /* 346 * Remove the message queue if it exists. 347 */ 348 sender_msqid = read_int("sender_msqid"); 349 if (sender_msqid != -1) 350 if (msgctl(sender_msqid, IPC_RMID, NULL) == -1) 351 err(1, "msgctl IPC_RMID"); 352 } 353 354 void 355 print_msqid_ds(struct msqid_ds *mp, mode_t mode) 356 { 357 uid_t uid = geteuid(); 358 gid_t gid = getegid(); 359 360 printf("PERM: uid %d, gid %d, cuid %d, cgid %d, mode 0%o\n", 361 mp->msg_perm.uid, mp->msg_perm.gid, 362 mp->msg_perm.cuid, mp->msg_perm.cgid, 363 mp->msg_perm.mode & 0777); 364 365 printf("qnum %lu, qbytes %lu, lspid %d, lrpid %d\n", 366 mp->msg_qnum, (u_long)mp->msg_qbytes, mp->msg_lspid, 367 mp->msg_lrpid); 368 369 printf("stime: %s", ctime(&mp->msg_stime)); 370 printf("rtime: %s", ctime(&mp->msg_rtime)); 371 printf("ctime: %s", ctime(&mp->msg_ctime)); 372 373 /* 374 * Sanity check a few things. 375 */ 376 377 ATF_REQUIRE_MSG(mp->msg_perm.uid == uid && mp->msg_perm.cuid == uid, 378 "uid mismatch"); 379 380 ATF_REQUIRE_MSG(mp->msg_perm.gid == gid && mp->msg_perm.cgid == gid, 381 "gid mismatch"); 382 383 ATF_REQUIRE_MSG((mp->msg_perm.mode & 0777) == mode, "mode mismatch"); 384 } 385 386 void 387 receiver(void) 388 { 389 struct testmsg m; 390 int msqid, loop; 391 392 if ((msqid = msgget(msgkey, 0)) == -1) 393 err(1, "receiver: msgget"); 394 395 for (loop = 0; loop < maxloop; loop++) { 396 /* 397 * Receive the first message, print it, and send an ACK. 398 */ 399 if (msgrcv(msqid, &m, MESSAGE_TEXT_LEN, MTYPE_1, 0) != MESSAGE_TEXT_LEN) 400 err(1, "receiver: msgrcv 1"); 401 402 printf("%s\n", m.mtext); 403 if (strcmp(m.mtext, m1_str) != 0) 404 err(1, "receiver: message 1 data isn't correct"); 405 406 m.mtype = MTYPE_1_ACK; 407 408 if (msgsnd(msqid, &m, MESSAGE_TEXT_LEN, 0) == -1) 409 err(1, "receiver: msgsnd ack 1"); 410 411 /* 412 * Receive the second message, print it, and send an ACK. 413 */ 414 415 if (msgrcv(msqid, &m, MESSAGE_TEXT_LEN, MTYPE_2, 0) != MESSAGE_TEXT_LEN) 416 err(1, "receiver: msgrcv 2"); 417 418 printf("%s\n", m.mtext); 419 if (strcmp(m.mtext, m2_str) != 0) 420 err(1, "receiver: message 2 data isn't correct"); 421 422 m.mtype = MTYPE_2_ACK; 423 424 if (msgsnd(msqid, &m, MESSAGE_TEXT_LEN, 0) == -1) 425 err(1, "receiver: msgsnd ack 2"); 426 } 427 428 exit(0); 429 } 430 431 /* 432 * Test the SVID-compatible Semaphore facility. 433 */ 434 435 ATF_TC_WITH_CLEANUP(sem); 436 ATF_TC_HEAD(sem, tc) 437 { 438 439 atf_tc_set_md_var(tc, "timeout", "3"); 440 atf_tc_set_md_var(tc, "descr", "Checks sysvmsg passing"); 441 } 442 443 ATF_TC_BODY(sem, tc) 444 { 445 struct sigaction sa; 446 union semun sun; 447 struct semid_ds s_ds; 448 sigset_t sigmask; 449 int sender_semid; 450 int i; 451 int c_status; 452 453 /* 454 * Install a SIGSYS handler so that we can exit gracefully if 455 * System V Semaphore support isn't in the kernel. 456 */ 457 did_sigsys = 0; 458 sa.sa_handler = sigsys_handler; 459 sigemptyset(&sa.sa_mask); 460 sa.sa_flags = 0; 461 ATF_REQUIRE_MSG(sigaction(SIGSYS, &sa, NULL) != -1, 462 "sigaction SIGSYS: %d", errno); 463 464 /* 465 * Install a SIGCHLD handler to deal with all possible exit 466 * conditions of the receiver. 467 */ 468 did_sigchild = 0; 469 child_count = 0; 470 sa.sa_handler = sigchld_handler; 471 sigemptyset(&sa.sa_mask); 472 sa.sa_flags = 0; 473 ATF_REQUIRE_MSG(sigaction(SIGCHLD, &sa, NULL) != -1, 474 "sigaction SIGCHLD: %d", errno); 475 476 semkey = get_ftok(4160); 477 ATF_REQUIRE_MSG(semkey != (key_t)-1, "get_ftok failed"); 478 479 sender_semid = semget(semkey, 1, IPC_CREAT | 0640); 480 ATF_REQUIRE_MSG(sender_semid != -1, "semget: %d", errno); 481 write_int("sender_semid", sender_semid); 482 483 if (did_sigsys) { 484 atf_tc_skip("SYSV Semaphore not supported"); 485 return; 486 } 487 488 sun.buf = &s_ds; 489 ATF_REQUIRE_MSG(semctl(sender_semid, 0, IPC_STAT, sun) != -1, 490 "semctl IPC_STAT: %d", errno); 491 492 print_semid_ds(&s_ds, 0640); 493 494 s_ds.sem_perm.mode = (s_ds.sem_perm.mode & ~0777) | 0600; 495 496 sun.buf = &s_ds; 497 ATF_REQUIRE_MSG(semctl(sender_semid, 0, IPC_SET, sun) != -1, 498 "semctl IPC_SET: %d", errno); 499 500 memset(&s_ds, 0, sizeof(s_ds)); 501 502 sun.buf = &s_ds; 503 ATF_REQUIRE_MSG(semctl(sender_semid, 0, IPC_STAT, sun) != -1, 504 "semctl IPC_STAT: %d", errno); 505 506 ATF_REQUIRE_MSG((s_ds.sem_perm.mode & 0777) == 0600, 507 "IPC_SET of mode didn't hold"); 508 509 print_semid_ds(&s_ds, 0600); 510 511 for (child_count = 0; child_count < 5; child_count++) { 512 switch ((child_pid = fork())) { 513 case -1: 514 atf_tc_fail("fork: %d", errno); 515 return; 516 517 case 0: 518 waiter(); 519 break; 520 521 default: 522 break; 523 } 524 } 525 526 /* 527 * Wait for all of the waiters to be attempting to acquire the 528 * semaphore. 529 */ 530 for (;;) { 531 i = semctl(sender_semid, 0, GETNCNT); 532 if (i == -1) 533 atf_tc_fail("semctl GETNCNT: %d", i); 534 if (i == 5) 535 break; 536 } 537 538 /* 539 * Now set the thundering herd in motion by initializing the 540 * semaphore to the value 1. 541 */ 542 sun.val = 1; 543 ATF_REQUIRE_MSG(semctl(sender_semid, 0, SETVAL, sun) != -1, 544 "sender: semctl SETVAL to 1: %d", errno); 545 546 /* 547 * Wait for all children to finish 548 */ 549 sigemptyset(&sigmask); 550 for (;;) { 551 (void) sigsuspend(&sigmask); 552 if (did_sigchild) { 553 c_status = child_status; 554 if (c_status < 0) 555 atf_tc_fail("waitpid: %d", -c_status); 556 else if (WIFEXITED(c_status) == 0) 557 atf_tc_fail("c abnormal exit: %d", c_status); 558 else if (WEXITSTATUS(c_status) != 0) 559 atf_tc_fail("c status: %d", 560 WEXITSTATUS(c_status)); 561 else { 562 sun.buf = &s_ds; 563 ATF_REQUIRE_MSG(semctl(sender_semid, 0, 564 IPC_STAT, sun) != -1, 565 "semctl IPC_STAT: %d", errno); 566 567 print_semid_ds(&s_ds, 0600); 568 atf_tc_pass(); 569 } 570 if (child_count <= 0) 571 break; 572 did_sigchild = 0; 573 } else { 574 atf_tc_fail("sender: received unexpected signal"); 575 break; 576 } 577 } 578 } 579 580 ATF_TC_CLEANUP(sem, tc) 581 { 582 int sender_semid; 583 584 /* 585 * Remove the semaphore if it exists 586 */ 587 sender_semid = read_int("sender_semid"); 588 if (sender_semid != -1) 589 if (semctl(sender_semid, 0, IPC_RMID) == -1) 590 err(1, "semctl IPC_RMID"); 591 } 592 593 void 594 print_semid_ds(struct semid_ds *sp, mode_t mode) 595 { 596 uid_t uid = geteuid(); 597 gid_t gid = getegid(); 598 599 printf("PERM: uid %d, gid %d, cuid %d, cgid %d, mode 0%o\n", 600 sp->sem_perm.uid, sp->sem_perm.gid, 601 sp->sem_perm.cuid, sp->sem_perm.cgid, 602 sp->sem_perm.mode & 0777); 603 604 printf("nsems %u\n", sp->sem_nsems); 605 606 printf("otime: %s", ctime(&sp->sem_otime)); 607 printf("ctime: %s", ctime(&sp->sem_ctime)); 608 609 /* 610 * Sanity check a few things. 611 */ 612 613 ATF_REQUIRE_MSG(sp->sem_perm.uid == uid && sp->sem_perm.cuid == uid, 614 "uid mismatch"); 615 616 ATF_REQUIRE_MSG(sp->sem_perm.gid == gid && sp->sem_perm.cgid == gid, 617 "gid mismatch"); 618 619 ATF_REQUIRE_MSG((sp->sem_perm.mode & 0777) == mode, 620 "mode mismatch %o != %o", (sp->sem_perm.mode & 0777), mode); 621 } 622 623 void 624 waiter(void) 625 { 626 struct sembuf s; 627 int semid; 628 629 if ((semid = semget(semkey, 1, 0)) == -1) 630 err(1, "waiter: semget"); 631 632 /* 633 * Attempt to acquire the semaphore. 634 */ 635 s.sem_num = 0; 636 s.sem_op = -1; 637 s.sem_flg = SEM_UNDO; 638 639 if (semop(semid, &s, 1) == -1) 640 err(1, "waiter: semop -1"); 641 642 printf("WOO! GOT THE SEMAPHORE!\n"); 643 sleep(1); 644 645 /* 646 * Release the semaphore and exit. 647 */ 648 s.sem_num = 0; 649 s.sem_op = 1; 650 s.sem_flg = SEM_UNDO; 651 652 if (semop(semid, &s, 1) == -1) 653 err(1, "waiter: semop +1"); 654 655 exit(0); 656 } 657 658 /* 659 * Test the SVID-compatible Shared Memory facility. 660 */ 661 662 ATF_TC_WITH_CLEANUP(shm); 663 ATF_TC_HEAD(shm, tc) 664 { 665 666 atf_tc_set_md_var(tc, "timeout", "3"); 667 atf_tc_set_md_var(tc, "descr", "Checks sysv shared memory"); 668 } 669 670 ATF_TC_BODY(shm, tc) 671 { 672 struct sigaction sa; 673 struct shmid_ds s_ds; 674 sigset_t sigmask; 675 char *shm_buf; 676 int sender_shmid; 677 int c_status; 678 679 /* 680 * Install a SIGSYS handler so that we can exit gracefully if 681 * System V Shared Memory support isn't in the kernel. 682 */ 683 did_sigsys = 0; 684 sa.sa_handler = sigsys_handler; 685 sigemptyset(&sa.sa_mask); 686 sa.sa_flags = 0; 687 ATF_REQUIRE_MSG(sigaction(SIGSYS, &sa, NULL) != -1, 688 "sigaction SIGSYS: %d", errno); 689 690 /* 691 * Install a SIGCHLD handler to deal with all possible exit 692 * conditions of the sharer. 693 */ 694 did_sigchild = 0; 695 child_count = 0; 696 sa.sa_handler = sigchld_handler; 697 sigemptyset(&sa.sa_mask); 698 sa.sa_flags = 0; 699 ATF_REQUIRE_MSG(sigaction(SIGCHLD, &sa, NULL) != -1, 700 "sigaction SIGCHLD: %d", errno); 701 702 pgsize = sysconf(_SC_PAGESIZE); 703 704 shmkey = get_ftok(4160); 705 ATF_REQUIRE_MSG(shmkey != (key_t)-1, "get_ftok failed"); 706 707 ATF_REQUIRE_MSG((sender_shmid = shmget(shmkey, pgsize, 708 IPC_CREAT | 0640)) != -1, 709 "shmget: %d", errno); 710 write_int("sender_shmid", sender_shmid); 711 712 ATF_REQUIRE_MSG(shmctl(sender_shmid, IPC_STAT, &s_ds) != -1, 713 "shmctl IPC_STAT: %d", errno); 714 715 print_shmid_ds(&s_ds, 0640); 716 717 s_ds.shm_perm.mode = (s_ds.shm_perm.mode & ~0777) | 0600; 718 719 ATF_REQUIRE_MSG(shmctl(sender_shmid, IPC_SET, &s_ds) != -1, 720 "shmctl IPC_SET: %d", errno); 721 722 memset(&s_ds, 0, sizeof(s_ds)); 723 724 ATF_REQUIRE_MSG(shmctl(sender_shmid, IPC_STAT, &s_ds) != -1, 725 "shmctl IPC_STAT: %d", errno); 726 727 ATF_REQUIRE_MSG((s_ds.shm_perm.mode & 0777) == 0600, 728 "IPC_SET of mode didn't hold"); 729 730 print_shmid_ds(&s_ds, 0600); 731 732 shm_buf = shmat(sender_shmid, NULL, 0); 733 ATF_REQUIRE_MSG(shm_buf != (void *) -1, "sender: shmat: %d", errno); 734 735 /* 736 * Write the test pattern into the shared memory buffer. 737 */ 738 strcpy(shm_buf, m2_str); 739 740 switch ((child_pid = fork())) { 741 case -1: 742 atf_tc_fail("fork: %d", errno); 743 return; 744 745 case 0: 746 sharer(); 747 break; 748 749 default: 750 break; 751 } 752 753 /* 754 * Wait for child to finish 755 */ 756 sigemptyset(&sigmask); 757 (void) sigsuspend(&sigmask); 758 759 if (did_sigchild) { 760 c_status = child_status; 761 if (c_status < 0) 762 atf_tc_fail("waitpid: %d", -c_status); 763 else if (WIFEXITED(c_status) == 0) 764 atf_tc_fail("c abnormal exit: %d", c_status); 765 else if (WEXITSTATUS(c_status) != 0) 766 atf_tc_fail("c status: %d", WEXITSTATUS(c_status)); 767 else { 768 ATF_REQUIRE_MSG(shmctl(sender_shmid, IPC_STAT, 769 &s_ds) != -1, 770 "shmctl IPC_STAT: %d", errno); 771 772 print_shmid_ds(&s_ds, 0600); 773 atf_tc_pass(); 774 } 775 } else 776 atf_tc_fail("sender: received unexpected signal"); 777 } 778 779 static void 780 shmid_cleanup(const char *name) 781 { 782 int shmid; 783 784 /* 785 * Remove the shared memory area if it exists. 786 */ 787 shmid = read_int(name); 788 if (shmid != -1) { 789 if (shmctl(shmid, IPC_RMID, NULL) == -1) 790 err(1, "shmctl IPC_RMID"); 791 } 792 } 793 794 ATF_TC_CLEANUP(shm, tc) 795 { 796 797 shmid_cleanup("sender_shmid"); 798 } 799 800 void 801 print_shmid_ds(struct shmid_ds *sp, mode_t mode) 802 { 803 uid_t uid = geteuid(); 804 gid_t gid = getegid(); 805 806 printf("PERM: uid %d, gid %d, cuid %d, cgid %d, mode 0%o\n", 807 sp->shm_perm.uid, sp->shm_perm.gid, 808 sp->shm_perm.cuid, sp->shm_perm.cgid, 809 sp->shm_perm.mode & 0777); 810 811 printf("segsz %lu, lpid %d, cpid %d, nattch %u\n", 812 (u_long)sp->shm_segsz, sp->shm_lpid, sp->shm_cpid, 813 sp->shm_nattch); 814 815 printf("atime: %s", ctime(&sp->shm_atime)); 816 printf("dtime: %s", ctime(&sp->shm_dtime)); 817 printf("ctime: %s", ctime(&sp->shm_ctime)); 818 819 /* 820 * Sanity check a few things. 821 */ 822 823 ATF_REQUIRE_MSG(sp->shm_perm.uid == uid && sp->shm_perm.cuid == uid, 824 "uid mismatch"); 825 826 ATF_REQUIRE_MSG(sp->shm_perm.gid == gid && sp->shm_perm.cgid == gid, 827 "gid mismatch"); 828 829 ATF_REQUIRE_MSG((sp->shm_perm.mode & 0777) == mode, "mode mismatch"); 830 } 831 832 void 833 sharer(void) 834 { 835 int shmid; 836 void *shm_buf; 837 838 shmid = shmget(shmkey, pgsize, 0); 839 ATF_REQUIRE_MSG(shmid != -1, "receiver: shmget:%d", errno); 840 841 shm_buf = shmat(shmid, NULL, 0); 842 ATF_REQUIRE_MSG(shm_buf != (void *) -1, "receiver: shmat: %d", errno); 843 844 printf("%s\n", (const char *)shm_buf); 845 846 ATF_REQUIRE_MSG(strcmp((const char *)shm_buf, m2_str) == 0, 847 "receiver: data isn't correct"); 848 849 exit(0); 850 } 851 852 #ifdef SHM_REMAP 853 ATF_TC_WITH_CLEANUP(shm_remap); 854 ATF_TC_HEAD(shm_remap, tc) 855 { 856 857 atf_tc_set_md_var(tc, "descr", "Checks SHM_REMAP"); 858 } 859 860 ATF_TC_BODY(shm_remap, tc) 861 { 862 char *shm_buf; 863 int shmid_remap; 864 865 pgsize = sysconf(_SC_PAGESIZE); 866 867 shmkey = get_ftok(4160); 868 ATF_REQUIRE_MSG(shmkey != (key_t)-1, "get_ftok failed"); 869 870 ATF_REQUIRE_MSG((shmid_remap = shmget(shmkey, pgsize, 871 IPC_CREAT | 0640)) != -1, "shmget: %d", errno); 872 write_int("shmid_remap", shmid_remap); 873 874 ATF_REQUIRE_MSG((shm_buf = mmap(NULL, pgsize, PROT_READ | PROT_WRITE, 875 MAP_ANON | MAP_PRIVATE, -1, 0)) != MAP_FAILED, "mmap: %d", errno); 876 877 ATF_REQUIRE_MSG(shmat(shmid_remap, shm_buf, 0) == (void *)-1, 878 "shmat without MAP_REMAP succeeded"); 879 ATF_REQUIRE_MSG(shmat(shmid_remap, shm_buf, SHM_REMAP) == shm_buf, 880 "shmat(SHM_REMAP): %d", errno); 881 } 882 883 ATF_TC_CLEANUP(shm_remap, tc) 884 { 885 886 shmid_cleanup("shmid_remap"); 887 } 888 #endif /* SHM_REMAP */ 889 890 ATF_TP_ADD_TCS(tp) 891 { 892 893 ATF_TP_ADD_TC(tp, msg); 894 ATF_TP_ADD_TC(tp, sem); 895 ATF_TP_ADD_TC(tp, shm); 896 #ifdef SHM_REMAP 897 ATF_TP_ADD_TC(tp, shm_remap); 898 #endif 899 900 return atf_no_error(); 901 } 902 903