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 : mlockall02
20 *
21 * EXECUTED BY : root / superuser
22 *
23 * TEST TITLE : Test for checking basic error conditions for
24 * mlockall(2)
25 *
26 * TEST CASE TOTAL : 3
27 *
28 * AUTHOR : Nirmala Devi Dhanasekar <nirmala.devi@wipro.com>
29 *
30 * SIGNALS
31 * Uses SIGUSR1 to pause before test if option set.
32 * (See the parse_opts(3) man page).
33 *
34 * DESCRIPTION
35 * Check for basic errors returned by mount(2) system call.
36 *$
37 * Verify that mount(2) returns -1 and sets errno to
38 *
39 * 1) ENOMEM - If process exceed maximum number of locked pages.
40 * 2) EPERM - If not super user
41 * 3) EINVAL - Unknown flags were specified.
42 *
43 * Setup:
44 * Setup signal handling.
45 * Pause for SIGUSR1 if option specified.
46 *
47 * Test:
48 * Loop if the proper options are given.
49 * Do necessary setup for each test.
50 * Execute system call
51 * Check return code, if system call failed and errno == expected errno
52 * Issue sys call passed with expected return value and errno.
53 * Otherwise,
54 * Issue sys call failed to produce expected error.
55 * Do cleanup for each test.
56 *
57 * Cleanup:
58 * Print errno log and/or timing stats if options given
59 *
60 * USAGE: <for command-line>
61 * mlockall02 [-c n] [-e] [-i n] [-I x] [-p x] [-t]
62 * where,
63 * -c n : Run n copies concurrently
64 * -e : Turn on errno logging.
65 * -h : Show this help screen
66 * -i n : Execute test n times.
67 * -I x : Execute test for x seconds.
68 * -p : Pause for SIGUSR1 before starting
69 * -P x : Pause for x seconds between iterations.
70 * -t : Turn on syscall timing.
71 *
72 * RESTRICTIONS
73 * Test must run as root.
74 *****************************************************************************/
75 #include <errno.h>
76 #include <unistd.h>
77 #include <pwd.h>
78 #include <sys/mman.h>
79 #include "test.h"
80 #include "safe_macros.h"
81 #include <sys/resource.h>
82
83 void setup();
84 int setup_test(int);
85 void cleanup_test(int);
86 void cleanup();
87
88 char *TCID = "mlockall02";
89 int TST_TOTAL = 3;
90
91 struct test_case_t {
92 int flag; /* flag value */
93 int error; /* error description */
94 char *edesc; /* Expected error no */
95 } TC[] = {
96 {
97 MCL_CURRENT, ENOMEM, "Process exceeds max locked pages"}, {
98 MCL_CURRENT, EPERM, "Not a superuser"}, {
99 0, EINVAL, "Unknown flag"}
100 };
101
102 #if !defined(UCLINUX)
103
main(int ac,char ** av)104 int main(int ac, char **av)
105 {
106 int lc, i;
107
108 tst_parse_opts(ac, av, NULL, NULL);
109
110 setup();
111
112 /* check looping state */
113 for (lc = 0; TEST_LOOPING(lc); lc++) {
114
115 tst_count = 0;
116
117 for (i = 0; i < TST_TOTAL; i++) {
118
119 if (setup_test(i)) {
120 tst_resm(TFAIL, "mlockall() Failed while setup "
121 "for checking error %s", TC[i].edesc);
122 continue;
123 }
124
125 TEST(mlockall(TC[i].flag));
126
127 /* check return code */
128 if (TEST_RETURN == -1) {
129 if (TEST_ERRNO != TC[i].error)
130 tst_brkm(TFAIL, cleanup,
131 "mlock() Failed with wrong "
132 "errno, expected errno=%s, "
133 "got errno=%d : %s",
134 TC[i].edesc, TEST_ERRNO,
135 strerror(TEST_ERRNO));
136 else
137 tst_resm(TPASS,
138 "expected failure - errno "
139 "= %d : %s",
140 TEST_ERRNO,
141 strerror(TEST_ERRNO));
142 } else {
143 if (i <= 1)
144 tst_resm(TCONF,
145 "mlockall02 did not BEHAVE as expected.");
146 else
147 tst_brkm(TFAIL, cleanup,
148 "mlock() Failed, expected "
149 "return value=-1, got %ld",
150 TEST_RETURN);
151 }
152 cleanup_test(i);
153 }
154 }
155
156 /* cleanup and exit */
157 cleanup();
158
159 tst_exit();
160 }
161
162 /*
163 * setup() - performs all ONE TIME setup for this test.
164 */
setup(void)165 void setup(void)
166 {
167
168 tst_require_root();
169
170 tst_sig(FORK, DEF_HANDLER, cleanup);
171
172 TEST_PAUSE;
173
174 return;
175 }
176
setup_test(int i)177 int setup_test(int i)
178 {
179 struct rlimit rl;
180 char nobody_uid[] = "nobody";
181 struct passwd *ltpuser;
182
183 switch (i) {
184 case 0:
185 rl.rlim_max = 10;
186 rl.rlim_cur = 7;
187
188 if (setrlimit(RLIMIT_MEMLOCK, &rl) != 0) {
189 tst_resm(TWARN, "setrlimit failed to set the "
190 "resource for RLIMIT_MEMLOCK to check "
191 "for mlockall error %s\n", TC[i].edesc);
192 return 1;
193 }
194 if (tst_kvercmp(2, 6, 9) >= 0) {
195 ltpuser = getpwnam(nobody_uid);
196 if (seteuid(ltpuser->pw_uid) == -1) {
197 tst_brkm(TBROK, cleanup, "seteuid() "
198 "failed to change euid to %d "
199 "errno = %d : %s",
200 ltpuser->pw_uid, TEST_ERRNO,
201 strerror(TEST_ERRNO));
202 return 1;
203 }
204 }
205 return 0;
206 case 1:
207 if (tst_kvercmp(2, 6, 9) >= 0) {
208 rl.rlim_max = 0;
209 rl.rlim_cur = 0;
210 if (setrlimit(RLIMIT_MEMLOCK, &rl) != 0) {
211 tst_resm(TWARN, "setrlimit failed to "
212 "set the resource for "
213 "RLIMIT_MEMLOCK to check for "
214 "mlockall error %s\n", TC[i].edesc);
215 return 1;
216 }
217 }
218 ltpuser = getpwnam(nobody_uid);
219 if (seteuid(ltpuser->pw_uid) == -1) {
220 tst_brkm(TBROK, cleanup, "seteuid() failed to "
221 "change euid to %d errno = %d : %s",
222 ltpuser->pw_uid, TEST_ERRNO,
223 strerror(TEST_ERRNO));
224 return 1;
225 }
226 return 0;
227 }
228 return 0;
229 }
230
cleanup_test(int i)231 void cleanup_test(int i)
232 {
233 struct rlimit rl;
234
235 switch (i) {
236 case 0:
237 if (tst_kvercmp(2, 6, 9) >= 0)
238 seteuid(0);
239
240 rl.rlim_max = -1;
241 rl.rlim_cur = -1;
242
243 if (setrlimit(RLIMIT_MEMLOCK, &rl) != 0) {
244 tst_brkm(TFAIL, cleanup,
245 "setrlimit failed to reset the "
246 "resource for RLIMIT_MEMLOCK while "
247 "checking for mlockall error %s\n",
248 TC[i].edesc);
249 }
250 return;
251 case 1:
252 SAFE_SETEUID(cleanup, 0);
253 return;
254
255 }
256 }
257
258 /*
259 * cleanup() - performs all ONE TIME cleanup for this test at
260 * completion or premature exit.
261 */
cleanup(void)262 void cleanup(void)
263 {
264 return;
265 }
266
267 #else
268
main(void)269 int main(void)
270 {
271 tst_resm(TINFO, "test is not available on uClinux");
272 tst_exit();
273 }
274
275 #endif /* if !defined(UCLINUX) */
276