1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2001 3f08c3bdfSopenharmony_ci * Ported by Wayne Boyer 4f08c3bdfSopenharmony_ci * Copyright (c) Cyril Hrubis <chrubis@suse.cz> 2013 5f08c3bdfSopenharmony_ci * 6f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify 7f08c3bdfSopenharmony_ci * it under the terms of the GNU General Public License as published by 8f08c3bdfSopenharmony_ci * the Free Software Foundation; either version 2 of the License, or 9f08c3bdfSopenharmony_ci * (at your option) any later version. 10f08c3bdfSopenharmony_ci * 11f08c3bdfSopenharmony_ci * This program is distributed in the hope that it will be useful, 12f08c3bdfSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 13f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 14f08c3bdfSopenharmony_ci * the GNU General Public License for more details. 15f08c3bdfSopenharmony_ci * 16f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License 17f08c3bdfSopenharmony_ci * along with this program; if not, write to the Free Software 18f08c3bdfSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19f08c3bdfSopenharmony_ci */ 20f08c3bdfSopenharmony_ci 21f08c3bdfSopenharmony_ci/* 22f08c3bdfSopenharmony_ci * Test Description: 23f08c3bdfSopenharmony_ci * Verify that, getgroups() system call gets the supplementary group IDs 24f08c3bdfSopenharmony_ci * of the calling process. 25f08c3bdfSopenharmony_ci * 26f08c3bdfSopenharmony_ci * Expected Result: 27f08c3bdfSopenharmony_ci * The call succeeds in getting all the supplementary group IDs of the 28f08c3bdfSopenharmony_ci * calling process. The effective group ID may or may not be returned. 29f08c3bdfSopenharmony_ci */ 30f08c3bdfSopenharmony_ci 31f08c3bdfSopenharmony_ci#include <stdio.h> 32f08c3bdfSopenharmony_ci#include <sys/types.h> 33f08c3bdfSopenharmony_ci#include <unistd.h> 34f08c3bdfSopenharmony_ci#include <errno.h> 35f08c3bdfSopenharmony_ci#include <string.h> 36f08c3bdfSopenharmony_ci#include <signal.h> 37f08c3bdfSopenharmony_ci#include <grp.h> 38f08c3bdfSopenharmony_ci#include <sys/stat.h> 39f08c3bdfSopenharmony_ci#include <sys/param.h> 40f08c3bdfSopenharmony_ci#include <pwd.h> 41f08c3bdfSopenharmony_ci 42f08c3bdfSopenharmony_ci#include "test.h" 43f08c3bdfSopenharmony_ci#include "compat_16.h" 44f08c3bdfSopenharmony_ci 45f08c3bdfSopenharmony_ci#define TESTUSER "root" 46f08c3bdfSopenharmony_ci 47f08c3bdfSopenharmony_ciTCID_DEFINE(getgroups03); 48f08c3bdfSopenharmony_ciint TST_TOTAL = 1; 49f08c3bdfSopenharmony_ci 50f08c3bdfSopenharmony_cistatic int ngroups; 51f08c3bdfSopenharmony_cistatic GID_T groups_list[NGROUPS]; 52f08c3bdfSopenharmony_cistatic GID_T groups[NGROUPS]; 53f08c3bdfSopenharmony_ci 54f08c3bdfSopenharmony_cistatic void verify_groups(int ret_ngroups); 55f08c3bdfSopenharmony_cistatic void setup(void); 56f08c3bdfSopenharmony_cistatic void cleanup(void); 57f08c3bdfSopenharmony_ci 58f08c3bdfSopenharmony_ciint main(int ac, char **av) 59f08c3bdfSopenharmony_ci{ 60f08c3bdfSopenharmony_ci int lc; 61f08c3bdfSopenharmony_ci int gidsetsize = NGROUPS; 62f08c3bdfSopenharmony_ci 63f08c3bdfSopenharmony_ci tst_parse_opts(ac, av, NULL, NULL); 64f08c3bdfSopenharmony_ci 65f08c3bdfSopenharmony_ci setup(); 66f08c3bdfSopenharmony_ci 67f08c3bdfSopenharmony_ci for (lc = 0; TEST_LOOPING(lc); lc++) { 68f08c3bdfSopenharmony_ci 69f08c3bdfSopenharmony_ci tst_count = 0; 70f08c3bdfSopenharmony_ci 71f08c3bdfSopenharmony_ci TEST(GETGROUPS(cleanup, gidsetsize, groups_list)); 72f08c3bdfSopenharmony_ci 73f08c3bdfSopenharmony_ci if (TEST_RETURN == -1) { 74f08c3bdfSopenharmony_ci tst_resm(TFAIL | TTERRNO, "getgroups failed"); 75f08c3bdfSopenharmony_ci continue; 76f08c3bdfSopenharmony_ci } 77f08c3bdfSopenharmony_ci 78f08c3bdfSopenharmony_ci verify_groups(TEST_RETURN); 79f08c3bdfSopenharmony_ci } 80f08c3bdfSopenharmony_ci 81f08c3bdfSopenharmony_ci cleanup(); 82f08c3bdfSopenharmony_ci tst_exit(); 83f08c3bdfSopenharmony_ci} 84f08c3bdfSopenharmony_ci 85f08c3bdfSopenharmony_ci/* 86f08c3bdfSopenharmony_ci * readgroups(GID_T *) - Read supplimentary group ids of "root" user 87f08c3bdfSopenharmony_ci * Scans the /etc/group file to get IDs of all the groups to which TESTUSER 88f08c3bdfSopenharmony_ci * belongs and puts them into the array passed. 89f08c3bdfSopenharmony_ci * Returns the no of gids read. 90f08c3bdfSopenharmony_ci */ 91f08c3bdfSopenharmony_cistatic int readgroups(GID_T groups[NGROUPS]) 92f08c3bdfSopenharmony_ci{ 93f08c3bdfSopenharmony_ci struct group *grp; 94f08c3bdfSopenharmony_ci int ngrps = 0; 95f08c3bdfSopenharmony_ci int i; 96f08c3bdfSopenharmony_ci int found; 97f08c3bdfSopenharmony_ci GID_T g; 98f08c3bdfSopenharmony_ci 99f08c3bdfSopenharmony_ci setgrent(); 100f08c3bdfSopenharmony_ci 101f08c3bdfSopenharmony_ci while ((grp = getgrent()) != 0) { 102f08c3bdfSopenharmony_ci for (i = 0; grp->gr_mem[i]; i++) { 103f08c3bdfSopenharmony_ci if (strcmp(grp->gr_mem[i], TESTUSER) == 0) { 104f08c3bdfSopenharmony_ci groups[ngrps++] = grp->gr_gid; 105f08c3bdfSopenharmony_ci } 106f08c3bdfSopenharmony_ci } 107f08c3bdfSopenharmony_ci } 108f08c3bdfSopenharmony_ci 109f08c3bdfSopenharmony_ci /* The getgroups specification says: 110f08c3bdfSopenharmony_ci It is unspecified whether the effective group ID of the 111f08c3bdfSopenharmony_ci calling process is included in the returned list. (Thus, 112f08c3bdfSopenharmony_ci an application should also call getegid(2) and add or 113f08c3bdfSopenharmony_ci remove the resulting value.). So, add the value here if 114f08c3bdfSopenharmony_ci it's not in. */ 115f08c3bdfSopenharmony_ci 116f08c3bdfSopenharmony_ci found = 0; 117f08c3bdfSopenharmony_ci g = getegid(); 118f08c3bdfSopenharmony_ci 119f08c3bdfSopenharmony_ci for (i = 0; i < ngrps; i++) { 120f08c3bdfSopenharmony_ci if (groups[i] == g) 121f08c3bdfSopenharmony_ci found = 1; 122f08c3bdfSopenharmony_ci } 123f08c3bdfSopenharmony_ci if (found == 0) 124f08c3bdfSopenharmony_ci groups[ngrps++] = g; 125f08c3bdfSopenharmony_ci 126f08c3bdfSopenharmony_ci endgrent(); 127f08c3bdfSopenharmony_ci return ngrps; 128f08c3bdfSopenharmony_ci} 129f08c3bdfSopenharmony_ci 130f08c3bdfSopenharmony_cistatic void setup(void) 131f08c3bdfSopenharmony_ci{ 132f08c3bdfSopenharmony_ci tst_require_root(); 133f08c3bdfSopenharmony_ci 134f08c3bdfSopenharmony_ci tst_sig(NOFORK, DEF_HANDLER, cleanup); 135f08c3bdfSopenharmony_ci 136f08c3bdfSopenharmony_ci TEST_PAUSE; 137f08c3bdfSopenharmony_ci 138f08c3bdfSopenharmony_ci /* 139f08c3bdfSopenharmony_ci * Get the IDs of all the groups of "root" 140f08c3bdfSopenharmony_ci * from /etc/group file 141f08c3bdfSopenharmony_ci */ 142f08c3bdfSopenharmony_ci ngroups = readgroups(groups); 143f08c3bdfSopenharmony_ci 144f08c3bdfSopenharmony_ci /* Setgroups is called by the login(1) process 145f08c3bdfSopenharmony_ci * if the testcase is executed via an ssh session this 146f08c3bdfSopenharmony_ci * testcase will fail. So execute setgroups() before executing 147f08c3bdfSopenharmony_ci * getgroups() 148f08c3bdfSopenharmony_ci */ 149f08c3bdfSopenharmony_ci if (SETGROUPS(cleanup, ngroups, groups) == -1) 150f08c3bdfSopenharmony_ci tst_brkm(TBROK | TERRNO, cleanup, "setgroups failed"); 151f08c3bdfSopenharmony_ci} 152f08c3bdfSopenharmony_ci 153f08c3bdfSopenharmony_ci/* 154f08c3bdfSopenharmony_ci * verify_groups(int) - Verify supplimentary group id values. 155f08c3bdfSopenharmony_ci * This function verifies the gid values returned by getgroups() with 156f08c3bdfSopenharmony_ci * the read values from /etc/group file. 157f08c3bdfSopenharmony_ci * This function returns flag value which indicates success or failure 158f08c3bdfSopenharmony_ci * of verification. 159f08c3bdfSopenharmony_ci */ 160f08c3bdfSopenharmony_cistatic void verify_groups(int ret_ngroups) 161f08c3bdfSopenharmony_ci{ 162f08c3bdfSopenharmony_ci int i, j; 163f08c3bdfSopenharmony_ci GID_T egid; 164f08c3bdfSopenharmony_ci int egid_flag = 1; 165f08c3bdfSopenharmony_ci int fflag = 1; 166f08c3bdfSopenharmony_ci 167f08c3bdfSopenharmony_ci /* 168f08c3bdfSopenharmony_ci * Loop through the array to verify the gids 169f08c3bdfSopenharmony_ci * returned by getgroups(). 170f08c3bdfSopenharmony_ci * First, compare each element of the array 171f08c3bdfSopenharmony_ci * returned by getgroups() with that read from 172f08c3bdfSopenharmony_ci * group file. 173f08c3bdfSopenharmony_ci */ 174f08c3bdfSopenharmony_ci for (i = 0; i < ret_ngroups; i++) { 175f08c3bdfSopenharmony_ci for (j = 0; j < ngroups; j++) { 176f08c3bdfSopenharmony_ci if (groups_list[i] != groups[j]) { 177f08c3bdfSopenharmony_ci /* If loop ends and gids are not matching */ 178f08c3bdfSopenharmony_ci if (j == ngroups - 1) { 179f08c3bdfSopenharmony_ci tst_resm(TFAIL, "getgroups returned " 180f08c3bdfSopenharmony_ci "incorrect gid %d", 181f08c3bdfSopenharmony_ci groups_list[i]); 182f08c3bdfSopenharmony_ci fflag = 0; 183f08c3bdfSopenharmony_ci } else { 184f08c3bdfSopenharmony_ci continue; 185f08c3bdfSopenharmony_ci } 186f08c3bdfSopenharmony_ci } else { 187f08c3bdfSopenharmony_ci break; 188f08c3bdfSopenharmony_ci } 189f08c3bdfSopenharmony_ci } 190f08c3bdfSopenharmony_ci } 191f08c3bdfSopenharmony_ci 192f08c3bdfSopenharmony_ci /* Now do the reverse comparison */ 193f08c3bdfSopenharmony_ci egid = getegid(); 194f08c3bdfSopenharmony_ci for (i = 0; i < ngroups; i++) { 195f08c3bdfSopenharmony_ci for (j = 0; j < ret_ngroups; j++) { 196f08c3bdfSopenharmony_ci if (groups[i] != groups_list[j]) { 197f08c3bdfSopenharmony_ci /* 198f08c3bdfSopenharmony_ci * If the loop ends & gids are not matching 199f08c3bdfSopenharmony_ci * if gid is not egid, exit with error 200f08c3bdfSopenharmony_ci * else egid is returned by getgroups() 201f08c3bdfSopenharmony_ci */ 202f08c3bdfSopenharmony_ci if (j == (ret_ngroups - 1)) { 203f08c3bdfSopenharmony_ci if (groups[i] != egid) { 204f08c3bdfSopenharmony_ci tst_resm(TFAIL, "getgroups " 205f08c3bdfSopenharmony_ci "didn't return %d one " 206f08c3bdfSopenharmony_ci "of the gids of %s", 207f08c3bdfSopenharmony_ci groups[i], TESTUSER); 208f08c3bdfSopenharmony_ci fflag = 0; 209f08c3bdfSopenharmony_ci } else { 210f08c3bdfSopenharmony_ci /* 211f08c3bdfSopenharmony_ci * egid is not present in 212f08c3bdfSopenharmony_ci * group_list. 213f08c3bdfSopenharmony_ci * Reset the egid flag 214f08c3bdfSopenharmony_ci */ 215f08c3bdfSopenharmony_ci egid_flag = 0; 216f08c3bdfSopenharmony_ci } 217f08c3bdfSopenharmony_ci } 218f08c3bdfSopenharmony_ci } else { 219f08c3bdfSopenharmony_ci break; 220f08c3bdfSopenharmony_ci } 221f08c3bdfSopenharmony_ci } 222f08c3bdfSopenharmony_ci } 223f08c3bdfSopenharmony_ci 224f08c3bdfSopenharmony_ci /* 225f08c3bdfSopenharmony_ci * getgroups() should return the no. of gids for TESTUSER with 226f08c3bdfSopenharmony_ci * or without egid taken into account. 227f08c3bdfSopenharmony_ci * Decrement ngroups, if egid is not returned by getgroups() 228f08c3bdfSopenharmony_ci * Now, if ngroups matches ret_val, as above comparisons of the array 229f08c3bdfSopenharmony_ci * are successful, this implies that the array contents match. 230f08c3bdfSopenharmony_ci */ 231f08c3bdfSopenharmony_ci if (egid_flag == 0) 232f08c3bdfSopenharmony_ci ngroups--; 233f08c3bdfSopenharmony_ci if (ngroups != ret_ngroups) { 234f08c3bdfSopenharmony_ci tst_resm(TFAIL, 235f08c3bdfSopenharmony_ci "getgroups(2) returned incorrect no. of gids %d " 236f08c3bdfSopenharmony_ci "(expected %d)", ret_ngroups, ngroups); 237f08c3bdfSopenharmony_ci fflag = 0; 238f08c3bdfSopenharmony_ci } 239f08c3bdfSopenharmony_ci 240f08c3bdfSopenharmony_ci if (fflag) 241f08c3bdfSopenharmony_ci tst_resm(TPASS, "getgroups functionality correct"); 242f08c3bdfSopenharmony_ci} 243f08c3bdfSopenharmony_ci 244f08c3bdfSopenharmony_cistatic void cleanup(void) 245f08c3bdfSopenharmony_ci{ 246f08c3bdfSopenharmony_ci} 247