OLD | NEW |
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 <sys/types.h> // Include something that will define __GLIBC__. | 5 #include <sys/types.h> // Include something that will define __GLIBC__. |
6 | 6 |
7 // The entire file is wrapped in this #if. We do this so this .cc file can be | 7 // The entire file is wrapped in this #if. We do this so this .cc file can be |
8 // compiled, even on a non-glibc build. | 8 // compiled, even on a non-glibc build. |
9 #if defined(__native_client__) && defined(__GLIBC__) | 9 #if defined(__native_client__) && defined(__GLIBC__) |
10 | 10 |
11 #include "nacl_io/kernel_wrap.h" | 11 #include "nacl_io/kernel_wrap.h" |
12 | 12 |
13 #include <alloca.h> | 13 #include <alloca.h> |
14 #include <assert.h> | 14 #include <assert.h> |
15 #include <dirent.h> | 15 #include <dirent.h> |
16 #include <errno.h> | 16 #include <errno.h> |
17 #include <irt.h> | 17 #include <irt.h> |
18 #include <irt_syscalls.h> | 18 #include <irt_syscalls.h> |
19 #include <nacl_stat.h> | 19 #include <nacl_stat.h> |
20 #include <string.h> | 20 #include <string.h> |
21 #include <sys/stat.h> | 21 #include <sys/stat.h> |
22 #include <sys/time.h> | 22 #include <sys/time.h> |
23 | 23 |
24 #include "nacl_io/kernel_intercept.h" | 24 #include "nacl_io/kernel_intercept.h" |
25 #include "nacl_io/kernel_wrap_real.h" | 25 #include "nacl_io/kernel_wrap_real.h" |
| 26 #include "nacl_io/log.h" |
26 #include "nacl_io/osmman.h" | 27 #include "nacl_io/osmman.h" |
27 | 28 |
28 | 29 |
29 namespace { | 30 namespace { |
30 | 31 |
31 void stat_to_nacl_stat(const struct stat* buf, nacl_abi_stat* nacl_buf) { | 32 void stat_to_nacl_stat(const struct stat* buf, nacl_abi_stat* nacl_buf) { |
32 memset(nacl_buf, 0, sizeof(struct nacl_abi_stat)); | 33 memset(nacl_buf, 0, sizeof(struct nacl_abi_stat)); |
33 nacl_buf->nacl_abi_st_dev = buf->st_dev; | 34 nacl_buf->nacl_abi_st_dev = buf->st_dev; |
34 nacl_buf->nacl_abi_st_ino = buf->st_ino; | 35 nacl_buf->nacl_abi_st_ino = buf->st_ino; |
35 nacl_buf->nacl_abi_st_mode = buf->st_mode; | 36 nacl_buf->nacl_abi_st_mode = buf->st_mode; |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 REAL(name) = __nacl_irt_##name; | 116 REAL(name) = __nacl_irt_##name; |
116 | 117 |
117 // Switch IRT's pointer to the REAL pointer | 118 // Switch IRT's pointer to the REAL pointer |
118 #define USE_REAL(name) \ | 119 #define USE_REAL(name) \ |
119 __nacl_irt_##name = (typeof(__nacl_irt_##name)) REAL(name) | 120 __nacl_irt_##name = (typeof(__nacl_irt_##name)) REAL(name) |
120 | 121 |
121 // Switch IRT's pointer to the WRAP function | 122 // Switch IRT's pointer to the WRAP function |
122 #define USE_WRAP(name) \ | 123 #define USE_WRAP(name) \ |
123 __nacl_irt_##name = (typeof(__nacl_irt_##name)) WRAP(name) | 124 __nacl_irt_##name = (typeof(__nacl_irt_##name)) WRAP(name) |
124 | 125 |
125 | |
126 #define EXPAND_SYMBOL_LIST_OPERATION(OP) \ | 126 #define EXPAND_SYMBOL_LIST_OPERATION(OP) \ |
127 OP(chdir); \ | 127 OP(chdir); \ |
128 OP(close); \ | 128 OP(close); \ |
129 OP(dup); \ | 129 OP(dup); \ |
130 OP(dup2); \ | 130 OP(dup2); \ |
131 OP(exit); \ | 131 OP(exit); \ |
132 OP(fstat); \ | 132 OP(fstat); \ |
133 OP(getcwd); \ | 133 OP(getcwd); \ |
134 OP(getdents); \ | 134 OP(getdents); \ |
135 OP(mkdir); \ | 135 OP(mkdir); \ |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 // OP(epoll_create1); | 168 // OP(epoll_create1); |
169 // OP(epoll_ctl); | 169 // OP(epoll_ctl); |
170 // OP(epoll_pwait); | 170 // OP(epoll_pwait); |
171 // OP(ppoll); | 171 // OP(ppoll); |
172 // OP(pselect); | 172 // OP(pselect); |
173 // | 173 // |
174 | 174 |
175 EXPAND_SYMBOL_LIST_OPERATION(DECLARE_REAL_PTR); | 175 EXPAND_SYMBOL_LIST_OPERATION(DECLARE_REAL_PTR); |
176 | 176 |
177 int WRAP(chdir)(const char* pathname) { | 177 int WRAP(chdir)(const char* pathname) { |
178 return (ki_chdir(pathname)) ? errno : 0; | 178 RTN_ERRNO_IF(ki_chdir(pathname) < 0); |
| 179 return 0; |
179 } | 180 } |
180 | 181 |
181 int WRAP(close)(int fd) { | 182 int WRAP(close)(int fd) { |
182 return (ki_close(fd) < 0) ? errno : 0; | 183 RTN_ERRNO_IF(ki_close(fd) < 0); |
| 184 return 0; |
183 } | 185 } |
184 | 186 |
185 int WRAP(dup)(int fd, int* newfd) NOTHROW { | 187 int WRAP(dup)(int fd, int* newfd) NOTHROW { |
186 *newfd = ki_dup(fd); | 188 *newfd = ki_dup(fd); |
187 return (*newfd < 0) ? errno : 0; | 189 RTN_ERRNO_IF(*newfd < 0); |
| 190 return 0; |
188 } | 191 } |
189 | 192 |
190 int WRAP(dup2)(int fd, int newfd) NOTHROW { | 193 int WRAP(dup2)(int fd, int newfd) NOTHROW { |
191 return (ki_dup2(fd, newfd) < 0) ? errno : 0; | 194 RTN_ERRNO_IF(ki_dup2(fd, newfd) < 0); |
| 195 return 0; |
192 } | 196 } |
193 | 197 |
194 void WRAP(exit)(int status) { | 198 void WRAP(exit)(int status) { |
195 ki_exit(status); | 199 ki_exit(status); |
196 } | 200 } |
197 | 201 |
198 int WRAP(fstat)(int fd, struct nacl_abi_stat *nacl_buf) { | 202 int WRAP(fstat)(int fd, struct nacl_abi_stat *nacl_buf) { |
199 struct stat buf; | 203 struct stat buf; |
200 memset(&buf, 0, sizeof(struct stat)); | 204 memset(&buf, 0, sizeof(struct stat)); |
201 int res = ki_fstat(fd, &buf); | 205 int res = ki_fstat(fd, &buf); |
202 if (res < 0) | 206 RTN_ERRNO_IF(res < 0); |
203 return errno; | |
204 stat_to_nacl_stat(&buf, nacl_buf); | 207 stat_to_nacl_stat(&buf, nacl_buf); |
205 return 0; | 208 return 0; |
206 } | 209 } |
207 | 210 |
208 int WRAP(getcwd)(char* buf, size_t size) { | 211 int WRAP(getcwd)(char* buf, size_t size) { |
209 if (ki_getcwd(buf, size) == NULL) | 212 RTN_ERRNO_IF(ki_getcwd(buf, size) == NULL); |
210 return errno; | |
211 return 0; | 213 return 0; |
212 } | 214 } |
213 | 215 |
214 int WRAP(getdents)(int fd, dirent* nacl_buf, size_t nacl_count, size_t *nread) { | 216 int WRAP(getdents)(int fd, dirent* nacl_buf, size_t nacl_count, size_t *nread) { |
215 int nacl_offset = 0; | 217 int nacl_offset = 0; |
216 // "buf" contains dirent(s); "nacl_buf" contains nacl_abi_dirent(s). | 218 // "buf" contains dirent(s); "nacl_buf" contains nacl_abi_dirent(s). |
217 // nacl_abi_dirent(s) are smaller than dirent(s), so nacl_count bytes buffer | 219 // nacl_abi_dirent(s) are smaller than dirent(s), so nacl_count bytes buffer |
218 // is enough | 220 // is enough |
219 char* buf = (char*)alloca(nacl_count); | 221 char* buf = (char*)alloca(nacl_count); |
220 int offset = 0; | 222 int offset = 0; |
221 int count; | 223 int count; |
222 | 224 |
223 count = ki_getdents(fd, buf, nacl_count); | 225 count = ki_getdents(fd, buf, nacl_count); |
224 if (count < 0) | 226 RTN_ERRNO_IF(count < 0); |
225 return errno; | |
226 | 227 |
227 while (offset < count) { | 228 while (offset < count) { |
228 dirent* d = (dirent*)(buf + offset); | 229 dirent* d = (dirent*)(buf + offset); |
229 nacl_abi_dirent* nacl_d = (nacl_abi_dirent*)((char*)nacl_buf + nacl_offset); | 230 nacl_abi_dirent* nacl_d = (nacl_abi_dirent*)((char*)nacl_buf + nacl_offset); |
230 nacl_d->nacl_abi_d_ino = d->d_ino; | 231 nacl_d->nacl_abi_d_ino = d->d_ino; |
231 nacl_d->nacl_abi_d_off = d->d_off; | 232 nacl_d->nacl_abi_d_off = d->d_off; |
232 nacl_d->nacl_abi_d_reclen = d->d_reclen - d_name_shift; | 233 nacl_d->nacl_abi_d_reclen = d->d_reclen - d_name_shift; |
233 size_t d_name_len = d->d_reclen - offsetof(dirent, d_name); | 234 size_t d_name_len = d->d_reclen - offsetof(dirent, d_name); |
234 memcpy(nacl_d->nacl_abi_d_name, d->d_name, d_name_len); | 235 memcpy(nacl_d->nacl_abi_d_name, d->d_name, d_name_len); |
235 | 236 |
236 offset += d->d_reclen; | 237 offset += d->d_reclen; |
237 nacl_offset += nacl_d->nacl_abi_d_reclen; | 238 nacl_offset += nacl_d->nacl_abi_d_reclen; |
238 } | 239 } |
239 | 240 |
240 *nread = nacl_offset; | 241 *nread = nacl_offset; |
241 return 0; | 242 return 0; |
242 } | 243 } |
243 | 244 |
244 int WRAP(mkdir)(const char* pathname, mode_t mode) { | 245 int WRAP(mkdir)(const char* pathname, mode_t mode) { |
245 return (ki_mkdir(pathname, mode)) ? errno : 0; | 246 RTN_ERRNO_IF(ki_mkdir(pathname, mode) < 0); |
| 247 return 0; |
246 } | 248 } |
247 | 249 |
248 int WRAP(mmap)(void** addr, size_t length, int prot, int flags, int fd, | 250 int WRAP(mmap)(void** addr, size_t length, int prot, int flags, int fd, |
249 off_t offset) { | 251 off_t offset) { |
250 if (flags & MAP_ANONYMOUS) | 252 if (flags & MAP_ANONYMOUS) |
251 return REAL(mmap)(addr, length, prot, flags, fd, offset); | 253 return REAL(mmap)(addr, length, prot, flags, fd, offset); |
252 | 254 |
253 *addr = ki_mmap(*addr, length, prot, flags, fd, offset); | 255 *addr = ki_mmap(*addr, length, prot, flags, fd, offset); |
254 return *addr == (void*)-1 ? errno : 0; | 256 RTN_ERRNO_IF(*addr == (void*)-1); |
| 257 return 0; |
255 } | 258 } |
256 | 259 |
257 int WRAP(munmap)(void* addr, size_t length) { | 260 int WRAP(munmap)(void* addr, size_t length) { |
258 // Always let the real munmap run on the address range. It is not an error if | 261 // Always let the real munmap run on the address range. It is not an error if |
259 // there are no mapped pages in that range. | 262 // there are no mapped pages in that range. |
260 ki_munmap(addr, length); | 263 ki_munmap(addr, length); |
261 return REAL(munmap)(addr, length); | 264 return REAL(munmap)(addr, length); |
262 } | 265 } |
263 | 266 |
264 int WRAP(open)(const char* pathname, int oflag, mode_t cmode, int* newfd) { | 267 int WRAP(open)(const char* pathname, int oflag, mode_t cmode, int* newfd) { |
265 *newfd = ki_open(pathname, oflag); | 268 *newfd = ki_open(pathname, oflag); |
266 return (*newfd < 0) ? errno : 0; | 269 RTN_ERRNO_IF(*newfd < 0); |
| 270 return 0; |
267 } | 271 } |
268 | 272 |
269 int WRAP(open_resource)(const char* file, int* fd) { | 273 int WRAP(open_resource)(const char* file, int* fd) { |
270 *fd = ki_open_resource(file); | 274 *fd = ki_open_resource(file); |
271 return (*fd < 0) ? errno : 0; | 275 RTN_ERRNO_IF(*fd < 0); |
| 276 return 0; |
272 } | 277 } |
273 | 278 |
274 int WRAP(poll)(struct pollfd *fds, nfds_t nfds, int timeout, int* count) { | 279 int WRAP(poll)(struct pollfd *fds, nfds_t nfds, int timeout, int* count) { |
275 *count = ki_poll(fds, nfds, timeout); | 280 *count = ki_poll(fds, nfds, timeout); |
276 return (*count < 0) ? errno : 0; | 281 RTN_ERRNO_IF(*count < 0); |
277 | 282 return 0; |
278 } | 283 } |
279 | 284 |
280 int WRAP(read)(int fd, void *buf, size_t count, size_t *nread) { | 285 int WRAP(read)(int fd, void *buf, size_t count, size_t *nread) { |
281 ssize_t signed_nread = ki_read(fd, buf, count); | 286 ssize_t signed_nread = ki_read(fd, buf, count); |
282 *nread = static_cast<size_t>(signed_nread); | 287 *nread = static_cast<size_t>(signed_nread); |
283 return (signed_nread < 0) ? errno : 0; | 288 RTN_ERRNO_IF(signed_nread < 0); |
| 289 return 0; |
284 } | 290 } |
285 | 291 |
286 int WRAP(rmdir)(const char* pathname) { | 292 int WRAP(rmdir)(const char* pathname) { |
287 return (ki_rmdir(pathname) < 0) ? errno : 0; | 293 RTN_ERRNO_IF(ki_rmdir(pathname) < 0); |
| 294 return 0; |
288 } | 295 } |
289 | 296 |
290 int WRAP(seek)(int fd, off_t offset, int whence, off_t* new_offset) { | 297 int WRAP(seek)(int fd, off_t offset, int whence, off_t* new_offset) { |
291 *new_offset = ki_lseek(fd, offset, whence); | 298 *new_offset = ki_lseek(fd, offset, whence); |
292 return (*new_offset < 0) ? errno : 0; | 299 RTN_ERRNO_IF(*new_offset < 0); |
| 300 return 0; |
293 } | 301 } |
294 | 302 |
295 int WRAP(select)(int nfds, fd_set* readfds, fd_set* writefds, | 303 int WRAP(select)(int nfds, fd_set* readfds, fd_set* writefds, |
296 fd_set* exceptfds, struct timeval* timeout, int* count) { | 304 fd_set* exceptfds, struct timeval* timeout, int* count) { |
297 *count = ki_select(nfds, readfds, writefds, exceptfds, timeout); | 305 *count = ki_select(nfds, readfds, writefds, exceptfds, timeout); |
298 return (*count < 0) ? errno : 0; | 306 RTN_ERRNO_IF(*count < 0); |
| 307 return 0; |
299 } | 308 } |
300 | 309 |
301 int WRAP(stat)(const char *pathname, struct nacl_abi_stat *nacl_buf) { | 310 int WRAP(stat)(const char *pathname, struct nacl_abi_stat *nacl_buf) { |
302 struct stat buf; | 311 struct stat buf; |
303 memset(&buf, 0, sizeof(struct stat)); | 312 memset(&buf, 0, sizeof(struct stat)); |
304 int res = ki_stat(pathname, &buf); | 313 int res = ki_stat(pathname, &buf); |
305 if (res < 0) | 314 RTN_ERRNO_IF(res < 0); |
306 return errno; | |
307 stat_to_nacl_stat(&buf, nacl_buf); | 315 stat_to_nacl_stat(&buf, nacl_buf); |
308 return 0; | 316 return 0; |
309 } | 317 } |
310 | 318 |
311 int WRAP(write)(int fd, const void* buf, size_t count, size_t* nwrote) { | 319 int WRAP(write)(int fd, const void* buf, size_t count, size_t* nwrote) { |
312 ssize_t signed_nwrote = ki_write(fd, buf, count); | 320 ssize_t signed_nwrote = ki_write(fd, buf, count); |
313 *nwrote = static_cast<size_t>(signed_nwrote); | 321 *nwrote = static_cast<size_t>(signed_nwrote); |
314 return (signed_nwrote < 0) ? errno : 0; | 322 RTN_ERRNO_IF(signed_nwrote < 0); |
| 323 return 0; |
315 } | 324 } |
316 | 325 |
317 int WRAP(accept)(int sockfd, struct sockaddr* addr, | 326 int WRAP(accept)(int sockfd, struct sockaddr* addr, |
318 socklen_t* addrlen, int *sd) { | 327 socklen_t* addrlen, int *sd) { |
319 int result = ki_accept(sockfd, addr, addrlen); | 328 int result = ki_accept(sockfd, addr, addrlen); |
320 if (result < 0) { | 329 if (result < 0) { |
321 *sd = -1; | 330 *sd = -1; |
322 return errno; | 331 return errno; |
323 } else { | 332 } else { |
324 *sd = result; | 333 *sd = result; |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
527 } | 536 } |
528 | 537 |
529 int _real_write(int fd, const void *buf, size_t count, size_t *nwrote) { | 538 int _real_write(int fd, const void *buf, size_t count, size_t *nwrote) { |
530 CHECK_REAL(write); | 539 CHECK_REAL(write); |
531 return REAL(write)(fd, buf, count, nwrote); | 540 return REAL(write)(fd, buf, count, nwrote); |
532 } | 541 } |
533 | 542 |
534 static bool s_wrapped = false; | 543 static bool s_wrapped = false; |
535 void kernel_wrap_init() { | 544 void kernel_wrap_init() { |
536 if (!s_wrapped) { | 545 if (!s_wrapped) { |
| 546 LOG_TRACE("kernel_wrap_init"); |
537 assign_real_pointers(); | 547 assign_real_pointers(); |
538 EXPAND_SYMBOL_LIST_OPERATION(USE_WRAP) | 548 EXPAND_SYMBOL_LIST_OPERATION(USE_WRAP) |
539 s_wrapped = true; | 549 s_wrapped = true; |
540 } | 550 } |
541 } | 551 } |
542 | 552 |
543 void kernel_wrap_uninit() { | 553 void kernel_wrap_uninit() { |
544 if (s_wrapped) { | 554 if (s_wrapped) { |
| 555 LOG_TRACE("kernel_wrap_uninit"); |
545 EXPAND_SYMBOL_LIST_OPERATION(USE_REAL) | 556 EXPAND_SYMBOL_LIST_OPERATION(USE_REAL) |
546 s_wrapped = false; | 557 s_wrapped = false; |
547 } | 558 } |
548 } | 559 } |
549 | 560 |
550 EXTERN_C_END | 561 EXTERN_C_END |
551 | 562 |
552 #endif // defined(__native_client__) && defined(__GLIBC__) | 563 #endif // defined(__native_client__) && defined(__GLIBC__) |
OLD | NEW |