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