OLD | NEW |
| (Empty) |
1 // Copyright (c) 2010 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 "debug.h" | |
6 #include "sandbox_impl.h" | |
7 | |
8 namespace playground { | |
9 | |
10 long Sandbox::sandbox_stat(const char *path, void *buf) { | |
11 long long tm; | |
12 Debug::syscall(&tm, __NR_stat, "Executing handler"); | |
13 size_t len = strlen(path); | |
14 struct Request { | |
15 int sysnum; | |
16 long long cookie; | |
17 Stat stat_req; | |
18 char pathname[0]; | |
19 } __attribute__((packed)) *request; | |
20 char data[sizeof(struct Request) + len]; | |
21 request = reinterpret_cast<struct Request*>(data); | |
22 request->sysnum = __NR_stat; | |
23 request->cookie = cookie(); | |
24 request->stat_req.sysnum = __NR_stat; | |
25 request->stat_req.path_length = len; | |
26 request->stat_req.buf = buf; | |
27 memcpy(request->pathname, path, len); | |
28 | |
29 long rc; | |
30 SysCalls sys; | |
31 if (write(sys, processFdPub(), request, sizeof(data)) != (int)sizeof(data) || | |
32 read(sys, threadFdPub(), &rc, sizeof(rc)) != sizeof(rc)) { | |
33 die("Failed to forward stat() request [sandbox]"); | |
34 } | |
35 Debug::elapsed(tm, __NR_stat); | |
36 return rc; | |
37 } | |
38 | |
39 long Sandbox::sandbox_lstat(const char *path, void *buf) { | |
40 long long tm; | |
41 Debug::syscall(&tm, __NR_lstat, "Executing handler"); | |
42 size_t len = strlen(path); | |
43 struct Request { | |
44 int sysnum; | |
45 long long cookie; | |
46 Stat stat_req; | |
47 char pathname[0]; | |
48 } __attribute__((packed)) *request; | |
49 char data[sizeof(struct Request) + len]; | |
50 request = reinterpret_cast<struct Request*>(data); | |
51 request->sysnum = __NR_lstat; | |
52 request->cookie = cookie(); | |
53 request->stat_req.sysnum = __NR_lstat; | |
54 request->stat_req.path_length = len; | |
55 request->stat_req.buf = buf; | |
56 memcpy(request->pathname, path, len); | |
57 | |
58 long rc; | |
59 SysCalls sys; | |
60 if (write(sys, processFdPub(), request, sizeof(data)) != (int)sizeof(data) || | |
61 read(sys, threadFdPub(), &rc, sizeof(rc)) != sizeof(rc)) { | |
62 die("Failed to forward lstat() request [sandbox]"); | |
63 } | |
64 Debug::elapsed(tm, __NR_lstat); | |
65 return rc; | |
66 } | |
67 | |
68 #if defined(__NR_stat64) | |
69 long Sandbox::sandbox_stat64(const char *path, void *buf) { | |
70 long long tm; | |
71 Debug::syscall(&tm, __NR_stat64, "Executing handler"); | |
72 size_t len = strlen(path); | |
73 struct Request { | |
74 int sysnum; | |
75 long long cookie; | |
76 Stat stat_req; | |
77 char pathname[0]; | |
78 } __attribute__((packed)) *request; | |
79 char data[sizeof(struct Request) + len]; | |
80 request = reinterpret_cast<struct Request*>(data); | |
81 request->sysnum = __NR_stat64; | |
82 request->cookie = cookie(); | |
83 request->stat_req.sysnum = __NR_stat64; | |
84 request->stat_req.path_length = len; | |
85 request->stat_req.buf = buf; | |
86 memcpy(request->pathname, path, len); | |
87 | |
88 long rc; | |
89 SysCalls sys; | |
90 if (write(sys, processFdPub(), request, sizeof(data)) != (int)sizeof(data) || | |
91 read(sys, threadFdPub(), &rc, sizeof(rc)) != sizeof(rc)) { | |
92 die("Failed to forward stat64() request [sandbox]"); | |
93 } | |
94 Debug::elapsed(tm, __NR_stat64); | |
95 return rc; | |
96 } | |
97 | |
98 long Sandbox::sandbox_lstat64(const char *path, void *buf) { | |
99 long long tm; | |
100 Debug::syscall(&tm, __NR_lstat64, "Executing handler"); | |
101 size_t len = strlen(path); | |
102 struct Request { | |
103 int sysnum; | |
104 long long cookie; | |
105 Stat stat_req; | |
106 char pathname[0]; | |
107 } __attribute__((packed)) *request; | |
108 char data[sizeof(struct Request) + len]; | |
109 request = reinterpret_cast<struct Request*>(data); | |
110 request->sysnum = __NR_lstat64; | |
111 request->cookie = cookie(); | |
112 request->stat_req.sysnum = __NR_lstat64; | |
113 request->stat_req.path_length = len; | |
114 request->stat_req.buf = buf; | |
115 memcpy(request->pathname, path, len); | |
116 | |
117 long rc; | |
118 SysCalls sys; | |
119 if (write(sys, processFdPub(), request, sizeof(data)) != (int)sizeof(data) || | |
120 read(sys, threadFdPub(), &rc, sizeof(rc)) != sizeof(rc)) { | |
121 die("Failed to forward lstat64() request [sandbox]"); | |
122 } | |
123 Debug::elapsed(tm, __NR_lstat64); | |
124 return rc; | |
125 } | |
126 #endif | |
127 | |
128 bool Sandbox::process_stat(int parentMapsFd, int sandboxFd, int threadFdPub, | |
129 int threadFd, SecureMem::Args* mem) { | |
130 // Read request | |
131 SysCalls sys; | |
132 Stat stat_req; | |
133 if (read(sys, sandboxFd, &stat_req, sizeof(stat_req)) != sizeof(stat_req)) { | |
134 read_parm_failed: | |
135 die("Failed to read parameters for stat() [process]"); | |
136 } | |
137 int rc = -ENAMETOOLONG; | |
138 if (stat_req.path_length >= (int)sizeof(mem->pathname)) { | |
139 char buf[32]; | |
140 while (stat_req.path_length > 0) { | |
141 size_t len = stat_req.path_length > sizeof(buf) ? | |
142 sizeof(buf) : stat_req.path_length; | |
143 ssize_t i = read(sys, sandboxFd, buf, len); | |
144 if (i <= 0) { | |
145 goto read_parm_failed; | |
146 } | |
147 stat_req.path_length -= i; | |
148 } | |
149 if (write(sys, threadFd, &rc, sizeof(rc)) != sizeof(rc)) { | |
150 die("Failed to return data from stat() [process]"); | |
151 } | |
152 return false; | |
153 } | |
154 if (stat_req.sysnum != __NR_stat && stat_req.sysnum != __NR_lstat | |
155 #ifdef __NR_stat64 | |
156 && stat_req.sysnum != __NR_stat64 | |
157 #endif | |
158 #ifdef __NR_lstat64 | |
159 && stat_req.sysnum != __NR_lstat64 | |
160 #endif | |
161 ) { | |
162 die("Corrupted stat() request"); | |
163 } | |
164 | |
165 if (!g_policy.allow_file_namespace) { | |
166 // After locking the mutex, we can no longer abandon the system call. So, | |
167 // perform checks before clobbering the securely shared memory. | |
168 char tmp[stat_req.path_length]; | |
169 if (read(sys, sandboxFd, tmp, stat_req.path_length) != | |
170 (ssize_t)stat_req.path_length) { | |
171 goto read_parm_failed; | |
172 } | |
173 Debug::message(("Denying access to \"" + std::string(tmp) + "\"").c_str()); | |
174 SecureMem::abandonSystemCall(threadFd, -EACCES); | |
175 return false; | |
176 } | |
177 | |
178 SecureMem::lockSystemCall(parentMapsFd, mem); | |
179 if (read(sys, sandboxFd, mem->pathname, stat_req.path_length) != | |
180 (ssize_t)stat_req.path_length) { | |
181 goto read_parm_failed; | |
182 } | |
183 mem->pathname[stat_req.path_length] = '\000'; | |
184 | |
185 // TODO(markus): Implement sandboxing policy | |
186 Debug::message(("Allowing access to \"" + std::string(mem->pathname) + | |
187 "\"").c_str()); | |
188 | |
189 // Tell trusted thread to stat the file. | |
190 SecureMem::sendSystemCall(threadFdPub, true, parentMapsFd, mem, | |
191 stat_req.sysnum, | |
192 mem->pathname - (char*)mem + (char*)mem->self, | |
193 stat_req.buf); | |
194 return true; | |
195 } | |
196 | |
197 } // namespace | |
OLD | NEW |