1 /****************************************************************************** 2 * Copyright (c) Kerlabs 2008. * 3 * Copyright (c) International Business Machines Corp., 2008 * 4 * Created by Renaud Lottiaux * 5 * * 6 * This program is free software; you can redistribute it and/or modify * 7 * it under the terms of the GNU General Public License as published by * 8 * the Free Software Foundation; either version 2 of the License, or * 9 * (at your option) any later version. * 10 * * 11 * This program is distributed in the hope that it will be useful, * 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * 14 * the GNU General Public License for more details. * 15 * * 16 * You should have received a copy of the GNU General Public License * 17 * along with this program; if not, write to the Free Software Foundation, * 18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * 19 *****************************************************************************/ 20 21 /* 22 * Check if setuid behaves correctly with file permissions. The test creates a 23 * file as ROOT with permissions 0644, does a setuid and then tries to open the 24 * file with RDWR permissions. The same test is done in a fork to check if new 25 * UIDs are correctly passed to the son. 26 */ 27 28 #include <errno.h> 29 #include <pwd.h> 30 #include <sys/types.h> 31 #include <sys/stat.h> 32 #include <sys/wait.h> 33 #include <fcntl.h> 34 #include <unistd.h> 35 36 #include "test.h" 37 #include "compat_16.h" 38 39 char *TCID = "setuid04"; 40 int TST_TOTAL = 1; 41 42 static char nobody_uid[] = "nobody"; 43 static char testfile[] = "setuid04_testfile"; 44 static struct passwd *ltpuser; 45 46 static int fd = -1; 47 48 static void setup(void); 49 static void cleanup(void); 50 static void do_master_child(void); 51 52 int main(int ac, char **av) 53 { 54 pid_t pid; 55 int status; 56 57 tst_parse_opts(ac, av, NULL, NULL); 58 59 setup(); 60 61 pid = FORK_OR_VFORK(); 62 if (pid < 0) 63 tst_brkm(TBROK, cleanup, "Fork failed"); 64 65 if (pid == 0) { 66 do_master_child(); 67 } else { 68 waitpid(pid, &status, 0); 69 if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) 70 tst_resm(WEXITSTATUS(status), 71 "son process exits with error"); 72 } 73 74 cleanup(); 75 tst_exit(); 76 } 77 78 static void do_master_child(void) 79 { 80 int lc; 81 int pid; 82 int status; 83 84 if (SETUID(NULL, ltpuser->pw_uid) == -1) { 85 tst_brkm(TBROK, NULL, 86 "setuid failed to set the effective uid to %d", 87 ltpuser->pw_uid); 88 } 89 90 for (lc = 0; TEST_LOOPING(lc); lc++) { 91 int tst_fd; 92 93 tst_count = 0; 94 95 TEST(tst_fd = open(testfile, O_RDWR)); 96 97 if (TEST_RETURN != -1) { 98 tst_resm(TFAIL, "call succeeded unexpectedly"); 99 close(tst_fd); 100 } 101 102 if (TEST_ERRNO == EACCES) { 103 tst_resm(TPASS, "open returned errno EACCES"); 104 } else { 105 tst_resm(TFAIL, "open returned unexpected errno - %d", 106 TEST_ERRNO); 107 continue; 108 } 109 110 pid = FORK_OR_VFORK(); 111 if (pid < 0) 112 tst_brkm(TBROK, NULL, "Fork failed"); 113 114 if (pid == 0) { 115 int tst_fd2; 116 117 /* Test to open the file in son process */ 118 TEST(tst_fd2 = open(testfile, O_RDWR)); 119 120 if (TEST_RETURN != -1) { 121 tst_resm(TFAIL, "call succeeded unexpectedly"); 122 close(tst_fd2); 123 } 124 125 if (TEST_ERRNO == EACCES) { 126 tst_resm(TPASS, "open returned errno EACCES"); 127 } else { 128 tst_resm(TFAIL, 129 "open returned unexpected errno - %d", 130 TEST_ERRNO); 131 } 132 tst_exit(); 133 } else { 134 /* Wait for son completion */ 135 waitpid(pid, &status, 0); 136 if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) 137 exit(WEXITSTATUS(status)); 138 } 139 } 140 tst_exit(); 141 } 142 143 static void setup(void) 144 { 145 tst_require_root(); 146 147 ltpuser = getpwnam(nobody_uid); 148 149 if (ltpuser == NULL) 150 tst_brkm(TBROK, cleanup, "getpwnam failed for user id %s", 151 nobody_uid); 152 153 UID16_CHECK(ltpuser->pw_uid, setuid, cleanup); 154 155 tst_tmpdir(); 156 157 /* Create test file */ 158 fd = open(testfile, O_CREAT | O_RDWR, 0644); 159 if (fd < 0) 160 tst_brkm(TBROK, cleanup, "cannot creat test file"); 161 162 tst_sig(FORK, DEF_HANDLER, cleanup); 163 164 TEST_PAUSE; 165 } 166 167 static void cleanup(void) 168 { 169 close(fd); 170 tst_rmdir(); 171 } 172