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 (at) 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 <sys/resource.h> 81 82 void setup(); 83 int setup_test(int); 84 void cleanup_test(int); 85 void cleanup(); 86 87 char *TCID = "mlockall02"; 88 int TST_TOTAL = 3; 89 90 struct test_case_t { 91 int flag; /* flag value */ 92 int error; /* error description */ 93 char *edesc; /* Expected error no */ 94 } TC[] = { 95 { 96 MCL_CURRENT, ENOMEM, "Process exceeds max locked pages"}, { 97 MCL_CURRENT, EPERM, "Not a superuser"}, { 98 0, EINVAL, "Unknown flag"} 99 }; 100 101 #if !defined(UCLINUX) 102 103 int main(int ac, char **av) 104 { 105 int lc, i; 106 107 tst_parse_opts(ac, av, NULL, NULL); 108 109 setup(); 110 111 /* check looping state */ 112 for (lc = 0; TEST_LOOPING(lc); lc++) { 113 114 tst_count = 0; 115 116 for (i = 0; i < TST_TOTAL; i++) { 117 118 if (setup_test(i)) { 119 tst_resm(TFAIL, "mlockall() Failed while setup " 120 "for checking error %s", TC[i].edesc); 121 continue; 122 } 123 124 TEST(mlockall(TC[i].flag)); 125 126 /* check return code */ 127 if (TEST_RETURN == -1) { 128 if (TEST_ERRNO != TC[i].error) 129 tst_brkm(TFAIL, cleanup, 130 "mlock() Failed with wrong " 131 "errno, expected errno=%s, " 132 "got errno=%d : %s", 133 TC[i].edesc, TEST_ERRNO, 134 strerror(TEST_ERRNO)); 135 else 136 tst_resm(TPASS, 137 "expected failure - errno " 138 "= %d : %s", 139 TEST_ERRNO, 140 strerror(TEST_ERRNO)); 141 } else { 142 if (i <= 1) 143 tst_resm(TCONF, 144 "mlockall02 did not BEHAVE as expected."); 145 else 146 tst_brkm(TFAIL, cleanup, 147 "mlock() Failed, expected " 148 "return value=-1, got %ld", 149 TEST_RETURN); 150 } 151 cleanup_test(i); 152 } 153 } 154 155 /* cleanup and exit */ 156 cleanup(); 157 158 tst_exit(); 159 } 160 161 /* 162 * setup() - performs all ONE TIME setup for this test. 163 */ 164 void setup(void) 165 { 166 167 tst_require_root(); 168 169 tst_sig(FORK, DEF_HANDLER, cleanup); 170 171 TEST_PAUSE; 172 173 return; 174 } 175 176 int setup_test(int i) 177 { 178 struct rlimit rl; 179 char nobody_uid[] = "nobody"; 180 struct passwd *ltpuser; 181 182 switch (i) { 183 case 0: 184 rl.rlim_max = 10; 185 rl.rlim_cur = 7; 186 187 if (setrlimit(RLIMIT_MEMLOCK, &rl) != 0) { 188 tst_resm(TWARN, "setrlimit failed to set the " 189 "resource for RLIMIT_MEMLOCK to check " 190 "for mlockall error %s\n", TC[i].edesc); 191 return 1; 192 } 193 if (tst_kvercmp(2, 6, 9) >= 0) { 194 ltpuser = getpwnam(nobody_uid); 195 if (seteuid(ltpuser->pw_uid) == -1) { 196 tst_brkm(TBROK, cleanup, "seteuid() " 197 "failed to change euid to %d " 198 "errno = %d : %s", 199 ltpuser->pw_uid, TEST_ERRNO, 200 strerror(TEST_ERRNO)); 201 return 1; 202 } 203 } 204 return 0; 205 case 1: 206 if (tst_kvercmp(2, 6, 9) >= 0) { 207 rl.rlim_max = 0; 208 rl.rlim_cur = 0; 209 if (setrlimit(RLIMIT_MEMLOCK, &rl) != 0) { 210 tst_resm(TWARN, "setrlimit failed to " 211 "set the resource for " 212 "RLIMIT_MEMLOCK to check for " 213 "mlockall error %s\n", TC[i].edesc); 214 return 1; 215 } 216 } 217 ltpuser = getpwnam(nobody_uid); 218 if (seteuid(ltpuser->pw_uid) == -1) { 219 tst_brkm(TBROK, cleanup, "seteuid() failed to " 220 "change euid to %d errno = %d : %s", 221 ltpuser->pw_uid, TEST_ERRNO, 222 strerror(TEST_ERRNO)); 223 return 1; 224 } 225 return 0; 226 } 227 return 0; 228 } 229 230 void cleanup_test(int i) 231 { 232 struct rlimit rl; 233 234 switch (i) { 235 case 0: 236 if (tst_kvercmp(2, 6, 9) >= 0) 237 seteuid(0); 238 239 rl.rlim_max = -1; 240 rl.rlim_cur = -1; 241 242 if (setrlimit(RLIMIT_MEMLOCK, &rl) != 0) { 243 tst_brkm(TFAIL, cleanup, 244 "setrlimit failed to reset the " 245 "resource for RLIMIT_MEMLOCK while " 246 "checking for mlockall error %s\n", 247 TC[i].edesc); 248 } 249 return; 250 case 1: 251 if (seteuid(0) == -1) { 252 tst_brkm(TBROK, cleanup, "seteuid() failed to " 253 "change euid to %d errno = %d : %s", 254 0, TEST_ERRNO, strerror(TEST_ERRNO)); 255 } 256 return; 257 258 } 259 } 260 261 /* 262 * cleanup() - performs all ONE TIME cleanup for this test at 263 * completion or premature exit. 264 */ 265 void cleanup(void) 266 { 267 return; 268 } 269 270 #else 271 272 int main(void) 273 { 274 tst_resm(TINFO, "test is not available on uClinux"); 275 tst_exit(); 276 } 277 278 #endif /* if !defined(UCLINUX) */ 279