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 : setresgid03 20 * 21 * EXECUTED BY : root / superuser 22 * 23 * TEST TITLE : Checking error conditions for setresgid(2) 24 * 25 * TEST CASE TOTAL : 4 26 * 27 * AUTHOR : Madhu T L <madhu.tarikere (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. setresgid(2) fails with EPERM for unprivileged user in setting 36 * saved group id. 37 * 2. setresgid(2) fails with EPERM for unprivileged user in setting 38 * effective group id. 39 * 3. setresgid(2) fails with EPERM for unprivileged user in setting 40 * real group id. 41 * 4. setresgid(2) fails with EPERM for unprivileged user in setting 42 * real/effective/saved group id. 43 * 44 * Setup: 45 * Setup signal handling. 46 * Test caller is superuser 47 * Check existence of user id's root/bin/nobody 48 * Set real/effective/saved gid to nobody 49 * Set effective uid to nobody 50 * Pause for SIGUSR1 if option specified. 51 * 52 * Test: 53 * Loop if the proper options are given. 54 * Execute system call 55 * Check return value, errno and functionality, if success, 56 * Issue PASS message 57 * Otherwise, 58 * Issue FAIL message 59 * 60 * Cleanup: 61 * Print errno log and/or timing stats if options given 62 * 63 * USAGE: <for command-line> 64 * setresgid03 [-c n] [-e] [-f] [-h] [-i n] [-I x] [-p] [-P x] [-t] 65 * where, -c n : Run n copies concurrently. 66 * -e : Turn on errno logging. 67 * -f : Turn off functional testing 68 * -h : Show help screen 69 * -i n : Execute test n times. 70 * -I x : Execute test for x seconds. 71 * -p : Pause for SIGUSR1 before starting 72 * -P x : Pause for x seconds between iterations. 73 * -t : Turn on syscall timing. 74 * 75 ****************************************************************/ 76 77 #define _GNU_SOURCE 1 78 #include <errno.h> 79 #include <pwd.h> 80 #include <sys/types.h> 81 #include <unistd.h> 82 #include "test.h" 83 #include "compat_16.h" 84 85 #define EXP_RET_VAL -1 86 #define EXP_ERRNO EPERM 87 #define TEST_DESC "unprivileged user" 88 89 struct test_case_t { /* test case structure */ 90 uid_t *rgid; /* real GID */ 91 uid_t *egid; /* effective GID */ 92 uid_t *sgid; /* saved GID */ 93 struct passwd *exp_rgid; /* Expected real GID */ 94 struct passwd *exp_egid; /* Expected effective GID */ 95 struct passwd *exp_sgid; /* Expected saved GID */ 96 }; 97 98 TCID_DEFINE(setresgid03); 99 static int testno; 100 static struct passwd nobody, bin, root; 101 static uid_t nobody_gid, bin_gid, neg = -1; 102 103 static int test_functionality(uid_t, uid_t, uid_t); 104 static void setup(void); 105 static void cleanup(void); 106 107 static struct test_case_t tdat[] = { 108 {&neg, &neg, &bin.pw_gid, &nobody, &nobody, &nobody}, 109 {&neg, &bin.pw_gid, &neg, &nobody, &nobody, &nobody}, 110 {&bin.pw_gid, &neg, &neg, &nobody, &nobody, &nobody}, 111 {&bin.pw_gid, &bin.pw_gid, &bin.pw_gid, &nobody, &nobody, &nobody}, 112 }; 113 114 int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]); 115 116 int main(int argc, char **argv) 117 { 118 int lc; 119 120 tst_parse_opts(argc, argv, NULL, NULL); 121 122 setup(); 123 124 for (lc = 0; TEST_LOOPING(lc); lc++) { 125 /* reset tst_count in case we are looping */ 126 tst_count = 0; 127 128 for (testno = 0; testno < TST_TOTAL; ++testno) { 129 130 TEST(SETRESGID(cleanup, *tdat[testno].rgid, *tdat[testno].egid, 131 *tdat[testno].sgid)); 132 133 if ((TEST_RETURN == EXP_RET_VAL) && 134 (TEST_ERRNO == EXP_ERRNO)) { 135 136 if (!test_functionality 137 (tdat[testno].exp_rgid->pw_gid, 138 tdat[testno].exp_egid->pw_gid, 139 tdat[testno].exp_sgid->pw_gid)) { 140 141 tst_resm(TPASS, "setresgid() failed as " 142 "expected for %s : errno %d", 143 TEST_DESC, TEST_ERRNO); 144 } else { 145 tst_resm(TFAIL, "Functionality test " 146 "for setresgid() for %s failed", 147 TEST_DESC); 148 } 149 150 } else { 151 tst_resm(TFAIL, "setresgid() returned " 152 "unexpected results for %s ; returned" 153 " %ld (expected %d), errno %d (expected" 154 " %d)", TEST_DESC, 155 TEST_RETURN, EXP_RET_VAL, TEST_ERRNO, 156 EXP_ERRNO); 157 } 158 } 159 } 160 cleanup(); 161 162 tst_exit(); 163 } 164 165 static int test_functionality(uid_t exp_rgid, uid_t exp_egid, uid_t exp_sgid) 166 { 167 uid_t cur_rgid, cur_egid, cur_sgid; 168 169 /* Get current real, effective and saved group id */ 170 if (getresgid(&cur_rgid, &cur_egid, &cur_sgid) == -1) { 171 tst_brkm(TBROK, cleanup, "getresgid() failed"); 172 173 } 174 175 if ((cur_rgid == exp_rgid) && (cur_egid == exp_egid) 176 && (cur_sgid == exp_sgid)) { 177 return 0; 178 } 179 return 1; 180 } 181 182 /* 183 * setup() 184 * performs all ONE TIME setup for this test 185 */ 186 void setup(void) 187 { 188 struct passwd *passwd_p; 189 190 tst_require_root(); 191 192 tst_sig(NOFORK, DEF_HANDLER, cleanup); 193 194 if ((passwd_p = getpwnam("root")) == NULL) { 195 tst_brkm(TBROK, NULL, "getpwnam() failed for root"); 196 197 } 198 root = *passwd_p; 199 200 if ((passwd_p = getpwnam("bin")) == NULL) { 201 tst_brkm(TBROK, NULL, "bin user id doesn't exist"); 202 203 } 204 bin = *passwd_p; 205 GID16_CHECK((bin_gid = bin.pw_gid), "setresgid", cleanup) 206 207 if ((passwd_p = getpwnam("nobody")) == NULL) { 208 tst_brkm(TBROK, NULL, "nobody user id doesn't exist"); 209 210 } 211 nobody = *passwd_p; 212 GID16_CHECK((nobody_gid = nobody.pw_gid), "setresgid", cleanup) 213 214 /* Set real/effective/saved gid to nobody */ 215 if (setresgid(nobody_gid, nobody_gid, nobody_gid) == -1) { 216 tst_brkm(TBROK, NULL, "setup() failed for setting while" 217 " setting real/effective/saved gid"); 218 } 219 /* Set euid to nobody */ 220 if (setuid(nobody.pw_uid) == -1) { 221 tst_brkm(TBROK, NULL, "setuid failed to " 222 "to set the effective uid to nodody"); 223 224 } 225 /* Pause if that option was specified 226 * TEST_PAUSE contains the code to fork the test with the -c option. 227 */ 228 TEST_PAUSE; 229 } 230 231 /* 232 * cleanup() 233 * performs all ONE TIME cleanup for this test at 234 * completion or premature exit 235 */ 236 void cleanup(void) 237 { 238 239 } 240