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 "safe_macros.h" 84 #include "compat_16.h" 85 86 #define EXP_RET_VAL -1 87 #define EXP_ERRNO EPERM 88 #define TEST_DESC "unprivileged user" 89 90 struct test_case_t { /* test case structure */ 91 uid_t *rgid; /* real GID */ 92 uid_t *egid; /* effective GID */ 93 uid_t *sgid; /* saved GID */ 94 struct passwd *exp_rgid; /* Expected real GID */ 95 struct passwd *exp_egid; /* Expected effective GID */ 96 struct passwd *exp_sgid; /* Expected saved GID */ 97 }; 98 99 TCID_DEFINE(setresgid03); 100 static int testno; 101 static struct passwd nobody, bin, root; 102 static uid_t nobody_gid, bin_gid, neg = -1; 103 104 static int test_functionality(uid_t, uid_t, uid_t); 105 static void setup(void); 106 static void cleanup(void); 107 108 static struct test_case_t tdat[] = { 109 {&neg, &neg, &bin.pw_gid, &nobody, &nobody, &nobody}, 110 {&neg, &bin.pw_gid, &neg, &nobody, &nobody, &nobody}, 111 {&bin.pw_gid, &neg, &neg, &nobody, &nobody, &nobody}, 112 {&bin.pw_gid, &bin.pw_gid, &bin.pw_gid, &nobody, &nobody, &nobody}, 113 }; 114 115 int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]); 116 117 int main(int argc, char **argv) 118 { 119 int lc; 120 121 tst_parse_opts(argc, argv, NULL, NULL); 122 123 setup(); 124 125 for (lc = 0; TEST_LOOPING(lc); lc++) { 126 /* reset tst_count in case we are looping */ 127 tst_count = 0; 128 129 for (testno = 0; testno < TST_TOTAL; ++testno) { 130 131 TEST(SETRESGID(cleanup, *tdat[testno].rgid, *tdat[testno].egid, 132 *tdat[testno].sgid)); 133 134 if ((TEST_RETURN == EXP_RET_VAL) && 135 (TEST_ERRNO == EXP_ERRNO)) { 136 137 if (!test_functionality 138 (tdat[testno].exp_rgid->pw_gid, 139 tdat[testno].exp_egid->pw_gid, 140 tdat[testno].exp_sgid->pw_gid)) { 141 142 tst_resm(TPASS, "setresgid() failed as " 143 "expected for %s : errno %d", 144 TEST_DESC, TEST_ERRNO); 145 } else { 146 tst_resm(TFAIL, "Functionality test " 147 "for setresgid() for %s failed", 148 TEST_DESC); 149 } 150 151 } else { 152 tst_resm(TFAIL, "setresgid() returned " 153 "unexpected results for %s ; returned" 154 " %ld (expected %d), errno %d (expected" 155 " %d)", TEST_DESC, 156 TEST_RETURN, EXP_RET_VAL, TEST_ERRNO, 157 EXP_ERRNO); 158 } 159 } 160 } 161 cleanup(); 162 163 tst_exit(); 164 } 165 166 static int test_functionality(uid_t exp_rgid, uid_t exp_egid, uid_t exp_sgid) 167 { 168 uid_t cur_rgid, cur_egid, cur_sgid; 169 170 /* Get current real, effective and saved group id */ 171 SAFE_GETRESGID(cleanup, &cur_rgid, &cur_egid, &cur_sgid); 172 173 if ((cur_rgid == exp_rgid) && (cur_egid == exp_egid) 174 && (cur_sgid == exp_sgid)) { 175 return 0; 176 } 177 return 1; 178 } 179 180 /* 181 * setup() 182 * performs all ONE TIME setup for this test 183 */ 184 void setup(void) 185 { 186 struct passwd *passwd_p; 187 188 tst_require_root(); 189 190 tst_sig(NOFORK, DEF_HANDLER, cleanup); 191 192 if ((passwd_p = getpwnam("root")) == NULL) { 193 tst_brkm(TBROK, NULL, "getpwnam() failed for root"); 194 195 } 196 root = *passwd_p; 197 198 if ((passwd_p = getpwnam("bin")) == NULL) { 199 tst_brkm(TBROK, NULL, "bin user id doesn't exist"); 200 201 } 202 bin = *passwd_p; 203 GID16_CHECK((bin_gid = bin.pw_gid), "setresgid", cleanup) 204 205 if ((passwd_p = getpwnam("nobody")) == NULL) { 206 tst_brkm(TBROK, NULL, "nobody user id doesn't exist"); 207 208 } 209 nobody = *passwd_p; 210 GID16_CHECK((nobody_gid = nobody.pw_gid), "setresgid", cleanup) 211 212 /* Set real/effective/saved gid to nobody */ 213 if (setresgid(nobody_gid, nobody_gid, nobody_gid) == -1) { 214 tst_brkm(TBROK, NULL, "setup() failed for setting while" 215 " setting real/effective/saved gid"); 216 } 217 /* Set euid to nobody */ 218 SAFE_SETUID(NULL, nobody.pw_uid); 219 /* Pause if that option was specified 220 * TEST_PAUSE contains the code to fork the test with the -c option. 221 */ 222 TEST_PAUSE; 223 } 224 225 /* 226 * cleanup() 227 * performs all ONE TIME cleanup for this test at 228 * completion or premature exit 229 */ 230 void cleanup(void) 231 { 232 233 } 234