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 * Ported by John George 20 */ 21 22 /* 23 * Test setreuid() when executed by an unpriviledged user. 24 */ 25 26 #include <errno.h> 27 #include <pwd.h> 28 #include <stdlib.h> 29 30 #include "test.h" 31 #include "safe_macros.h" 32 #include "compat_16.h" 33 34 #define FAILED 1 35 36 TCID_DEFINE(setreuid03); 37 38 static int fail = -1; 39 static int pass; 40 static uid_t neg_one = -1; 41 42 static struct passwd nobody, bin, root; 43 44 /* 45 * The following structure contains all test data. Each structure in the array 46 * is used for a separate test. The tests are executed in the for loop below. 47 */ 48 49 static struct test_data_t { 50 uid_t *real_uid; 51 uid_t *eff_uid; 52 int *exp_ret; 53 struct passwd *exp_real_usr; 54 struct passwd *exp_eff_usr; 55 char *test_msg; 56 } test_data[] = { 57 { 58 &nobody.pw_uid, &nobody.pw_uid, &pass, &nobody, &nobody, 59 "After setreuid(nobody, nobody),"}, { 60 &neg_one, &nobody.pw_uid, &pass, &nobody, &nobody, 61 "After setreuid(-1, nobody),"}, { 62 &nobody.pw_uid, &neg_one, &pass, &nobody, &nobody, 63 "After setreuid(nobody, -1),"}, { 64 &neg_one, &neg_one, &pass, &nobody, &nobody, "After setreuid(-1, -1),"}, 65 { 66 &neg_one, &root.pw_uid, &fail, &nobody, &nobody, 67 "After setreuid(-1, root),"}, { 68 &root.pw_uid, &neg_one, &fail, &nobody, &nobody, 69 "After setreuid(root, -1),"}, { 70 &root.pw_uid, &root.pw_uid, &fail, &nobody, &nobody, 71 "After setreuid(root, root),"}, { 72 &root.pw_uid, &nobody.pw_uid, &fail, &nobody, &nobody, 73 "After setreuid(root, nobody),"}, { 74 &root.pw_uid, &bin.pw_uid, &fail, &nobody, &nobody, 75 "After setreuid(root, nobody),"}, { 76 &bin.pw_uid, &root.pw_uid, &fail, &nobody, &nobody, 77 "After setreuid(bin, root),"}, { 78 &bin.pw_uid, &neg_one, &fail, &nobody, &nobody, 79 "After setreuid(bin, -1),"}, { 80 &bin.pw_uid, &bin.pw_uid, &fail, &nobody, &nobody, 81 "After setreuid(bin, bin,),"}, { 82 &bin.pw_uid, &nobody.pw_uid, &fail, &nobody, &nobody, 83 "After setreuid(bin, nobody),"}, { 84 &nobody.pw_uid, &bin.pw_uid, &fail, &nobody, &nobody, 85 "After setreuid(nobody, bin),"},}; 86 87 int TST_TOTAL = ARRAY_SIZE(test_data); 88 89 static void setup(void); 90 static void cleanup(void); 91 static void uid_verify(struct passwd *, struct passwd *, char *); 92 93 int main(int ac, char **av) 94 { 95 int lc; 96 97 tst_parse_opts(ac, av, NULL, NULL); 98 99 setup(); 100 101 for (lc = 0; TEST_LOOPING(lc); lc++) { 102 int i; 103 104 tst_count = 0; 105 106 for (i = 0; i < TST_TOTAL; i++) { 107 108 /* Set the real or effective user id */ 109 TEST(SETREUID(cleanup, *test_data[i].real_uid, 110 *test_data[i].eff_uid)); 111 112 if (TEST_RETURN == *test_data[i].exp_ret) { 113 if (TEST_RETURN == neg_one) { 114 if (TEST_ERRNO != EPERM) { 115 tst_resm(TFAIL, 116 "setreuid(%d, %d) " 117 "did not set errno " 118 "value as expected.", 119 *test_data[i].real_uid, 120 *test_data[i].eff_uid); 121 continue; 122 } 123 tst_resm(TPASS, "setreuid(%d, %d) " 124 "failed as expected.", 125 *test_data[i].real_uid, 126 *test_data[i].eff_uid); 127 } else { 128 tst_resm(TPASS, "setreuid(%d, %d) " 129 "succeeded as expected.", 130 *test_data[i].real_uid, 131 *test_data[i].eff_uid); 132 } 133 } else { 134 tst_resm(TFAIL, "setreuid(%d, %d) " 135 "did not return as expected.", 136 *test_data[i].real_uid, 137 *test_data[i].eff_uid); 138 } 139 140 if (TEST_RETURN == -1) { 141 } 142 uid_verify(test_data[i].exp_real_usr, 143 test_data[i].exp_eff_usr, 144 test_data[i].test_msg); 145 } 146 } 147 148 cleanup(); 149 tst_exit(); 150 } 151 152 static void setup(void) 153 { 154 tst_require_root(); 155 156 tst_sig(FORK, DEF_HANDLER, cleanup); 157 158 if (getpwnam("nobody") == NULL) 159 tst_brkm(TBROK, NULL, "nobody must be a valid user."); 160 161 if (getpwnam("bin") == NULL) 162 tst_brkm(TBROK, NULL, "bin must be a valid user."); 163 164 root = *(getpwnam("root")); 165 UID16_CHECK(root.pw_uid, setreuid, cleanup); 166 167 nobody = *(getpwnam("nobody")); 168 UID16_CHECK(nobody.pw_uid, setreuid, cleanup); 169 170 bin = *(getpwnam("bin")); 171 UID16_CHECK(bin.pw_uid, setreuid, cleanup); 172 173 SAFE_SETUID(NULL, nobody.pw_uid); 174 175 TEST_PAUSE; 176 } 177 178 static void cleanup(void) 179 { 180 } 181 182 static void uid_verify(struct passwd *ru, struct passwd *eu, char *when) 183 { 184 if ((getuid() != ru->pw_uid) || (geteuid() != eu->pw_uid)) { 185 tst_resm(TFAIL, "ERROR: %s real uid = %d; effective uid = %d", 186 when, getuid(), geteuid()); 187 tst_resm(TINFO, "Expected: real uid = %d; effective uid = %d", 188 ru->pw_uid, eu->pw_uid); 189 } 190 } 191