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 : ioperm02 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 (at) 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) ioperm(2) returns -1 and sets errno to EINVAL for I/O port 36 * address greater than 0x3ff. 37 * 2) ioperm(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 * Set expected errnos for logging 43 * Pause for SIGUSR1 if option specified. 44 * 45 * Test: 46 * Loop if the proper options are given. 47 * Execute system call 48 * Check return code and error number, if matching, 49 * Issue PASS message 50 * Otherwise, 51 * Issue FAIL message 52 * Perform testcase specific cleanup (if needed) 53 * 54 * Cleanup: 55 * Print errno log and/or timing stats if options given 56 * 57 * USAGE: <for command-line> 58 * ioperm02 [-c n] [-e] [-i n] [-I x] [-P x] [-t] [-h] [-f] [-p] 59 * where, -c n : Run n copies concurrently. 60 * -e : Turn on errno logging. 61 * -h : Show help screen 62 * -f : Turn off functional testing 63 * -i n : Execute test n times. 64 * -I x : Execute test for x seconds. 65 * -p : Pause for SIGUSR1 before starting 66 * -P x : Pause for x seconds between iterations. 67 * -t : Turn on syscall timing. 68 * 69 ****************************************************************/ 70 71 char *TCID = "ioperm02"; 72 73 #if defined __i386__ || defined(__x86_64__) 74 75 #include <errno.h> 76 #include <unistd.h> 77 #include <sys/io.h> 78 #include <pwd.h> 79 #include "test.h" 80 81 #define NUM_BYTES 3 82 #define TURN_ON 1 83 #define TURN_OFF 0 84 #define EXP_RET_VAL -1 85 #ifndef IO_BITMAP_BITS 86 #define IO_BITMAP_BITS 1024 /* set to default value since some H/W may not support 0x10000 even with a 2.6.8 kernel */ 87 #define IO_BITMAP_BITS_16 65536 88 #endif 89 90 static void setup(); 91 static int setup1(void); 92 static void cleanup1(); 93 static void cleanup(); 94 95 static char nobody_uid[] = "nobody"; 96 struct passwd *ltpuser; 97 98 struct test_cases_t { 99 long from; /* starting port address */ 100 long num; /* no. of bytes from starting address */ 101 int turn_on; 102 char *desc; /* test case description */ 103 int exp_errno; /* expected error number */ 104 }; 105 106 int TST_TOTAL = 2; 107 struct test_cases_t *test_cases; 108 109 int main(int ac, char **av) 110 { 111 int lc, i; 112 113 tst_parse_opts(ac, av, NULL, NULL); 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 /* Test the system call */ 132 133 TEST(ioperm(test_cases[i].from, 134 test_cases[i].num, test_cases[i].turn_on)); 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 } else { 154 } 155 } 156 157 } 158 159 /* cleanup and exit */ 160 cleanup(); 161 162 tst_exit(); 163 164 } 165 166 /* setup1() - set up non-super user for second test case */ 167 int setup1(void) 168 { 169 /* switch to "nobody" user */ 170 if (seteuid(ltpuser->pw_uid) == -1) { 171 tst_resm(TWARN, "Failed to set effective" 172 "uid to %d", ltpuser->pw_uid); 173 return 1; 174 } 175 return 0; 176 } 177 178 /* cleanup1() - reset to super user for second test case */ 179 void cleanup1(void) 180 { 181 /* reset user as root */ 182 if (seteuid(0) == -1) { 183 tst_brkm(TBROK, NULL, "Failed to set uid as root"); 184 } 185 } 186 187 /* setup() - performs all ONE TIME setup for this test */ 188 void setup(void) 189 { 190 tst_require_root(); 191 192 tst_sig(NOFORK, DEF_HANDLER, cleanup); 193 194 /* Check if "nobody" user id exists */ 195 if ((ltpuser = getpwnam(nobody_uid)) == NULL) { 196 tst_brkm(TBROK, NULL, "\"nobody\" user id doesn't exist"); 197 } 198 199 /* 200 * The value of IO_BITMAP_BITS (include/asm-i386/processor.h) changed 201 * from kernel 2.6.8 to permit 16-bits (65536) ioperm 202 * 203 * Ricky Ng-Adam, rngadam (at) yahoo.com 204 * */ 205 test_cases = malloc(sizeof(struct test_cases_t) * 2); 206 test_cases[0].num = NUM_BYTES; 207 test_cases[0].turn_on = TURN_ON; 208 test_cases[0].desc = "Invalid I/O address"; 209 test_cases[0].exp_errno = EINVAL; 210 test_cases[1].num = NUM_BYTES; 211 test_cases[1].turn_on = TURN_ON; 212 test_cases[1].desc = "Non super-user"; 213 test_cases[1].exp_errno = EPERM; 214 if ((tst_kvercmp(2, 6, 8) < 0) || (tst_kvercmp(2, 6, 9) == 0)) { 215 /*try invalid ioperm on 1022, 1023, 1024 */ 216 test_cases[0].from = (IO_BITMAP_BITS - NUM_BYTES) + 1; 217 218 /*try get valid ioperm on 1021, 1022, 1023 */ 219 test_cases[1].from = IO_BITMAP_BITS - NUM_BYTES; 220 } else { 221 /*try invalid ioperm on 65534, 65535, 65536 */ 222 test_cases[0].from = (IO_BITMAP_BITS_16 - NUM_BYTES) + 1; 223 224 /*try valid ioperm on 65533, 65534, 65535 */ 225 test_cases[1].from = IO_BITMAP_BITS_16 - NUM_BYTES; 226 } 227 228 TEST_PAUSE; 229 230 } 231 232 void cleanup(void) 233 { 234 235 } 236 237 #else /* __i386__ */ 238 239 #include "test.h" 240 241 int TST_TOTAL = 0; 242 243 int main(void) 244 { 245 tst_resm(TPASS, 246 "LSB v1.3 does not specify ioperm() for this architecture."); 247 tst_exit(); 248 } 249 250 #endif /* __i386__ */ 251