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
main(int ac,char ** av)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
do_master_child(void)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
setup(void)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
cleanup(void)167 static void cleanup(void)
168 {
169 close(fd);
170 tst_rmdir();
171 }
172