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 83void setup(); 84int setup_test(int); 85void cleanup_test(int); 86void cleanup(); 87 88char *TCID = "mlockall02"; 89int TST_TOTAL = 3; 90 91struct 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 104int 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 */ 165void 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 177int 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 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 return 0; 204 case 1: 205 rl.rlim_max = 0; 206 rl.rlim_cur = 0; 207 if (setrlimit(RLIMIT_MEMLOCK, &rl) != 0) { 208 tst_resm(TWARN, "setrlimit failed to " 209 "set the resource for " 210 "RLIMIT_MEMLOCK to check for " 211 "mlockall error %s\n", TC[i].edesc); 212 return 1; 213 } 214 ltpuser = getpwnam(nobody_uid); 215 if (seteuid(ltpuser->pw_uid) == -1) { 216 tst_brkm(TBROK, cleanup, "seteuid() failed to " 217 "change euid to %d errno = %d : %s", 218 ltpuser->pw_uid, TEST_ERRNO, 219 strerror(TEST_ERRNO)); 220 return 1; 221 } 222 return 0; 223 } 224 return 0; 225} 226 227void cleanup_test(int i) 228{ 229 struct rlimit rl; 230 231 switch (i) { 232 case 0: 233 seteuid(0); 234 235 rl.rlim_max = -1; 236 rl.rlim_cur = -1; 237 238 if (setrlimit(RLIMIT_MEMLOCK, &rl) != 0) { 239 tst_brkm(TFAIL, cleanup, 240 "setrlimit failed to reset the " 241 "resource for RLIMIT_MEMLOCK while " 242 "checking for mlockall error %s\n", 243 TC[i].edesc); 244 } 245 return; 246 case 1: 247 SAFE_SETEUID(cleanup, 0); 248 return; 249 250 } 251} 252 253/* 254 * cleanup() - performs all ONE TIME cleanup for this test at 255 * completion or premature exit. 256 */ 257void cleanup(void) 258{ 259 return; 260} 261 262#else 263 264int main(void) 265{ 266 tst_resm(TINFO, "test is not available on uClinux"); 267 tst_exit(); 268} 269 270#endif /* if !defined(UCLINUX) */ 271