OLD | NEW |
---|---|
(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 } | |
Markus (顧孟勤)
2012/12/14 00:40:34
Can you test with some invalid value too? E.g. O_R
jln (very slow on Chromium)
2012/12/14 01:11:29
Done.
| |
91 | |
92 // Run the same thing twice. The second time, we make sure that no security | |
93 // check is performed on the client. | |
94 TEST(BrokerProcess, OpenFilePermsWithClientCheck) { | |
95 TestOpenFilePerms(true /* fast_check_in_client */); | |
96 } | |
97 | |
98 TEST(BrokerProcess, OpenOpenFilePermsNoClientCheck) { | |
99 TestOpenFilePerms(false /* fast_check_in_client */); | |
100 } | |
101 | |
102 | |
103 void TestOpenCpuinfo(bool fast_check_in_client) { | |
104 const char kFileCpuInfo[] = "/proc/cpuinfo"; | |
105 std::vector<std::string> read_whitelist; | |
106 read_whitelist.push_back(kFileCpuInfo); | |
107 | |
108 BrokerProcess* open_broker = new BrokerProcess(read_whitelist, | |
109 std::vector<std::string>(), | |
110 fast_check_in_client); | |
111 ASSERT_TRUE(open_broker->Init(NULL)); | |
112 pid_t broker_pid = open_broker->broker_pid(); | |
113 | |
114 int fd = -1; | |
115 fd = open_broker->Open(kFileCpuInfo, O_RDWR); | |
116 EXPECT_EQ(fd, -EPERM); | |
117 | |
118 // Open cpuinfo via the broker. | |
119 int cpuinfo_fd = open_broker->Open(kFileCpuInfo, O_RDONLY); | |
120 ASSERT_GE(cpuinfo_fd, 0); | |
121 char buf[3]; | |
122 memset(buf, 0, sizeof(buf)); | |
123 int read_len1 = read(cpuinfo_fd, buf, sizeof(buf)); | |
124 EXPECT_GT(read_len1, 0); | |
125 | |
126 // Open cpuinfo directly. | |
127 int cpuinfo_fd2 = open(kFileCpuInfo, O_RDONLY); | |
128 ASSERT_GE(cpuinfo_fd2, 0); | |
129 char buf2[3]; | |
130 memset(buf2, 1, sizeof(buf2)); | |
131 int read_len2 = read(cpuinfo_fd2, buf2, sizeof(buf2)); | |
132 EXPECT_GT(read_len1, 0); | |
133 | |
134 // The following is not guaranteed true, but will be in practice. | |
135 EXPECT_EQ(read_len1, read_len2); | |
136 // Compare the cpuinfo as returned by the broker with the one we opened | |
137 // ourselves. | |
138 EXPECT_EQ(memcmp(buf, buf2, read_len1), 0); | |
139 | |
140 if (fd >= 0) | |
141 close(fd); | |
142 if (cpuinfo_fd >= 0) | |
143 close(cpuinfo_fd); | |
144 if (cpuinfo_fd2 >= 0) | |
145 close(cpuinfo_fd); | |
146 | |
147 delete(open_broker); | |
148 | |
149 // Now we check that the broker has exited properly. | |
150 int status = 0; | |
151 EXPECT_EQ(waitpid(broker_pid, &status, 0), broker_pid); | |
152 EXPECT_TRUE(WIFEXITED(status)); | |
153 EXPECT_EQ(WEXITSTATUS(status), 0); | |
154 } | |
155 | |
156 // Run the same thing twice. The second time, we make sure that no security | |
157 // check is performed on the client. | |
158 TEST(BrokerProcess, OpenCpuinfoWithClientCheck) { | |
159 TestOpenCpuinfo(true /* fast_check_in_client */); | |
160 } | |
161 | |
162 TEST(BrokerProcess, OpenCpuinfoNoClientCheck) { | |
163 TestOpenCpuinfo(false /* fast_check_in_client */); | |
164 } | |
165 | |
166 TEST(BrokerProcess, OpenFileRW) { | |
167 char templatename[] = "BrokerProcessXXXXXX"; | |
168 int tempfile = mkstemp(templatename); | |
169 ASSERT_GE(tempfile, 0); | |
170 char tempfile_name[2048]; | |
171 int written = snprintf(tempfile_name, sizeof(tempfile_name), | |
172 "/proc/self/fd/%d", tempfile); | |
173 ASSERT_LT(written, static_cast<int>(sizeof(tempfile_name))); | |
174 | |
175 std::vector<std::string> whitelist; | |
176 whitelist.push_back(tempfile_name); | |
177 | |
178 BrokerProcess open_broker(whitelist, whitelist); | |
179 ASSERT_TRUE(open_broker.Init(NULL)); | |
180 | |
181 int tempfile2 = -1; | |
182 tempfile2 = open_broker.Open(tempfile_name, O_RDWR); | |
183 ASSERT_GE(tempfile2, 0); | |
184 | |
185 // Write to the descriptor opened by the broker. | |
186 char test_text[] = "TESTTESTTEST"; | |
187 ssize_t len = write(tempfile2, test_text, sizeof(test_text)); | |
188 ASSERT_EQ(len, static_cast<ssize_t>(sizeof(test_text))); | |
189 | |
190 ASSERT_EQ(close(tempfile2), 0); | |
191 | |
192 // Read back from the original file descriptor what we wrote through | |
193 // the descriptor provided by the broker. | |
194 char buf[1024]; | |
195 len = read(tempfile, buf, sizeof(buf)); | |
196 | |
197 ASSERT_EQ(len, static_cast<ssize_t>(sizeof(test_text))); | |
198 ASSERT_EQ(memcmp(test_text, buf, sizeof(test_text)), 0); | |
199 | |
200 // Cleanup the temporary file. | |
201 char tempfile_full_path[2048]; | |
202 // Make sure tempfile_full_path will terminate with a 0. | |
203 bzero(tempfile_full_path, sizeof(tempfile_full_path)); | |
Markus (顧孟勤)
2012/12/14 00:40:34
bzero()? Really? Do we use that anywhere else?
I
jln (very slow on Chromium)
2012/12/14 01:11:29
Done.
| |
204 ssize_t ret = readlink(tempfile_name, tempfile_full_path, | |
205 sizeof(tempfile_full_path)); | |
206 ASSERT_GT(ret, 0); | |
207 // Make sure we still have a trailing zero in tempfile_full_path. | |
208 ASSERT_LT(ret, static_cast<ssize_t>(sizeof(tempfile_full_path))); | |
209 ASSERT_EQ(unlink(tempfile_full_path), 0); | |
210 } | |
211 | |
212 // Sandbox test because we could get a SIGPIPE. | |
213 SANDBOX_TEST(BrokerProcess, BrokerDied) { | |
214 std::vector<std::string> read_whitelist; | |
215 read_whitelist.push_back("/proc/cpuinfo"); | |
216 | |
217 BrokerProcess open_broker(read_whitelist, | |
218 std::vector<std::string>(), | |
219 true /* fast_check_in_client */, | |
220 true /* quiet_failures_for_tests */); | |
221 SANDBOX_ASSERT(open_broker.Init(NULL)); | |
222 pid_t broker_pid = open_broker.broker_pid(); | |
223 SANDBOX_ASSERT(kill(broker_pid, SIGKILL) == 0); | |
224 | |
225 // Now we check that the broker has exited properly. | |
226 int status = 0; | |
227 SANDBOX_ASSERT(waitpid(broker_pid, &status, 0) == broker_pid); | |
228 SANDBOX_ASSERT(WIFSIGNALED(status)); | |
229 SANDBOX_ASSERT(WTERMSIG(status) == SIGKILL); | |
230 // Hopefully doing Open with a dead broker won't SIGPIPE us. | |
231 SANDBOX_ASSERT(open_broker.Open("/proc/cpuinfo", O_RDONLY) == -ENOMEM); | |
232 } | |
233 | |
234 } // namespace sandbox | |
OLD | NEW |