Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Side by Side Diff: sandbox/linux/services/broker_process_unittest.cc

Issue 11557025: Linux sandbox: add a new low-level broker process mechanism. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Better support for flags. Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 #include "sandbox/linux/services/broker_process.h"
2
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <sys/stat.h>
6 #include <sys/types.h>
7 #include <sys/wait.h>
8 #include <string>
9 #include <vector>
10
11 #include "base/logging.h"
12 #include "sandbox/linux/tests/unit_tests.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 namespace sandbox {
16
17 TEST(BrokerProcess, CreateAndDestroy) {
18 std::vector<std::string> read_whitelist;
19 read_whitelist.push_back("/proc/cpuinfo");
20
21 BrokerProcess* open_broker = new BrokerProcess(read_whitelist,
22 std::vector<std::string>());
23 ASSERT_TRUE(open_broker->Init(NULL));
24 pid_t broker_pid = open_broker->broker_pid();
25 delete(open_broker);
26
27 // Now we check that the broker has exited properly.
28 int status = 0;
29 EXPECT_EQ(waitpid(broker_pid, &status, 0), broker_pid);
30 EXPECT_TRUE(WIFEXITED(status));
31 EXPECT_EQ(WEXITSTATUS(status), 0);
32 }
33
34 TEST(BrokerProcess, TestOpenNull) {
35 const std::vector<std::string> empty;
36 BrokerProcess open_broker(empty, empty);
37 ASSERT_TRUE(open_broker.Init(NULL));
38
39 int fd = open_broker.Open(NULL, O_RDONLY);
40 EXPECT_EQ(fd, -EFAULT);
41 }
42
43 void TestOpenFilePerms(bool fast_check_in_client) {
44 const char kR_WhiteListed[] = "/proc/DOESNOTEXIST1";
45 const char kW_WhiteListed[] = "/proc/DOESNOTEXIST2";
46 const char kRW_WhiteListed[] = "/proc/DOESNOTEXIST3";
47 const char k_NotWhitelisted[] = "/proc/DOESNOTEXIST4";
48
49 std::vector<std::string> read_whitelist;
50 read_whitelist.push_back(kR_WhiteListed);
51 read_whitelist.push_back(kRW_WhiteListed);
52
53 std::vector<std::string> write_whitelist;
54 write_whitelist.push_back(kW_WhiteListed);
55 write_whitelist.push_back(kRW_WhiteListed);
56
57 BrokerProcess open_broker(read_whitelist,
58 write_whitelist,
59 fast_check_in_client);
60 ASSERT_TRUE(open_broker.Init(NULL));
61
62 int fd = -1;
63 fd = open_broker.Open(kR_WhiteListed, O_RDONLY);
64 EXPECT_EQ(fd, -ENOENT);
65 fd = open_broker.Open(kR_WhiteListed, O_WRONLY);
66 EXPECT_EQ(fd, -EPERM);
67 fd = open_broker.Open(kR_WhiteListed, O_RDWR);
68 EXPECT_EQ(fd, -EPERM);
69
70 fd = open_broker.Open(kW_WhiteListed, O_RDONLY);
71 EXPECT_EQ(fd, -EPERM);
72 fd = open_broker.Open(kW_WhiteListed, O_WRONLY);
73 EXPECT_EQ(fd, -ENOENT);
74 fd = open_broker.Open(kW_WhiteListed, O_RDWR);
75 EXPECT_EQ(fd, -EPERM);
76
77 fd = open_broker.Open(kRW_WhiteListed, O_RDONLY);
78 EXPECT_EQ(fd, -ENOENT);
79 fd = open_broker.Open(kRW_WhiteListed, O_WRONLY);
80 EXPECT_EQ(fd, -ENOENT);
81 fd = open_broker.Open(kRW_WhiteListed, O_RDWR);
82 EXPECT_EQ(fd, -ENOENT);
83
84 fd = open_broker.Open(k_NotWhitelisted, O_RDONLY);
85 EXPECT_EQ(fd, -EPERM);
86 fd = open_broker.Open(k_NotWhitelisted, O_WRONLY);
87 EXPECT_EQ(fd, -EPERM);
88 fd = open_broker.Open(k_NotWhitelisted, O_RDWR);
89 EXPECT_EQ(fd, -EPERM);
90
91 // We have some extra sanity check for clearly wrong values.
92 fd = open_broker.Open(kRW_WhiteListed, O_RDONLY|O_WRONLY|O_RDWR);
93 EXPECT_EQ(fd, -EPERM);
94 }
95
96 // Run the same thing twice. The second time, we make sure that no security
97 // check is performed on the client.
98 TEST(BrokerProcess, OpenFilePermsWithClientCheck) {
99 TestOpenFilePerms(true /* fast_check_in_client */);
100 }
101
102 TEST(BrokerProcess, OpenOpenFilePermsNoClientCheck) {
103 TestOpenFilePerms(false /* fast_check_in_client */);
104 }
105
106
107 void TestOpenCpuinfo(bool fast_check_in_client) {
108 const char kFileCpuInfo[] = "/proc/cpuinfo";
109 std::vector<std::string> read_whitelist;
110 read_whitelist.push_back(kFileCpuInfo);
111
112 BrokerProcess* open_broker = new BrokerProcess(read_whitelist,
113 std::vector<std::string>(),
114 fast_check_in_client);
115 ASSERT_TRUE(open_broker->Init(NULL));
116 pid_t broker_pid = open_broker->broker_pid();
117
118 int fd = -1;
119 fd = open_broker->Open(kFileCpuInfo, O_RDWR);
120 EXPECT_EQ(fd, -EPERM);
121
122 // Open cpuinfo via the broker.
123 int cpuinfo_fd = open_broker->Open(kFileCpuInfo, O_RDONLY);
124 ASSERT_GE(cpuinfo_fd, 0);
125 char buf[3];
126 memset(buf, 0, sizeof(buf));
127 int read_len1 = read(cpuinfo_fd, buf, sizeof(buf));
128 EXPECT_GT(read_len1, 0);
129
130 // Open cpuinfo directly.
131 int cpuinfo_fd2 = open(kFileCpuInfo, O_RDONLY);
132 ASSERT_GE(cpuinfo_fd2, 0);
133 char buf2[3];
134 memset(buf2, 1, sizeof(buf2));
135 int read_len2 = read(cpuinfo_fd2, buf2, sizeof(buf2));
136 EXPECT_GT(read_len1, 0);
137
138 // The following is not guaranteed true, but will be in practice.
139 EXPECT_EQ(read_len1, read_len2);
140 // Compare the cpuinfo as returned by the broker with the one we opened
141 // ourselves.
142 EXPECT_EQ(memcmp(buf, buf2, read_len1), 0);
143
144 if (fd >= 0)
145 close(fd);
146 if (cpuinfo_fd >= 0)
147 close(cpuinfo_fd);
148 if (cpuinfo_fd2 >= 0)
149 close(cpuinfo_fd);
150
151 delete(open_broker);
152
153 // Now we check that the broker has exited properly.
154 int status = 0;
155 EXPECT_EQ(waitpid(broker_pid, &status, 0), broker_pid);
156 EXPECT_TRUE(WIFEXITED(status));
157 EXPECT_EQ(WEXITSTATUS(status), 0);
158 }
159
160 // Run the same thing twice. The second time, we make sure that no security
161 // check is performed on the client.
162 TEST(BrokerProcess, OpenCpuinfoWithClientCheck) {
163 TestOpenCpuinfo(true /* fast_check_in_client */);
164 }
165
166 TEST(BrokerProcess, OpenCpuinfoNoClientCheck) {
167 TestOpenCpuinfo(false /* fast_check_in_client */);
168 }
169
170 TEST(BrokerProcess, OpenFileRW) {
171 char templatename[] = "BrokerProcessXXXXXX";
172 int tempfile = mkstemp(templatename);
173 ASSERT_GE(tempfile, 0);
174 char tempfile_name[2048];
175 int written = snprintf(tempfile_name, sizeof(tempfile_name),
176 "/proc/self/fd/%d", tempfile);
177 ASSERT_LT(written, static_cast<int>(sizeof(tempfile_name)));
178
179 std::vector<std::string> whitelist;
180 whitelist.push_back(tempfile_name);
181
182 BrokerProcess open_broker(whitelist, whitelist);
183 ASSERT_TRUE(open_broker.Init(NULL));
184
185 int tempfile2 = -1;
186 tempfile2 = open_broker.Open(tempfile_name, O_RDWR);
187 ASSERT_GE(tempfile2, 0);
188
189 // Write to the descriptor opened by the broker.
190 char test_text[] = "TESTTESTTEST";
191 ssize_t len = write(tempfile2, test_text, sizeof(test_text));
192 ASSERT_EQ(len, static_cast<ssize_t>(sizeof(test_text)));
193
194 // Read back from the original file descriptor what we wrote through
195 // the descriptor provided by the broker.
196 char buf[1024];
197 len = read(tempfile, buf, sizeof(buf));
198
199 ASSERT_EQ(len, static_cast<ssize_t>(sizeof(test_text)));
200 ASSERT_EQ(memcmp(test_text, buf, sizeof(test_text)), 0);
201
202 // Cleanup the temporary file.
203 char tempfile_full_path[2048];
204 // Make sure tempfile_full_path will terminate with a 0.
205 memset(tempfile_full_path, 0, sizeof(tempfile_full_path));
206 ssize_t ret = readlink(tempfile_name, tempfile_full_path,
207 sizeof(tempfile_full_path));
208 ASSERT_GT(ret, 0);
209 // Make sure we still have a trailing zero in tempfile_full_path.
210 ASSERT_LT(ret, static_cast<ssize_t>(sizeof(tempfile_full_path)));
211 ASSERT_EQ(unlink(tempfile_full_path), 0);
212
213 EXPECT_EQ(close(tempfile), 0);
214 EXPECT_EQ(close(tempfile2), 0);
215 }
216
217 // Sandbox test because we could get a SIGPIPE.
218 SANDBOX_TEST(BrokerProcess, BrokerDied) {
219 std::vector<std::string> read_whitelist;
220 read_whitelist.push_back("/proc/cpuinfo");
221
222 BrokerProcess open_broker(read_whitelist,
223 std::vector<std::string>(),
224 true /* fast_check_in_client */,
225 true /* quiet_failures_for_tests */);
226 SANDBOX_ASSERT(open_broker.Init(NULL));
227 pid_t broker_pid = open_broker.broker_pid();
228 SANDBOX_ASSERT(kill(broker_pid, SIGKILL) == 0);
229
230 // Now we check that the broker has exited properly.
231 int status = 0;
232 SANDBOX_ASSERT(waitpid(broker_pid, &status, 0) == broker_pid);
233 SANDBOX_ASSERT(WIFSIGNALED(status));
234 SANDBOX_ASSERT(WTERMSIG(status) == SIGKILL);
235 // Hopefully doing Open with a dead broker won't SIGPIPE us.
236 SANDBOX_ASSERT(open_broker.Open("/proc/cpuinfo", O_RDONLY) == -ENOMEM);
237 }
238
239 void TestComplexFlags(bool fast_check_in_client) {
240 std::vector<std::string> whitelist;
241 whitelist.push_back("/proc/cpuinfo");
242
243 BrokerProcess open_broker(whitelist,
244 whitelist,
245 fast_check_in_client);
246 ASSERT_TRUE(open_broker.Init(NULL));
247 // Test that we do the right thing for O_CLOEXEC and O_NONBLOCK.
248 // Presently, the right thing is to always deny them since they are not
249 // supported.
250 int fd = -1;
251 fd = open_broker.Open("/proc/cpuinfo", O_RDONLY);
252 ASSERT_GE(fd, 0);
253 ASSERT_EQ(close(fd), 0);
254
255 ASSERT_EQ(open_broker.Open("/proc/cpuinfo", O_RDONLY | O_CLOEXEC), -EPERM);
256 ASSERT_EQ(open_broker.Open("/proc/cpuinfo", O_RDONLY | O_NONBLOCK), -EPERM);
257 }
258
259 TEST(BrokerProcess, ComplexFlagsWithClientCheck) {
260 TestComplexFlags(true /* fast_check_in_client */);
261 }
262
263 TEST(BrokerProcess, ComplexFlagsNoClientCheck) {
264 TestComplexFlags(false /* fast_check_in_client */);
265 }
266
267 } // namespace sandbox
OLDNEW
« sandbox/linux/services/broker_process.cc ('K') | « sandbox/linux/services/broker_process.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698