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 * open10.c - Verifies that the group ID and setgid bit are
23 * set correctly when a new file is created using open.
24 * (ported from SPIE, section2/iosuite/open5.c, by
31 * Create two directories, one with the group ID of this process
32 * and the setgid bit not set, and the other with a group ID
33 * other than that of this process and with the setgid bit set.
34 * In each directory, create a file with and without the setgid
35 * bit set in the creation modes. Verify that the modes and group
36 * ID are correct on each of the 4 files.
37 * As root, create a file with the setgid bit on in the
38 * directory with the setgid bit.
39 * This tests the SVID3 create group semantics.
48 #include <stdio.h> /* needed by testhead.h */
49 #include <sys/types.h>
51 #include <sys/fcntl.h>
58 char *TCID
= "open10";
68 #define MODE_RWX S_IRWXU | S_IRWXG | S_IRWXO
69 #define MODE_SGID S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO
70 #define DIR_A_TEMP "open10.testdir.A.%d"
71 #define DIR_B_TEMP "open10.testdir.B.%d"
72 #define SETGID "setgid"
73 #define NOSETGID "nosetgid"
74 #define ROOT_SETGID "root_setgid"
78 char progname
[]= "open10()";
89 fprintf(stderr
,"geteuid: failed in issu()");
96 fprintf(stderr
,"*** NOT SUPERUSER must be root %s\n",progname
);
102 /*--------------------------------------------------------------*/
103 int main (int ac
, char *av
[])
108 struct passwd
*user1
;
109 char DIR_A
[MSGSIZE
], DIR_B
[MSGSIZE
];
110 char setgid_A
[MSGSIZE
], nosetgid_A
[MSGSIZE
];
111 char setgid_B
[MSGSIZE
], nosetgid_B
[MSGSIZE
], root_setgid_B
[MSGSIZE
];
112 gid_t group1_gid
, group2_gid
, mygid
;
113 uid_t save_myuid
, user1_uid
;
117 int lc
; /* loop counter */
118 char *msg
; /* message returned from parse_opts */
122 * parse standard options
124 if ((msg
= parse_opts(ac
, av
, (option_t
*)NULL
, NULL
)) != (char *)NULL
){
125 tst_resm(TBROK
, "OPTION PARSING ERROR - %s", msg
);
132 tst_resm(TINFO
, "Must be root to run this test.");
135 for (lc
= 0; TEST_LOOPING(lc
); lc
++) {
139 save_myuid
= getuid();
141 sprintf(DIR_A
, DIR_A_TEMP
, mypid
);
142 sprintf(DIR_B
, DIR_B_TEMP
, mypid
);
143 sprintf(setgid_A
, "%s/%s", DIR_A
, SETGID
);
144 sprintf(nosetgid_A
, "%s/%s", DIR_A
, NOSETGID
);
145 sprintf(setgid_B
, "%s/%s", DIR_B
, SETGID
);
146 sprintf(nosetgid_B
, "%s/%s", DIR_B
, NOSETGID
);
147 sprintf(root_setgid_B
, "%s/%s", DIR_B
, ROOT_SETGID
);
149 /* Get the uid of user1 */
150 if ((user1
= getpwnam("nobody")) == NULL
) {
151 tst_resm(TBROK
, "nobody not in /etc/passwd");
154 user1_uid
= user1
->pw_uid
;
157 * Get the group IDs of group1 and group2.
159 if ((group
= getgrnam("nobody")) == NULL
) {
160 if ((group
= getgrnam("nogroup")) == NULL
) {
161 tst_resm(TBROK
, "nobody/nogroup not in /etc/group");
165 group1_gid
= group
->gr_gid
;
166 if ((group
= getgrnam("bin")) == NULL
) {
167 tst_resm(TBROK
, "bin not in /etc/group");
169 group2_gid
= group
->gr_gid
;
171 /*--------------------------------------------------------------*/
172 /* Block0: Set up the parent directories */
173 /*--------------------------------------------------------------*/
177 * Create a directory with group id the same as this process
178 * and with no setgid bit.
180 if ((ret
= mkdir(DIR_A
, MODE_RWX
)) < 0) {
181 tst_resm(TFAIL
, "Creation dir of %s failed", DIR_A
);
185 if ((ret
= chown(DIR_A
, user1_uid
, group2_gid
)) < 0) {
186 tst_resm(TFAIL
, "Chown of %d failed",DIR_A
);
190 if ((ret
= stat(DIR_A
, &buf
)) < 0) {
191 tst_resm(TFAIL
,"Stat of %s failed",DIR_A
);
196 if (buf
.st_mode
& S_ISGID
) {
197 tst_resm(TFAIL
, "%s: Incorrect modes, setgid bit set",
202 /* Verify group ID */
203 if (buf
.st_gid
!= group2_gid
) {
204 tst_resm(TFAIL
, "%s: Incorrect group", DIR_A
);
205 tst_resm(TINFO
,"got %ld and %ld",buf
.st_gid
, group2_gid
);
210 * Create a directory with group id different from that of
211 * this process and with the setgid bit set.
213 if ((ret
= mkdir(DIR_B
, MODE_RWX
)) < 0) {
214 tst_resm(TFAIL
, "Creation of %s failed", DIR_B
);
218 if ((ret
= chown(DIR_B
, user1_uid
, group2_gid
)) < 0) {
219 tst_resm(TFAIL
, "Chown of %s failed", DIR_B
);
223 if ((ret
= chmod(DIR_B
, MODE_SGID
)) < 0) {
224 tst_resm(TFAIL
, "Chmod of %s failed", DIR_B
);
228 if ((ret
= stat(DIR_B
, &buf
)) < 0) {
229 tst_resm(TFAIL
, "Stat of %s failed", DIR_B
);
234 if (!(buf
.st_mode
& S_ISGID
)) {
235 tst_resm(TFAIL
, "%s: Incorrect modes, setgid bit not set",
240 /* Verify group ID */
241 if (buf
.st_gid
!= group2_gid
) {
242 tst_resm(TFAIL
, "%s: Incorrect group", DIR_B
);
243 tst_resm(TINFO
, "got %ld and %ld",buf
.st_gid
, group2_gid
);
247 if (local_flag
== PASSED
) {
248 tst_resm(TPASS
, "Test passed in block0.");
250 tst_resm(TFAIL
, "Test failed in block0.");
256 /*--------------------------------------------------------------*/
257 /* Block1: Create two files in testdir.A, one with the setgid */
258 /* bit set in the creation modes and the other without. */
259 /* Both should inherit the group ID of the process and */
260 /* maintain the setgid bit as specified in the creation */
262 /*--------------------------------------------------------------*/
266 * Now become user1, group1
268 if ((ret
= setgid(group1_gid
)) < 0) {
269 tst_resm(TINFO
, 0, "Unable to set process group ID to group1");
272 if ((ret
= setreuid(-1, user1_uid
)) < 0) {
273 tst_resm(TINFO
, 0, "Unable to set process uid to user1");
278 * Create the file with setgid not set
280 if ((ret
= open(nosetgid_A
, O_CREAT
|O_EXCL
|O_RDWR
, MODE_RWX
)) < 0) {
281 tst_resm(TFAIL
, "Creation of %s failed", nosetgid_A
);
285 if ((ret
= stat(nosetgid_A
, &buf
)) < 0) {
286 tst_resm(TFAIL
, "Stat of %s failed", nosetgid_A
);
291 if (buf
.st_mode
& S_ISGID
) {
292 tst_resm(TFAIL
, "%s: Incorrect modes, setgid bit set", nosetgid_A
);
296 /* Verify group ID */
297 if (buf
.st_gid
!= mygid
) {
298 tst_resm(TFAIL
, "%s: Incorrect group", nosetgid_A
);
299 tst_resm(TINFO
, "got %ld and %ld",buf
.st_gid
, mygid
);
304 * Create the file with setgid set
306 if ((ret
= open(setgid_A
, O_CREAT
|O_EXCL
|O_RDWR
, MODE_SGID
)) < 0) {
307 tst_resm(TFAIL
, "Creation of %s failed", setgid_A
);
311 if ((ret
= stat(setgid_A
, &buf
)) < 0) {
312 tst_resm(TFAIL
, "Stat of %s failed", setgid_A
);
317 if (!(buf
.st_mode
& S_ISGID
)) {
318 tst_resm(TFAIL
, "%s: Incorrect modes, setgid bit not set",
323 /* Verify group ID */
324 if (buf
.st_gid
!= mygid
) {
325 tst_resm(TFAIL
, "%s: Incorrect group", setgid_A
);
326 tst_resm(TINFO
, "got %ld and %ld",buf
.st_gid
, mygid
);
330 if (local_flag
== PASSED
) {
331 tst_resm(TPASS
, "Test passed in block1.");
333 tst_resm(TFAIL
, "Test failed in block1.");
339 /*--------------------------------------------------------------*/
340 /* Block2: Create two files in testdir.B, one with the setgid */
341 /* bit set in the creation modes and the other without. */
342 /* Both should inherit the group ID of the parent */
343 /* directory, group2. Either file should have the segid */
344 /* bit set in the modes. */
345 /*--------------------------------------------------------------*/
349 * Create the file with setgid not set
351 if ((ret
= open(nosetgid_B
, O_CREAT
|O_EXCL
|O_RDWR
, MODE_RWX
)) < 0) {
352 tst_resm(TFAIL
, "Creation of %s failed", nosetgid_B
);
356 if ((ret
= stat(nosetgid_B
, &buf
)) < 0) {
357 tst_resm(TFAIL
, "Stat of %s failed", nosetgid_B
);
362 if (buf
.st_mode
& S_ISGID
) {
363 tst_resm(TFAIL
, "%s: Incorrect modes, setgid bit should be set",
368 /* Verify group ID */
369 if (buf
.st_gid
!= group2_gid
) {
370 tst_resm(TFAIL
, "%s: Incorrect group", nosetgid_B
);
371 tst_resm(TINFO
, "got %ld and %ld",buf
.st_gid
, group2_gid
);
376 * Create the file with setgid set
378 if ((ret
= open(setgid_B
, O_CREAT
|O_EXCL
|O_RDWR
, MODE_SGID
)) < 0) {
379 tst_resm(TFAIL
, "Creation of %s failed", setgid_B
);
383 if ((ret
= stat(setgid_B
, &buf
)) < 0) {
384 tst_resm(TFAIL
, "Stat of %s failed", setgid_B
);
388 /* Verify group ID */
389 if (buf
.st_gid
!= group2_gid
) {
390 tst_resm(TFAIL
, "%s: Incorrect group", setgid_B
);
391 tst_resm(TINFO
,"got %ld and %ld",buf
.st_gid
, group2_gid
);
396 if (!(buf
.st_mode
& S_ISGID
)) {
397 tst_resm(TFAIL
, "%s: Incorrect modes, setgid bit not set",
402 if (local_flag
== PASSED
) {
403 tst_resm(TPASS
, "Test passed in block2.");
405 tst_resm(TFAIL
, "Test failed in block2.");
411 /*--------------------------------------------------------------*/
412 /* Block3: Create a file in testdir.B, with the setgid bit set */
413 /* in the creation modes and do so as root. The file */
414 /* should inherit the group ID of the parent directory, */
415 /* group2 and should have the setgid bit set. */
416 /*--------------------------------------------------------------*/
419 /* Become root again */
420 if ((ret
= setreuid(-1, save_myuid
)) < 0) {
421 tst_resm(TFAIL
, 0, "Changing back to root failed");
425 /* Create the file with setgid set */
426 if ((ret
= open(root_setgid_B
, O_CREAT
|O_EXCL
|O_RDWR
,
428 tst_resm(TFAIL
, "Creation of %s failed", root_setgid_B
);
432 if ((ret
= stat(root_setgid_B
, &buf
)) < 0) {
433 tst_resm(TFAIL
, "Stat of %s failed", root_setgid_B
);
438 if (!(buf
.st_mode
& S_ISGID
)) {
439 tst_resm(TFAIL
, "%s: Incorrect modes, setgid bit not set",
444 /* Verify group ID */
445 if (buf
.st_gid
!= group2_gid
) {
446 tst_resm(TFAIL
, "%s: Incorrect group", root_setgid_B
);
447 tst_resm(TINFO
, "got %ld and %ld",buf
.st_gid
, group2_gid
);
451 if (local_flag
== PASSED
) {
452 tst_resm(TPASS
, "Test passed in block3.");
454 tst_resm(TFAIL
, "Test failed in block3.");
459 /*--------------------------------------------------------------*/
460 /* Clean up any files created by test before call to anyfail. */
461 /* Remove the directories. */
462 /*--------------------------------------------------------------*/
463 if ((ret
= unlink(setgid_A
)) < 0) {
464 tst_resm(TINFO
, "Warning: %s not removed", setgid_A
);
466 if ((ret
= unlink(nosetgid_A
)) < 0) {
467 tst_resm(TINFO
, "Warning: %s not removed", nosetgid_A
);
469 if ((ret
= rmdir(DIR_A
)) < 0) {
470 tst_resm(TINFO
, "Warning: %s not removed", DIR_A
);
473 if ((ret
= unlink(setgid_B
)) < 0) {
474 tst_resm(TINFO
, "Warning: %s not removed", setgid_B
);
476 if ((ret
= unlink(root_setgid_B
)) < 0) {
477 tst_resm(TINFO
, "Warning: %s not removed", root_setgid_B
);
479 if ((ret
= unlink(nosetgid_B
)) < 0) {
480 tst_resm(TINFO
, "Warning: %s not removed", nosetgid_B
);
482 if ((ret
= rmdir(DIR_B
)) < 0) {
483 tst_resm(TINFO
, "Warning: %s not removed", DIR_B
);
484 printf("errno is %d\n", errno
);
486 if (fail_count
== 0 ) {
487 tst_resm(TPASS
, "Test passed.");
489 tst_resm(TFAIL
, "Test failed because of above failures.");