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