Imported Upstream version 20080930
[ltp-debian.git] / testcases / kernel / syscalls / creat / creat08.c
blob02e60961797e3d5440dad881c046a4b14584f411
1 /*
3 * Copyright (c) International Business Machines Corp., 2002
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * NAME
22 * creat08.c - Verifies that the group ID and setgid bit are
23 * set correctly when a new file is created.
24 * (ported from SPIE, section2/iosuite/creat5.c,
25 * by Airong Zhang <zhanga@us.ibm.com>)
26 * CALLS
27 * creat
29 * ALGORITHM
30 * Create two directories, one with the group ID of this process
31 * and the setgid bit not set, and the other with a group ID
32 * other than that of this process and with the setgid bit set.
33 * In each directory, create a file with and without the setgid
34 * bit set in the creation modes. Verify that the modes and group
35 * ID are correct on each of the 4 files.
36 * As root, create a file with the setgid bit on in the
37 * directory with the setgid bit.
38 * This tests the SVID3 create group semantics.
40 * USAGE
41 * creat08
43 * RESTRICTIONS
47 #include <stdio.h> /* needed by testhead.h */
48 #include <sys/types.h>
49 #include <sys/stat.h>
50 #include <sys/fcntl.h>
51 #include <errno.h>
52 #include <grp.h>
53 #include <pwd.h>
54 #include "test.h"
55 #include "usctest.h"
57 char *TCID = "creat08";
58 int TST_TOTAL = 1;
59 extern int Tst_count;
60 int local_flag;
62 #define PASSED 1
63 #define FAILED 0
65 #define MODE_RWX S_IRWXU | S_IRWXG | S_IRWXO
66 #define MODE_SGID S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO
67 #define DIR_A_TEMP "testdir.A.%d"
68 #define DIR_B_TEMP "testdir.B.%d"
69 #define SETGID "setgid"
70 #define NOSETGID "nosetgid"
71 #define ROOT_SETGID "root_setgid"
72 #define MSGSIZE 150
74 int issu();
76 /*--------------------------------------------------------------*/
77 int main (int ac, char **av)
79 int ret;
80 struct stat buf;
81 struct group *group;
82 struct passwd *user1;
83 char DIR_A[MSGSIZE], DIR_B[MSGSIZE];
84 char setgid_A[MSGSIZE], nosetgid_A[MSGSIZE];
85 char setgid_B[MSGSIZE], nosetgid_B[MSGSIZE], root_setgid_B[MSGSIZE];
86 int fail_count = 0;
87 gid_t group1_gid, group2_gid, mygid;
88 uid_t save_myuid, user1_uid;
89 pid_t mypid;
91 int lc; /* loop counter */
92 char *msg; /* message returned from parse_opts */
95 * parse standard options
97 if ((msg = parse_opts(ac, av, (option_t *)NULL, NULL)) != (char *)NULL){
98 tst_resm(TBROK, "OPTION PARSING ERROR - %s", msg);
99 tst_exit();
100 /*NOTREACHED*/
103 if (issu() != 0) {
104 tst_resm(TINFO, "Must be root to run this test.");
105 tst_exit();
108 for (lc = 0; TEST_LOOPING(lc); lc++) {
110 local_flag = PASSED;
112 save_myuid = getuid();
113 mypid = getpid();
114 sprintf(DIR_A, DIR_A_TEMP, mypid);
115 sprintf(DIR_B, DIR_B_TEMP, mypid);
116 sprintf(setgid_A, "%s/%s", DIR_A, SETGID);
117 sprintf(nosetgid_A, "%s/%s", DIR_A, NOSETGID);
118 sprintf(setgid_B, "%s/%s", DIR_B, SETGID);
119 sprintf(nosetgid_B, "%s/%s", DIR_B, NOSETGID);
120 sprintf(root_setgid_B, "%s/%s", DIR_B, ROOT_SETGID);
122 /* Get the uid of user1 */
123 if ((user1 = getpwnam("nobody")) == NULL) {
124 tst_resm(TBROK, "nobody not in /etc/passwd");
125 tst_exit();
128 user1_uid = user1->pw_uid;
131 * Get the group IDs of group1 and group2.
133 if ((group = getgrnam("nobody")) == NULL) {
134 if ((group = getgrnam("nogroup")) == NULL)
136 tst_resm(TBROK, "nobody/nogroup not in /etc/group");
137 tst_exit();
140 group1_gid = group->gr_gid;
141 if ((group = getgrnam("bin")) == NULL) {
142 tst_resm(TBROK, "bin not in /etc/group");
143 tst_exit();
145 group2_gid = group->gr_gid;
147 /*--------------------------------------------------------------*/
148 /* Block0: Set up the parent directories */
149 /*--------------------------------------------------------------*/
151 * Create a directory with group id the same as this process
152 * and with no setgid bit.
154 if ((ret = mkdir(DIR_A, MODE_RWX)) < 0) {
155 tst_resm(TFAIL, "Creation of %s failed", DIR_A);
156 local_flag = FAILED;
159 if ((ret = chown(DIR_A, user1_uid, group2_gid)) < 0) {
160 tst_resm(TFAIL, "Chown of %s failed", DIR_A);
161 local_flag = FAILED;
164 if ((ret = stat(DIR_A, &buf)) < 0) {
165 tst_resm(TFAIL, "Stat of %s failed", DIR_A);
166 local_flag = FAILED;
169 /* Verify modes */
170 if (buf.st_mode & S_ISGID) {
171 tst_resm(TFAIL, "%s: Incorrect modes, setgid bit set", DIR_A);
172 local_flag = FAILED;
175 /* Verify group ID */
176 if (buf.st_gid != group2_gid) {
177 tst_resm(TFAIL, "%s: Incorrect group", DIR_A);
178 tst_resm(TINFO,"got %ld and %ld", buf.st_gid, group2_gid);
179 local_flag = FAILED;
183 * Create a directory with group id different from that of
184 * this process and with the setgid bit set.
186 if ((ret = mkdir(DIR_B, MODE_RWX)) < 0) {
187 tst_resm(TFAIL, "Creation of %s failed", DIR_B);
188 local_flag = FAILED;
191 if ((ret = chown(DIR_B, user1_uid, group2_gid)) < 0) {
192 tst_resm(TFAIL, "Chown of %s failed", DIR_B);
193 local_flag = FAILED;
196 if ((ret = chmod(DIR_B, MODE_SGID)) < 0) {
197 tst_resm(TFAIL, "Chmod of %s failed", DIR_B);
198 local_flag = FAILED;
201 if ((ret = stat(DIR_B, &buf)) < 0) {
202 tst_resm(TFAIL, "Stat of %s failed", DIR_B);
203 local_flag = FAILED;
206 /* Verify modes */
207 if (!(buf.st_mode & S_ISGID)) {
208 tst_resm(TFAIL, "%s: Incorrect modes, setgid bit not set",
209 DIR_B);
210 local_flag = FAILED;
213 /* Verify group ID */
214 if (buf.st_gid != group2_gid) {
215 tst_resm(TFAIL, "%s: Incorrect group", DIR_B);
216 tst_resm(TINFO,"got %ld and %ld",buf.st_gid, group2_gid);
217 local_flag = FAILED;
220 if (local_flag == PASSED) {
221 tst_resm(TPASS, "Test passed in block0.");
222 } else {
223 tst_resm(TFAIL, "Test failed in block0.");
224 fail_count++;
227 local_flag = PASSED;
229 /*--------------------------------------------------------------*/
230 /* Block1: Create two files in testdir.A, one with the setgid */
231 /* bit set in the creation modes and the other without. */
232 /* Both should inherit the group ID of the process and */
233 /* maintain the setgid bit as specified in the creation */
234 /* modes. */
235 /*--------------------------------------------------------------*/
237 * Now become user1, group1
239 if ((ret = setgid(group1_gid)) < 0) {
240 tst_resm(TINFO,"Unable to set process group ID to group1");
243 if ((ret = setreuid(-1, user1_uid)) < 0) {
244 tst_resm(TINFO, "Unable to set process uid to user1");
246 mygid = getgid();
249 * Create the file with setgid not set
251 if ((ret = open(nosetgid_A, O_CREAT|O_EXCL|O_RDWR, MODE_RWX)) < 0) {
252 tst_resm(TFAIL, "Creation of %s failed", nosetgid_A);
253 local_flag = FAILED;
256 if ((ret = stat(nosetgid_A, &buf)) < 0) {
257 tst_resm(TFAIL, "Stat of %s failed", nosetgid_A);
258 local_flag = FAILED;
261 /* Verify modes */
262 if (buf.st_mode & S_ISGID) {
263 tst_resm(TFAIL, "%s: Incorrect modes, setgid bit set", nosetgid_A);
264 local_flag = FAILED;
267 /* Verify group ID */
268 if (buf.st_gid != mygid) {
269 tst_resm(TFAIL, "%s: Incorrect group", nosetgid_A);
270 local_flag = FAILED;
274 * Create the file with setgid set
276 if ((ret = open(setgid_A, O_CREAT|O_EXCL|O_RDWR, MODE_SGID)) < 0) {
277 tst_resm(TFAIL, "Creation of %s failed", setgid_A);
278 local_flag = FAILED;
281 if ((ret = stat(setgid_A, &buf)) < 0) {
282 tst_resm(TFAIL, "Stat of %s failed", setgid_A);
283 local_flag = FAILED;
286 /* Verify modes */
287 if (!(buf.st_mode & S_ISGID)) {
288 tst_resm(TFAIL, "%s: Incorrect modes, setgid bit not set",
289 setgid_A);
290 local_flag = FAILED;
293 /* Verify group ID */
294 if (buf.st_gid != mygid) {
295 tst_resm(TFAIL, "%s: Incorrect group", setgid_A);
296 tst_resm(TINFO,"got %ld and %ld",buf.st_gid, mygid);
297 local_flag = FAILED;
299 if (local_flag == PASSED) {
300 tst_resm(TPASS, "Test passed in block1.");
301 } else {
302 tst_resm(TFAIL, "Test failed in block1.");
303 fail_count++;
306 local_flag = PASSED;
308 /*--------------------------------------------------------------*/
309 /* Block2: Create two files in testdir.B, one with the setgid */
310 /* bit set in the creation modes and the other without. */
311 /* Both should inherit the group ID of the parent */
312 /* directory, group2. */
313 /*--------------------------------------------------------------*/
315 * Create the file with setgid not set
317 if ((ret = creat(nosetgid_B, MODE_RWX)) < 0) {
318 tst_resm(TFAIL, "Creation of %s failed", nosetgid_B);
319 local_flag = FAILED;
322 if ((ret = stat(nosetgid_B, &buf)) < 0) {
323 tst_resm(TFAIL, "Stat of %s failed", nosetgid_B);
324 local_flag = FAILED;
327 /* Verify modes */
328 if (buf.st_mode & S_ISGID) {
329 tst_resm(TFAIL, "%s: Incorrect modes, setgid bit should not be set",
330 nosetgid_B);
331 local_flag = FAILED;
334 /* Verify group ID */
335 if (buf.st_gid != group2_gid) {
336 tst_resm(TFAIL, "%s: Incorrect group", nosetgid_B);
337 local_flag = FAILED;
341 * Create the file with setgid set
343 if ((ret = creat(setgid_B, MODE_SGID)) < 0) {
344 tst_resm(TFAIL, "Creation of %s failed", setgid_B);
345 local_flag = FAILED;
348 if ((ret = stat(setgid_B, &buf)) < 0) {
349 tst_resm(TFAIL, "Stat of %s failed", setgid_B);
350 local_flag = FAILED;
353 /* Verify group ID */
354 if (buf.st_gid != group2_gid) {
355 tst_resm(TFAIL, "%s: Incorrect group", setgid_B);
356 tst_resm(TFAIL,"got %ld and %ld",buf.st_gid, group2_gid);
357 local_flag = FAILED;
360 /* Verify modes */
361 if ( !(buf.st_mode & S_ISGID) ) {
362 tst_resm(TFAIL, "%s: Incorrect modes, setgid bit should be set",
363 setgid_B);
364 local_flag = FAILED;
367 if (local_flag == PASSED) {
368 tst_resm(TPASS, "Test passed in block2.");
369 } else {
370 tst_resm(TFAIL, "Test failed in block2.");
371 fail_count++;
374 local_flag = PASSED;
375 /*--------------------------------------------------------------*/
376 /* Block3: Create a file in testdir.B, with the setgid bit set */
377 /* in the creation modes and do so as root. The file */
378 /* should inherit the group ID of the parent directory, */
379 /* group2 and should have the setgid bit set. */
380 /*--------------------------------------------------------------*/
381 /* Become root again */
382 if ((ret = setreuid(-1, save_myuid)) < 0) {
383 tst_resm(errno, 0, "Changing back to root failed");
384 local_flag = FAILED;
387 /* Create the file with setgid set */
388 if ((ret = creat(root_setgid_B, MODE_SGID)) < 0) {
389 tst_resm(TFAIL, "Creation of %s failed", root_setgid_B);
390 local_flag = FAILED;
393 if ((ret = stat(root_setgid_B, &buf)) < 0) {
394 tst_resm(TFAIL, "Stat of %s failed", root_setgid_B);
395 local_flag = FAILED;
398 /* Verify modes */
399 if (!(buf.st_mode & S_ISGID)) {
400 tst_resm(TFAIL, "%s: Incorrect modes, setgid bit not set",
401 root_setgid_B);
402 local_flag = FAILED;
405 /* Verify group ID */
406 if (buf.st_gid != group2_gid) {
407 tst_resm(TFAIL, "%s: Incorrect group", root_setgid_B);
408 tst_resm(TINFO,"got %ld and %ld",buf.st_gid, group2_gid);
409 local_flag = FAILED;
412 if (local_flag == PASSED) {
413 tst_resm(TPASS, "Test passed in block3.");
414 } else {
415 tst_resm(TFAIL, "Test failed in block3.");
416 fail_count++;
419 /*--------------------------------------------------------------
420 * Clean up any files created by test before call to anyfail.
421 * Remove the directories.
422 *--------------------------------------------------------------*/
423 if ((ret = unlink(setgid_A)) < 0) {
424 tst_resm(TBROK, "Warning: %s not removed", setgid_A);
426 if ((ret = unlink(nosetgid_A)) < 0) {
427 tst_resm(TBROK, "Warning: %s not removed", nosetgid_A);
429 if ((ret = rmdir(DIR_A)) < 0) {
430 tst_resm(TBROK, "Warning: %s not removed", DIR_A);
433 if ((ret = unlink(setgid_B)) < 0) {
434 tst_resm(TBROK, "Warning: %s not removed", setgid_B);
436 if ((ret = unlink(root_setgid_B)) < 0) {
437 tst_resm(TBROK, "Warning: %s not removed", root_setgid_B);
439 if ((ret = unlink(nosetgid_B)) < 0) {
440 tst_resm(TBROK, "Warning: %s not removed", nosetgid_B);
442 if ((ret = rmdir(DIR_B)) < 0) {
443 tst_resm(TBROK, "Warning: %s not removed", DIR_B);
446 if (fail_count == 0 ) {
447 tst_resm(TPASS, "Test passed.");
448 } else {
449 tst_resm(TFAIL, "Test failed because of above failures.");
451 /*system("userdel,user1");
452 *system("groupdel,group1");
453 *system("groupdel,group2");
455 } /* end for */
456 return(0);
459 int issu() {
461 int uid;
463 uid = (-1);
464 uid = geteuid();
466 if (uid == (-1)) {
467 tst_resm(TINFO,"geteuid: failed in issu()");
468 return(-1);
471 if ( uid == 0) {
472 return(0);
473 } else {
474 tst_resm(TINFO,"*** NOT SUPERUSER must be root %s",TCID);
475 return(uid);
477 return(0);