delete_module02.c revision 72521cf0741034f67dd17107453cda9a9819264c
1/*
2 * Copyright (c) Wipro Technologies Ltd, 2002.  All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * You should have received a copy of the GNU General Public License along
13 * with this program; if not, write the Free Software Foundation, Inc., 59
14 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
15 *
16 */
17/**********************************************************
18 *
19 *    TEST IDENTIFIER   : delete_module02
20 *
21 *    EXECUTED BY       : root / superuser
22 *
23 *    TEST TITLE        : Checking error conditions for delete_module(2)
24 *
25 *    TEST CASE TOTAL   : 5
26 *
27 *    AUTHOR            : Madhu T L <madhu.tarikere@wipro.com>
28 *
29 *    SIGNALS
30 *      Uses SIGUSR1 to pause before test if option set.
31 *      (See the parse_opts(3) man page).
32 *
33 *    DESCRIPTION
34 *      Verify that,
35 *      1. delete_module(2) returns -1 and sets errno to ENOENT for nonexistent
36 *	   module entry.
37 *      2. delete_module(2) returns -1 and sets errno to EINVAL, if module
38 *         name parameter is null terminated (zero length) string.
39 *      3. delete_module(2) returns -1 and sets errno to EFAULT, if
40 *         module name parameter is outside program's accessible address space.
41 *      4. delete_module(2) returns -1 and sets errno to ENAMETOOLONG, if
42 *         module name parameter is too long.
43 *      5. delete_module(2) returns -1 and sets errno to EPERM, if effective
44 *         user id of the caller is not superuser.
45 *
46 *      Setup:
47 *        Setup signal handling.
48 *        Test caller is super user
49 *        Check existances of "nobody" user id.
50 *        Initialize  long module name
51 *        Set expected errnos for logging
52 *        Pause for SIGUSR1 if option specified.
53 *		   Initialize modname for each child process
54 *
55 *      Test:
56 *       Loop if the proper options are given.
57 *		   Perform testcase specific setup (if needed)
58 *        Execute system call
59 *        Check return code and error number, if matching,
60 *                   Issue PASS message
61 *        Otherwise,
62 *                   Issue FAIL message
63 *		   Perform testcase specific cleanup (if needed)
64 *
65 *      Cleanup:
66 *        Print errno log and/or timing stats if options given
67 *
68 * USAGE:  <for command-line>
69 *  delete_module02 [-c n] [-e] [-f] [-h] [-i n] [-I x] [-p] [-P x] [-t]
70 *		 		 where,  -c n : Run n copies concurrently.
71 *	 		 		 -e   : Turn on errno logging.
72 *	 		 		 -f   : Turn off functional testing
73 *	 		 		 -h   : Show help screen
74 *	 		 		 -i n : Execute test n times.
75 *	 		 		 -I x : Execute test for x seconds.
76 *	 		 		 -p   : Pause for SIGUSR1 before
77 *	 		 		 	starting test.
78 *	 		 		 -P x : Pause for x seconds between
79 *	 		 		 	iterations.
80 *	 		 		 -t   : Turn on syscall timing.
81 *
82 ****************************************************************/
83
84#include <errno.h>
85#include <pwd.h>
86#include <sys/types.h>
87#include <unistd.h>
88#include <limits.h>
89#if HAVE_LINUX_MODULE_H
90#include <linux/module.h>
91#else
92/* As per http://tomoyo.sourceforge.jp/cgi-bin/lxr/source/include/linux/moduleparam.h?a=ppc#L17 ... */
93#define MODULE_NAME_LEN	( 64 - sizeof(unsigned long) )
94#endif
95#include <sys/mman.h>
96#include "test.h"
97#include "usctest.h"
98
99
100#define NULLMODNAME ""
101#define BASEMODNAME "dummy"
102#define LONGMODNAMECHAR 'm'			/* Arbitrarily selected */
103#define EXP_RET_VAL -1
104
105/* Test case structure */
106struct test_case_t {
107	char 		 *modname;
108	/* Expected errno. */
109	int		 experrno;
110	char		 *desc;
111	/* Individual setup routine. */
112	int		 (*setup)(void);
113	/* Individual cleanup routine */
114	void		 (*cleanup)(void);
115};
116
117char *TCID = "delete_module02";
118static int exp_enos[] = { EPERM, EINVAL, ENOENT, EFAULT, ENAMETOOLONG, 0 };
119static char nobody_uid[] = "nobody";
120struct passwd *ltpuser;
121static char longmodname[MODULE_NAME_LEN];
122static int testno;
123/* Name of the module */
124static char modname[20];
125
126char * bad_addr = 0;
127
128static void setup(void);
129static void cleanup(void);
130static int setup1(void);
131static void cleanup1(void);
132
133struct test_case_t;
134
135static struct test_case_t  tdat[] = {
136		 { modname, ENOENT,
137		 	"nonexistent module", NULL, NULL},
138		 { NULLMODNAME, ENOENT,
139		 	"null terminated module name", NULL, NULL},
140		 { (char *) -1, EFAULT,
141			"module name outside program's "
142			"accessible address space", NULL, NULL},
143		 { longmodname, ENOENT,
144		 	"long module name", NULL, NULL},
145		 { modname, EPERM,
146		 	"non-superuser", setup1, cleanup1},
147};
148
149int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]);
150
151int
152main(int argc, char **argv)
153{
154	int lc; 		 /* loop counter */
155	char *msg; 		 /* message returned from parse_opts */
156
157	/* parse standard options */
158	if ((msg = parse_opts(argc, argv, NULL, NULL)) != NULL)
159		tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
160
161	setup();
162
163	for (lc = 0; TEST_LOOPING(lc); lc++) {
164		/* reset Tst_count in case we are looping */
165		Tst_count = 0;
166
167		for (testno = 0; testno < TST_TOTAL; ++testno) {
168			if ((tdat[testno].setup) && (tdat[testno].setup())) {
169		 		/* setup() failed, skip this test */
170		 		continue;
171		 	}
172			/* Test the system call */
173		 	TEST(delete_module(tdat[testno].modname));
174		 	TEST_ERROR_LOG(TEST_ERRNO);
175		 	printf("TEST_RETURN is %d, TEST_ERRNO is %d\n",
176				TEST_RETURN, TEST_ERRNO);
177		 	if ((TEST_RETURN == EXP_RET_VAL) &&
178		 	     (TEST_ERRNO == tdat[testno].experrno) ) {
179		 		tst_resm(TPASS, "Expected results for %s, "
180		 				"errno: %d", tdat[testno].desc,
181		 		 		TEST_ERRNO);
182		 	} else {
183				tst_resm(TFAIL, "Unexpected results for %s ; "
184						"returned %d (expected %d), "
185						"errno %d (expected %d)",
186						tdat[testno].desc,
187						TEST_RETURN, EXP_RET_VAL,
188						TEST_ERRNO,
189						tdat[testno].experrno);
190			}
191			if (tdat[testno].cleanup) {
192				tdat[testno].cleanup();
193			}
194		}
195	}
196	cleanup();
197	tst_exit();
198}
199
200int
201setup1(void)
202{
203	/* Change effective user id to nodody */
204	if (seteuid(ltpuser->pw_uid) == -1) {
205		tst_resm(TBROK, "seteuid failed to set the effective"
206				" uid to %d", ltpuser->pw_uid);
207		return 1;
208	}
209	return 0;
210}
211
212void
213cleanup1(void)
214{
215	/* Change effective user id to root */
216	if (seteuid(0) == -1) {
217		tst_brkm(TBROK, NULL, "seteuid failed to set the effective"
218					  " uid to root");
219	}
220}
221
222/*
223 * setup()
224 *	performs all ONE TIME setup for this test
225 */
226void
227setup(void)
228{
229
230	tst_sig(NOFORK, DEF_HANDLER, cleanup);
231
232	/* Check whether it is root  */
233	if (geteuid() != 0) {
234		tst_brkm(TBROK, NULL, "Must be root for this test!");
235
236	}
237
238	/*if (tst_kvercmp(2,5,48) >= 0)
239		tst_brkm(TCONF, NULL, "This test will not work on "
240					  "kernels after 2.5.48");
241	 */
242
243	/* Check for nobody_uid user id */
244	if ((ltpuser = getpwnam(nobody_uid)) == NULL) {
245		tst_brkm(TBROK, NULL, "Required user %s doesn't exists",
246			 nobody_uid);
247	}
248
249	/* Initialize longmodname to LONGMODNAMECHAR character */
250	memset(longmodname, LONGMODNAMECHAR, MODULE_NAME_LEN - 1);
251
252	/* set the expected errnos... */
253	TEST_EXP_ENOS(exp_enos);
254
255	/* Pause if that option was specified
256	 * TEST_PAUSE contains the code to fork the test with the -c option.
257	 */
258	TEST_PAUSE;
259
260	/* Get unique module name for each child process */
261	if (sprintf(modname, "%s_%d", BASEMODNAME, getpid()) <= 0) {
262		tst_brkm(TBROK, NULL, "Failed to initialize module name");
263	}
264        bad_addr = mmap(0, 1, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
265        if (bad_addr == MAP_FAILED) {
266		tst_brkm(TBROK, cleanup, "mmap failed");
267	}
268	tdat[2].modname = bad_addr;
269
270}
271
272/*
273 * cleanup()
274 *	performs all ONE TIME cleanup for this test at
275 *	completion or premature exit
276 */
277void
278cleanup(void)
279{
280	/*
281	 * print timing stats if that option was specified.
282	 * print errno log if that option was specified.
283	 */
284	TEST_CLEANUP;
285}