blob: 28e80f5b9a194aa50d600784d668d3d5f220d0af [file] [log] [blame]
plars865695b2001-08-27 22:15:12 +00001/*
Cyril Hrubisc515be22013-04-04 16:46:39 +02002 * Copyright (c) International Business Machines Corp., 2001
3 * Ported by Wayne Boyer
4 * Copyright (c) Cyril Hrubis <chrubis@suse.cz> 2013
plars865695b2001-08-27 22:15:12 +00005 *
Cyril Hrubisc515be22013-04-04 16:46:39 +02006 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
plars865695b2001-08-27 22:15:12 +000010 *
Cyril Hrubisc515be22013-04-04 16:46:39 +020011 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14 * the GNU General Public License for more details.
plars865695b2001-08-27 22:15:12 +000015 *
Cyril Hrubisc515be22013-04-04 16:46:39 +020016 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
plars865695b2001-08-27 22:15:12 +000019 */
20
subrata_modak4bb656a2009-02-26 12:02:09 +000021/*
plars865695b2001-08-27 22:15:12 +000022 * Test Description:
23 * Verify that, getgroups() system call gets the supplementary group IDs
24 * of the calling process.
25 *
26 * Expected Result:
27 * The call succeeds in getting all the supplementary group IDs of the
28 * calling process. The effective group ID may or may not be returned.
plars865695b2001-08-27 22:15:12 +000029 */
30
31#include <stdio.h>
32#include <sys/types.h>
33#include <unistd.h>
34#include <errno.h>
35#include <string.h>
36#include <signal.h>
37#include <grp.h>
38#include <sys/stat.h>
39#include <sys/param.h>
robbiew05e61752001-08-31 18:11:58 +000040#include <pwd.h>
plars865695b2001-08-27 22:15:12 +000041
42#include "test.h"
Stanislav Kholmanskikh0f3ac8c2013-09-05 11:01:49 +040043#include "compat_16.h"
plars865695b2001-08-27 22:15:12 +000044
Cyril Hrubisc515be22013-04-04 16:46:39 +020045#define TESTUSER "root"
plars865695b2001-08-27 22:15:12 +000046
Stanislav Kholmanskikh15f73032013-09-17 14:55:01 +040047TCID_DEFINE(getgroups03);
Cyril Hrubisc515be22013-04-04 16:46:39 +020048int TST_TOTAL = 1;
plars865695b2001-08-27 22:15:12 +000049
Cyril Hrubisc515be22013-04-04 16:46:39 +020050static int ngroups;
Stanislav Kholmanskikh0f3ac8c2013-09-05 11:01:49 +040051static GID_T groups_list[NGROUPS];
52static GID_T groups[NGROUPS];
Cyril Hrubisc515be22013-04-04 16:46:39 +020053
54static void verify_groups(int ret_ngroups);
55static void setup(void);
56static void cleanup(void);
plars865695b2001-08-27 22:15:12 +000057
subrata_modak56207ce2009-03-23 13:35:39 +000058int main(int ac, char **av)
plars865695b2001-08-27 22:15:12 +000059{
Cyril Hrubis89af32a2012-10-24 16:39:11 +020060 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020061 const char *msg;
Cyril Hrubisc515be22013-04-04 16:46:39 +020062 int gidsetsize = NGROUPS;
subrata_modakbdbaec52009-02-26 12:14:51 +000063
Garrett Cooperebf7df22010-12-19 01:52:15 -080064 if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
plars865695b2001-08-27 22:15:12 +000065 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
Garrett Cooper2c282152010-12-16 00:55:50 -080066
plars865695b2001-08-27 22:15:12 +000067 setup();
68
plars865695b2001-08-27 22:15:12 +000069 for (lc = 0; TEST_LOOPING(lc); lc++) {
Garrett Cooper2c282152010-12-16 00:55:50 -080070
Caspar Zhangd59a6592013-03-07 14:59:12 +080071 tst_count = 0;
plars865695b2001-08-27 22:15:12 +000072
Stanislav Kholmanskikh0f3ac8c2013-09-05 11:01:49 +040073 TEST(GETGROUPS(cleanup, gidsetsize, groups_list));
subrata_modakbdbaec52009-02-26 12:14:51 +000074
Cyril Hrubisc515be22013-04-04 16:46:39 +020075 if (TEST_RETURN == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +080076 tst_resm(TFAIL | TTERRNO, "getgroups failed");
plars865695b2001-08-27 22:15:12 +000077 continue;
78 }
Cyril Hrubisc515be22013-04-04 16:46:39 +020079
Cyril Hrubise38b9612014-06-02 17:20:57 +020080 verify_groups(TEST_RETURN);
Garrett Cooper2c282152010-12-16 00:55:50 -080081 }
plars865695b2001-08-27 22:15:12 +000082
plars865695b2001-08-27 22:15:12 +000083 cleanup();
Garrett Cooper7d0a4a52010-12-16 10:05:08 -080084 tst_exit();
Garrett Cooper2c282152010-12-16 00:55:50 -080085}
plars865695b2001-08-27 22:15:12 +000086
plars865695b2001-08-27 22:15:12 +000087/*
Stanislav Kholmanskikh0f3ac8c2013-09-05 11:01:49 +040088 * readgroups(GID_T *) - Read supplimentary group ids of "root" user
plars865695b2001-08-27 22:15:12 +000089 * Scans the /etc/group file to get IDs of all the groups to which TESTUSER
90 * belongs and puts them into the array passed.
91 * Returns the no of gids read.
92 */
Stanislav Kholmanskikh0f3ac8c2013-09-05 11:01:49 +040093static int readgroups(GID_T groups[NGROUPS])
plars865695b2001-08-27 22:15:12 +000094{
Cyril Hrubisc515be22013-04-04 16:46:39 +020095 struct group *grp;
96 int ngrps = 0;
plars865695b2001-08-27 22:15:12 +000097 int i;
robbiewb1cae062003-04-29 14:20:11 +000098 int found;
Stanislav Kholmanskikh0f3ac8c2013-09-05 11:01:49 +040099 GID_T g;
subrata_modakbdbaec52009-02-26 12:14:51 +0000100
plars865695b2001-08-27 22:15:12 +0000101 setgrent();
102
plars74948ad2002-11-14 16:16:14 +0000103 while ((grp = getgrent()) != 0) {
plars865695b2001-08-27 22:15:12 +0000104 for (i = 0; grp->gr_mem[i]; i++) {
105 if (strcmp(grp->gr_mem[i], TESTUSER) == 0) {
106 groups[ngrps++] = grp->gr_gid;
107 }
108 }
109 }
110
robbiewb1cae062003-04-29 14:20:11 +0000111 /* The getgroups specification says:
112 It is unspecified whether the effective group ID of the
113 calling process is included in the returned list. (Thus,
114 an application should also call getegid(2) and add or
115 remove the resulting value.). So, add the value here if
116 it's not in. */
subrata_modak56207ce2009-03-23 13:35:39 +0000117
robbiewb1cae062003-04-29 14:20:11 +0000118 found = 0;
subrata_modak56207ce2009-03-23 13:35:39 +0000119 g = getegid();
robbiewb1cae062003-04-29 14:20:11 +0000120
121 for (i = 0; i < ngrps; i++) {
subrata_modak56207ce2009-03-23 13:35:39 +0000122 if (groups[i] == g)
123 found = 1;
robbiewb1cae062003-04-29 14:20:11 +0000124 }
125 if (found == 0)
subrata_modak56207ce2009-03-23 13:35:39 +0000126 groups[ngrps++] = g;
subrata_modakbdbaec52009-02-26 12:14:51 +0000127
plars865695b2001-08-27 22:15:12 +0000128 endgrent();
Cyril Hrubisc515be22013-04-04 16:46:39 +0200129 return ngrps;
130}
131
132static void setup(void)
133{
134 tst_require_root(NULL);
135
136 tst_sig(NOFORK, DEF_HANDLER, cleanup);
137
138 TEST_PAUSE;
139
140 /*
141 * Get the IDs of all the groups of "root"
142 * from /etc/group file
143 */
144 ngroups = readgroups(groups);
145
146 /* Setgroups is called by the login(1) process
147 * if the testcase is executed via an ssh session this
148 * testcase will fail. So execute setgroups() before executing
149 * getgroups()
150 */
Stanislav Kholmanskikh0f3ac8c2013-09-05 11:01:49 +0400151 if (SETGROUPS(cleanup, ngroups, groups) == -1)
Cyril Hrubisc515be22013-04-04 16:46:39 +0200152 tst_brkm(TBROK | TERRNO, cleanup, "setgroups failed");
plars865695b2001-08-27 22:15:12 +0000153}
154
155/*
156 * verify_groups(int) - Verify supplimentary group id values.
157 * This function verifies the gid values returned by getgroups() with
158 * the read values from /etc/group file.
159 * This function returns flag value which indicates success or failure
160 * of verification.
161 */
Cyril Hrubisc515be22013-04-04 16:46:39 +0200162static void verify_groups(int ret_ngroups)
plars865695b2001-08-27 22:15:12 +0000163{
Cyril Hrubisc515be22013-04-04 16:46:39 +0200164 int i, j;
Stanislav Kholmanskikh0f3ac8c2013-09-05 11:01:49 +0400165 GID_T egid;
Cyril Hrubisc515be22013-04-04 16:46:39 +0200166 int egid_flag = 1;
167 int fflag = 1;
plars865695b2001-08-27 22:15:12 +0000168
169 /*
subrata_modak4bb656a2009-02-26 12:02:09 +0000170 * Loop through the array to verify the gids
plars865695b2001-08-27 22:15:12 +0000171 * returned by getgroups().
172 * First, compare each element of the array
173 * returned by getgroups() with that read from
174 * group file.
175 */
Cyril Hrubisc515be22013-04-04 16:46:39 +0200176 for (i = 0; i < ret_ngroups; i++) {
plars865695b2001-08-27 22:15:12 +0000177 for (j = 0; j < ngroups; j++) {
178 if (groups_list[i] != groups[j]) {
179 /* If loop ends and gids are not matching */
180 if (j == ngroups - 1) {
Garrett Cooperebf7df22010-12-19 01:52:15 -0800181 tst_resm(TFAIL, "getgroups returned "
plars865695b2001-08-27 22:15:12 +0000182 "incorrect gid %d",
183 groups_list[i]);
184 fflag = 0;
185 } else {
186 continue;
187 }
Cyril Hrubisc515be22013-04-04 16:46:39 +0200188 } else {
plars865695b2001-08-27 22:15:12 +0000189 break;
190 }
191 }
192 }
193
194 /* Now do the reverse comparison */
Cyril Hrubisc515be22013-04-04 16:46:39 +0200195 egid = getegid();
plars865695b2001-08-27 22:15:12 +0000196 for (i = 0; i < ngroups; i++) {
Cyril Hrubisc515be22013-04-04 16:46:39 +0200197 for (j = 0; j < ret_ngroups; j++) {
plars865695b2001-08-27 22:15:12 +0000198 if (groups[i] != groups_list[j]) {
199 /*
200 * If the loop ends & gids are not matching
201 * if gid is not egid, exit with error
202 * else egid is returned by getgroups()
203 */
Cyril Hrubisc515be22013-04-04 16:46:39 +0200204 if (j == (ret_ngroups - 1)) {
plars865695b2001-08-27 22:15:12 +0000205 if (groups[i] != egid) {
Garrett Cooperebf7df22010-12-19 01:52:15 -0800206 tst_resm(TFAIL, "getgroups "
plars865695b2001-08-27 22:15:12 +0000207 "didn't return %d one "
208 "of the gids of %s",
209 groups[i], TESTUSER);
210 fflag = 0;
211 } else {
212 /*
213 * egid is not present in
214 * group_list.
215 * Reset the egid flag
216 */
Cyril Hrubisc515be22013-04-04 16:46:39 +0200217 egid_flag = 0;
plars865695b2001-08-27 22:15:12 +0000218 }
plars865695b2001-08-27 22:15:12 +0000219 }
Cyril Hrubisc515be22013-04-04 16:46:39 +0200220 } else {
plars865695b2001-08-27 22:15:12 +0000221 break;
222 }
223 }
224 }
225
226 /*
227 * getgroups() should return the no. of gids for TESTUSER with
228 * or without egid taken into account.
229 * Decrement ngroups, if egid is not returned by getgroups()
230 * Now, if ngroups matches ret_val, as above comparisons of the array
231 * are successful, this implies that the array contents match.
232 */
Cyril Hrubisc515be22013-04-04 16:46:39 +0200233 if (egid_flag == 0)
subrata_modak56207ce2009-03-23 13:35:39 +0000234 ngroups--;
Cyril Hrubisc515be22013-04-04 16:46:39 +0200235 if (ngroups != ret_ngroups) {
subrata_modak56207ce2009-03-23 13:35:39 +0000236 tst_resm(TFAIL,
Garrett Cooperebf7df22010-12-19 01:52:15 -0800237 "getgroups(2) returned incorrect no. of gids %d "
Cyril Hrubisc515be22013-04-04 16:46:39 +0200238 "(expected %d)", ret_ngroups, ngroups);
plars865695b2001-08-27 22:15:12 +0000239 fflag = 0;
240 }
241
Cyril Hrubisc515be22013-04-04 16:46:39 +0200242 if (fflag)
243 tst_resm(TPASS, "getgroups functionality correct");
plars865695b2001-08-27 22:15:12 +0000244}
subrata_modakbdbaec52009-02-26 12:14:51 +0000245
Cyril Hrubisc515be22013-04-04 16:46:39 +0200246static void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000247{
Chris Dearmanec6edca2012-10-17 19:54:01 -0700248}