- add sources.
[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/stat.h>
10 #include <sys/types.h>
11 #include <sys/wait.h>
12 #include <unistd.h>
13
14 #include <string>
15 #include <vector>
16
17 #include "base/basictypes.h"
18 #include "base/logging.h"
19 #include "base/posix/eintr_wrapper.h"
20 #include "sandbox/linux/tests/unit_tests.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22
23 namespace sandbox {
24
25 namespace {
26
27 // Creates and open a temporary file on creation and closes
28 // and removes it on destruction.
29 // Unlike base/ helpers, this does not require JNI on Android.
30 class ScopedTemporaryFile {
31  public:
32   ScopedTemporaryFile()
33       : fd_(-1) {
34 #if defined(OS_ANDROID)
35     static const char file_template[] = "/data/local/tmp/ScopedTempFileXXXXXX";
36 #else
37     static const char file_template[] = "/tmp/ScopedTempFileXXXXXX";
38 #endif  // defined(OS_ANDROID)
39     COMPILE_ASSERT(sizeof(full_file_name_) >= sizeof(file_template),
40                    full_file_name_is_large_enough);
41     memcpy(full_file_name_, file_template, sizeof(file_template));
42     fd_ = mkstemp(full_file_name_);
43     CHECK_LE(0, fd_);
44   }
45   ~ScopedTemporaryFile() {
46     CHECK_EQ(0, unlink(full_file_name_));
47     CHECK_EQ(0, HANDLE_EINTR(close(fd_)));
48   }
49
50   int fd() const { return fd_; }
51   const char* full_file_name() const { return full_file_name_; }
52
53  private:
54   int fd_;
55   char full_file_name_[128];
56   DISALLOW_COPY_AND_ASSIGN(ScopedTemporaryFile);
57 };
58
59 }  // namespace
60
61 #if defined(OS_ANDROID)
62   #define DISABLE_ON_ANDROID(function) DISABLED_##function
63 #else
64   #define DISABLE_ON_ANDROID(function) function
65 #endif
66
67 TEST(BrokerProcess, CreateAndDestroy) {
68   std::vector<std::string> read_whitelist;
69   read_whitelist.push_back("/proc/cpuinfo");
70
71   BrokerProcess* open_broker = new BrokerProcess(EPERM,
72                                                  read_whitelist,
73                                                  std::vector<std::string>());
74   ASSERT_TRUE(open_broker->Init(NULL));
75   pid_t broker_pid = open_broker->broker_pid();
76   delete(open_broker);
77
78   // Now we check that the broker has exited properly.
79   int status = 0;
80   ASSERT_EQ(waitpid(broker_pid, &status, 0), broker_pid);
81   ASSERT_TRUE(WIFEXITED(status));
82   ASSERT_EQ(WEXITSTATUS(status), 0);
83 }
84
85 TEST(BrokerProcess, TestOpenAccessNull) {
86   const std::vector<std::string> empty;
87   BrokerProcess open_broker(EPERM, empty, empty);
88   ASSERT_TRUE(open_broker.Init(NULL));
89
90   int fd = open_broker.Open(NULL, O_RDONLY);
91   ASSERT_EQ(fd, -EFAULT);
92
93   int ret = open_broker.Access(NULL, F_OK);
94   ASSERT_EQ(ret, -EFAULT);
95 }
96
97 void TestOpenFilePerms(bool fast_check_in_client, int denied_errno) {
98   const char kR_WhiteListed[] = "/proc/DOESNOTEXIST1";
99   // We can't debug the init process, and shouldn't be able to access
100   // its auxv file.
101   const char kR_WhiteListedButDenied[] = "/proc/1/auxv";
102   const char kW_WhiteListed[] = "/proc/DOESNOTEXIST2";
103   const char kRW_WhiteListed[] = "/proc/DOESNOTEXIST3";
104   const char k_NotWhitelisted[] = "/proc/DOESNOTEXIST4";
105
106   std::vector<std::string> read_whitelist;
107   read_whitelist.push_back(kR_WhiteListed);
108   read_whitelist.push_back(kR_WhiteListedButDenied);
109   read_whitelist.push_back(kRW_WhiteListed);
110
111   std::vector<std::string> write_whitelist;
112   write_whitelist.push_back(kW_WhiteListed);
113   write_whitelist.push_back(kRW_WhiteListed);
114
115   BrokerProcess open_broker(denied_errno,
116                             read_whitelist,
117                             write_whitelist,
118                             fast_check_in_client);
119   ASSERT_TRUE(open_broker.Init(NULL));
120
121   int fd = -1;
122   fd = open_broker.Open(kR_WhiteListed, O_RDONLY);
123   ASSERT_EQ(fd, -ENOENT);
124   fd = open_broker.Open(kR_WhiteListed, O_WRONLY);
125   ASSERT_EQ(fd, -denied_errno);
126   fd = open_broker.Open(kR_WhiteListed, O_RDWR);
127   ASSERT_EQ(fd, -denied_errno);
128   int ret = -1;
129   ret = open_broker.Access(kR_WhiteListed, F_OK);
130   ASSERT_EQ(ret, -ENOENT);
131   ret = open_broker.Access(kR_WhiteListed, R_OK);
132   ASSERT_EQ(ret, -ENOENT);
133   ret = open_broker.Access(kR_WhiteListed, W_OK);
134   ASSERT_EQ(ret, -denied_errno);
135   ret = open_broker.Access(kR_WhiteListed, R_OK | W_OK);
136   ASSERT_EQ(ret, -denied_errno);
137   ret = open_broker.Access(kR_WhiteListed, X_OK);
138   ASSERT_EQ(ret, -denied_errno);
139   ret = open_broker.Access(kR_WhiteListed, R_OK | X_OK);
140   ASSERT_EQ(ret, -denied_errno);
141
142   // Android sometimes runs tests as root.
143   // This part of the test requires a process that doesn't have
144   // CAP_DAC_OVERRIDE. We check against a root euid as a proxy for that.
145   if (geteuid()) {
146     fd = open_broker.Open(kR_WhiteListedButDenied, O_RDONLY);
147     // The broker process will allow this, but the normal permission system
148     // won't.
149     ASSERT_EQ(fd, -EACCES);
150     fd = open_broker.Open(kR_WhiteListedButDenied, O_WRONLY);
151     ASSERT_EQ(fd, -denied_errno);
152     fd = open_broker.Open(kR_WhiteListedButDenied, O_RDWR);
153     ASSERT_EQ(fd, -denied_errno);
154     ret = open_broker.Access(kR_WhiteListedButDenied, F_OK);
155     // The normal permission system will let us check that the file exists.
156     ASSERT_EQ(ret, 0);
157     ret = open_broker.Access(kR_WhiteListedButDenied, R_OK);
158     ASSERT_EQ(ret, -EACCES);
159     ret = open_broker.Access(kR_WhiteListedButDenied, W_OK);
160     ASSERT_EQ(ret, -denied_errno);
161     ret = open_broker.Access(kR_WhiteListedButDenied, R_OK | W_OK);
162     ASSERT_EQ(ret, -denied_errno);
163     ret = open_broker.Access(kR_WhiteListedButDenied, X_OK);
164     ASSERT_EQ(ret, -denied_errno);
165     ret = open_broker.Access(kR_WhiteListedButDenied, R_OK | X_OK);
166     ASSERT_EQ(ret, -denied_errno);
167   }
168
169   fd = open_broker.Open(kW_WhiteListed, O_RDONLY);
170   ASSERT_EQ(fd, -denied_errno);
171   fd = open_broker.Open(kW_WhiteListed, O_WRONLY);
172   ASSERT_EQ(fd, -ENOENT);
173   fd = open_broker.Open(kW_WhiteListed, O_RDWR);
174   ASSERT_EQ(fd, -denied_errno);
175   ret = open_broker.Access(kW_WhiteListed, F_OK);
176   ASSERT_EQ(ret, -ENOENT);
177   ret = open_broker.Access(kW_WhiteListed, R_OK);
178   ASSERT_EQ(ret, -denied_errno);
179   ret = open_broker.Access(kW_WhiteListed, W_OK);
180   ASSERT_EQ(ret, -ENOENT);
181   ret = open_broker.Access(kW_WhiteListed, R_OK | W_OK);
182   ASSERT_EQ(ret, -denied_errno);
183   ret = open_broker.Access(kW_WhiteListed, X_OK);
184   ASSERT_EQ(ret, -denied_errno);
185   ret = open_broker.Access(kW_WhiteListed, R_OK | X_OK);
186   ASSERT_EQ(ret, -denied_errno);
187
188   fd = open_broker.Open(kRW_WhiteListed, O_RDONLY);
189   ASSERT_EQ(fd, -ENOENT);
190   fd = open_broker.Open(kRW_WhiteListed, O_WRONLY);
191   ASSERT_EQ(fd, -ENOENT);
192   fd = open_broker.Open(kRW_WhiteListed, O_RDWR);
193   ASSERT_EQ(fd, -ENOENT);
194   ret = open_broker.Access(kRW_WhiteListed, F_OK);
195   ASSERT_EQ(ret, -ENOENT);
196   ret = open_broker.Access(kRW_WhiteListed, R_OK);
197   ASSERT_EQ(ret, -ENOENT);
198   ret = open_broker.Access(kRW_WhiteListed, W_OK);
199   ASSERT_EQ(ret, -ENOENT);
200   ret = open_broker.Access(kRW_WhiteListed, R_OK | W_OK);
201   ASSERT_EQ(ret, -ENOENT);
202   ret = open_broker.Access(kRW_WhiteListed, X_OK);
203   ASSERT_EQ(ret, -denied_errno);
204   ret = open_broker.Access(kRW_WhiteListed, R_OK | X_OK);
205   ASSERT_EQ(ret, -denied_errno);
206
207   fd = open_broker.Open(k_NotWhitelisted, O_RDONLY);
208   ASSERT_EQ(fd, -denied_errno);
209   fd = open_broker.Open(k_NotWhitelisted, O_WRONLY);
210   ASSERT_EQ(fd, -denied_errno);
211   fd = open_broker.Open(k_NotWhitelisted, O_RDWR);
212   ASSERT_EQ(fd, -denied_errno);
213   ret = open_broker.Access(k_NotWhitelisted, F_OK);
214   ASSERT_EQ(ret, -denied_errno);
215   ret = open_broker.Access(k_NotWhitelisted, R_OK);
216   ASSERT_EQ(ret, -denied_errno);
217   ret = open_broker.Access(k_NotWhitelisted, W_OK);
218   ASSERT_EQ(ret, -denied_errno);
219   ret = open_broker.Access(k_NotWhitelisted, R_OK | W_OK);
220   ASSERT_EQ(ret, -denied_errno);
221   ret = open_broker.Access(k_NotWhitelisted, X_OK);
222   ASSERT_EQ(ret, -denied_errno);
223   ret = open_broker.Access(k_NotWhitelisted, R_OK | X_OK);
224   ASSERT_EQ(ret, -denied_errno);
225
226   // We have some extra sanity check for clearly wrong values.
227   fd = open_broker.Open(kRW_WhiteListed, O_RDONLY|O_WRONLY|O_RDWR);
228   ASSERT_EQ(fd, -denied_errno);
229
230   // It makes no sense to allow O_CREAT in a 2-parameters open. Ensure this
231   // is denied.
232   fd = open_broker.Open(kRW_WhiteListed, O_RDWR|O_CREAT);
233   ASSERT_EQ(fd, -denied_errno);
234 }
235
236 // Run the same thing twice. The second time, we make sure that no security
237 // check is performed on the client.
238 TEST(BrokerProcess, OpenFilePermsWithClientCheck) {
239   TestOpenFilePerms(true /* fast_check_in_client */, EPERM);
240   // Don't do anything here, so that ASSERT works in the subfunction as
241   // expected.
242 }
243
244 TEST(BrokerProcess, OpenOpenFilePermsNoClientCheck) {
245   TestOpenFilePerms(false /* fast_check_in_client */, EPERM);
246   // Don't do anything here, so that ASSERT works in the subfunction as
247   // expected.
248 }
249
250 // Run the same twice again, but with ENOENT instead of EPERM.
251 TEST(BrokerProcess, OpenFilePermsWithClientCheckNoEnt) {
252   TestOpenFilePerms(true /* fast_check_in_client */, ENOENT);
253   // Don't do anything here, so that ASSERT works in the subfunction as
254   // expected.
255 }
256
257 TEST(BrokerProcess, OpenOpenFilePermsNoClientCheckNoEnt) {
258   TestOpenFilePerms(false /* fast_check_in_client */, ENOENT);
259   // Don't do anything here, so that ASSERT works in the subfunction as
260   // expected.
261 }
262
263 void TestOpenCpuinfo(bool fast_check_in_client) {
264   const char kFileCpuInfo[] = "/proc/cpuinfo";
265   std::vector<std::string> read_whitelist;
266   read_whitelist.push_back(kFileCpuInfo);
267
268   BrokerProcess* open_broker = new BrokerProcess(EPERM,
269                                                  read_whitelist,
270                                                  std::vector<std::string>(),
271                                                  fast_check_in_client);
272   ASSERT_TRUE(open_broker->Init(NULL));
273   pid_t broker_pid = open_broker->broker_pid();
274
275   int fd = -1;
276   fd = open_broker->Open(kFileCpuInfo, O_RDWR);
277   ASSERT_EQ(fd, -EPERM);
278
279   // Check we can read /proc/cpuinfo.
280   int can_access = open_broker->Access(kFileCpuInfo, R_OK);
281   ASSERT_EQ(can_access, 0);
282   can_access = open_broker->Access(kFileCpuInfo, W_OK);
283   ASSERT_EQ(can_access, -EPERM);
284   // Check we can not write /proc/cpuinfo.
285
286   // Open cpuinfo via the broker.
287   int cpuinfo_fd = open_broker->Open(kFileCpuInfo, O_RDONLY);
288   ASSERT_GE(cpuinfo_fd, 0);
289   char buf[3];
290   memset(buf, 0, sizeof(buf));
291   int read_len1 = read(cpuinfo_fd, buf, sizeof(buf));
292   ASSERT_GT(read_len1, 0);
293
294   // Open cpuinfo directly.
295   int cpuinfo_fd2 = open(kFileCpuInfo, O_RDONLY);
296   ASSERT_GE(cpuinfo_fd2, 0);
297   char buf2[3];
298   memset(buf2, 1, sizeof(buf2));
299   int read_len2 = read(cpuinfo_fd2, buf2, sizeof(buf2));
300   ASSERT_GT(read_len1, 0);
301
302   // The following is not guaranteed true, but will be in practice.
303   ASSERT_EQ(read_len1, read_len2);
304   // Compare the cpuinfo as returned by the broker with the one we opened
305   // ourselves.
306   ASSERT_EQ(memcmp(buf, buf2, read_len1), 0);
307
308   if (fd >= 0)
309     close(fd);
310   if (cpuinfo_fd >= 0)
311     close(cpuinfo_fd);
312   if (cpuinfo_fd2 >= 0)
313     close(cpuinfo_fd);
314
315   delete(open_broker);
316
317   // Now we check that the broker has exited properly.
318   int status = 0;
319   ASSERT_EQ(waitpid(broker_pid, &status, 0), broker_pid);
320   ASSERT_TRUE(WIFEXITED(status));
321   ASSERT_EQ(WEXITSTATUS(status), 0);
322 }
323
324 // Run the same thing twice. The second time, we make sure that no security
325 // check is performed on the client.
326 TEST(BrokerProcess, OpenCpuinfoWithClientCheck) {
327   TestOpenCpuinfo(true /* fast_check_in_client */);
328   // Don't do anything here, so that ASSERT works in the subfunction as
329   // expected.
330 }
331
332 TEST(BrokerProcess, OpenCpuinfoNoClientCheck) {
333   TestOpenCpuinfo(false /* fast_check_in_client */);
334   // Don't do anything here, so that ASSERT works in the subfunction as
335   // expected.
336 }
337
338 TEST(BrokerProcess, OpenFileRW) {
339   ScopedTemporaryFile tempfile;
340   const char* tempfile_name = tempfile.full_file_name();
341
342   std::vector<std::string> whitelist;
343   whitelist.push_back(tempfile_name);
344
345   BrokerProcess open_broker(EPERM, whitelist, whitelist);
346   ASSERT_TRUE(open_broker.Init(NULL));
347
348   // Check we can access that file with read or write.
349   int can_access = open_broker.Access(tempfile_name, R_OK | W_OK);
350   ASSERT_EQ(can_access, 0);
351
352   int tempfile2 = -1;
353   tempfile2 = open_broker.Open(tempfile_name, O_RDWR);
354   ASSERT_GE(tempfile2, 0);
355
356   // Write to the descriptor opened by the broker.
357   char test_text[] = "TESTTESTTEST";
358   ssize_t len = write(tempfile2, test_text, sizeof(test_text));
359   ASSERT_EQ(len, static_cast<ssize_t>(sizeof(test_text)));
360
361   // Read back from the original file descriptor what we wrote through
362   // the descriptor provided by the broker.
363   char buf[1024];
364   len = read(tempfile.fd(), buf, sizeof(buf));
365
366   ASSERT_EQ(len, static_cast<ssize_t>(sizeof(test_text)));
367   ASSERT_EQ(memcmp(test_text, buf, sizeof(test_text)), 0);
368
369   ASSERT_EQ(close(tempfile2), 0);
370 }
371
372 // SANDBOX_TEST because the process could die with a SIGPIPE
373 // and we want this to happen in a subprocess.
374 SANDBOX_TEST(BrokerProcess, BrokerDied) {
375   std::vector<std::string> read_whitelist;
376   read_whitelist.push_back("/proc/cpuinfo");
377
378   BrokerProcess open_broker(EPERM,
379                             read_whitelist,
380                             std::vector<std::string>(),
381                             true /* fast_check_in_client */,
382                             true /* quiet_failures_for_tests */);
383   SANDBOX_ASSERT(open_broker.Init(NULL));
384   pid_t broker_pid = open_broker.broker_pid();
385   SANDBOX_ASSERT(kill(broker_pid, SIGKILL) == 0);
386
387   // Now we check that the broker has exited properly.
388   int status = 0;
389   SANDBOX_ASSERT(waitpid(broker_pid, &status, 0) == broker_pid);
390   SANDBOX_ASSERT(WIFSIGNALED(status));
391   SANDBOX_ASSERT(WTERMSIG(status) == SIGKILL);
392   // Check that doing Open with a dead broker won't SIGPIPE us.
393   SANDBOX_ASSERT(open_broker.Open("/proc/cpuinfo", O_RDONLY) == -ENOMEM);
394   SANDBOX_ASSERT(open_broker.Access("/proc/cpuinfo", O_RDONLY) == -ENOMEM);
395 }
396
397 void TestOpenComplexFlags(bool fast_check_in_client) {
398   const char kCpuInfo[] = "/proc/cpuinfo";
399   std::vector<std::string> whitelist;
400   whitelist.push_back(kCpuInfo);
401
402   BrokerProcess open_broker(EPERM,
403                             whitelist,
404                             whitelist,
405                             fast_check_in_client);
406   ASSERT_TRUE(open_broker.Init(NULL));
407   // Test that we do the right thing for O_CLOEXEC and O_NONBLOCK.
408   int fd = -1;
409   int ret = 0;
410   fd = open_broker.Open(kCpuInfo, O_RDONLY);
411   ASSERT_GE(fd, 0);
412   ret = fcntl(fd, F_GETFL);
413   ASSERT_NE(-1, ret);
414   // The descriptor shouldn't have the O_CLOEXEC attribute, nor O_NONBLOCK.
415   ASSERT_EQ(0, ret & (O_CLOEXEC | O_NONBLOCK));
416   ASSERT_EQ(0, close(fd));
417
418   fd = open_broker.Open(kCpuInfo, O_RDONLY | O_CLOEXEC);
419   ASSERT_GE(fd, 0);
420   ret = fcntl(fd, F_GETFD);
421   ASSERT_NE(-1, ret);
422   // Important: use F_GETFD, not F_GETFL. The O_CLOEXEC flag in F_GETFL
423   // is actually not used by the kernel.
424   ASSERT_TRUE(FD_CLOEXEC & ret);
425   ASSERT_EQ(0, close(fd));
426
427   fd = open_broker.Open(kCpuInfo, O_RDONLY | O_NONBLOCK);
428   ASSERT_GE(fd, 0);
429   ret = fcntl(fd, F_GETFL);
430   ASSERT_NE(-1, ret);
431   ASSERT_TRUE(O_NONBLOCK & ret);
432   ASSERT_EQ(0, close(fd));
433 }
434
435 TEST(BrokerProcess, OpenComplexFlagsWithClientCheck) {
436   TestOpenComplexFlags(true /* fast_check_in_client */);
437   // Don't do anything here, so that ASSERT works in the subfunction as
438   // expected.
439 }
440
441 TEST(BrokerProcess, OpenComplexFlagsNoClientCheck) {
442   TestOpenComplexFlags(false /* fast_check_in_client */);
443   // Don't do anything here, so that ASSERT works in the subfunction as
444   // expected.
445 }
446
447 }  // namespace sandbox