1 /* 2 * 3 * Copyright (c) International Business Machines Corp., 2001 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13 * the GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20 /* 21 * NAME 22 * setresuid01.c 23 * 24 * DESCRIPTION 25 * Test setresuid() when executed by root. 26 * 27 * ALGORITHM 28 * 29 * Setup: 30 * Setup signal handling 31 * Get user information. 32 * Pause for SIGUSER1 if option specified. 33 * Setup test values. 34 * Loop if the proper options are given. 35 * For each test execute the system call 36 * Check return code, if system call failed (return=-1) 37 * Log the errno and Issue a FAIL message. 38 * Otherwise, 39 * Verify the Functionality of system call 40 * if successful, 41 * Issue Functionality-Pass message. 42 * Otherwise, 43 * Issue Functionality-Fail message. 44 * Cleanup: 45 * Print errno log and/or timing stats if options given. 46 * 47 * USAGE: <for command-line> 48 * setresuid01 [-c n] [-e] [-f] [-i n] [-I x] [-P x] [-t] 49 * where, -c n : Run n copies concurrently. 50 * -e : Turn on errno logging. 51 * -f : Turn off functionality Testing. 52 * -i n : Execute test n times. 53 * -I x : Execute test for x seconds. 54 * -P x : Pause for x seconds between iterations. 55 * -t : Turn on syscall timing. 56 * History 57 * 07/2001 John George 58 * -Ported 59 * 60 * Restrictions 61 * This test must be ran as root. 62 * nobody and bin must be valid users. 63 */ 64 65 #define _GNU_SOURCE 1 66 #include <pwd.h> 67 #include <stdlib.h> 68 #include <string.h> 69 #include "test.h" 70 #include <errno.h> 71 #include "compat_16.h" 72 73 TCID_DEFINE(setresuid01); 74 75 uid_t nobody_pw_uid, root_pw_uid, bin_pw_uid; 76 uid_t neg_one = -1; 77 78 struct passwd nobody, bin, root; 79 80 /* 81 * The following structure contains all test data. Each structure in the array 82 * is used for a separate test. The tests are executed in the for loop below. 83 */ 84 85 struct test_data_t { 86 uid_t *real_uid; 87 uid_t *eff_uid; 88 uid_t *sav_uid; 89 struct passwd *exp_real_usr; 90 struct passwd *exp_eff_usr; 91 struct passwd *exp_sav_usr; 92 char *test_msg; 93 } test_data[] = { 94 { 95 &neg_one, &neg_one, &neg_one, &root, &root, &root, 96 "After setresuid(-1, -1, -1),"}, { 97 &neg_one, &neg_one, &nobody_pw_uid, &root, &root, &nobody, 98 "After setresuid(-1, -1, nobody),"}, { 99 &neg_one, &bin_pw_uid, &neg_one, &root, &bin, &nobody, 100 "After setresuid(-1, bin, -1),"}, { 101 &neg_one, &neg_one, &root_pw_uid, &root, &bin, &root, 102 "After setresuid(-1, -1, root),"}, { 103 &neg_one, &neg_one, &bin_pw_uid, &root, &bin, &bin, 104 "After setresuid(-1, -1, bin),"}, { 105 &neg_one, &root_pw_uid, &neg_one, &root, &root, &bin, 106 "After setresuid(-1, root, -1),"}, { 107 &nobody_pw_uid, &neg_one, &neg_one, &nobody, &root, &bin, 108 "After setresuid(nobody, -1, -1)"}, { 109 &neg_one, &root_pw_uid, &neg_one, &nobody, &root, &bin, 110 "After setresuid(-1, root, -1),"}, { 111 &root_pw_uid, &neg_one, &root_pw_uid, &root, &root, &root, 112 "After setresuid(root, -1, -1),"},}; 113 114 int TST_TOTAL = sizeof(test_data) / sizeof(test_data[0]); 115 116 void setup(void); 117 void cleanup(void); 118 119 void 120 uid_verify(struct passwd *ru, struct passwd *eu, struct passwd *su, char *when); 121 122 int main(int ac, char **av) 123 { 124 int lc; 125 126 tst_parse_opts(ac, av, NULL, NULL); 127 128 setup(); 129 130 for (lc = 0; TEST_LOOPING(lc); lc++) { 131 int i; 132 133 /* reset tst_count in case we are looping */ 134 tst_count = 0; 135 136 for (i = 0; i < TST_TOTAL; i++) { 137 /* Set the real, effective or user id */ 138 TEST(SETRESUID(cleanup, *test_data[i].real_uid, 139 *test_data[i].eff_uid, 140 *test_data[i].sav_uid)); 141 142 if (TEST_RETURN == -1) { 143 tst_resm(TFAIL, "setresuid(%d, %d, %d) failed", 144 *test_data[i].real_uid, 145 *test_data[i].eff_uid, 146 *test_data[i].sav_uid); 147 } else { 148 uid_verify(test_data[i].exp_real_usr, 149 test_data[i].exp_eff_usr, 150 test_data[i].exp_sav_usr, 151 test_data[i].test_msg); 152 } 153 } 154 } 155 156 cleanup(); 157 tst_exit(); 158 } 159 160 /* 161 * setup() 162 * performs all ONE TIME setup for this test 163 */ 164 void setup(void) 165 { 166 tst_require_root(); 167 168 tst_sig(FORK, DEF_HANDLER, cleanup); 169 170 if (getpwnam("nobody") == NULL) { 171 tst_brkm(TBROK, NULL, "nobody must be a valid user."); 172 } 173 174 if (getpwnam("bin") == NULL) { 175 tst_brkm(TBROK, NULL, "bin must be a valid user."); 176 } 177 178 root = *(getpwnam("root")); 179 UID16_CHECK((root_pw_uid = root.pw_uid), "setresuid", cleanup) 180 181 nobody = *(getpwnam("nobody")); 182 UID16_CHECK((nobody_pw_uid = nobody.pw_uid), "setresuid", cleanup) 183 184 bin = *(getpwnam("bin")); 185 UID16_CHECK((bin_pw_uid = bin.pw_uid), "setresuid", cleanup) 186 187 /* Pause if that option was specified 188 * TEST_PAUSE contains the code to fork the test with the -c option. 189 */ 190 TEST_PAUSE; 191 } 192 193 /* 194 * cleanup() 195 * performs all ONE TIME cleanup for this test at 196 * completion or premature exit 197 */ 198 void cleanup(void) 199 { 200 201 } 202 203 void 204 uid_verify(struct passwd *ru, struct passwd *eu, struct passwd *su, char *when) 205 { 206 uid_t cur_ru, cur_eu, cur_su; 207 if (getresuid(&cur_ru, &cur_eu, &cur_su) != 0) { 208 tst_brkm(TBROK, cleanup, "Set getresuid() failed"); 209 } 210 if ((cur_ru != ru->pw_uid) || (cur_eu != eu->pw_uid) || (cur_su != 211 su->pw_uid)) { 212 tst_resm(TFAIL, "ERROR: %s real uid = %d; effective uid = %d; " 213 "saved uid = %d", when, cur_ru, cur_eu, cur_su); 214 tst_resm(TINFO, "Expected: real uid = %d, effective uid = %d " 215 "saved uid = %d", ru->pw_uid, eu->pw_uid, su->pw_uid); 216 } else { 217 tst_resm(TPASS, 218 "real uid = %d, effective uid = %d, and saved uid = " 219 "%d as expected", cur_ru, cur_eu, cur_su); 220 } 221 } 222