t_sysv.c revision 343426
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 57volatile int did_sigsys, did_sigchild; 58volatile int child_status, child_count; 59 60void sigsys_handler(int); 61void sigchld_handler(int); 62 63key_t get_ftok(int); 64 65void print_msqid_ds(struct msqid_ds *, mode_t); 66void receiver(void); 67 68void print_semid_ds(struct semid_ds *, mode_t); 69void waiter(void); 70 71void print_shmid_ds(struct shmid_ds *, mode_t); 72void sharer(void); 73 74#define MESSAGE_TEXT_LEN 256 75 76struct testmsg { 77 long mtype; 78 char mtext[MESSAGE_TEXT_LEN]; 79}; 80 81const char *m1_str = "California is overrated."; 82const char *m2_str = "The quick brown fox jumped over the lazy dog."; 83 84size_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 92pid_t child_pid; 93 94key_t msgkey, semkey, shmkey; 95 96int maxloop = 1; 97 98#ifndef __FreeBSD__ 99union semun { 100 int val; /* value for SETVAL */ 101 struct semid_ds *buf; /* buffer for IPC_{STAT,SET} */ 102 u_short *array; /* array for GETALL & SETALL */ 103}; 104#endif 105 106 107/* Writes an integer to a file. To be used from the body of the test 108 * cases below to pass any global identifiers to the cleanup routine. */ 109static void 110write_int(const char *path, const int value) 111{ 112 int output; 113 114 output = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600); 115 ATF_REQUIRE_MSG(output != -1, "Failed to create %s", path); 116 write(output, &value, sizeof(value)); 117 close(output); 118} 119 120 121/* Reads an integer from a file. To be used from the cleanup routines 122 * of the test cases below. */ 123static int 124read_int(const char *path) 125{ 126 int input; 127 128 input = open(path, O_RDONLY); 129 if (input == -1) 130 return -1; 131 else { 132 int value; 133 ATF_REQUIRE_EQ(read(input, &value, sizeof(value)), sizeof(value)); 134 close(input); 135 return value; 136 } 137} 138 139 140void 141sigsys_handler(int signo) 142{ 143 144 did_sigsys = 1; 145} 146 147void 148sigchld_handler(int signo) 149{ 150 int c_status; 151 152 did_sigchild = 1; 153 /* 154 * Reap the child and return its status 155 */ 156 if (wait(&c_status) == -1) 157 child_status = -errno; 158 else 159 child_status = c_status; 160 161 child_count--; 162} 163 164key_t get_ftok(int id) 165{ 166 int fd; 167 char token_key[64], token_dir[64]; 168 char *tmpdir; 169 key_t key; 170 171 strlcpy(token_key, "/tmp/t_sysv.XXXXXX", sizeof(token_key)); 172 tmpdir = mkdtemp(token_key); 173 ATF_REQUIRE_MSG(tmpdir != NULL, "mkdtemp() failed: %d", errno); 174 175 strlcpy(token_dir, tmpdir, sizeof(token_dir)); 176 strlcpy(token_key, tmpdir, sizeof(token_key)); 177 strlcat(token_key, "/token_key", sizeof(token_key)); 178 179 /* Create the file, since ftok() requires it to exist! */ 180 181 fd = open(token_key, O_RDWR | O_CREAT | O_EXCL, 0600); 182 if (fd == -1) { 183 rmdir(tmpdir); 184 atf_tc_fail("open() of temp file failed: %d", errno); 185 return (key_t)-1; 186 } else 187 close(fd); 188 189 key = ftok(token_key, id); 190 191 ATF_REQUIRE_MSG(unlink(token_key) != -1, "unlink() failed: %d", errno); 192 ATF_REQUIRE_MSG(rmdir(token_dir) != -1, "rmdir() failed: %d", errno); 193 194 return key; 195} 196 197ATF_TC_WITH_CLEANUP(msg); 198ATF_TC_HEAD(msg, tc) 199{ 200 201 atf_tc_set_md_var(tc, "timeout", "3"); 202 atf_tc_set_md_var(tc, "descr", "Checks sysvmsg passing"); 203} 204 205ATF_TC_BODY(msg, tc) 206{ 207 struct sigaction sa; 208 struct msqid_ds m_ds; 209 struct testmsg m; 210 sigset_t sigmask; 211 int sender_msqid; 212 int loop; 213 int c_status; 214 215 /* 216 * Install a SIGSYS handler so that we can exit gracefully if 217 * System V Message Queue support isn't in the kernel. 218 */ 219 did_sigsys = 0; 220 sa.sa_handler = sigsys_handler; 221 sigemptyset(&sa.sa_mask); 222 sa.sa_flags = 0; 223 ATF_REQUIRE_MSG(sigaction(SIGSYS, &sa, NULL) != -1, 224 "sigaction SIGSYS: %d", errno); 225 226 /* 227 * Install a SIGCHLD handler to deal with all possible exit 228 * conditions of the receiver. 229 */ 230 did_sigchild = 0; 231 child_count = 0; 232 sa.sa_handler = sigchld_handler; 233 sigemptyset(&sa.sa_mask); 234 sa.sa_flags = 0; 235 ATF_REQUIRE_MSG(sigaction(SIGCHLD, &sa, NULL) != -1, 236 "sigaction SIGCHLD: %d", errno); 237 238 msgkey = get_ftok(4160); 239 ATF_REQUIRE_MSG(msgkey != (key_t)-1, "get_ftok failed"); 240 241 sender_msqid = msgget(msgkey, IPC_CREAT | 0640); 242 ATF_REQUIRE_MSG(sender_msqid != -1, "msgget: %d", errno); 243 write_int("sender_msqid", sender_msqid); 244 245 if (did_sigsys) { 246 atf_tc_skip("SYSV Message Queue not supported"); 247 return; 248 } 249 250 ATF_REQUIRE_MSG(msgctl(sender_msqid, IPC_STAT, &m_ds) != -1, 251 "msgctl IPC_STAT 1: %d", errno); 252 253 print_msqid_ds(&m_ds, 0640); 254 255 m_ds.msg_perm.mode = (m_ds.msg_perm.mode & ~0777) | 0600; 256 257 ATF_REQUIRE_MSG(msgctl(sender_msqid, IPC_SET, &m_ds) != -1, 258 "msgctl IPC_SET: %d", errno); 259 260 memset(&m_ds, 0, sizeof(m_ds)); 261 262 ATF_REQUIRE_MSG(msgctl(sender_msqid, IPC_STAT, &m_ds) != -1, 263 "msgctl IPC_STAT 2: %d", errno); 264 265 ATF_REQUIRE_MSG((m_ds.msg_perm.mode & 0777) == 0600, 266 "IPC_SET of mode didn't hold"); 267 268 print_msqid_ds(&m_ds, 0600); 269 270 switch ((child_pid = fork())) { 271 case -1: 272 atf_tc_fail("fork: %d", errno); 273 return; 274 275 case 0: 276 child_count++; 277 receiver(); 278 break; 279 280 default: 281 break; 282 } 283 284 for (loop = 0; loop < maxloop; loop++) { 285 /* 286 * Send the first message to the receiver and wait for the ACK. 287 */ 288 m.mtype = MTYPE_1; 289 strlcpy(m.mtext, m1_str, sizeof(m.mtext)); 290 ATF_REQUIRE_MSG(msgsnd(sender_msqid, &m, MESSAGE_TEXT_LEN, 291 0) != -1, "sender: msgsnd 1: %d", errno); 292 293 ATF_REQUIRE_MSG(msgrcv(sender_msqid, &m, MESSAGE_TEXT_LEN, 294 MTYPE_1_ACK, 0) == MESSAGE_TEXT_LEN, 295 "sender: msgrcv 1 ack: %d", errno); 296 297 print_msqid_ds(&m_ds, 0600); 298 299 /* 300 * Send the second message to the receiver and wait for the ACK. 301 */ 302 m.mtype = MTYPE_2; 303 strlcpy(m.mtext, m2_str, sizeof(m.mtext)); 304 ATF_REQUIRE_MSG(msgsnd(sender_msqid, &m, MESSAGE_TEXT_LEN, 0) != -1, 305 "sender: msgsnd 2: %d", errno); 306 307 ATF_REQUIRE_MSG(msgrcv(sender_msqid, &m, MESSAGE_TEXT_LEN, 308 MTYPE_2_ACK, 0) == MESSAGE_TEXT_LEN, 309 "sender: msgrcv 2 ack: %d", errno); 310 } 311 312 /* 313 * Wait for child to finish 314 */ 315 sigemptyset(&sigmask); 316 (void) sigsuspend(&sigmask); 317 318 /* 319 * ...and any other signal is an unexpected error. 320 */ 321 if (did_sigchild) { 322 c_status = child_status; 323 if (c_status < 0) 324 atf_tc_fail("waitpid: %d", -c_status); 325 else if (WIFEXITED(c_status) == 0) 326 atf_tc_fail("child abnormal exit: %d", c_status); 327 else if (WEXITSTATUS(c_status) != 0) 328 atf_tc_fail("c status: %d", WEXITSTATUS(c_status)); 329 else { 330 ATF_REQUIRE_MSG(msgctl(sender_msqid, IPC_STAT, &m_ds) 331 != -1, "msgctl IPC_STAT: %d", errno); 332 333 print_msqid_ds(&m_ds, 0600); 334 atf_tc_pass(); 335 } 336 } else 337 atf_tc_fail("sender: received unexpected signal"); 338} 339 340ATF_TC_CLEANUP(msg, tc) 341{ 342 int sender_msqid; 343 344 /* 345 * Remove the message queue if it exists. 346 */ 347 sender_msqid = read_int("sender_msqid"); 348 if (sender_msqid != -1) 349 if (msgctl(sender_msqid, IPC_RMID, NULL) == -1) 350 err(1, "msgctl IPC_RMID"); 351} 352 353void 354print_msqid_ds(struct msqid_ds *mp, mode_t mode) 355{ 356 uid_t uid = geteuid(); 357 gid_t gid = getegid(); 358 359 printf("PERM: uid %d, gid %d, cuid %d, cgid %d, mode 0%o\n", 360 mp->msg_perm.uid, mp->msg_perm.gid, 361 mp->msg_perm.cuid, mp->msg_perm.cgid, 362 mp->msg_perm.mode & 0777); 363 364 printf("qnum %lu, qbytes %lu, lspid %d, lrpid %d\n", 365 mp->msg_qnum, (u_long)mp->msg_qbytes, mp->msg_lspid, 366 mp->msg_lrpid); 367 368 printf("stime: %s", ctime(&mp->msg_stime)); 369 printf("rtime: %s", ctime(&mp->msg_rtime)); 370 printf("ctime: %s", ctime(&mp->msg_ctime)); 371 372 /* 373 * Sanity check a few things. 374 */ 375 376 ATF_REQUIRE_MSG(mp->msg_perm.uid == uid && mp->msg_perm.cuid == uid, 377 "uid mismatch"); 378 379 ATF_REQUIRE_MSG(mp->msg_perm.gid == gid && mp->msg_perm.cgid == gid, 380 "gid mismatch"); 381 382 ATF_REQUIRE_MSG((mp->msg_perm.mode & 0777) == mode, "mode mismatch"); 383} 384 385void 386receiver(void) 387{ 388 struct testmsg m; 389 int msqid, loop; 390 391 if ((msqid = msgget(msgkey, 0)) == -1) 392 err(1, "receiver: msgget"); 393 394 for (loop = 0; loop < maxloop; loop++) { 395 /* 396 * Receive the first message, print it, and send an ACK. 397 */ 398 if (msgrcv(msqid, &m, MESSAGE_TEXT_LEN, MTYPE_1, 0) != MESSAGE_TEXT_LEN) 399 err(1, "receiver: msgrcv 1"); 400 401 printf("%s\n", m.mtext); 402 if (strcmp(m.mtext, m1_str) != 0) 403 err(1, "receiver: message 1 data isn't correct"); 404 405 m.mtype = MTYPE_1_ACK; 406 407 if (msgsnd(msqid, &m, MESSAGE_TEXT_LEN, 0) == -1) 408 err(1, "receiver: msgsnd ack 1"); 409 410 /* 411 * Receive the second message, print it, and send an ACK. 412 */ 413 414 if (msgrcv(msqid, &m, MESSAGE_TEXT_LEN, MTYPE_2, 0) != MESSAGE_TEXT_LEN) 415 err(1, "receiver: msgrcv 2"); 416 417 printf("%s\n", m.mtext); 418 if (strcmp(m.mtext, m2_str) != 0) 419 err(1, "receiver: message 2 data isn't correct"); 420 421 m.mtype = MTYPE_2_ACK; 422 423 if (msgsnd(msqid, &m, MESSAGE_TEXT_LEN, 0) == -1) 424 err(1, "receiver: msgsnd ack 2"); 425 } 426 427 exit(0); 428} 429 430/* 431 * Test the SVID-compatible Semaphore facility. 432 */ 433 434ATF_TC_WITH_CLEANUP(sem); 435ATF_TC_HEAD(sem, tc) 436{ 437 438 atf_tc_set_md_var(tc, "timeout", "3"); 439 atf_tc_set_md_var(tc, "descr", "Checks sysvmsg passing"); 440} 441 442ATF_TC_BODY(sem, tc) 443{ 444 struct sigaction sa; 445 union semun sun; 446 struct semid_ds s_ds; 447 sigset_t sigmask; 448 int sender_semid; 449 int i; 450 int c_status; 451 452 /* 453 * Install a SIGSYS handler so that we can exit gracefully if 454 * System V Semaphore support isn't in the kernel. 455 */ 456 did_sigsys = 0; 457 sa.sa_handler = sigsys_handler; 458 sigemptyset(&sa.sa_mask); 459 sa.sa_flags = 0; 460 ATF_REQUIRE_MSG(sigaction(SIGSYS, &sa, NULL) != -1, 461 "sigaction SIGSYS: %d", errno); 462 463 /* 464 * Install a SIGCHLD handler to deal with all possible exit 465 * conditions of the receiver. 466 */ 467 did_sigchild = 0; 468 child_count = 0; 469 sa.sa_handler = sigchld_handler; 470 sigemptyset(&sa.sa_mask); 471 sa.sa_flags = 0; 472 ATF_REQUIRE_MSG(sigaction(SIGCHLD, &sa, NULL) != -1, 473 "sigaction SIGCHLD: %d", errno); 474 475 semkey = get_ftok(4160); 476 ATF_REQUIRE_MSG(semkey != (key_t)-1, "get_ftok failed"); 477 478 sender_semid = semget(semkey, 1, IPC_CREAT | 0640); 479 ATF_REQUIRE_MSG(sender_semid != -1, "semget: %d", errno); 480 write_int("sender_semid", sender_semid); 481 482 if (did_sigsys) { 483 atf_tc_skip("SYSV Semaphore not supported"); 484 return; 485 } 486 487 sun.buf = &s_ds; 488 ATF_REQUIRE_MSG(semctl(sender_semid, 0, IPC_STAT, sun) != -1, 489 "semctl IPC_STAT: %d", errno); 490 491 print_semid_ds(&s_ds, 0640); 492 493 s_ds.sem_perm.mode = (s_ds.sem_perm.mode & ~0777) | 0600; 494 495 sun.buf = &s_ds; 496 ATF_REQUIRE_MSG(semctl(sender_semid, 0, IPC_SET, sun) != -1, 497 "semctl IPC_SET: %d", errno); 498 499 memset(&s_ds, 0, sizeof(s_ds)); 500 501 sun.buf = &s_ds; 502 ATF_REQUIRE_MSG(semctl(sender_semid, 0, IPC_STAT, sun) != -1, 503 "semctl IPC_STAT: %d", errno); 504 505 ATF_REQUIRE_MSG((s_ds.sem_perm.mode & 0777) == 0600, 506 "IPC_SET of mode didn't hold"); 507 508 print_semid_ds(&s_ds, 0600); 509 510 for (child_count = 0; child_count < 5; child_count++) { 511 switch ((child_pid = fork())) { 512 case -1: 513 atf_tc_fail("fork: %d", errno); 514 return; 515 516 case 0: 517 waiter(); 518 break; 519 520 default: 521 break; 522 } 523 } 524 525 /* 526 * Wait for all of the waiters to be attempting to acquire the 527 * semaphore. 528 */ 529 for (;;) { 530 i = semctl(sender_semid, 0, GETNCNT); 531 if (i == -1) 532 atf_tc_fail("semctl GETNCNT: %d", i); 533 if (i == 5) 534 break; 535 } 536 537 /* 538 * Now set the thundering herd in motion by initializing the 539 * semaphore to the value 1. 540 */ 541 sun.val = 1; 542 ATF_REQUIRE_MSG(semctl(sender_semid, 0, SETVAL, sun) != -1, 543 "sender: semctl SETVAL to 1: %d", errno); 544 545 /* 546 * Wait for all children to finish 547 */ 548 sigemptyset(&sigmask); 549 for (;;) { 550 (void) sigsuspend(&sigmask); 551 if (did_sigchild) { 552 c_status = child_status; 553 if (c_status < 0) 554 atf_tc_fail("waitpid: %d", -c_status); 555 else if (WIFEXITED(c_status) == 0) 556 atf_tc_fail("c abnormal exit: %d", c_status); 557 else if (WEXITSTATUS(c_status) != 0) 558 atf_tc_fail("c status: %d", 559 WEXITSTATUS(c_status)); 560 else { 561 sun.buf = &s_ds; 562 ATF_REQUIRE_MSG(semctl(sender_semid, 0, 563 IPC_STAT, sun) != -1, 564 "semctl IPC_STAT: %d", errno); 565 566 print_semid_ds(&s_ds, 0600); 567 atf_tc_pass(); 568 } 569 if (child_count <= 0) 570 break; 571 did_sigchild = 0; 572 } else { 573 atf_tc_fail("sender: received unexpected signal"); 574 break; 575 } 576 } 577} 578 579ATF_TC_CLEANUP(sem, tc) 580{ 581 int sender_semid; 582 583 /* 584 * Remove the semaphore if it exists 585 */ 586 sender_semid = read_int("sender_semid"); 587 if (sender_semid != -1) 588 if (semctl(sender_semid, 0, IPC_RMID) == -1) 589 err(1, "semctl IPC_RMID"); 590} 591 592void 593print_semid_ds(struct semid_ds *sp, 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 622void 623waiter(void) 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 661ATF_TC_WITH_CLEANUP(shm); 662ATF_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 669ATF_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 778static void 779shmid_cleanup(const char *name) 780{ 781 int shmid; 782 783 /* 784 * Remove the shared memory area if it exists. 785 */ 786 shmid = read_int(name); 787 if (shmid != -1) { 788 if (shmctl(shmid, IPC_RMID, NULL) == -1) 789 err(1, "shmctl IPC_RMID"); 790 } 791} 792 793ATF_TC_CLEANUP(shm, tc) 794{ 795 796 shmid_cleanup("sender_shmid"); 797} 798 799void 800print_shmid_ds(struct shmid_ds *sp, mode_t mode) 801{ 802 uid_t uid = geteuid(); 803 gid_t gid = getegid(); 804 805 printf("PERM: uid %d, gid %d, cuid %d, cgid %d, mode 0%o\n", 806 sp->shm_perm.uid, sp->shm_perm.gid, 807 sp->shm_perm.cuid, sp->shm_perm.cgid, 808 sp->shm_perm.mode & 0777); 809 810 printf("segsz %lu, lpid %d, cpid %d, nattch %u\n", 811 (u_long)sp->shm_segsz, sp->shm_lpid, sp->shm_cpid, 812 sp->shm_nattch); 813 814 printf("atime: %s", ctime(&sp->shm_atime)); 815 printf("dtime: %s", ctime(&sp->shm_dtime)); 816 printf("ctime: %s", ctime(&sp->shm_ctime)); 817 818 /* 819 * Sanity check a few things. 820 */ 821 822 ATF_REQUIRE_MSG(sp->shm_perm.uid == uid && sp->shm_perm.cuid == uid, 823 "uid mismatch"); 824 825 ATF_REQUIRE_MSG(sp->shm_perm.gid == gid && sp->shm_perm.cgid == gid, 826 "gid mismatch"); 827 828 ATF_REQUIRE_MSG((sp->shm_perm.mode & 0777) == mode, "mode mismatch"); 829} 830 831void 832sharer(void) 833{ 834 int shmid; 835 void *shm_buf; 836 837 shmid = shmget(shmkey, pgsize, 0); 838 ATF_REQUIRE_MSG(shmid != -1, "receiver: shmget:%d", errno); 839 840 shm_buf = shmat(shmid, NULL, 0); 841 ATF_REQUIRE_MSG(shm_buf != (void *) -1, "receiver: shmat: %d", errno); 842 843 printf("%s\n", (const char *)shm_buf); 844 845 ATF_REQUIRE_MSG(strcmp((const char *)shm_buf, m2_str) == 0, 846 "receiver: data isn't correct"); 847 848 exit(0); 849} 850 851#ifdef SHM_REMAP 852ATF_TC_WITH_CLEANUP(shm_remap); 853ATF_TC_HEAD(shm_remap, tc) 854{ 855 856 atf_tc_set_md_var(tc, "descr", "Checks SHM_REMAP"); 857} 858 859ATF_TC_BODY(shm_remap, tc) 860{ 861 char *shm_buf; 862 int shmid_remap; 863 864 pgsize = sysconf(_SC_PAGESIZE); 865 866 shmkey = get_ftok(4160); 867 ATF_REQUIRE_MSG(shmkey != (key_t)-1, "get_ftok failed"); 868 869 ATF_REQUIRE_MSG((shmid_remap = shmget(shmkey, pgsize, 870 IPC_CREAT | 0640)) != -1, "shmget: %d", errno); 871 write_int("shmid_remap", shmid_remap); 872 873 ATF_REQUIRE_MSG((shm_buf = mmap(NULL, pgsize, PROT_READ | PROT_WRITE, 874 MAP_ANON | MAP_PRIVATE, -1, 0)) != MAP_FAILED, "mmap: %d", errno); 875 876 ATF_REQUIRE_MSG(shmat(shmid_remap, shm_buf, 0) == (void *)-1, 877 "shmat without MAP_REMAP succeeded"); 878 ATF_REQUIRE_MSG(shmat(shmid_remap, shm_buf, SHM_REMAP) == shm_buf, 879 "shmat(SHM_REMAP): %d", errno); 880} 881 882ATF_TC_CLEANUP(shm_remap, tc) 883{ 884 885 shmid_cleanup("shmid_remap"); 886} 887#endif /* SHM_REMAP */ 888 889ATF_TP_ADD_TCS(tp) 890{ 891 892 ATF_TP_ADD_TC(tp, msg); 893 ATF_TP_ADD_TC(tp, sem); 894 ATF_TP_ADD_TC(tp, shm); 895#ifdef SHM_REMAP 896 ATF_TP_ADD_TC(tp, shm_remap); 897#endif 898 899 return atf_no_error(); 900} 901 902