Home | History | Annotate | Download | only in setuid
      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