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

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

Issue 721553002: sandbox: Extend BrokerPolicy to support file creation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: minor fix Created 6 years, 1 month 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "sandbox/linux/syscall_broker/broker_process.h" 5 #include "sandbox/linux/syscall_broker/broker_process.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #include <sys/resource.h> 9 #include <sys/resource.h>
10 #include <sys/stat.h> 10 #include <sys/stat.h>
(...skipping 12 matching lines...) Expand all
23 #include "base/logging.h" 23 #include "base/logging.h"
24 #include "base/memory/scoped_ptr.h" 24 #include "base/memory/scoped_ptr.h"
25 #include "base/posix/eintr_wrapper.h" 25 #include "base/posix/eintr_wrapper.h"
26 #include "base/posix/unix_domain_socket_linux.h" 26 #include "base/posix/unix_domain_socket_linux.h"
27 #include "sandbox/linux/tests/scoped_temporary_file.h" 27 #include "sandbox/linux/tests/scoped_temporary_file.h"
28 #include "sandbox/linux/tests/test_utils.h" 28 #include "sandbox/linux/tests/test_utils.h"
29 #include "sandbox/linux/tests/unit_tests.h" 29 #include "sandbox/linux/tests/unit_tests.h"
30 #include "testing/gtest/include/gtest/gtest.h" 30 #include "testing/gtest/include/gtest/gtest.h"
31 31
32 namespace sandbox { 32 namespace sandbox {
33 using syscall_broker::BrokerPermission;
33 34
34 class BrokerProcessTestHelper { 35 class BrokerProcessTestHelper {
35 public: 36 public:
36 static int get_ipc_socketpair(const BrokerProcess* broker) { 37 static int get_ipc_socketpair(const BrokerProcess* broker) {
37 return broker->ipc_socketpair_; 38 return broker->ipc_socketpair_;
38 } 39 }
39 }; 40 };
40 41
41 namespace { 42 namespace {
42 43
43 bool NoOpCallback() { 44 bool NoOpCallback() {
44 return true; 45 return true;
45 } 46 }
46 47
47 } // namespace 48 } // namespace
48 49
49 TEST(BrokerProcess, CreateAndDestroy) { 50 TEST(BrokerProcess, CreateAndDestroy) {
50 std::vector<std::string> read_whitelist; 51 std::vector<syscall_broker::BrokerPermission> permissions;
51 read_whitelist.push_back("/proc/cpuinfo"); 52 permissions.push_back(BROKER_PERM_READ_ONLY("/proc/cpuinfo"));
52 53
53 scoped_ptr<BrokerProcess> open_broker( 54 scoped_ptr<BrokerProcess> open_broker(new BrokerProcess(EPERM, permissions));
54 new BrokerProcess(EPERM, read_whitelist, std::vector<std::string>()));
55 ASSERT_TRUE(open_broker->Init(base::Bind(&NoOpCallback))); 55 ASSERT_TRUE(open_broker->Init(base::Bind(&NoOpCallback)));
56 56
57 ASSERT_TRUE(TestUtils::CurrentProcessHasChildren()); 57 ASSERT_TRUE(TestUtils::CurrentProcessHasChildren());
58 // Destroy the broker and check it has exited properly. 58 // Destroy the broker and check it has exited properly.
59 open_broker.reset(); 59 open_broker.reset();
60 ASSERT_FALSE(TestUtils::CurrentProcessHasChildren()); 60 ASSERT_FALSE(TestUtils::CurrentProcessHasChildren());
61 } 61 }
62 62
63 TEST(BrokerProcess, TestOpenAccessNull) { 63 TEST(BrokerProcess, TestOpenAccessNull) {
64 const std::vector<std::string> empty; 64 std::vector<syscall_broker::BrokerPermission> empty;
65 BrokerProcess open_broker(EPERM, empty, empty); 65 BrokerProcess open_broker(EPERM, empty);
66 ASSERT_TRUE(open_broker.Init(base::Bind(&NoOpCallback))); 66 ASSERT_TRUE(open_broker.Init(base::Bind(&NoOpCallback)));
67 67
68 int fd = open_broker.Open(NULL, O_RDONLY); 68 int fd = open_broker.Open(NULL, O_RDONLY);
69 ASSERT_EQ(fd, -EFAULT); 69 ASSERT_EQ(fd, -EFAULT);
70 70
71 int ret = open_broker.Access(NULL, F_OK); 71 int ret = open_broker.Access(NULL, F_OK);
72 ASSERT_EQ(ret, -EFAULT); 72 ASSERT_EQ(ret, -EFAULT);
73 } 73 }
74 74
75 void TestOpenFilePerms(bool fast_check_in_client, int denied_errno) { 75 void TestOpenFilePerms(bool fast_check_in_client, int denied_errno) {
76 const char kR_WhiteListed[] = "/proc/DOESNOTEXIST1"; 76 const char kR_WhiteListed[] = "/proc/DOESNOTEXIST1";
77 // We can't debug the init process, and shouldn't be able to access 77 // We can't debug the init process, and shouldn't be able to access
78 // its auxv file. 78 // its auxv file.
79 const char kR_WhiteListedButDenied[] = "/proc/1/auxv"; 79 const char kR_WhiteListedButDenied[] = "/proc/1/auxv";
80 const char kW_WhiteListed[] = "/proc/DOESNOTEXIST2"; 80 const char kW_WhiteListed[] = "/proc/DOESNOTEXIST2";
81 const char kRW_WhiteListed[] = "/proc/DOESNOTEXIST3"; 81 const char kRW_WhiteListed[] = "/proc/DOESNOTEXIST3";
82 const char k_NotWhitelisted[] = "/proc/DOESNOTEXIST4"; 82 const char k_NotWhitelisted[] = "/proc/DOESNOTEXIST4";
83 83
84 std::vector<std::string> read_whitelist; 84 std::vector<syscall_broker::BrokerPermission> permissions;
85 read_whitelist.push_back(kR_WhiteListed); 85 permissions.push_back(BROKER_PERM_READ_ONLY(kR_WhiteListed));
86 read_whitelist.push_back(kR_WhiteListedButDenied); 86 permissions.push_back(BROKER_PERM_READ_ONLY(kR_WhiteListedButDenied));
87 read_whitelist.push_back(kRW_WhiteListed); 87 permissions.push_back(BROKER_PERM_WRITE_ONLY(kW_WhiteListed));
88 permissions.push_back(BROKER_PERM_READ_WRITE(kRW_WhiteListed));
88 89
89 std::vector<std::string> write_whitelist; 90 BrokerProcess open_broker(denied_errno, permissions, fast_check_in_client);
90 write_whitelist.push_back(kW_WhiteListed);
91 write_whitelist.push_back(kRW_WhiteListed);
92
93 BrokerProcess open_broker(
94 denied_errno, read_whitelist, write_whitelist, fast_check_in_client);
95 ASSERT_TRUE(open_broker.Init(base::Bind(&NoOpCallback))); 91 ASSERT_TRUE(open_broker.Init(base::Bind(&NoOpCallback)));
96 92
97 int fd = -1; 93 int fd = -1;
98 fd = open_broker.Open(kR_WhiteListed, O_RDONLY); 94 fd = open_broker.Open(kR_WhiteListed, O_RDONLY);
99 ASSERT_EQ(fd, -ENOENT); 95 ASSERT_EQ(fd, -ENOENT);
100 fd = open_broker.Open(kR_WhiteListed, O_WRONLY); 96 fd = open_broker.Open(kR_WhiteListed, O_WRONLY);
101 ASSERT_EQ(fd, -denied_errno); 97 ASSERT_EQ(fd, -denied_errno);
102 fd = open_broker.Open(kR_WhiteListed, O_RDWR); 98 fd = open_broker.Open(kR_WhiteListed, O_RDWR);
103 ASSERT_EQ(fd, -denied_errno); 99 ASSERT_EQ(fd, -denied_errno);
104 int ret = -1; 100 int ret = -1;
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 // Don't do anything here, so that ASSERT works in the subfunction as 225 // Don't do anything here, so that ASSERT works in the subfunction as
230 // expected. 226 // expected.
231 } 227 }
232 228
233 TEST(BrokerProcess, OpenOpenFilePermsNoClientCheckNoEnt) { 229 TEST(BrokerProcess, OpenOpenFilePermsNoClientCheckNoEnt) {
234 TestOpenFilePerms(false /* fast_check_in_client */, ENOENT); 230 TestOpenFilePerms(false /* fast_check_in_client */, ENOENT);
235 // Don't do anything here, so that ASSERT works in the subfunction as 231 // Don't do anything here, so that ASSERT works in the subfunction as
236 // expected. 232 // expected.
237 } 233 }
238 234
239 void TestOpenCpuinfo(bool fast_check_in_client) { 235 void TestBadPaths(bool fast_check_in_client) {
240 const char kFileCpuInfo[] = "/proc/cpuinfo"; 236 const char kFileCpuInfo[] = "/proc/cpuinfo";
241 std::vector<std::string> read_whitelist; 237 const char kNotAbsPath[] = "proc/cpuinfo";
242 read_whitelist.push_back(kFileCpuInfo); 238 const char kDotDotStart[] = "/../proc/cpuinfo";
239 const char kDotDotMiddle[] = "/proc/self/../cpuinfo";
240 const char kDotDotEnd[] = "/proc/..";
241 const char kTrailingSlash[] = "/proc/";
243 242
244 scoped_ptr<BrokerProcess> open_broker(new BrokerProcess( 243 std::vector<syscall_broker::BrokerPermission> permissions;
245 EPERM, read_whitelist, std::vector<std::string>(), fast_check_in_client)); 244
245 permissions.push_back(BROKER_PERM_READ_ONLY_RECURSIVE("/proc/"));
246 scoped_ptr<BrokerProcess> open_broker(
247 new BrokerProcess(EPERM, permissions, fast_check_in_client));
248 ASSERT_TRUE(open_broker->Init(base::Bind(&NoOpCallback)));
249 // Open cpuinfo via the broker.
250 int cpuinfo_fd = open_broker->Open(kFileCpuInfo, O_RDONLY);
251 base::ScopedFD cpuinfo_fd_closer(cpuinfo_fd);
252 ASSERT_GE(cpuinfo_fd, 0);
253
254 int fd = -1;
255 int can_access;
256
257 can_access = open_broker->Access(kNotAbsPath, R_OK);
258 ASSERT_EQ(can_access, -EPERM);
259 fd = open_broker->Open(kNotAbsPath, O_RDONLY);
260 ASSERT_EQ(fd, -EPERM);
261
262 can_access = open_broker->Access(kDotDotStart, R_OK);
263 ASSERT_EQ(can_access, -EPERM);
264 fd = open_broker->Open(kDotDotStart, O_RDONLY);
265 ASSERT_EQ(fd, -EPERM);
266
267 can_access = open_broker->Access(kDotDotMiddle, R_OK);
268 ASSERT_EQ(can_access, -EPERM);
269 fd = open_broker->Open(kDotDotMiddle, O_RDONLY);
270 ASSERT_EQ(fd, -EPERM);
271
272 can_access = open_broker->Access(kDotDotEnd, R_OK);
273 ASSERT_EQ(can_access, -EPERM);
274 fd = open_broker->Open(kDotDotEnd, O_RDONLY);
275 ASSERT_EQ(fd, -EPERM);
276
277 can_access = open_broker->Access(kTrailingSlash, R_OK);
278 ASSERT_EQ(can_access, -EPERM);
279 fd = open_broker->Open(kTrailingSlash, O_RDONLY);
280 ASSERT_EQ(fd, -EPERM);
281 }
282
283 TEST(BrokerProcess, BadPathsClientCheck) {
284 TestBadPaths(true /* fast_check_in_client */);
285 // Don't do anything here, so that ASSERT works in the subfunction as
286 // expected.
287 }
288
289 TEST(BrokerProcess, BadPathsNoClientCheck) {
290 TestBadPaths(false /* fast_check_in_client */);
291 // Don't do anything here, so that ASSERT works in the subfunction as
292 // expected.
293 }
294
295 void TestOpenCpuinfo(bool fast_check_in_client, bool recursive) {
296 const char kFileCpuInfo[] = "/proc/cpuinfo";
297 const char kDirProc[] = "/proc/";
298
299 std::vector<syscall_broker::BrokerPermission> permissions;
300 if (recursive)
301 permissions.push_back(BROKER_PERM_READ_ONLY_RECURSIVE(kDirProc));
302 else
303 permissions.push_back(BROKER_PERM_READ_ONLY(kFileCpuInfo));
304
305 scoped_ptr<BrokerProcess> open_broker(
306 new BrokerProcess(EPERM, permissions, fast_check_in_client));
246 ASSERT_TRUE(open_broker->Init(base::Bind(&NoOpCallback))); 307 ASSERT_TRUE(open_broker->Init(base::Bind(&NoOpCallback)));
247 308
248 int fd = -1; 309 int fd = -1;
249 fd = open_broker->Open(kFileCpuInfo, O_RDWR); 310 fd = open_broker->Open(kFileCpuInfo, O_RDWR);
250 base::ScopedFD fd_closer(fd); 311 base::ScopedFD fd_closer(fd);
251 ASSERT_EQ(fd, -EPERM); 312 ASSERT_EQ(fd, -EPERM);
252 313
253 // Check we can read /proc/cpuinfo. 314 // Check we can read /proc/cpuinfo.
254 int can_access = open_broker->Access(kFileCpuInfo, R_OK); 315 int can_access = open_broker->Access(kFileCpuInfo, R_OK);
255 ASSERT_EQ(can_access, 0); 316 ASSERT_EQ(can_access, 0);
(...skipping 23 matching lines...) Expand all
279 ASSERT_EQ(read_len1, read_len2); 340 ASSERT_EQ(read_len1, read_len2);
280 // Compare the cpuinfo as returned by the broker with the one we opened 341 // Compare the cpuinfo as returned by the broker with the one we opened
281 // ourselves. 342 // ourselves.
282 ASSERT_EQ(memcmp(buf, buf2, read_len1), 0); 343 ASSERT_EQ(memcmp(buf, buf2, read_len1), 0);
283 344
284 ASSERT_TRUE(TestUtils::CurrentProcessHasChildren()); 345 ASSERT_TRUE(TestUtils::CurrentProcessHasChildren());
285 open_broker.reset(); 346 open_broker.reset();
286 ASSERT_FALSE(TestUtils::CurrentProcessHasChildren()); 347 ASSERT_FALSE(TestUtils::CurrentProcessHasChildren());
287 } 348 }
288 349
289 // Run the same thing twice. The second time, we make sure that no security 350 // Run this test 4 times. With and without the check in client
290 // check is performed on the client. 351 // and using a recursive path.
291 TEST(BrokerProcess, OpenCpuinfoWithClientCheck) { 352 TEST(BrokerProcess, OpenCpuinfoWithClientCheck) {
292 TestOpenCpuinfo(true /* fast_check_in_client */); 353 TestOpenCpuinfo(true /* fast_check_in_client */, false /* not recursive */);
293 // Don't do anything here, so that ASSERT works in the subfunction as 354 // Don't do anything here, so that ASSERT works in the subfunction as
294 // expected. 355 // expected.
295 } 356 }
296 357
297 TEST(BrokerProcess, OpenCpuinfoNoClientCheck) { 358 TEST(BrokerProcess, OpenCpuinfoNoClientCheck) {
298 TestOpenCpuinfo(false /* fast_check_in_client */); 359 TestOpenCpuinfo(false /* fast_check_in_client */, false /* not recursive */);
299 // Don't do anything here, so that ASSERT works in the subfunction as 360 // Don't do anything here, so that ASSERT works in the subfunction as
300 // expected. 361 // expected.
301 } 362 }
363
364 TEST(BrokerProcess, OpenCpuinfoWithClientCheckRecursive) {
365 TestOpenCpuinfo(true /* fast_check_in_client */, true /* recursive */);
366 // Don't do anything here, so that ASSERT works in the subfunction as
367 // expected.
368 }
369
370 TEST(BrokerProcess, OpenCpuinfoNoClientCheckRecursive) {
371 TestOpenCpuinfo(false /* fast_check_in_client */, true /* recursive */);
372 // Don't do anything here, so that ASSERT works in the subfunction as
373 // expected.
374 }
302 375
303 TEST(BrokerProcess, OpenFileRW) { 376 TEST(BrokerProcess, OpenFileRW) {
304 ScopedTemporaryFile tempfile; 377 ScopedTemporaryFile tempfile;
305 const char* tempfile_name = tempfile.full_file_name(); 378 const char* tempfile_name = tempfile.full_file_name();
306 379
307 std::vector<std::string> whitelist; 380 std::vector<syscall_broker::BrokerPermission> permissions;
308 whitelist.push_back(tempfile_name); 381 permissions.push_back(BROKER_PERM_READ_WRITE(tempfile_name));
309 382
310 BrokerProcess open_broker(EPERM, whitelist, whitelist); 383 BrokerProcess open_broker(EPERM, permissions);
311 ASSERT_TRUE(open_broker.Init(base::Bind(&NoOpCallback))); 384 ASSERT_TRUE(open_broker.Init(base::Bind(&NoOpCallback)));
312 385
313 // Check we can access that file with read or write. 386 // Check we can access that file with read or write.
314 int can_access = open_broker.Access(tempfile_name, R_OK | W_OK); 387 int can_access = open_broker.Access(tempfile_name, R_OK | W_OK);
315 ASSERT_EQ(can_access, 0); 388 ASSERT_EQ(can_access, 0);
316 389
317 int tempfile2 = -1; 390 int tempfile2 = -1;
318 tempfile2 = open_broker.Open(tempfile_name, O_RDWR); 391 tempfile2 = open_broker.Open(tempfile_name, O_RDWR);
319 ASSERT_GE(tempfile2, 0); 392 ASSERT_GE(tempfile2, 0);
320 393
321 // Write to the descriptor opened by the broker. 394 // Write to the descriptor opened by the broker.
322 char test_text[] = "TESTTESTTEST"; 395 char test_text[] = "TESTTESTTEST";
323 ssize_t len = write(tempfile2, test_text, sizeof(test_text)); 396 ssize_t len = write(tempfile2, test_text, sizeof(test_text));
324 ASSERT_EQ(len, static_cast<ssize_t>(sizeof(test_text))); 397 ASSERT_EQ(len, static_cast<ssize_t>(sizeof(test_text)));
325 398
326 // Read back from the original file descriptor what we wrote through 399 // Read back from the original file descriptor what we wrote through
327 // the descriptor provided by the broker. 400 // the descriptor provided by the broker.
328 char buf[1024]; 401 char buf[1024];
329 len = read(tempfile.fd(), buf, sizeof(buf)); 402 len = read(tempfile.fd(), buf, sizeof(buf));
330 403
331 ASSERT_EQ(len, static_cast<ssize_t>(sizeof(test_text))); 404 ASSERT_EQ(len, static_cast<ssize_t>(sizeof(test_text)));
332 ASSERT_EQ(memcmp(test_text, buf, sizeof(test_text)), 0); 405 ASSERT_EQ(memcmp(test_text, buf, sizeof(test_text)), 0);
333 406
334 ASSERT_EQ(close(tempfile2), 0); 407 ASSERT_EQ(close(tempfile2), 0);
335 } 408 }
336 409
337 // SANDBOX_TEST because the process could die with a SIGPIPE 410 // SANDBOX_TEST because the process could die with a SIGPIPE
338 // and we want this to happen in a subprocess. 411 // and we want this to happen in a subprocess.
339 SANDBOX_TEST(BrokerProcess, BrokerDied) { 412 SANDBOX_TEST(BrokerProcess, BrokerDied) {
340 std::vector<std::string> read_whitelist; 413 const char kCpuInfo[] = "/proc/cpuinfo";
341 read_whitelist.push_back("/proc/cpuinfo"); 414 std::vector<syscall_broker::BrokerPermission> permissions;
415 permissions.push_back(BROKER_PERM_READ_ONLY(kCpuInfo));
342 416
343 BrokerProcess open_broker(EPERM, 417 BrokerProcess open_broker(EPERM, permissions, true /* fast_check_in_client */,
344 read_whitelist,
345 std::vector<std::string>(),
346 true /* fast_check_in_client */,
347 true /* quiet_failures_for_tests */); 418 true /* quiet_failures_for_tests */);
348 SANDBOX_ASSERT(open_broker.Init(base::Bind(&NoOpCallback))); 419 SANDBOX_ASSERT(open_broker.Init(base::Bind(&NoOpCallback)));
349 const pid_t broker_pid = open_broker.broker_pid(); 420 const pid_t broker_pid = open_broker.broker_pid();
350 SANDBOX_ASSERT(kill(broker_pid, SIGKILL) == 0); 421 SANDBOX_ASSERT(kill(broker_pid, SIGKILL) == 0);
351 422
352 // Now we check that the broker has been signaled, but do not reap it. 423 // Now we check that the broker has been signaled, but do not reap it.
353 siginfo_t process_info; 424 siginfo_t process_info;
354 SANDBOX_ASSERT(HANDLE_EINTR(waitid( 425 SANDBOX_ASSERT(HANDLE_EINTR(waitid(
355 P_PID, broker_pid, &process_info, WEXITED | WNOWAIT)) == 426 P_PID, broker_pid, &process_info, WEXITED | WNOWAIT)) ==
356 0); 427 0);
357 SANDBOX_ASSERT(broker_pid == process_info.si_pid); 428 SANDBOX_ASSERT(broker_pid == process_info.si_pid);
358 SANDBOX_ASSERT(CLD_KILLED == process_info.si_code); 429 SANDBOX_ASSERT(CLD_KILLED == process_info.si_code);
359 SANDBOX_ASSERT(SIGKILL == process_info.si_status); 430 SANDBOX_ASSERT(SIGKILL == process_info.si_status);
360 431
361 // Check that doing Open with a dead broker won't SIGPIPE us. 432 // Check that doing Open with a dead broker won't SIGPIPE us.
362 SANDBOX_ASSERT(open_broker.Open("/proc/cpuinfo", O_RDONLY) == -ENOMEM); 433 SANDBOX_ASSERT(open_broker.Open(kCpuInfo, O_RDONLY) == -ENOMEM);
363 SANDBOX_ASSERT(open_broker.Access("/proc/cpuinfo", O_RDONLY) == -ENOMEM); 434 SANDBOX_ASSERT(open_broker.Access(kCpuInfo, O_RDONLY) == -ENOMEM);
364 } 435 }
365 436
366 void TestOpenComplexFlags(bool fast_check_in_client) { 437 void TestOpenComplexFlags(bool fast_check_in_client) {
367 const char kCpuInfo[] = "/proc/cpuinfo"; 438 const char kCpuInfo[] = "/proc/cpuinfo";
368 std::vector<std::string> whitelist; 439 std::vector<syscall_broker::BrokerPermission> permissions;
369 whitelist.push_back(kCpuInfo); 440 permissions.push_back(BROKER_PERM_READ_ONLY(kCpuInfo));
370 441
371 BrokerProcess open_broker(EPERM, whitelist, whitelist, fast_check_in_client); 442 BrokerProcess open_broker(EPERM, permissions, fast_check_in_client);
372 ASSERT_TRUE(open_broker.Init(base::Bind(&NoOpCallback))); 443 ASSERT_TRUE(open_broker.Init(base::Bind(&NoOpCallback)));
373 // Test that we do the right thing for O_CLOEXEC and O_NONBLOCK. 444 // Test that we do the right thing for O_CLOEXEC and O_NONBLOCK.
374 int fd = -1; 445 int fd = -1;
375 int ret = 0; 446 int ret = 0;
376 fd = open_broker.Open(kCpuInfo, O_RDONLY); 447 fd = open_broker.Open(kCpuInfo, O_RDONLY);
377 ASSERT_GE(fd, 0); 448 ASSERT_GE(fd, 0);
378 ret = fcntl(fd, F_GETFL); 449 ret = fcntl(fd, F_GETFL);
379 ASSERT_NE(-1, ret); 450 ASSERT_NE(-1, ret);
380 // The descriptor shouldn't have the O_CLOEXEC attribute, nor O_NONBLOCK. 451 // The descriptor shouldn't have the O_CLOEXEC attribute, nor O_NONBLOCK.
381 ASSERT_EQ(0, ret & (O_CLOEXEC | O_NONBLOCK)); 452 ASSERT_EQ(0, ret & (O_CLOEXEC | O_NONBLOCK));
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 511
441 // Valgrind doesn't allow changing the hard descriptor limit, so we only 512 // Valgrind doesn't allow changing the hard descriptor limit, so we only
442 // change the soft descriptor limit here. 513 // change the soft descriptor limit here.
443 struct rlimit rlim; 514 struct rlimit rlim;
444 SANDBOX_ASSERT(0 == getrlimit(RLIMIT_NOFILE, &rlim)); 515 SANDBOX_ASSERT(0 == getrlimit(RLIMIT_NOFILE, &rlim));
445 SANDBOX_ASSERT(fd_limit <= rlim.rlim_cur); 516 SANDBOX_ASSERT(fd_limit <= rlim.rlim_cur);
446 rlim.rlim_cur = fd_limit; 517 rlim.rlim_cur = fd_limit;
447 SANDBOX_ASSERT(0 == setrlimit(RLIMIT_NOFILE, &rlim)); 518 SANDBOX_ASSERT(0 == setrlimit(RLIMIT_NOFILE, &rlim));
448 519
449 static const char kCpuInfo[] = "/proc/cpuinfo"; 520 static const char kCpuInfo[] = "/proc/cpuinfo";
450 std::vector<std::string> read_whitelist; 521 std::vector<syscall_broker::BrokerPermission> permissions;
451 read_whitelist.push_back(kCpuInfo); 522 permissions.push_back(BROKER_PERM_READ_ONLY(kCpuInfo));
452 523
453 BrokerProcess open_broker(EPERM, read_whitelist, std::vector<std::string>()); 524 BrokerProcess open_broker(EPERM, permissions);
454 SANDBOX_ASSERT(open_broker.Init(base::Bind(&NoOpCallback))); 525 SANDBOX_ASSERT(open_broker.Init(base::Bind(&NoOpCallback)));
455 526
456 const int ipc_fd = BrokerProcessTestHelper::get_ipc_socketpair(&open_broker); 527 const int ipc_fd = BrokerProcessTestHelper::get_ipc_socketpair(&open_broker);
457 SANDBOX_ASSERT(ipc_fd >= 0); 528 SANDBOX_ASSERT(ipc_fd >= 0);
458 529
459 static const char kBogus[] = "not a pickle"; 530 static const char kBogus[] = "not a pickle";
460 std::vector<int> fds; 531 std::vector<int> fds;
461 fds.push_back(message_fd.get()); 532 fds.push_back(message_fd.get());
462 533
463 // The broker process should only have a couple spare file descriptors 534 // The broker process should only have a couple spare file descriptors
464 // available, but for good measure we send it fd_limit bogus IPCs anyway. 535 // available, but for good measure we send it fd_limit bogus IPCs anyway.
465 for (rlim_t i = 0; i < fd_limit; ++i) { 536 for (rlim_t i = 0; i < fd_limit; ++i) {
466 SANDBOX_ASSERT( 537 SANDBOX_ASSERT(
467 UnixDomainSocket::SendMsg(ipc_fd, kBogus, sizeof(kBogus), fds)); 538 UnixDomainSocket::SendMsg(ipc_fd, kBogus, sizeof(kBogus), fds));
468 } 539 }
469 540
470 const int fd = open_broker.Open(kCpuInfo, O_RDONLY); 541 const int fd = open_broker.Open(kCpuInfo, O_RDONLY);
471 SANDBOX_ASSERT(fd >= 0); 542 SANDBOX_ASSERT(fd >= 0);
472 SANDBOX_ASSERT(0 == IGNORE_EINTR(close(fd))); 543 SANDBOX_ASSERT(0 == IGNORE_EINTR(close(fd)));
473 } 544 }
474 545
546 void GetTempFileName(char* name, size_t len) {
547 #if defined(OS_ANDROID)
548 static const char file_template[] = "/data/local/tmp/BrokerTempFileXXXXXX";
549 #else
550 static const char file_template[] = "/tmp/BrokerTempFileXXXXXX";
551 #endif // defined(OS_ANDROID)
552
553 ASSERT_GT(len, sizeof(file_template));
554
555 strncpy(name, file_template, len);
556 int fd = mkstemp(name);
557 ASSERT_GT(fd, 0);
558 ASSERT_EQ(0, unlink(name));
559 ASSERT_EQ(0, IGNORE_EINTR(close(fd)));
560 }
561
562 TEST(BrokerProcess, CreateFile) {
563 char tempfile_name[256] = "";
564
565 GetTempFileName(tempfile_name, sizeof(tempfile_name));
566
567 std::vector<syscall_broker::BrokerPermission> permissions;
568 permissions.push_back(BROKER_PERM_READ_WRITE_CREATE(tempfile_name));
569
570 BrokerProcess open_broker(EPERM, permissions);
571 ASSERT_TRUE(open_broker.Init(base::Bind(&NoOpCallback)));
572
573 int fd = -1;
574
575 // Try without O_EXCL
576 fd = open_broker.Open(tempfile_name, O_RDWR | O_CREAT);
577 ASSERT_EQ(fd, -1);
578
579 // Create a file
580 fd = open_broker.Open(tempfile_name, O_RDWR | O_CREAT | O_EXCL);
581 ASSERT_GE(fd, 0);
582
583 // Write to the descriptor opened by the broker.
584 char test_text[] = "TESTTESTTEST";
585 ssize_t len = write(fd, test_text, sizeof(test_text));
586 ASSERT_EQ(len, static_cast<ssize_t>(sizeof(test_text)));
587
588 ASSERT_EQ(close(fd), 0);
589
590 int fd_check = open(tempfile_name, O_RDONLY);
591 ASSERT_GE(fd_check, 0);
592 char buf[1024];
593 len = read(fd_check, buf, sizeof(buf));
594
595 ASSERT_EQ(len, static_cast<ssize_t>(sizeof(test_text)));
596 ASSERT_EQ(memcmp(test_text, buf, sizeof(test_text)), 0);
597
598 ASSERT_EQ(close(fd_check), 0);
599 }
600
475 } // namespace sandbox 601 } // namespace sandbox
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698