Home | History | Annotate | Download | only in msgctl
      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  *	msgctl04.c
     23  *
     24  * DESCRIPTION
     25  *	msgctl04 - test for EACCES, EFAULT and EINVAL errors using
     26  *		   a variety of incorrect calls.
     27  *
     28  * ALGORITHM
     29  *	create two message queues
     30  *	loop if that option was specified
     31  *	try to access a queue with some invalid argument
     32  *	check the errno value
     33  *	  issue a PASS message if we get EACCES, EFAULT or EINVAL
     34  *	  depending on the test case
     35  *	otherwise, the tests fails
     36  *	  issue a FAIL message
     37  *	call cleanup
     38  *
     39  * USAGE:  <for command-line>
     40  *  msgctl04 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
     41  *     where,  -c n : Run n copies concurrently.
     42  *             -e   : Turn on errno logging.
     43  *	       -i n : Execute test n times.
     44  *	       -I x : Execute test for x seconds.
     45  *	       -P x : Pause for x seconds between iterations.
     46  *	       -t   : Turn on syscall timing.
     47  *
     48  * HISTORY
     49  *	03/2001 - Written by Wayne Boyer
     50  *      12/03/2008 Matthieu Fertr (Matthieu.Fertre (at) irisa.fr)
     51  *      - Fix concurrency issue. The second key used for this test could
     52  *        conflict with the key from another task.
     53  *
     54  * RESTRICTIONS
     55  *	none
     56  */
     57 #include <pwd.h>
     58 
     59 #include "test.h"
     60 
     61 #include "ipcmsg.h"
     62 
     63 char *TCID = "msgctl04";
     64 int TST_TOTAL = 6;
     65 
     66 char nobody_uid[] = "nobody";
     67 struct passwd *ltpuser;
     68 
     69 int msg_q_1 = -1;		/* The message queue id created in setup */
     70 int msg_q_2 = -1;		/* Another queue id created in setup */
     71 int bad_q = -1;			/* a value to use as a bad queue id */
     72 
     73 struct msqid_ds q_buf;
     74 
     75 struct test_case_t {		/* This allows testing of many negative */
     76 	int *queue_id;		/* test cases that can all use the same */
     77 	int ipc_cmd;		/* basic test setup.                    */
     78 	struct msqid_ds *buf;
     79 	int error;
     80 } TC[] = {
     81 	/* EACCES - there is no read permission for the queue */
     82 	{
     83 	&msg_q_1, IPC_STAT, &q_buf, EACCES},
     84 	    /* EFAULT - the structure address is invalid - IPC_STAT */
     85 	{
     86 	&msg_q_2, IPC_STAT, (struct msqid_ds *)-1, EFAULT},
     87 	    /* EFAULT - the structure address is invalid - IPC_SET */
     88 	{
     89 	&msg_q_2, IPC_SET, (struct msqid_ds *)-1, EFAULT},
     90 	    /* EINVAL - the command (-1) is invalid */
     91 	{
     92 	&msg_q_2, -1, &q_buf, EINVAL},
     93 	    /* EINVAL - the queue id is invalid - IPC_STAT */
     94 	{
     95 	&bad_q, IPC_STAT, &q_buf, EINVAL},
     96 	    /* EINVAL - the queue id is invalid - IPC_SET */
     97 	{
     98 	&bad_q, IPC_SET, &q_buf, EINVAL}
     99 };
    100 
    101 int main(int ac, char **av)
    102 {
    103 	int lc;
    104 	int i;
    105 
    106 	tst_parse_opts(ac, av, NULL, NULL);
    107 
    108 	setup();		/* global setup */
    109 
    110 	/* The following loop checks looping state if -i option given */
    111 
    112 	for (lc = 0; TEST_LOOPING(lc); lc++) {
    113 		/* reset tst_count in case we are looping */
    114 		tst_count = 0;
    115 
    116 		/* loop through the test cases */
    117 
    118 		for (i = 0; i < TST_TOTAL; i++) {
    119 
    120 			TEST(msgctl(*(TC[i].queue_id), TC[i].ipc_cmd,
    121 				    TC[i].buf));
    122 
    123 			if (TEST_RETURN != -1) {
    124 				tst_resm(TFAIL, "msgctl() call succeeded "
    125 					 "on expected fail");
    126 				continue;
    127 			}
    128 
    129 			if (TEST_ERRNO == TC[i].error) {
    130 				tst_resm(TPASS | TTERRNO, "expected failure");
    131 			} else {
    132 				tst_resm(TFAIL | TTERRNO, "unexpected error");
    133 				tst_resm(TINFO, "expected error is - %d : %s",
    134 					 TC[i].error, strerror(TC[i].error));
    135 			}
    136 		}
    137 	}
    138 
    139 	cleanup();
    140 
    141 	tst_exit();
    142 }
    143 
    144 /*
    145  * setup() - performs all the ONE TIME setup for this test.
    146  */
    147 void setup(void)
    148 {
    149 	key_t msgkey2;
    150 
    151 	tst_require_root();
    152 
    153 	tst_sig(NOFORK, DEF_HANDLER, cleanup);
    154 
    155 	TEST_PAUSE;
    156 
    157 	/* Switch to nobody user for correct error code collection */
    158 	ltpuser = getpwnam(nobody_uid);
    159 	if (setuid(ltpuser->pw_uid) == -1)
    160 		tst_resm(TINFO, "setuid(%d) failed", ltpuser->pw_uid);
    161 
    162 	/*
    163 	 * Create a temporary directory and cd into it.
    164 	 * This helps to ensure that a unique msgkey is created.
    165 	 * See ../lib/libipc.c for more information.
    166 	 */
    167 	tst_tmpdir();
    168 
    169 	msgkey = getipckey();
    170 
    171 	/* Get an new IPC resource key. */
    172 	msgkey2 = getipckey();
    173 
    174 	/* now we have a key, so let's create a message queue */
    175 	if ((msg_q_1 = msgget(msgkey, IPC_CREAT | IPC_EXCL)) == -1) {
    176 		tst_brkm(TBROK | TERRNO, cleanup,
    177 			 "Can't create message queue #1");
    178 	}
    179 
    180 	/* now let's create another message queue with read & write access */
    181 	if ((msg_q_2 =
    182 	     msgget(msgkey2, IPC_CREAT | IPC_EXCL | MSG_RD | MSG_WR)) == -1) {
    183 		tst_brkm(TBROK | TERRNO, cleanup,
    184 			 "Can't create message queue #2");
    185 	}
    186 }
    187 
    188 /*
    189  * cleanup() - performs all the ONE TIME cleanup for this test at completion
    190  * 	       or premature exit.
    191  */
    192 void cleanup(void)
    193 {
    194 	/*
    195 	 * remove the message queues that were created.
    196 	 */
    197 	rm_queue(msg_q_1);
    198 
    199 	rm_queue(msg_q_2);
    200 
    201 	tst_rmdir();
    202 
    203 }
    204