1 /* 2 * Copyright (c) Kerlabs 2008. 3 * Copyright (c) International Business Machines Corp., 2008 4 * 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. 9 * 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. 14 * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 * 19 * Created by Renaud Lottiaux 20 */ 21 22 /* 23 * Check if setreuid behaves correctly with file permissions. 24 * The test creates a file as ROOT with permissions 0644, does a setreuid 25 * and then tries to open the file with RDWR permissions. 26 * The same test is done in a fork to check if new UIDs are correctly 27 * passed to the son. 28 */ 29 30 #include <errno.h> 31 #include <sys/types.h> 32 #include <sys/stat.h> 33 #include <sys/wait.h> 34 #include <fcntl.h> 35 #include <unistd.h> 36 #include <pwd.h> 37 38 #include "test.h" 39 #include "safe_macros.h" 40 #include "compat_16.h" 41 42 TCID_DEFINE(setreuid07); 43 int TST_TOTAL = 1; 44 45 static char testfile[256] = ""; 46 static struct passwd *ltpuser; 47 48 static int fd = -1; 49 50 static void setup(void); 51 static void cleanup(void); 52 static void do_master_child(void); 53 54 int main(int ac, char **av) 55 { 56 pid_t pid; 57 58 tst_parse_opts(ac, av, NULL, NULL); 59 60 setup(); 61 62 pid = FORK_OR_VFORK(); 63 if (pid < 0) 64 tst_brkm(TBROK, cleanup, "Fork failed"); 65 66 if (pid == 0) 67 do_master_child(); 68 69 tst_record_childstatus(cleanup, pid); 70 71 cleanup(); 72 tst_exit(); 73 } 74 75 static void do_master_child(void) 76 { 77 int lc; 78 int pid; 79 int status; 80 81 for (lc = 0; TEST_LOOPING(lc); lc++) { 82 int tst_fd; 83 84 tst_count = 0; 85 86 if (SETREUID(NULL, 0, ltpuser->pw_uid) == -1) { 87 perror("setreuid failed"); 88 exit(TFAIL); 89 } 90 91 /* Test 1: Check the process with new uid cannot open the file 92 * with RDWR permissions. 93 */ 94 TEST(tst_fd = open(testfile, O_RDWR)); 95 96 if (TEST_RETURN != -1) { 97 printf("open succeeded unexpectedly\n"); 98 close(tst_fd); 99 exit(TFAIL); 100 } 101 102 if (TEST_ERRNO == EACCES) { 103 printf("open failed with EACCES as expected\n"); 104 } else { 105 perror("open failed unexpectedly"); 106 exit(TFAIL); 107 } 108 109 /* Test 2: Check a son process cannot open the file 110 * with RDWR permissions. 111 */ 112 pid = FORK_OR_VFORK(); 113 if (pid < 0) 114 tst_brkm(TBROK, cleanup, "Fork failed"); 115 116 if (pid == 0) { 117 int tst_fd2; 118 119 /* Test to open the file in son process */ 120 TEST(tst_fd2 = open(testfile, O_RDWR)); 121 122 if (TEST_RETURN != -1) { 123 printf("call succeeded unexpectedly\n"); 124 close(tst_fd2); 125 exit(TFAIL); 126 } 127 128 if (TEST_ERRNO == EACCES) { 129 printf("open failed with EACCES as expected\n"); 130 exit(TPASS); 131 } else { 132 printf("open failed unexpectedly\n"); 133 exit(TFAIL); 134 } 135 } else { 136 /* Wait for son completion */ 137 if (waitpid(pid, &status, 0) == -1) { 138 perror("waitpid failed"); 139 exit(TFAIL); 140 } 141 if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) 142 exit(WEXITSTATUS(status)); 143 } 144 145 /* Test 3: Fallback to initial uid and check we can again open 146 * the file with RDWR permissions. 147 */ 148 tst_count++; 149 if (SETREUID(NULL, 0, 0) == -1) { 150 perror("setreuid failed"); 151 exit(TFAIL); 152 } 153 154 TEST(tst_fd = open(testfile, O_RDWR)); 155 156 if (TEST_RETURN == -1) { 157 perror("open failed unexpectedly"); 158 exit(TFAIL); 159 } else { 160 printf("open call succeeded\n"); 161 close(tst_fd); 162 } 163 } 164 exit(TPASS); 165 } 166 167 static void setup(void) 168 { 169 tst_require_root(); 170 171 ltpuser = getpwnam("nobody"); 172 if (ltpuser == NULL) 173 tst_brkm(TBROK, NULL, "nobody must be a valid user."); 174 175 tst_tmpdir(); 176 177 sprintf(testfile, "setreuid07file%d.tst", getpid()); 178 179 /* Create test file */ 180 fd = SAFE_OPEN(cleanup, testfile, O_CREAT | O_RDWR, 0644); 181 182 tst_sig(FORK, DEF_HANDLER, cleanup); 183 184 TEST_PAUSE; 185 } 186 187 static void cleanup(void) 188 { 189 close(fd); 190 191 tst_rmdir(); 192 } 193