Home | History | Annotate | Download | only in shmat
      1 /*
      2  *
      3  *   Copyright (c) International Business Machines  Corp., 2001
      4  *
      5  *   This program is free software;  you can redistribute it and/or modify
      6  *   it under the terms of the GNU General Public License as published by
      7  *   the Free Software Foundation; either version 2 of the License, or
      8  *   (at your option) any later version.
      9  *
     10  *   This program is distributed in the hope that it will be useful,
     11  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
     12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
     13  *   the GNU General Public License for more details.
     14  *
     15  *   You should have received a copy of the GNU General Public License
     16  *   along with this program;  if not, write to the Free Software
     17  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     18  */
     19 
     20 /*
     21  * NAME
     22  *	shmat02.c
     23  *
     24  * DESCRIPTION
     25  *	shmat02 - check for EINVAL and EACCES errors
     26  *
     27  * ALGORITHM
     28  *	loop if that option was specified
     29  *	  call shmat() using three invalid test cases
     30  *	  check the errno value
     31  *	    issue a PASS message if we get EINVAL or EACCES
     32  *	  otherwise, the tests fails
     33  *	    issue a FAIL message
     34  *	call cleanup
     35  *
     36  * USAGE:  <for command-line>
     37  *  shmat02 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
     38  *     where,  -c n : Run n copies concurrently.
     39  *             -e   : Turn on errno logging.
     40  *	       -i n : Execute test n times.
     41  *	       -I x : Execute test for x seconds.
     42  *	       -P x : Pause for x seconds between iterations.
     43  *	       -t   : Turn on syscall timing.
     44  *
     45  * HISTORY
     46  *	03/2001 - Written by Wayne Boyer
     47  *
     48  *      27/02/2008 Renaud Lottiaux (Renaud.Lottiaux (at) kerlabs.com)
     49  *      - Fix concurrency issue. The second key used for this test could
     50  *        conflict with the key from another task.
     51  *
     52  * RESTRICTIONS
     53  *	Must be ran as non-root
     54  */
     55 
     56 #include "ipcshm.h"
     57 #include <pwd.h>
     58 #include "shmat_common.h"
     59 
     60 char *TCID = "shmat02";
     61 char nobody_uid[] = "nobody";
     62 struct passwd *ltpuser;
     63 
     64 int shm_id_1 = -1;
     65 int shm_id_2 = -1;
     66 int shm_id_3 = -1;
     67 
     68 void *base_addr;		/* By probing this address first, we can make
     69 				 * non-aligned addresses from it for different
     70 				 * architectures without explicitly code it.
     71 				 */
     72 
     73 void *addr;			/* for result of shmat-call */
     74 
     75 struct test_case_t {
     76 	int *shmid;
     77 	int offset;
     78 	int error;
     79 };
     80 
     81 int TST_TOTAL = 3;
     82 
     83 static void setup_tc(int i, struct test_case_t *tc)
     84 {
     85 
     86 	struct test_case_t TC[] = {
     87 		/* EINVAL - the shared memory ID is not valid */
     88 		{&shm_id_1, 0, EINVAL},
     89 		/* EINVAL - the address is not page aligned and SHM_RND is not given */
     90 		{&shm_id_2, SHMLBA - 1, EINVAL},
     91 		/* EACCES - the shared memory resource has no read/write permission */
     92 		{&shm_id_3, 0, EACCES}
     93 	};
     94 
     95 	if (i > TST_TOTAL || i < 0)
     96 		return;
     97 
     98 	*tc = TC[i];
     99 }
    100 
    101 int main(int ac, char **av)
    102 {
    103 	int lc;
    104 	int i;
    105 	struct test_case_t *tc;
    106 
    107 	tc = NULL;
    108 
    109 	tst_parse_opts(ac, av, NULL, NULL);
    110 
    111 	tc = malloc(sizeof(struct test_case_t));
    112 	if (tc == NULL)
    113 		tst_brkm(TBROK | TERRNO, cleanup, "malloc failed");
    114 
    115 	setup();
    116 
    117 	for (lc = 0; TEST_LOOPING(lc); lc++) {
    118 		tst_count = 0;
    119 
    120 		for (i = 0; i < TST_TOTAL; i++) {
    121 
    122 			setup_tc(i, tc);
    123 
    124 			base_addr = probe_free_addr();
    125 			errno = 0;
    126 			addr = shmat(*(tc->shmid), base_addr + tc->offset, 0);
    127 
    128 			if (addr != (void *)-1) {
    129 				tst_resm(TFAIL, "call succeeded unexpectedly");
    130 				continue;
    131 			}
    132 
    133 			if (errno == tc->error)
    134 				tst_resm(TPASS | TERRNO,
    135 					 "shmat failed as expected");
    136 			else
    137 				tst_resm(TFAIL,
    138 					 "shmat failed unexpectedly; expected: "
    139 					 "%d - %s", tc->error,
    140 					 strerror(tc->error));
    141 		}
    142 	}
    143 
    144 	cleanup();
    145 
    146 	tst_exit();
    147 }
    148 
    149 void setup(void)
    150 {
    151 	key_t shmkey2;
    152 
    153 	tst_require_root();
    154 	ltpuser = getpwnam(nobody_uid);
    155 	if (ltpuser == NULL)
    156 		tst_brkm(TBROK | TERRNO, NULL, "getpwnam failed");
    157 	if (setuid(ltpuser->pw_uid) == -1)
    158 		tst_brkm(TBROK | TERRNO, NULL, "setuid failed");
    159 
    160 	tst_sig(NOFORK, DEF_HANDLER, cleanup);
    161 
    162 	TEST_PAUSE;
    163 
    164 	tst_tmpdir();
    165 
    166 	shmkey = getipckey();
    167 
    168 	shm_id_2 = shmget(shmkey, INT_SIZE, SHM_RW | IPC_CREAT | IPC_EXCL);
    169 	if (shm_id_2 == -1)
    170 		tst_brkm(TBROK | TERRNO, cleanup, "shmget #1 failed");
    171 
    172 	/* Get an new IPC resource key. */
    173 	shmkey2 = getipckey();
    174 
    175 	/* create a shared memory resource without read and write permissions */
    176 	shm_id_3 = shmget(shmkey2, INT_SIZE, IPC_CREAT | IPC_EXCL);
    177 	if (shm_id_3 == -1)
    178 		tst_brkm(TBROK | TERRNO, cleanup, "shmget #2 failed");
    179 }
    180 
    181 void cleanup(void)
    182 {
    183 	/* if they exist, remove the shared memory resources */
    184 	rm_shm(shm_id_2);
    185 	rm_shm(shm_id_3);
    186 
    187 	tst_rmdir();
    188 
    189 }
    190