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