• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  *   Copyright (c) International Business Machines  Corp., 2001
4  *
5  *   This program is free software;  you can redistribute it and/or modify
6  *   it under the terms of the GNU General Public License as published by
7  *   the Free Software Foundation; either version 2 of the License, or
8  *   (at your option) any later version.
9  *
10  *   This program is distributed in the hope that it will be useful,
11  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13  *   the GNU General Public License for more details.
14  *
15  *   You should have received a copy of the GNU General Public License
16  *   along with this program;  if not, write to the Free Software
17  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 /*
21  * Test Name: setgroups03
22  *
23  * Test Description:
24  *  Verify that,
25  *   1. setgroups() fails with -1 and sets errno to EINVAL if the size
26  *      argument value is > NGROUPS
27  *   2. setgroups() fails with -1 and sets errno to EPERM if the
28  *	calling process is not super-user.
29  *
30  * Expected Result:
31  *  setgroups() should fail with return value -1 and set expected errno.
32  *
33  * Algorithm:
34  *  Setup:
35  *   Setup signal handling.
36  *   Pause for SIGUSR1 if option specified.
37  *
38  *  Test:
39  *   Loop if the proper options are given.
40  *   Execute system call
41  *   Check return code, if system call failed (return=-1)
42  *   	if errno set == expected errno
43  *   		Issue sys call fails with expected return value and errno.
44  *   	Otherwise,
45  *		Issue sys call fails with unexpected errno.
46  *   Otherwise,
47  *	Issue sys call returns unexpected value.
48  *
49  *  Cleanup:
50  *   Print errno log and/or timing stats if options given
51  *
52  * Usage:  <for command-line>
53  *  setgroups03 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
54  *     where,  -c n : Run n copies concurrently.
55  *             -f   : Turn off functionality Testing.
56  *	       -i n : Execute test n times.
57  *	       -I x : Execute test for x seconds.
58  *	       -P x : Pause for x seconds between iterations.
59  *	       -t   : Turn on syscall timing.
60  *
61  * HISTORY
62  *	07/2001 Ported by Wayne Boyer
63  *
64  * RESTRICTIONS:
65  *  This test should be executed by 'non-super-user' only.
66  *
67  */
68 #include <limits.h>
69 #include <sys/types.h>
70 #include <unistd.h>
71 #include <errno.h>
72 #include <pwd.h>
73 #include <grp.h>
74 
75 #include "test.h"
76 
77 #include "compat_16.h"
78 
79 #define TESTUSER	"nobody"
80 
81 char nobody_uid[] = "nobody";
82 struct passwd *ltpuser;
83 
84 TCID_DEFINE(setgroups03);
85 int TST_TOTAL = 2;
86 
87 GID_T *groups_list;		/* Array to hold gids for getgroups() */
88 
89 int setup1();			/* setup function to test error EPERM */
90 void setup();			/* setup function for the test */
91 void cleanup();			/* cleanup function for the test */
92 
93 struct test_case_t {		/* test case struct. to hold ref. test cond's */
94 	size_t gsize_add;
95 	int list;
96 	char *desc;
97 	int exp_errno;
98 	int (*setupfunc) ();
99 } Test_cases[] = {
100 	{
101 	1, 1, "Size is > sysconf(_SC_NGROUPS_MAX)", EINVAL, NULL}, {
102 	0, 2, "Permission denied, not super-user", EPERM, setup1}
103 };
104 
main(int ac,char ** av)105 int main(int ac, char **av)
106 {
107 	int lc;
108 	int gidsetsize;		/* total no. of groups */
109 	int i;
110 	char *test_desc;	/* test specific error message */
111 	int ngroups_max = sysconf(_SC_NGROUPS_MAX);	/* max no. of groups in the current system */
112 
113 	tst_parse_opts(ac, av, NULL, NULL);
114 
115 	groups_list = malloc(ngroups_max * sizeof(GID_T));
116 	if (groups_list == NULL) {
117 		tst_brkm(TBROK, NULL, "malloc failed to alloc %zu errno "
118 			 " %d ", ngroups_max * sizeof(GID_T), errno);
119 	}
120 
121 	setup();
122 
123 	for (lc = 0; TEST_LOOPING(lc); lc++) {
124 
125 		tst_count = 0;
126 
127 		for (i = 0; i < TST_TOTAL; i++) {
128 			if (Test_cases[i].setupfunc != NULL) {
129 				Test_cases[i].setupfunc();
130 			}
131 
132 			gidsetsize = ngroups_max + Test_cases[i].gsize_add;
133 			test_desc = Test_cases[i].desc;
134 
135 			/*
136 			 * Call setgroups() to test different test conditions
137 			 * verify that it fails with -1 return value and
138 			 * sets appropriate errno.
139 			 */
140 			TEST(SETGROUPS(cleanup, gidsetsize, groups_list));
141 
142 			if (TEST_RETURN != -1) {
143 				tst_resm(TFAIL, "setgroups(%d) returned %ld, "
144 					 "expected -1, errno=%d", gidsetsize,
145 					 TEST_RETURN, Test_cases[i].exp_errno);
146 				continue;
147 			}
148 
149 			if (TEST_ERRNO == Test_cases[i].exp_errno) {
150 				tst_resm(TPASS,
151 					 "setgroups(%d) fails, %s, errno=%d",
152 					 gidsetsize, test_desc, TEST_ERRNO);
153 			} else {
154 				tst_resm(TFAIL, "setgroups(%d) fails, %s, "
155 					 "errno=%d, expected errno=%d",
156 					 gidsetsize, test_desc, TEST_ERRNO,
157 					 Test_cases[i].exp_errno);
158 			}
159 		}
160 
161 	}
162 
163 	cleanup();
164 
165 	tst_exit();
166 }
167 
168 /*
169  * setup() - performs all ONE TIME setup for this test.
170  *
171  *  Call individual test specific setup functions.
172  */
setup(void)173 void setup(void)
174 {
175 	tst_require_root();
176 
177 	tst_sig(NOFORK, DEF_HANDLER, cleanup);
178 
179 	TEST_PAUSE;
180 
181 }
182 
183 /*
184  * setup1 -  Setup function to test setgroups() which returns -1
185  *	     and sets errno to EPERM.
186  *
187  *  Get the user info. from /etc/passwd file.
188  *  This function returns 0 on success.
189  */
setup1(void)190 int setup1(void)
191 {
192 	struct passwd *user_info;	/* struct. to hold test user info */
193 
194 /* Switch to nobody user for correct error code collection */
195 	ltpuser = getpwnam(nobody_uid);
196 	if (seteuid(ltpuser->pw_uid) == -1) {
197 		tst_resm(TINFO, "setreuid failed to "
198 			 "to set the effective uid to %d", ltpuser->pw_uid);
199 		perror("setreuid");
200 	}
201 
202 	if ((user_info = getpwnam(TESTUSER)) == NULL) {
203 		tst_brkm(TFAIL, cleanup, "getpwnam(2) of %s Failed", TESTUSER);
204 	}
205 
206 	if (!GID_SIZE_CHECK(user_info->pw_gid)) {
207 		tst_brkm(TBROK,
208 			 cleanup,
209 			 "gid returned from getpwnam is too large for testing setgroups16");
210 	}
211 	groups_list[0] = user_info->pw_gid;
212 	return 0;
213 }
214 
215 /*
216  * cleanup() - performs all ONE TIME cleanup for this test at
217  *             completion or premature exit.
218  */
cleanup(void)219 void cleanup(void)
220 {
221 
222 }
223