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