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
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>)
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.
47 #include <stdio.h> /* needed by testhead.h */
48 #include <sys/types.h>
50 #include <sys/fcntl.h>
57 char *TCID
= "creat08";
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"
76 /*--------------------------------------------------------------*/
77 int main (int ac
, char **av
)
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
];
87 gid_t group1_gid
, group2_gid
, mygid
;
88 uid_t save_myuid
, user1_uid
;
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
);
104 tst_resm(TINFO
, "Must be root to run this test.");
108 for (lc
= 0; TEST_LOOPING(lc
); lc
++) {
112 save_myuid
= getuid();
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");
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");
140 group1_gid
= group
->gr_gid
;
141 if ((group
= getgrnam("bin")) == NULL
) {
142 tst_resm(TBROK
, "bin not in /etc/group");
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
);
159 if ((ret
= chown(DIR_A
, user1_uid
, group2_gid
)) < 0) {
160 tst_resm(TFAIL
, "Chown of %s failed", DIR_A
);
164 if ((ret
= stat(DIR_A
, &buf
)) < 0) {
165 tst_resm(TFAIL
, "Stat of %s failed", DIR_A
);
170 if (buf
.st_mode
& S_ISGID
) {
171 tst_resm(TFAIL
, "%s: Incorrect modes, setgid bit set", DIR_A
);
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
);
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
);
191 if ((ret
= chown(DIR_B
, user1_uid
, group2_gid
)) < 0) {
192 tst_resm(TFAIL
, "Chown of %s failed", DIR_B
);
196 if ((ret
= chmod(DIR_B
, MODE_SGID
)) < 0) {
197 tst_resm(TFAIL
, "Chmod of %s failed", DIR_B
);
201 if ((ret
= stat(DIR_B
, &buf
)) < 0) {
202 tst_resm(TFAIL
, "Stat of %s failed", DIR_B
);
207 if (!(buf
.st_mode
& S_ISGID
)) {
208 tst_resm(TFAIL
, "%s: Incorrect modes, setgid bit not set",
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
);
220 if (local_flag
== PASSED
) {
221 tst_resm(TPASS
, "Test passed in block0.");
223 tst_resm(TFAIL
, "Test failed in block0.");
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 */
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");
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
);
256 if ((ret
= stat(nosetgid_A
, &buf
)) < 0) {
257 tst_resm(TFAIL
, "Stat of %s failed", nosetgid_A
);
262 if (buf
.st_mode
& S_ISGID
) {
263 tst_resm(TFAIL
, "%s: Incorrect modes, setgid bit set", nosetgid_A
);
267 /* Verify group ID */
268 if (buf
.st_gid
!= mygid
) {
269 tst_resm(TFAIL
, "%s: Incorrect group", nosetgid_A
);
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
);
281 if ((ret
= stat(setgid_A
, &buf
)) < 0) {
282 tst_resm(TFAIL
, "Stat of %s failed", setgid_A
);
287 if (!(buf
.st_mode
& S_ISGID
)) {
288 tst_resm(TFAIL
, "%s: Incorrect modes, setgid bit not set",
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
);
299 if (local_flag
== PASSED
) {
300 tst_resm(TPASS
, "Test passed in block1.");
302 tst_resm(TFAIL
, "Test failed in block1.");
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
);
322 if ((ret
= stat(nosetgid_B
, &buf
)) < 0) {
323 tst_resm(TFAIL
, "Stat of %s failed", nosetgid_B
);
328 if (buf
.st_mode
& S_ISGID
) {
329 tst_resm(TFAIL
, "%s: Incorrect modes, setgid bit should not be set",
334 /* Verify group ID */
335 if (buf
.st_gid
!= group2_gid
) {
336 tst_resm(TFAIL
, "%s: Incorrect group", nosetgid_B
);
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
);
348 if ((ret
= stat(setgid_B
, &buf
)) < 0) {
349 tst_resm(TFAIL
, "Stat of %s failed", setgid_B
);
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
);
361 if ( !(buf
.st_mode
& S_ISGID
) ) {
362 tst_resm(TFAIL
, "%s: Incorrect modes, setgid bit should be set",
367 if (local_flag
== PASSED
) {
368 tst_resm(TPASS
, "Test passed in block2.");
370 tst_resm(TFAIL
, "Test failed in block2.");
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");
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
);
393 if ((ret
= stat(root_setgid_B
, &buf
)) < 0) {
394 tst_resm(TFAIL
, "Stat of %s failed", root_setgid_B
);
399 if (!(buf
.st_mode
& S_ISGID
)) {
400 tst_resm(TFAIL
, "%s: Incorrect modes, setgid bit not set",
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
);
412 if (local_flag
== PASSED
) {
413 tst_resm(TPASS
, "Test passed in block3.");
415 tst_resm(TFAIL
, "Test failed in block3.");
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.");
449 tst_resm(TFAIL
, "Test failed because of above failures.");
451 /*system("userdel,user1");
452 *system("groupdel,group1");
453 *system("groupdel,group2");
467 tst_resm(TINFO
,"geteuid: failed in issu()");
474 tst_resm(TINFO
,"*** NOT SUPERUSER must be root %s",TCID
);