Home | History | Annotate | Download | only in shmat
      1 /*
      2  * Copyright (c) International Business Machines  Corp., 2001
      3  *
      4  * This program is free software;  you can redistribute it and/or modify
      5  * it under the terms of the GNU General Public License as published by
      6  * the Free Software Foundation; either version 2 of the License, or
      7  * (at your option) any later version.
      8  *
      9  * This program is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY;  without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
     12  * the GNU General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU General Public License
     15  * along with this program.
     16  */
     17 
     18 /*
     19  * DESCRIPTION
     20  *
     21  * 1) shmat() fails and set errno to EINVAL when shmid is invalid.
     22  * 2) shmat() fails and set errno to EINVAL when shmaddr is not page
     23  *    aligned and SHM_RND is not given
     24  * 3) shmat() fails and set errno to EACCES when the shm resource has
     25  *    no read/write permission.
     26  */
     27 
     28 #include <errno.h>
     29 #include <stdlib.h>
     30 #include <sys/types.h>
     31 #include <sys/ipc.h>
     32 #include <sys/shm.h>
     33 #include <pwd.h>
     34 
     35 #include "tst_test.h"
     36 #include "tst_safe_sysv_ipc.h"
     37 #include "libnewipc.h"
     38 
     39 static int shm_id1 = -1;
     40 static int shm_id2 = -1;
     41 static void *aligned_addr;
     42 static void *unaligned_addr;
     43 static key_t shm_key1;
     44 static struct passwd *pw;
     45 
     46 static struct test_case_t {
     47 	int *shmid;
     48 	void **shmaddr;
     49 	int exp_err;
     50 	int exp_user;
     51 } tcases[] = {
     52 	{&shm_id1, &aligned_addr, EINVAL, 0},
     53 	{&shm_id2, &unaligned_addr, EINVAL, 0},
     54 	{&shm_id2, &aligned_addr, EACCES, 1},
     55 };
     56 
     57 static void verify_shmat(struct test_case_t *tc)
     58 {
     59 	void *addr;
     60 
     61 	addr = shmat(*tc->shmid, *tc->shmaddr, 0);
     62 	if (addr != (void *)-1) {
     63 		tst_res(TFAIL, "shmat() succeeded unexpectedly");
     64 		return;
     65 	}
     66 
     67 	if (errno == tc->exp_err) {
     68 		tst_res(TPASS | TERRNO, "shmat() failed as expected");
     69 	} else {
     70 		tst_res(TFAIL | TERRNO, "shmat() failed unexpectedly,"
     71 			 "expected: %s", tst_strerrno(tc->exp_err));
     72 	}
     73 }
     74 
     75 static void do_shmat(unsigned int n)
     76 {
     77 	pid_t pid;
     78 
     79 	struct test_case_t *tc = &tcases[n];
     80 
     81 	if (!tc->exp_user) {
     82 		verify_shmat(tc);
     83 	} else {
     84 		pid = SAFE_FORK();
     85 		if (pid) {
     86 			tst_reap_children();
     87 		} else {
     88 			SAFE_SETUID(pw->pw_uid);
     89 			verify_shmat(tc);
     90 			exit(0);
     91 		}
     92 	}
     93 }
     94 
     95 static void setup(void)
     96 {
     97 	aligned_addr = PROBE_FREE_ADDR();
     98 	unaligned_addr = aligned_addr + SHMLBA - 1;
     99 
    100 	shm_key1 = GETIPCKEY();
    101 
    102 	shm_id2 = SAFE_SHMGET(shm_key1, INT_SIZE, SHM_RW | IPC_CREAT | IPC_EXCL);
    103 
    104 	pw = SAFE_GETPWNAM("nobody");
    105 }
    106 
    107 static void cleanup(void)
    108 {
    109 	if (shm_id2 != -1)
    110 		SAFE_SHMCTL(shm_id2, IPC_RMID, NULL);
    111 }
    112 
    113 static struct tst_test test = {
    114 	.needs_root = 1,
    115 	.forks_child = 1,
    116 	.test = do_shmat,
    117 	.tcnt = ARRAY_SIZE(tcases),
    118 	.setup = setup,
    119 	.cleanup = cleanup
    120 };
    121