Home | History | Annotate | Download | only in setresuid
      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 /******************************************************************************/
     20 /*
     21  * NAME
     22  * 	setresuid04.c
     23  *
     24  * DESCRIPTION
     25  * 	Check if setresuid behaves correctly with file permissions.
     26  *      The test creates a file as ROOT with permissions 0644, does a setresuid
     27  *      and then tries to open the file with RDWR permissions.
     28  *      The same test is done in a fork to check if new UIDs are correctly
     29  *      passed to the son.
     30  *
     31  * USAGE:  <for command-line>
     32  *  setresuid04 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
     33  *     where,  -c n : Run n copies concurrently.
     34  *             -e   : Turn on errno logging.
     35  *             -i n : Execute test n times.
     36  *             -I x : Execute test for x seconds.
     37  *             -P x : Pause for x seconds between iterations.
     38  *             -t   : Turn on syscall timing.
     39  *
     40  * HISTORY
     41  *	07/2001 Created by Renaud Lottiaux
     42  *
     43  * RESTRICTIONS
     44  * 	Must be run as root.
     45  */
     46 #define _GNU_SOURCE 1
     47 #include <errno.h>
     48 #include <sys/types.h>
     49 #include <sys/stat.h>
     50 #include <sys/wait.h>
     51 #include <fcntl.h>
     52 #include <unistd.h>
     53 #include "test.h"
     54 #include "safe_macros.h"
     55 #include <pwd.h>
     56 #include "compat_16.h"
     57 
     58 TCID_DEFINE(setresuid04);
     59 int TST_TOTAL = 1;
     60 char nobody_uid[] = "nobody";
     61 char testfile[256] = "";
     62 struct passwd *ltpuser;
     63 
     64 int fd = -1;
     65 
     66 void setup(void);
     67 void cleanup(void);
     68 void do_master_child();
     69 
     70 int main(int ac, char **av)
     71 {
     72 	pid_t pid;
     73 
     74 	tst_parse_opts(ac, av, NULL, NULL);
     75 	setup();
     76 
     77 	pid = FORK_OR_VFORK();
     78 	if (pid < 0)
     79 		tst_brkm(TBROK, cleanup, "Fork failed");
     80 
     81 	if (pid == 0)
     82 		do_master_child();
     83 
     84 	tst_record_childstatus(cleanup, pid);
     85 
     86 	cleanup();
     87 	tst_exit();
     88 }
     89 
     90 /*
     91  * do_master_child()
     92  */
     93 void do_master_child(void)
     94 {
     95 	int lc;
     96 	int pid;
     97 	int status;
     98 
     99 	for (lc = 0; TEST_LOOPING(lc); lc++) {
    100 		int tst_fd;
    101 
    102 		/* Reset tst_count in case we are looping */
    103 		tst_count = 0;
    104 
    105 		if (SETRESUID(NULL, 0, ltpuser->pw_uid, 0) == -1) {
    106 			perror("setresuid failed");
    107 			exit(TFAIL);
    108 		}
    109 
    110 		/* Test 1: Check the process with new uid cannot open the file
    111 		 *         with RDWR permissions.
    112 		 */
    113 		TEST(tst_fd = open(testfile, O_RDWR));
    114 
    115 		if (TEST_RETURN != -1) {
    116 			printf("open succeeded unexpectedly\n");
    117 			close(tst_fd);
    118 			exit(TFAIL);
    119 		}
    120 
    121 		if (TEST_ERRNO == EACCES) {
    122 			printf("open failed with EACCES as expected\n");
    123 		} else {
    124 			perror("open failed unexpectedly");
    125 			exit(TFAIL);
    126 		}
    127 
    128 		/* Test 2: Check a son process cannot open the file
    129 		 *         with RDWR permissions.
    130 		 */
    131 		pid = FORK_OR_VFORK();
    132 		if (pid < 0)
    133 			tst_brkm(TBROK, NULL, "Fork failed");
    134 
    135 		if (pid == 0) {
    136 			int tst_fd2;
    137 
    138 			/* Test to open the file in son process */
    139 			TEST(tst_fd2 = open(testfile, O_RDWR));
    140 
    141 			if (TEST_RETURN != -1) {
    142 				printf("call succeeded unexpectedly\n");
    143 				close(tst_fd2);
    144 				exit(TFAIL);
    145 			}
    146 
    147 			if (TEST_ERRNO == EACCES) {
    148 				printf("open failed with EACCES as expected\n");
    149 				exit(TPASS);
    150 			} else {
    151 				printf("open failed unexpectedly\n");
    152 				exit(TFAIL);
    153 			}
    154 		} else {
    155 			/* Wait for son completion */
    156 			if (waitpid(pid, &status, 0) == -1) {
    157 				perror("waitpid failed");
    158 				exit(TFAIL);
    159 			}
    160 
    161 			if (!WIFEXITED(status))
    162 				exit(TFAIL);
    163 
    164 			if (WEXITSTATUS(status) != TPASS)
    165 				exit(WEXITSTATUS(status));
    166 		}
    167 
    168 		/* Test 3: Fallback to initial uid and check we can again open
    169 		 *         the file with RDWR permissions.
    170 		 */
    171 		tst_count++;
    172 		if (SETRESUID(NULL, 0, 0, 0) == -1) {
    173 			perror("setresuid failed");
    174 			exit(TFAIL);
    175 		}
    176 
    177 		TEST(tst_fd = open(testfile, O_RDWR));
    178 
    179 		if (TEST_RETURN == -1) {
    180 			perror("open failed unexpectedly");
    181 			exit(TFAIL);
    182 		} else {
    183 			printf("open call succeeded\n");
    184 			close(tst_fd);
    185 		}
    186 	}
    187 	exit(TPASS);
    188 }
    189 
    190 /*
    191  * setup() - performs all ONE TIME setup for this test
    192  */
    193 void setup(void)
    194 {
    195 	tst_require_root();
    196 
    197 	ltpuser = getpwnam(nobody_uid);
    198 
    199 	UID16_CHECK(ltpuser->pw_uid, "setresuid", cleanup)
    200 
    201 	tst_tmpdir();
    202 
    203 	sprintf(testfile, "setresuid04file%d.tst", getpid());
    204 
    205 	/* Create test file */
    206 	fd = SAFE_OPEN(cleanup, testfile, O_CREAT | O_RDWR, 0644);
    207 
    208 	tst_sig(FORK, DEF_HANDLER, cleanup);
    209 
    210 	TEST_PAUSE;
    211 }
    212 
    213 /*
    214  * cleanup() - performs all the ONE TIME cleanup for this test at completion
    215  * 	       or premature exit
    216  */
    217 void cleanup(void)
    218 {
    219 	close(fd);
    220 
    221 	tst_rmdir();
    222 
    223 }
    224