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 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 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