Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / sandbox / linux / services / broker_process_unittest.cc
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
3 // found in the LICENSE file.
4
5 #include "sandbox/linux/services/broker_process.h"
6
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <sys/resource.h>
10 #include <sys/stat.h>
11 #include <sys/types.h>
12 #include <sys/wait.h>
13 #include <unistd.h>
14
15 #include <algorithm>
16 #include <string>
17 #include <vector>
18
19 #include "base/basictypes.h"
20 #include "base/bind.h"
21 #include "base/files/file_util.h"
22 #include "base/files/scoped_file.h"
23 #include "base/logging.h"
24 #include "base/memory/scoped_ptr.h"
25 #include "base/posix/eintr_wrapper.h"
26 #include "base/posix/unix_domain_socket_linux.h"
27 #include "sandbox/linux/tests/scoped_temporary_file.h"
28 #include "sandbox/linux/tests/test_utils.h"
29 #include "sandbox/linux/tests/unit_tests.h"
30 #include "testing/gtest/include/gtest/gtest.h"
31
32 namespace sandbox {
33
34 class BrokerProcessTestHelper {
35  public:
36   static int get_ipc_socketpair(const BrokerProcess* broker) {
37     return broker->ipc_socketpair_;
38   }
39 };
40
41 namespace {
42
43 bool NoOpCallback() { return true; }
44
45 }  // namespace
46
47 TEST(BrokerProcess, CreateAndDestroy) {
48   std::vector<std::string> read_whitelist;
49   read_whitelist.push_back("/proc/cpuinfo");
50
51   scoped_ptr<BrokerProcess> open_broker(
52       new BrokerProcess(EPERM, read_whitelist, std::vector<std::string>()));
53   ASSERT_TRUE(open_broker->Init(base::Bind(&NoOpCallback)));
54
55   ASSERT_TRUE(TestUtils::CurrentProcessHasChildren());
56   // Destroy the broker and check it has exited properly.
57   open_broker.reset();
58   ASSERT_FALSE(TestUtils::CurrentProcessHasChildren());
59 }
60
61 TEST(BrokerProcess, TestOpenAccessNull) {
62   const std::vector<std::string> empty;
63   BrokerProcess open_broker(EPERM, empty, empty);
64   ASSERT_TRUE(open_broker.Init(base::Bind(&NoOpCallback)));
65
66   int fd = open_broker.Open(NULL, O_RDONLY);
67   ASSERT_EQ(fd, -EFAULT);
68
69   int ret = open_broker.Access(NULL, F_OK);
70   ASSERT_EQ(ret, -EFAULT);
71 }
72
73 void TestOpenFilePerms(bool fast_check_in_client, int denied_errno) {
74   const char kR_WhiteListed[] = "/proc/DOESNOTEXIST1";
75   // We can't debug the init process, and shouldn't be able to access
76   // its auxv file.
77   const char kR_WhiteListedButDenied[] = "/proc/1/auxv";
78   const char kW_WhiteListed[] = "/proc/DOESNOTEXIST2";
79   const char kRW_WhiteListed[] = "/proc/DOESNOTEXIST3";
80   const char k_NotWhitelisted[] = "/proc/DOESNOTEXIST4";
81
82   std::vector<std::string> read_whitelist;
83   read_whitelist.push_back(kR_WhiteListed);
84   read_whitelist.push_back(kR_WhiteListedButDenied);
85   read_whitelist.push_back(kRW_WhiteListed);
86
87   std::vector<std::string> write_whitelist;
88   write_whitelist.push_back(kW_WhiteListed);
89   write_whitelist.push_back(kRW_WhiteListed);
90
91   BrokerProcess open_broker(denied_errno,
92                             read_whitelist,
93                             write_whitelist,
94                             fast_check_in_client);
95   ASSERT_TRUE(open_broker.Init(base::Bind(&NoOpCallback)));
96
97   int fd = -1;
98   fd = open_broker.Open(kR_WhiteListed, O_RDONLY);
99   ASSERT_EQ(fd, -ENOENT);
100   fd = open_broker.Open(kR_WhiteListed, O_WRONLY);
101   ASSERT_EQ(fd, -denied_errno);
102   fd = open_broker.Open(kR_WhiteListed, O_RDWR);
103   ASSERT_EQ(fd, -denied_errno);
104   int ret = -1;
105   ret = open_broker.Access(kR_WhiteListed, F_OK);
106   ASSERT_EQ(ret, -ENOENT);
107   ret = open_broker.Access(kR_WhiteListed, R_OK);
108   ASSERT_EQ(ret, -ENOENT);
109   ret = open_broker.Access(kR_WhiteListed, W_OK);
110   ASSERT_EQ(ret, -denied_errno);
111   ret = open_broker.Access(kR_WhiteListed, R_OK | W_OK);
112   ASSERT_EQ(ret, -denied_errno);
113   ret = open_broker.Access(kR_WhiteListed, X_OK);
114   ASSERT_EQ(ret, -denied_errno);
115   ret = open_broker.Access(kR_WhiteListed, R_OK | X_OK);
116   ASSERT_EQ(ret, -denied_errno);
117
118   // Android sometimes runs tests as root.
119   // This part of the test requires a process that doesn't have
120   // CAP_DAC_OVERRIDE. We check against a root euid as a proxy for that.
121   if (geteuid()) {
122     fd = open_broker.Open(kR_WhiteListedButDenied, O_RDONLY);
123     // The broker process will allow this, but the normal permission system
124     // won't.
125     ASSERT_EQ(fd, -EACCES);
126     fd = open_broker.Open(kR_WhiteListedButDenied, O_WRONLY);
127     ASSERT_EQ(fd, -denied_errno);
128     fd = open_broker.Open(kR_WhiteListedButDenied, O_RDWR);
129     ASSERT_EQ(fd, -denied_errno);
130     ret = open_broker.Access(kR_WhiteListedButDenied, F_OK);
131     // The normal permission system will let us check that the file exists.
132     ASSERT_EQ(ret, 0);
133     ret = open_broker.Access(kR_WhiteListedButDenied, R_OK);
134     ASSERT_EQ(ret, -EACCES);
135     ret = open_broker.Access(kR_WhiteListedButDenied, W_OK);
136     ASSERT_EQ(ret, -denied_errno);
137     ret = open_broker.Access(kR_WhiteListedButDenied, R_OK | W_OK);
138     ASSERT_EQ(ret, -denied_errno);
139     ret = open_broker.Access(kR_WhiteListedButDenied, X_OK);
140     ASSERT_EQ(ret, -denied_errno);
141     ret = open_broker.Access(kR_WhiteListedButDenied, R_OK | X_OK);
142     ASSERT_EQ(ret, -denied_errno);
143   }
144
145   fd = open_broker.Open(kW_WhiteListed, O_RDONLY);
146   ASSERT_EQ(fd, -denied_errno);
147   fd = open_broker.Open(kW_WhiteListed, O_WRONLY);
148   ASSERT_EQ(fd, -ENOENT);
149   fd = open_broker.Open(kW_WhiteListed, O_RDWR);
150   ASSERT_EQ(fd, -denied_errno);
151   ret = open_broker.Access(kW_WhiteListed, F_OK);
152   ASSERT_EQ(ret, -ENOENT);
153   ret = open_broker.Access(kW_WhiteListed, R_OK);
154   ASSERT_EQ(ret, -denied_errno);
155   ret = open_broker.Access(kW_WhiteListed, W_OK);
156   ASSERT_EQ(ret, -ENOENT);
157   ret = open_broker.Access(kW_WhiteListed, R_OK | W_OK);
158   ASSERT_EQ(ret, -denied_errno);
159   ret = open_broker.Access(kW_WhiteListed, X_OK);
160   ASSERT_EQ(ret, -denied_errno);
161   ret = open_broker.Access(kW_WhiteListed, R_OK | X_OK);
162   ASSERT_EQ(ret, -denied_errno);
163
164   fd = open_broker.Open(kRW_WhiteListed, O_RDONLY);
165   ASSERT_EQ(fd, -ENOENT);
166   fd = open_broker.Open(kRW_WhiteListed, O_WRONLY);
167   ASSERT_EQ(fd, -ENOENT);
168   fd = open_broker.Open(kRW_WhiteListed, O_RDWR);
169   ASSERT_EQ(fd, -ENOENT);
170   ret = open_broker.Access(kRW_WhiteListed, F_OK);
171   ASSERT_EQ(ret, -ENOENT);
172   ret = open_broker.Access(kRW_WhiteListed, R_OK);
173   ASSERT_EQ(ret, -ENOENT);
174   ret = open_broker.Access(kRW_WhiteListed, W_OK);
175   ASSERT_EQ(ret, -ENOENT);
176   ret = open_broker.Access(kRW_WhiteListed, R_OK | W_OK);
177   ASSERT_EQ(ret, -ENOENT);
178   ret = open_broker.Access(kRW_WhiteListed, X_OK);
179   ASSERT_EQ(ret, -denied_errno);
180   ret = open_broker.Access(kRW_WhiteListed, R_OK | X_OK);
181   ASSERT_EQ(ret, -denied_errno);
182
183   fd = open_broker.Open(k_NotWhitelisted, O_RDONLY);
184   ASSERT_EQ(fd, -denied_errno);
185   fd = open_broker.Open(k_NotWhitelisted, O_WRONLY);
186   ASSERT_EQ(fd, -denied_errno);
187   fd = open_broker.Open(k_NotWhitelisted, O_RDWR);
188   ASSERT_EQ(fd, -denied_errno);
189   ret = open_broker.Access(k_NotWhitelisted, F_OK);
190   ASSERT_EQ(ret, -denied_errno);
191   ret = open_broker.Access(k_NotWhitelisted, R_OK);
192   ASSERT_EQ(ret, -denied_errno);
193   ret = open_broker.Access(k_NotWhitelisted, W_OK);
194   ASSERT_EQ(ret, -denied_errno);
195   ret = open_broker.Access(k_NotWhitelisted, R_OK | W_OK);
196   ASSERT_EQ(ret, -denied_errno);
197   ret = open_broker.Access(k_NotWhitelisted, X_OK);
198   ASSERT_EQ(ret, -denied_errno);
199   ret = open_broker.Access(k_NotWhitelisted, R_OK | X_OK);
200   ASSERT_EQ(ret, -denied_errno);
201
202   // We have some extra sanity check for clearly wrong values.
203   fd = open_broker.Open(kRW_WhiteListed, O_RDONLY | O_WRONLY | O_RDWR);
204   ASSERT_EQ(fd, -denied_errno);
205
206   // It makes no sense to allow O_CREAT in a 2-parameters open. Ensure this
207   // is denied.
208   fd = open_broker.Open(kRW_WhiteListed, O_RDWR | O_CREAT);
209   ASSERT_EQ(fd, -denied_errno);
210 }
211
212 // Run the same thing twice. The second time, we make sure that no security
213 // check is performed on the client.
214 TEST(BrokerProcess, OpenFilePermsWithClientCheck) {
215   TestOpenFilePerms(true /* fast_check_in_client */, EPERM);
216   // Don't do anything here, so that ASSERT works in the subfunction as
217   // expected.
218 }
219
220 TEST(BrokerProcess, OpenOpenFilePermsNoClientCheck) {
221   TestOpenFilePerms(false /* fast_check_in_client */, EPERM);
222   // Don't do anything here, so that ASSERT works in the subfunction as
223   // expected.
224 }
225
226 // Run the same twice again, but with ENOENT instead of EPERM.
227 TEST(BrokerProcess, OpenFilePermsWithClientCheckNoEnt) {
228   TestOpenFilePerms(true /* fast_check_in_client */, ENOENT);
229   // Don't do anything here, so that ASSERT works in the subfunction as
230   // expected.
231 }
232
233 TEST(BrokerProcess, OpenOpenFilePermsNoClientCheckNoEnt) {
234   TestOpenFilePerms(false /* fast_check_in_client */, ENOENT);
235   // Don't do anything here, so that ASSERT works in the subfunction as
236   // expected.
237 }
238
239 void TestOpenCpuinfo(bool fast_check_in_client) {
240   const char kFileCpuInfo[] = "/proc/cpuinfo";
241   std::vector<std::string> read_whitelist;
242   read_whitelist.push_back(kFileCpuInfo);
243
244   scoped_ptr<BrokerProcess> open_broker(new BrokerProcess(
245       EPERM, read_whitelist, std::vector<std::string>(), fast_check_in_client));
246   ASSERT_TRUE(open_broker->Init(base::Bind(&NoOpCallback)));
247
248   int fd = -1;
249   fd = open_broker->Open(kFileCpuInfo, O_RDWR);
250   base::ScopedFD fd_closer(fd);
251   ASSERT_EQ(fd, -EPERM);
252
253   // Check we can read /proc/cpuinfo.
254   int can_access = open_broker->Access(kFileCpuInfo, R_OK);
255   ASSERT_EQ(can_access, 0);
256   can_access = open_broker->Access(kFileCpuInfo, W_OK);
257   ASSERT_EQ(can_access, -EPERM);
258   // Check we can not write /proc/cpuinfo.
259
260   // Open cpuinfo via the broker.
261   int cpuinfo_fd = open_broker->Open(kFileCpuInfo, O_RDONLY);
262   base::ScopedFD cpuinfo_fd_closer(cpuinfo_fd);
263   ASSERT_GE(cpuinfo_fd, 0);
264   char buf[3];
265   memset(buf, 0, sizeof(buf));
266   int read_len1 = read(cpuinfo_fd, buf, sizeof(buf));
267   ASSERT_GT(read_len1, 0);
268
269   // Open cpuinfo directly.
270   int cpuinfo_fd2 = open(kFileCpuInfo, O_RDONLY);
271   base::ScopedFD cpuinfo_fd2_closer(cpuinfo_fd2);
272   ASSERT_GE(cpuinfo_fd2, 0);
273   char buf2[3];
274   memset(buf2, 1, sizeof(buf2));
275   int read_len2 = read(cpuinfo_fd2, buf2, sizeof(buf2));
276   ASSERT_GT(read_len1, 0);
277
278   // The following is not guaranteed true, but will be in practice.
279   ASSERT_EQ(read_len1, read_len2);
280   // Compare the cpuinfo as returned by the broker with the one we opened
281   // ourselves.
282   ASSERT_EQ(memcmp(buf, buf2, read_len1), 0);
283
284   ASSERT_TRUE(TestUtils::CurrentProcessHasChildren());
285   open_broker.reset();
286   ASSERT_FALSE(TestUtils::CurrentProcessHasChildren());
287 }
288
289 // Run the same thing twice. The second time, we make sure that no security
290 // check is performed on the client.
291 TEST(BrokerProcess, OpenCpuinfoWithClientCheck) {
292   TestOpenCpuinfo(true /* fast_check_in_client */);
293   // Don't do anything here, so that ASSERT works in the subfunction as
294   // expected.
295 }
296
297 TEST(BrokerProcess, OpenCpuinfoNoClientCheck) {
298   TestOpenCpuinfo(false /* fast_check_in_client */);
299   // Don't do anything here, so that ASSERT works in the subfunction as
300   // expected.
301 }
302
303 TEST(BrokerProcess, OpenFileRW) {
304   ScopedTemporaryFile tempfile;
305   const char* tempfile_name = tempfile.full_file_name();
306
307   std::vector<std::string> whitelist;
308   whitelist.push_back(tempfile_name);
309
310   BrokerProcess open_broker(EPERM, whitelist, whitelist);
311   ASSERT_TRUE(open_broker.Init(base::Bind(&NoOpCallback)));
312
313   // Check we can access that file with read or write.
314   int can_access = open_broker.Access(tempfile_name, R_OK | W_OK);
315   ASSERT_EQ(can_access, 0);
316
317   int tempfile2 = -1;
318   tempfile2 = open_broker.Open(tempfile_name, O_RDWR);
319   ASSERT_GE(tempfile2, 0);
320
321   // Write to the descriptor opened by the broker.
322   char test_text[] = "TESTTESTTEST";
323   ssize_t len = write(tempfile2, test_text, sizeof(test_text));
324   ASSERT_EQ(len, static_cast<ssize_t>(sizeof(test_text)));
325
326   // Read back from the original file descriptor what we wrote through
327   // the descriptor provided by the broker.
328   char buf[1024];
329   len = read(tempfile.fd(), buf, sizeof(buf));
330
331   ASSERT_EQ(len, static_cast<ssize_t>(sizeof(test_text)));
332   ASSERT_EQ(memcmp(test_text, buf, sizeof(test_text)), 0);
333
334   ASSERT_EQ(close(tempfile2), 0);
335 }
336
337 // SANDBOX_TEST because the process could die with a SIGPIPE
338 // and we want this to happen in a subprocess.
339 SANDBOX_TEST(BrokerProcess, BrokerDied) {
340   std::vector<std::string> read_whitelist;
341   read_whitelist.push_back("/proc/cpuinfo");
342
343   BrokerProcess open_broker(EPERM,
344                             read_whitelist,
345                             std::vector<std::string>(),
346                             true /* fast_check_in_client */,
347                             true /* quiet_failures_for_tests */);
348   SANDBOX_ASSERT(open_broker.Init(base::Bind(&NoOpCallback)));
349   const pid_t broker_pid = open_broker.broker_pid();
350   SANDBOX_ASSERT(kill(broker_pid, SIGKILL) == 0);
351
352   // Now we check that the broker has been signaled, but do not reap it.
353   siginfo_t process_info;
354   SANDBOX_ASSERT(HANDLE_EINTR(waitid(
355                      P_PID, broker_pid, &process_info, WEXITED | WNOWAIT)) ==
356                  0);
357   SANDBOX_ASSERT(broker_pid == process_info.si_pid);
358   SANDBOX_ASSERT(CLD_KILLED == process_info.si_code);
359   SANDBOX_ASSERT(SIGKILL == process_info.si_status);
360
361   // Check that doing Open with a dead broker won't SIGPIPE us.
362   SANDBOX_ASSERT(open_broker.Open("/proc/cpuinfo", O_RDONLY) == -ENOMEM);
363   SANDBOX_ASSERT(open_broker.Access("/proc/cpuinfo", O_RDONLY) == -ENOMEM);
364 }
365
366 void TestOpenComplexFlags(bool fast_check_in_client) {
367   const char kCpuInfo[] = "/proc/cpuinfo";
368   std::vector<std::string> whitelist;
369   whitelist.push_back(kCpuInfo);
370
371   BrokerProcess open_broker(EPERM,
372                             whitelist,
373                             whitelist,
374                             fast_check_in_client);
375   ASSERT_TRUE(open_broker.Init(base::Bind(&NoOpCallback)));
376   // Test that we do the right thing for O_CLOEXEC and O_NONBLOCK.
377   int fd = -1;
378   int ret = 0;
379   fd = open_broker.Open(kCpuInfo, O_RDONLY);
380   ASSERT_GE(fd, 0);
381   ret = fcntl(fd, F_GETFL);
382   ASSERT_NE(-1, ret);
383   // The descriptor shouldn't have the O_CLOEXEC attribute, nor O_NONBLOCK.
384   ASSERT_EQ(0, ret & (O_CLOEXEC | O_NONBLOCK));
385   ASSERT_EQ(0, close(fd));
386
387   fd = open_broker.Open(kCpuInfo, O_RDONLY | O_CLOEXEC);
388   ASSERT_GE(fd, 0);
389   ret = fcntl(fd, F_GETFD);
390   ASSERT_NE(-1, ret);
391   // Important: use F_GETFD, not F_GETFL. The O_CLOEXEC flag in F_GETFL
392   // is actually not used by the kernel.
393   ASSERT_TRUE(FD_CLOEXEC & ret);
394   ASSERT_EQ(0, close(fd));
395
396   fd = open_broker.Open(kCpuInfo, O_RDONLY | O_NONBLOCK);
397   ASSERT_GE(fd, 0);
398   ret = fcntl(fd, F_GETFL);
399   ASSERT_NE(-1, ret);
400   ASSERT_TRUE(O_NONBLOCK & ret);
401   ASSERT_EQ(0, close(fd));
402 }
403
404 TEST(BrokerProcess, OpenComplexFlagsWithClientCheck) {
405   TestOpenComplexFlags(true /* fast_check_in_client */);
406   // Don't do anything here, so that ASSERT works in the subfunction as
407   // expected.
408 }
409
410 TEST(BrokerProcess, OpenComplexFlagsNoClientCheck) {
411   TestOpenComplexFlags(false /* fast_check_in_client */);
412   // Don't do anything here, so that ASSERT works in the subfunction as
413   // expected.
414 }
415
416 // We need to allow noise because the broker will log when it receives our
417 // bogus IPCs.
418 SANDBOX_TEST_ALLOW_NOISE(BrokerProcess, RecvMsgDescriptorLeak) {
419   // Android creates a socket on first use of the LOG call.
420   // We need to ensure this socket is open before we
421   // begin the test.
422   LOG(INFO) << "Ensure Android LOG socket is allocated";
423
424   // Find the four lowest available file descriptors.
425   int available_fds[4];
426   SANDBOX_ASSERT(0 == pipe(available_fds));
427   SANDBOX_ASSERT(0 == pipe(available_fds + 2));
428
429   // Save one FD to send to the broker later, and close the others.
430   base::ScopedFD message_fd(available_fds[0]);
431   for (size_t i = 1; i < arraysize(available_fds); i++) {
432     SANDBOX_ASSERT(0 == IGNORE_EINTR(close(available_fds[i])));
433   }
434
435   // Lower our file descriptor limit to just allow three more file descriptors
436   // to be allocated.  (N.B., RLIMIT_NOFILE doesn't limit the number of file
437   // descriptors a process can have: it only limits the highest value that can
438   // be assigned to newly-created descriptors allocated by the process.)
439   const rlim_t fd_limit =
440       1 + *std::max_element(available_fds,
441                             available_fds + arraysize(available_fds));
442
443   // Valgrind doesn't allow changing the hard descriptor limit, so we only
444   // change the soft descriptor limit here.
445   struct rlimit rlim;
446   SANDBOX_ASSERT(0 == getrlimit(RLIMIT_NOFILE, &rlim));
447   SANDBOX_ASSERT(fd_limit <= rlim.rlim_cur);
448   rlim.rlim_cur = fd_limit;
449   SANDBOX_ASSERT(0 == setrlimit(RLIMIT_NOFILE, &rlim));
450
451   static const char kCpuInfo[] = "/proc/cpuinfo";
452   std::vector<std::string> read_whitelist;
453   read_whitelist.push_back(kCpuInfo);
454
455   BrokerProcess open_broker(EPERM, read_whitelist, std::vector<std::string>());
456   SANDBOX_ASSERT(open_broker.Init(base::Bind(&NoOpCallback)));
457
458   const int ipc_fd = BrokerProcessTestHelper::get_ipc_socketpair(&open_broker);
459   SANDBOX_ASSERT(ipc_fd >= 0);
460
461   static const char kBogus[] = "not a pickle";
462   std::vector<int> fds;
463   fds.push_back(message_fd.get());
464
465   // The broker process should only have a couple spare file descriptors
466   // available, but for good measure we send it fd_limit bogus IPCs anyway.
467   for (rlim_t i = 0; i < fd_limit; ++i) {
468     SANDBOX_ASSERT(
469         UnixDomainSocket::SendMsg(ipc_fd, kBogus, sizeof(kBogus), fds));
470   }
471
472   const int fd = open_broker.Open(kCpuInfo, O_RDONLY);
473   SANDBOX_ASSERT(fd >= 0);
474   SANDBOX_ASSERT(0 == IGNORE_EINTR(close(fd)));
475 }
476
477 }  // namespace sandbox