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 "compat_16.h" 79 80 #define EXP_RET_VAL 0 81 82 struct test_case_t { /* test case structure */ 83 uid_t *rgid; /* real GID */ 84 uid_t *egid; /* effective GID */ 85 uid_t *sgid; /* saved GID */ 86 struct passwd *exp_rgid; /* Expected real GID */ 87 struct passwd *exp_egid; /* Expected effective GID */ 88 struct passwd *exp_sgid; /* Expected saved GID */ 89 char *desc; /* Test description */ 90 }; 91 92 TCID_DEFINE(setresgid01); 93 static int testno; 94 static struct passwd nobody, root; 95 static uid_t nobody_gid, root_gid, neg = -1; 96 97 static int test_functionality(uid_t, uid_t, uid_t); 98 static void setup(void); 99 static void cleanup(void); 100 101 /* Don't change order of these test cases */ 102 static struct test_case_t tdat[] = { 103 {&neg, &neg, &neg, &root, &root, &root, 104 "setresgid(-1, -1, -1)"}, 105 {&neg, &neg, &nobody.pw_gid, &root, &root, &nobody, 106 "setresgid(-1, -1, nobody)"}, 107 {&neg, &nobody.pw_gid, &neg, &root, &nobody, &nobody, 108 "setresgid(-1, nobody, -1)"}, 109 {&nobody.pw_gid, &neg, &neg, &nobody, &nobody, &nobody, 110 "setresgid(nobody, -1, -1)"}, 111 {&root.pw_gid, &root.pw_gid, &root.pw_gid, &root, &root, &root, 112 "setresgid(root, root, root)"}, 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 if (!test_functionality 136 (tdat[testno].exp_rgid->pw_gid, 137 tdat[testno].exp_egid->pw_gid, 138 tdat[testno].exp_sgid->pw_gid)) { 139 140 tst_resm(TPASS, "Test for %s " 141 "successful", 142 tdat[testno].desc); 143 } else { 144 tst_resm(TFAIL, "Functionality test " 145 "for %s failed", 146 tdat[testno].desc); 147 } 148 } else { 149 tst_resm(TFAIL, "Test for %s failed; returned" 150 " %ld (expected %d), errno %d (expected" 151 " 0)", tdat[testno].desc, 152 TEST_RETURN, EXP_RET_VAL, TEST_ERRNO); 153 } 154 } 155 } 156 cleanup(); 157 158 tst_exit(); 159 } 160 161 static int test_functionality(uid_t exp_rgid, uid_t exp_egid, uid_t exp_sgid) 162 { 163 uid_t cur_rgid, cur_egid, cur_sgid; 164 165 /* Get current real, effective and saved group id's */ 166 if (getresgid(&cur_rgid, &cur_egid, &cur_sgid) == -1) { 167 tst_brkm(TBROK, cleanup, "getresgid() failed"); 168 169 } 170 171 if ((cur_rgid == exp_rgid) && (cur_egid == exp_egid) 172 && (cur_sgid == exp_sgid)) { 173 return 0; 174 } 175 return 1; 176 } 177 178 /* 179 * setup() 180 * performs all ONE TIME setup for this test 181 */ 182 void setup(void) 183 { 184 struct passwd *passwd_p; 185 186 tst_require_root(); 187 188 tst_sig(NOFORK, DEF_HANDLER, cleanup); 189 190 if ((passwd_p = getpwnam("root")) == NULL) { 191 tst_brkm(TBROK, NULL, "getpwnam() failed for root"); 192 193 } 194 root = *passwd_p; 195 GID16_CHECK((root_gid = root.pw_gid), "setresgid", cleanup) 196 197 if ((passwd_p = getpwnam("nobody")) == NULL) { 198 tst_brkm(TBROK, NULL, "nobody user id doesn't exist"); 199 200 } 201 nobody = *passwd_p; 202 GID16_CHECK((nobody_gid = nobody.pw_gid), "setresgid", cleanup) 203 204 /* Pause if that option was specified 205 * TEST_PAUSE contains the code to fork the test with the -c option. 206 */ 207 TEST_PAUSE; 208 } 209 210 /* 211 * cleanup() 212 * performs all ONE TIME cleanup for this test at 213 * completion or premature exit 214 */ 215 void cleanup(void) 216 { 217 218 } 219