Imported Upstream version 20080930
[ltp-debian.git] / testcases / kernel / syscalls / open / open10.c
blobb88f63ba2de7f5b13f78fcc50e4be81f91b38f5a
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 * 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
25 * Airong Zhang)
27 * CALLS
28 * open
30 * ALGORITHM
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.
41 * USAGE
42 * open10
44 * RESTRICTIONS
48 #include <stdio.h> /* needed by testhead.h */
49 #include <sys/types.h>
50 #include <sys/stat.h>
51 #include <sys/fcntl.h>
52 #include <errno.h>
53 #include <grp.h>
54 #include <pwd.h>
55 #include "usctest.h"
56 #include "test.h"
58 char *TCID = "open10";
59 int TST_TOTAL = 1;
60 extern int Tst_count;
61 int local_flag;
63 #define PASSED 1
64 #define FAILED 0
66 int local_flag;
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"
75 #define MSGSIZE 150
78 char progname[]= "open10()";
81 int issu() {
83 int uid;
85 uid = (-1);
86 uid = geteuid();
88 if (uid == (-1)) {
89 fprintf(stderr,"geteuid: failed in issu()");
90 return(-1);
93 if ( uid == 0) {
94 return(0);
95 } else {
96 fprintf(stderr,"*** NOT SUPERUSER must be root %s\n",progname);
97 return(uid);
99 return(0);
102 /*--------------------------------------------------------------*/
103 int main (int ac, char *av[])
105 int ret;
106 struct stat buf;
107 struct group *group;
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;
114 pid_t mypid;
117 int lc; /* loop counter */
118 char *msg; /* message returned from parse_opts */
119 int fail_count = 0;
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);
126 tst_exit();
127 /*NOTREACHED*/
131 if (issu() != 0) {
132 tst_resm(TINFO, "Must be root to run this test.");
133 tst_exit();
135 for (lc = 0; TEST_LOOPING(lc); lc++) {
137 local_flag = PASSED;
139 save_myuid = getuid();
140 mypid = getpid();
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");
152 tst_exit();
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");
162 tst_exit();
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 /*--------------------------------------------------------------*/
174 //block0:
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);
182 local_flag = FAILED;
185 if ((ret = chown(DIR_A, user1_uid, group2_gid)) < 0) {
186 tst_resm(TFAIL, "Chown of %d failed",DIR_A);
187 local_flag = FAILED;
190 if ((ret = stat(DIR_A, &buf)) < 0) {
191 tst_resm(TFAIL,"Stat of %s failed",DIR_A);
192 local_flag = FAILED;
195 /* Verify modes */
196 if (buf.st_mode & S_ISGID) {
197 tst_resm(TFAIL, "%s: Incorrect modes, setgid bit set",
198 DIR_A);
199 local_flag = FAILED;
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);
206 local_flag = FAILED;
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);
215 local_flag = FAILED;
218 if ((ret = chown(DIR_B, user1_uid, group2_gid)) < 0) {
219 tst_resm(TFAIL, "Chown of %s failed", DIR_B);
220 local_flag = FAILED;
223 if ((ret = chmod(DIR_B, MODE_SGID)) < 0) {
224 tst_resm(TFAIL, "Chmod of %s failed", DIR_B);
225 local_flag = FAILED;
228 if ((ret = stat(DIR_B, &buf)) < 0) {
229 tst_resm(TFAIL, "Stat of %s failed", DIR_B);
230 local_flag = FAILED;
233 /* Verify modes */
234 if (!(buf.st_mode & S_ISGID)) {
235 tst_resm(TFAIL, "%s: Incorrect modes, setgid bit not set",
236 DIR_B);
237 local_flag = FAILED;
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);
244 local_flag = FAILED;
247 if (local_flag == PASSED) {
248 tst_resm(TPASS, "Test passed in block0.");
249 } else {
250 tst_resm(TFAIL, "Test failed in block0.");
251 fail_count++;
254 local_flag = PASSED;
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 */
261 /* modes. */
262 /*--------------------------------------------------------------*/
263 //block1:
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");
275 mygid = getgid();
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);
282 local_flag = FAILED;
285 if ((ret = stat(nosetgid_A, &buf)) < 0) {
286 tst_resm(TFAIL, "Stat of %s failed", nosetgid_A);
287 local_flag = FAILED;
290 /* Verify modes */
291 if (buf.st_mode & S_ISGID) {
292 tst_resm(TFAIL, "%s: Incorrect modes, setgid bit set", nosetgid_A);
293 local_flag = FAILED;
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);
300 local_flag = FAILED;
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);
308 local_flag = FAILED;
311 if ((ret = stat(setgid_A, &buf)) < 0) {
312 tst_resm(TFAIL, "Stat of %s failed", setgid_A);
313 local_flag = FAILED;
316 /* Verify modes */
317 if (!(buf.st_mode & S_ISGID)) {
318 tst_resm(TFAIL, "%s: Incorrect modes, setgid bit not set",
319 setgid_A);
320 local_flag = FAILED;
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);
327 local_flag = FAILED;
330 if (local_flag == PASSED) {
331 tst_resm(TPASS, "Test passed in block1.");
332 } else {
333 tst_resm(TFAIL, "Test failed in block1.");
334 fail_count++;
337 local_flag = PASSED;
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 /*--------------------------------------------------------------*/
346 //block2:
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);
353 local_flag = FAILED;
356 if ((ret = stat(nosetgid_B, &buf)) < 0) {
357 tst_resm(TFAIL, "Stat of %s failed", nosetgid_B);
358 local_flag = FAILED;
361 /* Verify modes */
362 if (buf.st_mode & S_ISGID) {
363 tst_resm(TFAIL, "%s: Incorrect modes, setgid bit should be set",
364 nosetgid_B);
365 local_flag = FAILED;
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);
372 local_flag = FAILED;
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);
380 local_flag = FAILED;
383 if ((ret = stat(setgid_B, &buf)) < 0) {
384 tst_resm(TFAIL, "Stat of %s failed", setgid_B);
385 local_flag = FAILED;
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);
392 local_flag = FAILED;
395 /* Verify modes */
396 if (!(buf.st_mode & S_ISGID)) {
397 tst_resm(TFAIL, "%s: Incorrect modes, setgid bit not set",
398 setgid_B);
399 local_flag = FAILED;
402 if (local_flag == PASSED) {
403 tst_resm(TPASS, "Test passed in block2.");
404 } else {
405 tst_resm(TFAIL, "Test failed in block2.");
406 fail_count++;
409 local_flag = PASSED;
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 /*--------------------------------------------------------------*/
417 //block3:
419 /* Become root again */
420 if ((ret = setreuid(-1, save_myuid)) < 0) {
421 tst_resm(TFAIL, 0, "Changing back to root failed");
422 local_flag = FAILED;
425 /* Create the file with setgid set */
426 if ((ret = open(root_setgid_B, O_CREAT|O_EXCL|O_RDWR,
427 MODE_SGID)) < 0) {
428 tst_resm(TFAIL, "Creation of %s failed", root_setgid_B);
429 local_flag = FAILED;
432 if ((ret = stat(root_setgid_B, &buf)) < 0) {
433 tst_resm(TFAIL, "Stat of %s failed", root_setgid_B);
434 local_flag = FAILED;
437 /* Verify modes */
438 if (!(buf.st_mode & S_ISGID)) {
439 tst_resm(TFAIL, "%s: Incorrect modes, setgid bit not set",
440 root_setgid_B);
441 local_flag = FAILED;
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);
448 local_flag = FAILED;
451 if (local_flag == PASSED) {
452 tst_resm(TPASS, "Test passed in block3.");
453 } else {
454 tst_resm(TFAIL, "Test failed in block3.");
455 fail_count++;
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.");
488 } else {
489 tst_resm(TFAIL, "Test failed because of above failures.");
493 tst_exit();
494 return(0);