create_module02.c revision 4edbd06d0a42d7d889fb85364bba42bae8595413
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   : create_module02
20 *
21 *    EXECUTED BY       : root / superuser
22 *
23 *    TEST TITLE        : Checking error conditions for create_module(2)
24 *
25 *    TEST CASE TOTAL   : 8
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. create_module(2) returns -1 and sets errno to EPERM, if effective
36 *         user id of the caller is not superuser.
37 *      2. create_module(2) returns -1 and sets errno to EFAULT, if module
38 *         name is outside the  program's  accessible  address space.
39 *      3. create_module(2) returns -1 and sets errno to EFAULT, if module
40 *         name parameter is NULL.
41 *      4. create_module(2) returns -1 and sets errno to EINVAL, if module
42 *         name parameter is null terminated (zero length) string.
43 *      5. create_module(2) returns -1 and sets errno to EEXIST, if module
44 *         entry with the same name already exists.
45 *      6. create_module(2) returns -1 and sets errno to EINVAL, if module
46 *         size parameter is too small.
47 *      7. create_module(2) returns -1 and sets errno to ENAMETOOLONG, if
48 *         module name parameter is too long.
49 *      8. create_module(2) returns -1 and sets errno to ENOMEM, if module
50 *         size parameter is too large.
51 *
52 *      Setup:
53 *        Setup signal handling.
54 *        Test caller is super user
55 *        Check existances of "nobody" user id.
56 *        Initialize  long module name
57 *        Set expected errnos for logging
58 *        Pause for SIGUSR1 if option specified.
59 *	  Initialize modname for each child process
60 *
61 *      Test:
62 *       Loop if the proper options are given.
63 *        Execute system call
64 *        Check return code and error number, if matching,
65 *                   Issue PASS message
66 *        Otherwise,
67 *                   Issue FAIL message
68 *
69 *      Cleanup:
70 *        Print errno log and/or timing stats if options given
71 *
72 * USAGE:  <for command-line>
73 *  create_module02 [-c n] [-e] [-f] [-h] [-i n] [-I x] [-p] [-P x] [-t]
74 *		where,  -c n : Run n copies concurrently.
75 *			-e   : Turn on errno logging.
76 *			-f   : Turn off functional testing
77 *			-h   : Show help screen
78 *			-i n : Execute test n times.
79 *			-I x : Execute test for x seconds.
80 *			-p   : Pause for SIGUSR1 before starting
81 *			-P x : Pause for x seconds between iterations.
82 *			-t   : Turn on syscall timing.
83 *
84 ****************************************************************/
85
86#include <errno.h>
87#include <pwd.h>
88#include <sys/types.h>
89#include <asm/page.h>
90#include <asm/atomic.h>
91#include <linux/module.h>
92#include "test.h"
93#include "usctest.h"
94
95extern int Tst_count;
96
97#define MODSIZE 10000			/* Arbitrarily selected MODSIZE */
98#define NULLMODNAME ""
99#define MAXMODSIZE  0xffffffffffffffff	/* Max size of size_t */
100#define SMALLMODSIZE  1			/* Arbitrarily selected SMALLMODSIZE */
101#define BASEMODNAME "dummy"
102#define LONGMODNAMECHAR 'm'		/* Arbitrarily selected the alphabet */
103#define MODNAMEMAX (PAGE_SIZE + 1)
104
105struct test_case_t {			/* test case structure */
106	char 	*modname;
107	size_t  size;
108	caddr_t retval;			/* syscall return value */
109	int	experrno;		/* expected errno */
110	char *desc;
111	int	(*setup)(void);		/* Individual setup routine */
112	void	(*cleanup)(void);	/* Individual cleanup routine */
113};
114
115char *TCID = "create_module02";
116static int exp_enos[]={EFAULT, EPERM, EEXIST, EINVAL, ENOMEM, ENAMETOOLONG, 0};
117static char nobody_uid[] = "nobody";
118struct passwd *ltpuser;
119static char longmodname[MODNAMEMAX];
120static int testno;
121static char modname[20];		/* Name of the module */
122
123static void setup(void);
124static void cleanup(void);
125static int setup1(void);
126static void cleanup1(void);
127static int setup2(void);
128static void cleanup2(void);
129
130static struct test_case_t  tdat[] = {
131	{ modname, MODSIZE, (caddr_t)-1, EPERM,
132		"non-superuser", setup1, cleanup1},
133	{ (char *)-1, MODSIZE, (caddr_t)-1, EFAULT,
134		"module name outside the  program's  accessible  address space",	 NULL, NULL},
135	{ NULL, MODSIZE, (caddr_t)-1, EFAULT,
136		"NULL module name", NULL, NULL},
137	{ NULLMODNAME, MODSIZE, (caddr_t)-1, EINVAL,
138		"null terminated module name", NULL, NULL},
139	{ modname, MODSIZE, (caddr_t)-1, EEXIST,
140		"already existing module", setup2, cleanup2},
141	{ modname, SMALLMODSIZE, (caddr_t)-1, EINVAL,
142		"insufficient module size", NULL, NULL},
143	{ longmodname, MODSIZE, (caddr_t)-1, ENAMETOOLONG,
144		"long module name", NULL, NULL},
145
146	/*
147	 *This test case is giving segmentation fault on
148	 * 2.4.* series, but works as expected with 2.5.* series of kernel.
149	 */
150	{ modname, MAXMODSIZE, (caddr_t)-1, ENOMEM,
151		"large module size", NULL, NULL},
152};
153
154int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]);
155
156int
157main(int argc, char **argv)
158{
159	int lc;				/* loop counter */
160	char *msg;			/* message returned from parse_opts */
161
162	/* parse standard options */
163	if ((msg = parse_opts(argc, argv, (option_t *)NULL, NULL)) !=
164	    (char *)NULL) {
165		tst_brkm(TBROK, tst_exit, "OPTION PARSING ERROR - %s", msg);
166	}
167
168	setup();
169
170	/* check looping state if -i option is given */
171	for (lc = 0; TEST_LOOPING(lc); lc++) {
172		/* reset Tst_count in case we are looping */
173		Tst_count = 0;
174
175		for (testno = 0; testno < TST_TOTAL; ++testno) {
176			if( (tdat[testno].setup) && (tdat[testno].setup()) ) {
177				/* setup() failed, skip this test */
178				continue;
179			}
180
181			TEST(create_module(tdat[testno].modname,
182				tdat[testno].size));
183			TEST_ERROR_LOG(TEST_ERRNO);
184			if ( (TEST_RETURN == (int) tdat[testno].retval) &&
185				(TEST_ERRNO == tdat[testno].experrno) ) {
186				tst_resm(TPASS, "Expected results for %s, "
187					"errno: %d",
188					tdat[testno].desc, TEST_ERRNO);
189			} else {
190				tst_resm(TFAIL, "Unexpected results for %s ; "
191					"returned %d (expected %d), errno %d "
192					"(expected %d)", tdat[testno].desc,
193					TEST_RETURN, tdat[testno].retval,
194					TEST_ERRNO, tdat[testno].experrno);
195			}
196			if(tdat[testno].cleanup) {
197				tdat[testno].cleanup();
198			}
199		}
200	}
201	cleanup();
202
203	/*NOTREACHED*/
204	return 0;
205}
206
207int
208setup1(void)
209{
210	/* Change effective user id to nodody */
211	if (seteuid(ltpuser->pw_uid) == -1) {
212		tst_resm(TBROK, "seteuid failed to set the effective"
213				" uid to %d", ltpuser->pw_uid);
214		return 1;
215	}
216	return 0;
217}
218
219void
220cleanup1(void)
221{
222	 /* Change effective user id to root */
223         if (seteuid(0) == -1) {
224		tst_brkm(TBROK, tst_exit, "seteuid failed to set the effective"
225			" uid to root");
226         }
227}
228
229int
230setup2(void)
231{
232	/* Create a loadable module entry */
233	if(create_module(modname, MODSIZE) == -1) {
234		tst_resm(TBROK, "Failed to create module entry"
235			" for %s", modname);
236		return 1;
237	}
238	return 0;
239}
240
241void
242cleanup2(void)
243{
244	 /* Remove loadable module entry */
245	if(delete_module(modname) == -1) {
246		tst_brkm(TBROK, tst_exit, "Failed to delete module entry"
247			" for %s", modname);
248	}
249}
250
251/*
252 * setup()
253 *	performs all ONE TIME setup for this test
254 */
255void
256setup(void)
257{
258	/* capture signals */
259	tst_sig(NOFORK, DEF_HANDLER, cleanup);
260
261	/* Check whether it is root  */
262	if (geteuid() != 0) {
263		tst_brkm(TBROK, tst_exit, "Must be root for this test!");
264		/*NOTREACHED*/
265	}
266
267	if (tst_kvercmp(2,5,48) >= 0)
268		tst_brkm(TCONF, tst_exit, "This test will not work on "
269				"kernels after 2.5.48");
270
271        /* Check for nobody_uid user id */
272	 if( (ltpuser = getpwnam(nobody_uid)) == NULL) {
273		tst_brkm(TBROK, tst_exit, "Required user %s doesn't exists",
274				nobody_uid);
275		/*NOTREACHED*/
276	 }
277
278	/* Initialize longmodname to LONGMODNAMECHAR character */
279	memset(longmodname, LONGMODNAMECHAR, MODNAMEMAX - 1);
280
281	/* set the expected errnos... */
282	TEST_EXP_ENOS(exp_enos);
283
284	/* Pause if that option was specified
285	 * TEST_PAUSE contains the code to fork the test with the -c option.
286	 */
287	TEST_PAUSE;
288
289	/* Get unique module name for each child process */
290	if( sprintf(modname, "%s_%d",BASEMODNAME, getpid()) == -1) {
291		tst_brkm(TBROK, tst_exit, "Failed to initialize module name");
292	}
293}
294
295/*
296 * cleanup()
297 *	performs all ONE TIME cleanup for this test at
298 *	completion or premature exit
299 */
300void
301cleanup(void)
302{
303	/*
304	 * print timing stats if that option was specified.
305	 * print errno log if that option was specified.
306	 */
307	TEST_CLEANUP;
308
309	/* exit with return code appropriate for results */
310	tst_exit();
311	/*NOTREACHED*/
312}
313