1 /*
2 * Copyright (c) International Business Machines Corp., 2001
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12 * the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 /* DESCRIPTION
19 * This test will verify that new directory created by mkdir(2) inherites
20 * the group ID from the parent directory and S_ISGID bit, if the S_ISGID
21 * bit is set in the parent directory.
22 */
23
24 #include <errno.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <pwd.h>
28 #include <sys/wait.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include "tst_test.h"
32
33 #define TESTDIR1 "testdir1"
34 #define TESTDIR2 "testdir1/testdir2"
35
36 static uid_t nobody_uid, bin_uid;
37 static gid_t nobody_gid, bin_gid;
38
verify_mkdir(void)39 static void verify_mkdir(void)
40 {
41 struct stat buf1, buf2;
42 pid_t pid;
43 int fail = 0;
44
45 pid = SAFE_FORK();
46 if (pid == 0) {
47 SAFE_SETREGID(bin_gid, bin_gid);
48 SAFE_SETREUID(bin_uid, bin_uid);
49 SAFE_MKDIR(TESTDIR2, 0777);
50
51 SAFE_STAT(TESTDIR2, &buf2);
52 SAFE_STAT(TESTDIR1, &buf1);
53
54 if (buf2.st_gid != buf1.st_gid) {
55 tst_res(TFAIL,
56 "New dir FAILED to inherit GID have %d expected %d",
57 buf2.st_gid, buf1.st_gid);
58 fail = 1;
59 }
60
61 if (!(buf2.st_mode & S_ISGID)) {
62 tst_res(TFAIL, "New dir FAILED to inherit S_ISGID");
63 fail = 1;
64 }
65
66 if (!fail)
67 tst_res(TPASS, "New dir inherited GID and S_ISGID");
68
69 exit(0);
70 }
71
72 tst_reap_children();
73 SAFE_RMDIR(TESTDIR2);
74 }
75
76
setup(void)77 static void setup(void)
78 {
79 struct passwd *pw;
80 struct stat buf;
81 pid_t pid;
82
83 pw = SAFE_GETPWNAM("nobody");
84 nobody_uid = pw->pw_uid;
85 nobody_gid = pw->pw_gid;
86 pw = SAFE_GETPWNAM("bin");
87 bin_uid = pw->pw_uid;
88 bin_gid = pw->pw_gid;
89
90 umask(0);
91
92 pid = SAFE_FORK();
93 if (pid == 0) {
94 SAFE_SETREGID(nobody_gid, nobody_gid);
95 SAFE_SETREUID(nobody_uid, nobody_uid);
96 SAFE_MKDIR(TESTDIR1, 0777);
97 SAFE_STAT(TESTDIR1, &buf);
98 SAFE_CHMOD(TESTDIR1, buf.st_mode | S_ISGID);
99 exit(0);
100 }
101
102 tst_reap_children();
103 }
104
105 static struct tst_test test = {
106 .setup = setup,
107 .needs_tmpdir = 1,
108 .needs_root = 1,
109 .test_all = verify_mkdir,
110 .forks_child = 1,
111 };
112