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