| 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 |