iopl02.c revision 605fa3362fd7cef0baa2131be32cf44661783d3e
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.,
14 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
15 *
16 */
17/**********************************************************
18 *
19 *    TEST IDENTIFIER	: iopl02
20 *
21 *    EXECUTED BY	: superuser
22 *
23 *    TEST TITLE	: Tests for error conditions
24 *
25 *    TEST CASE TOTAL	: 2
26 *
27 *    AUTHOR		: Subhab Biwas <subhabrata.biswas@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) iopl(2) returns -1 and sets errno to EINVAL for privilege
36 *	   level greater than 3.
37 *	2) iopl(2) returns -1 and sets errno to EPERM if the current
38 *	   user is not the super-user.
39 *
40 * 	Setup:
41 * 	  Setup signal handling.
42 *	  Test caller is superuser
43 *	  Set expected errnos for logging
44 *	  Pause for SIGUSR1 if option specified.
45 *
46 * 	Test:
47 *	 Loop if the proper options are given.
48 * 	  Execute system call
49 *	  Check return code and error number, if matching,
50 *		     Issue PASS message
51 *	  Otherwise,
52 *		     Issue FAIL message
53 *	  Perform testcase specific cleanup (if needed)
54 *
55 * 	Cleanup:
56 * 	  Print errno log and/or timing stats if options given
57 *
58 * USAGE:  <for command-line>
59 * iopl02 [-c n] [-e] [-i n] [-I x] [-P x] [-t] [-h] [-f] [-p]
60 *			where,  -c n : Run n copies concurrently.
61 *				-e   : Turn on errno logging.
62 *				-h   : Show help screen
63 *				-f   : Turn off functional testing
64 *				-i n : Execute test n times.
65 *				-I x : Execute test for x seconds.
66 *				-p   : Pause for SIGUSR1 before starting
67 *				-P x : Pause for x seconds between iterations.
68 *				-t   : Turn on syscall timing.
69 *
70 ****************************************************************/
71
72char *TCID = "iopl02";
73
74#if defined __i386__ || defined(__x86_64__)
75
76#include <errno.h>
77#include <unistd.h>
78#include <sys/io.h>
79#include <pwd.h>
80#include "test.h"
81#include "usctest.h"
82
83#define INVALID_LEVEL 4		/* Invalid privilege level */
84#define EXP_RET_VAL -1
85
86static void setup();
87static int setup1(void);
88static void cleanup1();
89static void cleanup();
90
91static char nobody_uid[] = "nobody";
92struct passwd *ltpuser;
93
94struct test_cases_t {
95	int level;		/* I/O privilege level */
96	char *desc;		/* test case description */
97	int exp_errno;		/* expected error number */
98} test_cases[] = {
99	{
100	INVALID_LEVEL, "Invalid privilege level", EINVAL}, {
101	1, "Non super-user", EPERM}
102};
103
104int TST_TOTAL = sizeof(test_cases) / sizeof(test_cases[0]);
105
106int main(int ac, char **av)
107{
108
109	int lc, i;
110	const char *msg;
111
112	if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
113		tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
114
115	setup();
116
117	for (lc = 0; TEST_LOOPING(lc); lc++) {
118
119		tst_count = 0;
120
121		for (i = 0; i < TST_TOTAL; ++i) {
122
123			if (i == 1) {
124				/* setup Non super-user for second test */
125				if (setup1()) {
126					/* setup1() failed, skip this test */
127					continue;
128				}
129			}
130
131			/*
132			 * Call iopl(2)
133			 */
134			TEST(iopl(test_cases[i].level));
135
136			if ((TEST_RETURN == EXP_RET_VAL) &&
137			    (TEST_ERRNO == test_cases[i].exp_errno)) {
138				tst_resm(TPASS, "Expected failure for %s, "
139					 "errno: %d", test_cases[i].desc,
140					 TEST_ERRNO);
141			} else {
142				tst_resm(TFAIL, "Unexpected results for %s ; "
143					 "returned %ld (expected %d), errno %d "
144					 "(expected errno  %d)",
145					 test_cases[i].desc,
146					 TEST_RETURN, EXP_RET_VAL,
147					 TEST_ERRNO, test_cases[i].exp_errno);
148			}
149
150			if (i == 1) {
151				/* revert back to super user */
152				cleanup1();
153			}
154
155		}
156	}
157
158	/* cleanup and exit */
159	cleanup();
160
161	tst_exit();
162
163}
164
165/* setup1() - set up non-super user for second test case */
166int setup1(void)
167{
168	/* switch to "nobody" user */
169	if (seteuid(ltpuser->pw_uid) == -1) {
170		tst_resm(TWARN, "Failed to set effective"
171			 "uid to %d", ltpuser->pw_uid);
172		return 1;
173	}
174	return 0;
175}
176
177/* cleanup1() - reset to super user for first test case */
178void cleanup1(void)
179{
180	/* reset user as root */
181	if (seteuid(0) == -1) {
182		tst_brkm(TBROK, NULL, "Failed to set uid as root");
183	}
184}
185
186/* setup() - performs all ONE TIME setup for this test */
187void setup(void)
188{
189	tst_require_root(NULL);
190
191	tst_sig(NOFORK, DEF_HANDLER, cleanup);
192
193	/* Check if "nobody" user id exists */
194	if ((ltpuser = getpwnam(nobody_uid)) == NULL) {
195		tst_brkm(TBROK, NULL, "\"nobody\" user id doesn't exist");
196	}
197
198	TEST_PAUSE;
199
200}
201
202/*
203 *cleanup() -  performs all ONE TIME cleanup for this test at
204 *		completion or premature exit.
205 */
206void cleanup(void)
207{
208
209}
210
211#else /* __i386__ */
212
213#include "test.h"
214#include "usctest.h"
215
216int TST_TOTAL = 0;
217
218int main(void)
219{
220	tst_resm(TPASS,
221		 "LSB v1.3 does not specify iopl() for this architecture.");
222	tst_exit();
223}
224
225#endif /* __i386__ */
226