Home | History | Annotate | Download | only in nacl_io
      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 "nacl_io/kernel_intercept.h"
      6 
      7 #include <assert.h>
      8 #include <errno.h>
      9 #include <string.h>
     10 
     11 #include "nacl_io/kernel_proxy.h"
     12 #include "nacl_io/kernel_wrap.h"
     13 #include "nacl_io/kernel_wrap_real.h"
     14 #include "nacl_io/log.h"
     15 #include "nacl_io/osmman.h"
     16 #include "nacl_io/ossocket.h"
     17 #include "nacl_io/pepper_interface.h"
     18 #include "nacl_io/real_pepper_interface.h"
     19 
     20 using namespace nacl_io;
     21 
     22 #define ON_NOSYS_RETURN(x)    \
     23   if (!ki_is_initialized()) { \
     24     errno = ENOSYS;           \
     25     return x;                 \
     26   }
     27 
     28 struct KernelInterceptState {
     29   KernelProxy* kp;
     30   PepperInterface* ppapi;
     31   bool kp_owned;
     32 };
     33 
     34 static KernelInterceptState s_state;
     35 
     36 // The the test code we want to be able to save the previous kernel
     37 // proxy when intialising and restore it on uninit.
     38 static KernelInterceptState s_saved_state;
     39 
     40 int ki_push_state_for_testing() {
     41   assert(s_saved_state.kp == NULL);
     42   if (s_saved_state.kp != NULL)
     43     return 1;
     44   s_saved_state = s_state;
     45   s_state.kp = NULL;
     46   s_state.ppapi = NULL;
     47   s_state.kp_owned = false;
     48   return 0;
     49 }
     50 
     51 int ki_init(void* kp) {
     52   LOG_TRACE("ki_init: %p", kp);
     53   return ki_init_ppapi(kp, 0, NULL);
     54 }
     55 
     56 int ki_init_ppapi(void* kp,
     57                   PP_Instance instance,
     58                   PPB_GetInterface get_browser_interface) {
     59   assert(!s_state.kp);
     60   if (s_state.kp != NULL)
     61     return 1;
     62   PepperInterface* ppapi = NULL;
     63   if (instance && get_browser_interface) {
     64     ppapi = new RealPepperInterface(instance, get_browser_interface);
     65     s_state.ppapi = ppapi;
     66   }
     67   int rtn = ki_init_interface(kp, ppapi);
     68   return rtn;
     69 }
     70 
     71 int ki_init_interface(void* kp, void* pepper_interface) {
     72   LOG_TRACE("ki_init_interface: %p %p", kp, pepper_interface);
     73   assert(!s_state.kp);
     74   if (s_state.kp != NULL)
     75     return 1;
     76   PepperInterface* ppapi = static_cast<PepperInterface*>(pepper_interface);
     77   kernel_wrap_init();
     78 
     79   if (kp == NULL) {
     80     s_state.kp = new KernelProxy();
     81     s_state.kp_owned = true;
     82   } else {
     83     s_state.kp = static_cast<KernelProxy*>(kp);
     84     s_state.kp_owned = false;
     85   }
     86 
     87   if (s_state.kp->Init(ppapi) != 0)
     88     return 1;
     89 
     90   return 0;
     91 }
     92 
     93 int ki_is_initialized() {
     94   return s_state.kp != NULL;
     95 }
     96 
     97 void ki_uninit() {
     98   LOG_TRACE("ki_uninit");
     99   if (s_saved_state.kp == NULL)
    100     kernel_wrap_uninit();
    101 
    102   // If we are going to delete the KernelProxy don't do it
    103   // until we've swapped it out.
    104   KernelInterceptState state_to_delete = s_state;
    105 
    106   // Swap out the KernelProxy. This will normally reset the
    107   // proxy to NULL, aside from in test code that has called
    108   // ki_push_state_for_testing().
    109   s_state = s_saved_state;
    110   s_saved_state.kp = NULL;
    111   s_saved_state.ppapi = NULL;
    112   s_saved_state.kp_owned = false;
    113 
    114   if (state_to_delete.kp_owned)
    115     delete state_to_delete.kp;
    116 
    117   delete state_to_delete.ppapi;
    118 }
    119 
    120 nacl_io::KernelProxy* ki_get_proxy() {
    121   return s_state.kp;
    122 }
    123 
    124 int ki_chdir(const char* path) {
    125   ON_NOSYS_RETURN(-1);
    126   return s_state.kp->chdir(path);
    127 }
    128 
    129 void ki_exit(int status) {
    130   if (ki_is_initialized())
    131     s_state.kp->exit(status);
    132 
    133   _real_exit(status);
    134 }
    135 
    136 char* ki_getcwd(char* buf, size_t size) {
    137   // gtest uses getcwd in a static initializer. If we haven't initialized the
    138   // kernel-intercept yet, just return ".".
    139   if (!ki_is_initialized()) {
    140     if (size < 2) {
    141       errno = ERANGE;
    142       return NULL;
    143     }
    144     buf[0] = '.';
    145     buf[1] = 0;
    146     return buf;
    147   }
    148   return s_state.kp->getcwd(buf, size);
    149 }
    150 
    151 char* ki_getwd(char* buf) {
    152   ON_NOSYS_RETURN(NULL);
    153   return s_state.kp->getwd(buf);
    154 }
    155 
    156 int ki_dup(int oldfd) {
    157   ON_NOSYS_RETURN(-1);
    158   return s_state.kp->dup(oldfd);
    159 }
    160 
    161 int ki_dup2(int oldfd, int newfd) {
    162   ON_NOSYS_RETURN(-1);
    163   return s_state.kp->dup2(oldfd, newfd);
    164 }
    165 
    166 int ki_chmod(const char* path, mode_t mode) {
    167   ON_NOSYS_RETURN(-1);
    168   return s_state.kp->chmod(path, mode);
    169 }
    170 
    171 int ki_fchdir(int fd) {
    172   ON_NOSYS_RETURN(-1);
    173   return s_state.kp->fchdir(fd);
    174 }
    175 
    176 int ki_fchmod(int fd, mode_t mode) {
    177   ON_NOSYS_RETURN(-1);
    178   return s_state.kp->fchmod(fd, mode);
    179 }
    180 
    181 int ki_stat(const char* path, struct stat* buf) {
    182   ON_NOSYS_RETURN(-1);
    183   return s_state.kp->stat(path, buf);
    184 }
    185 
    186 int ki_mkdir(const char* path, mode_t mode) {
    187   ON_NOSYS_RETURN(-1);
    188   return s_state.kp->mkdir(path, mode);
    189 }
    190 
    191 int ki_rmdir(const char* path) {
    192   ON_NOSYS_RETURN(-1);
    193   return s_state.kp->rmdir(path);
    194 }
    195 
    196 int ki_mount(const char* source,
    197              const char* target,
    198              const char* filesystemtype,
    199              unsigned long mountflags,
    200              const void* data) {
    201   ON_NOSYS_RETURN(-1);
    202   return s_state.kp->mount(source, target, filesystemtype, mountflags, data);
    203 }
    204 
    205 int ki_umount(const char* path) {
    206   ON_NOSYS_RETURN(-1);
    207   return s_state.kp->umount(path);
    208 }
    209 
    210 int ki_open(const char* path, int oflag) {
    211   ON_NOSYS_RETURN(-1);
    212   return s_state.kp->open(path, oflag);
    213 }
    214 
    215 int ki_pipe(int pipefds[2]) {
    216   ON_NOSYS_RETURN(-1);
    217   return s_state.kp->pipe(pipefds);
    218 }
    219 
    220 ssize_t ki_read(int fd, void* buf, size_t nbyte) {
    221   ON_NOSYS_RETURN(-1);
    222   return s_state.kp->read(fd, buf, nbyte);
    223 }
    224 
    225 ssize_t ki_write(int fd, const void* buf, size_t nbyte) {
    226   ON_NOSYS_RETURN(-1);
    227   return s_state.kp->write(fd, buf, nbyte);
    228 }
    229 
    230 int ki_fstat(int fd, struct stat* buf) {
    231   ON_NOSYS_RETURN(-1);
    232   return s_state.kp->fstat(fd, buf);
    233 }
    234 
    235 int ki_getdents(int fd, void* buf, unsigned int count) {
    236   ON_NOSYS_RETURN(-1);
    237   return s_state.kp->getdents(fd, buf, count);
    238 }
    239 
    240 int ki_ftruncate(int fd, off_t length) {
    241   ON_NOSYS_RETURN(-1);
    242   return s_state.kp->ftruncate(fd, length);
    243 }
    244 
    245 int ki_fsync(int fd) {
    246   ON_NOSYS_RETURN(-1);
    247   return s_state.kp->fsync(fd);
    248 }
    249 
    250 int ki_fdatasync(int fd) {
    251   ON_NOSYS_RETURN(-1);
    252   return s_state.kp->fdatasync(fd);
    253 }
    254 
    255 int ki_isatty(int fd) {
    256   ON_NOSYS_RETURN(0);
    257   return s_state.kp->isatty(fd);
    258 }
    259 
    260 int ki_close(int fd) {
    261   ON_NOSYS_RETURN(-1);
    262   return s_state.kp->close(fd);
    263 }
    264 
    265 off_t ki_lseek(int fd, off_t offset, int whence) {
    266   ON_NOSYS_RETURN(-1);
    267   return s_state.kp->lseek(fd, offset, whence);
    268 }
    269 
    270 int ki_remove(const char* path) {
    271   ON_NOSYS_RETURN(-1);
    272   return s_state.kp->remove(path);
    273 }
    274 
    275 int ki_unlink(const char* path) {
    276   ON_NOSYS_RETURN(-1);
    277   return s_state.kp->unlink(path);
    278 }
    279 
    280 int ki_truncate(const char* path, off_t length) {
    281   ON_NOSYS_RETURN(-1);
    282   return s_state.kp->truncate(path, length);
    283 }
    284 
    285 int ki_lstat(const char* path, struct stat* buf) {
    286   ON_NOSYS_RETURN(-1);
    287   return s_state.kp->lstat(path, buf);
    288 }
    289 
    290 int ki_link(const char* oldpath, const char* newpath) {
    291   ON_NOSYS_RETURN(-1);
    292   return s_state.kp->link(oldpath, newpath);
    293 }
    294 
    295 int ki_rename(const char* path, const char* newpath) {
    296   ON_NOSYS_RETURN(-1);
    297   return s_state.kp->rename(path, newpath);
    298 }
    299 
    300 int ki_symlink(const char* oldpath, const char* newpath) {
    301   ON_NOSYS_RETURN(-1);
    302   return s_state.kp->symlink(oldpath, newpath);
    303 }
    304 
    305 int ki_access(const char* path, int amode) {
    306   ON_NOSYS_RETURN(-1);
    307   return s_state.kp->access(path, amode);
    308 }
    309 
    310 int ki_readlink(const char* path, char* buf, size_t count) {
    311   ON_NOSYS_RETURN(-1);
    312   return s_state.kp->readlink(path, buf, count);
    313 }
    314 
    315 int ki_utimes(const char* path, const struct timeval times[2]) {
    316   ON_NOSYS_RETURN(-1);
    317   return s_state.kp->utimes(path, times);
    318 }
    319 
    320 void* ki_mmap(void* addr,
    321               size_t length,
    322               int prot,
    323               int flags,
    324               int fd,
    325               off_t offset) {
    326   ON_NOSYS_RETURN(MAP_FAILED);
    327   return s_state.kp->mmap(addr, length, prot, flags, fd, offset);
    328 }
    329 
    330 int ki_munmap(void* addr, size_t length) {
    331   ON_NOSYS_RETURN(-1);
    332   return s_state.kp->munmap(addr, length);
    333 }
    334 
    335 int ki_open_resource(const char* file) {
    336   ON_NOSYS_RETURN(-1);
    337   return s_state.kp->open_resource(file);
    338 }
    339 
    340 int ki_fcntl(int d, int request, va_list args) {
    341   ON_NOSYS_RETURN(-1);
    342   return s_state.kp->fcntl(d, request, args);
    343 }
    344 
    345 int ki_ioctl(int d, int request, va_list args) {
    346   ON_NOSYS_RETURN(-1);
    347   return s_state.kp->ioctl(d, request, args);
    348 }
    349 
    350 int ki_chown(const char* path, uid_t owner, gid_t group) {
    351   ON_NOSYS_RETURN(-1);
    352   return s_state.kp->chown(path, owner, group);
    353 }
    354 
    355 int ki_fchown(int fd, uid_t owner, gid_t group) {
    356   ON_NOSYS_RETURN(-1);
    357   return s_state.kp->fchown(fd, owner, group);
    358 }
    359 
    360 int ki_lchown(const char* path, uid_t owner, gid_t group) {
    361   ON_NOSYS_RETURN(-1);
    362   return s_state.kp->lchown(path, owner, group);
    363 }
    364 
    365 int ki_utime(const char* filename, const struct utimbuf* times) {
    366   ON_NOSYS_RETURN(-1);
    367   return s_state.kp->utime(filename, times);
    368 }
    369 
    370 int ki_poll(struct pollfd* fds, nfds_t nfds, int timeout) {
    371   return s_state.kp->poll(fds, nfds, timeout);
    372 }
    373 
    374 int ki_select(int nfds,
    375               fd_set* readfds,
    376               fd_set* writefds,
    377               fd_set* exceptfds,
    378               struct timeval* timeout) {
    379   return s_state.kp->select(nfds, readfds, writefds, exceptfds, timeout);
    380 }
    381 
    382 int ki_tcflush(int fd, int queue_selector) {
    383   ON_NOSYS_RETURN(-1);
    384   return s_state.kp->tcflush(fd, queue_selector);
    385 }
    386 
    387 int ki_tcgetattr(int fd, struct termios* termios_p) {
    388   ON_NOSYS_RETURN(-1);
    389   return s_state.kp->tcgetattr(fd, termios_p);
    390 }
    391 
    392 int ki_tcsetattr(int fd,
    393                  int optional_actions,
    394                  const struct termios* termios_p) {
    395   ON_NOSYS_RETURN(-1);
    396   return s_state.kp->tcsetattr(fd, optional_actions, termios_p);
    397 }
    398 
    399 int ki_kill(pid_t pid, int sig) {
    400   ON_NOSYS_RETURN(-1);
    401   return s_state.kp->kill(pid, sig);
    402 }
    403 
    404 int ki_killpg(pid_t pid, int sig) {
    405   errno = ENOSYS;
    406   return -1;
    407 }
    408 
    409 int ki_sigaction(int signum,
    410                  const struct sigaction* action,
    411                  struct sigaction* oaction) {
    412   ON_NOSYS_RETURN(-1);
    413   return s_state.kp->sigaction(signum, action, oaction);
    414 }
    415 
    416 int ki_sigpause(int sigmask) {
    417   errno = ENOSYS;
    418   return -1;
    419 }
    420 
    421 int ki_sigpending(sigset_t* set) {
    422   errno = ENOSYS;
    423   return -1;
    424 }
    425 
    426 int ki_sigsuspend(const sigset_t* set) {
    427   errno = ENOSYS;
    428   return -1;
    429 }
    430 
    431 sighandler_t ki_signal(int signum, sighandler_t handler) {
    432   return ki_sigset(signum, handler);
    433 }
    434 
    435 sighandler_t ki_sigset(int signum, sighandler_t handler) {
    436   ON_NOSYS_RETURN(SIG_ERR);
    437   // Implement sigset(2) in terms of sigaction(2).
    438   struct sigaction action;
    439   struct sigaction oaction;
    440   memset(&action, 0, sizeof(action));
    441   memset(&oaction, 0, sizeof(oaction));
    442   action.sa_handler = handler;
    443   int rtn = s_state.kp->sigaction(signum, &action, &oaction);
    444   if (rtn)
    445     return SIG_ERR;
    446   return oaction.sa_handler;
    447 }
    448 
    449 #ifdef PROVIDES_SOCKET_API
    450 // Socket Functions
    451 int ki_accept(int fd, struct sockaddr* addr, socklen_t* len) {
    452   ON_NOSYS_RETURN(-1);
    453   return s_state.kp->accept(fd, addr, len);
    454 }
    455 
    456 int ki_bind(int fd, const struct sockaddr* addr, socklen_t len) {
    457   ON_NOSYS_RETURN(-1);
    458   return s_state.kp->bind(fd, addr, len);
    459 }
    460 
    461 int ki_connect(int fd, const struct sockaddr* addr, socklen_t len) {
    462   ON_NOSYS_RETURN(-1);
    463   return s_state.kp->connect(fd, addr, len);
    464 }
    465 
    466 struct hostent* ki_gethostbyname(const char* name) {
    467   ON_NOSYS_RETURN(NULL);
    468   return s_state.kp->gethostbyname(name);
    469 }
    470 
    471 int ki_getaddrinfo(const char* node,
    472                    const char* service,
    473                    const struct addrinfo* hints,
    474                    struct addrinfo** res) {
    475   ON_NOSYS_RETURN(EAI_SYSTEM);
    476   return s_state.kp->getaddrinfo(node, service, hints, res);
    477 }
    478 
    479 void ki_freeaddrinfo(struct addrinfo* res) {
    480   s_state.kp->freeaddrinfo(res);
    481 }
    482 
    483 int ki_getpeername(int fd, struct sockaddr* addr, socklen_t* len) {
    484   ON_NOSYS_RETURN(-1);
    485   return s_state.kp->getpeername(fd, addr, len);
    486 }
    487 
    488 int ki_getsockname(int fd, struct sockaddr* addr, socklen_t* len) {
    489   ON_NOSYS_RETURN(-1);
    490   return s_state.kp->getsockname(fd, addr, len);
    491 }
    492 
    493 int ki_getsockopt(int fd, int lvl, int optname, void* optval, socklen_t* len) {
    494   ON_NOSYS_RETURN(-1);
    495   return s_state.kp->getsockopt(fd, lvl, optname, optval, len);
    496 }
    497 
    498 int ki_listen(int fd, int backlog) {
    499   ON_NOSYS_RETURN(-1);
    500   return s_state.kp->listen(fd, backlog);
    501 }
    502 
    503 ssize_t ki_recv(int fd, void* buf, size_t len, int flags) {
    504   ON_NOSYS_RETURN(-1);
    505   return s_state.kp->recv(fd, buf, len, flags);
    506 }
    507 
    508 ssize_t ki_recvfrom(int fd,
    509                     void* buf,
    510                     size_t len,
    511                     int flags,
    512                     struct sockaddr* addr,
    513                     socklen_t* addrlen) {
    514   ON_NOSYS_RETURN(-1);
    515   return s_state.kp->recvfrom(fd, buf, len, flags, addr, addrlen);
    516 }
    517 
    518 ssize_t ki_recvmsg(int fd, struct msghdr* msg, int flags) {
    519   ON_NOSYS_RETURN(-1);
    520   return s_state.kp->recvmsg(fd, msg, flags);
    521 }
    522 
    523 ssize_t ki_send(int fd, const void* buf, size_t len, int flags) {
    524   ON_NOSYS_RETURN(-1);
    525   return s_state.kp->send(fd, buf, len, flags);
    526 }
    527 
    528 ssize_t ki_sendto(int fd,
    529                   const void* buf,
    530                   size_t len,
    531                   int flags,
    532                   const struct sockaddr* addr,
    533                   socklen_t addrlen) {
    534   ON_NOSYS_RETURN(-1);
    535   return s_state.kp->sendto(fd, buf, len, flags, addr, addrlen);
    536 }
    537 
    538 ssize_t ki_sendmsg(int fd, const struct msghdr* msg, int flags) {
    539   ON_NOSYS_RETURN(-1);
    540   return s_state.kp->sendmsg(fd, msg, flags);
    541 }
    542 
    543 int ki_setsockopt(int fd,
    544                   int lvl,
    545                   int optname,
    546                   const void* optval,
    547                   socklen_t len) {
    548   ON_NOSYS_RETURN(-1);
    549   return s_state.kp->setsockopt(fd, lvl, optname, optval, len);
    550 }
    551 
    552 int ki_shutdown(int fd, int how) {
    553   ON_NOSYS_RETURN(-1);
    554   return s_state.kp->shutdown(fd, how);
    555 }
    556 
    557 int ki_socket(int domain, int type, int protocol) {
    558   ON_NOSYS_RETURN(-1);
    559   return s_state.kp->socket(domain, type, protocol);
    560 }
    561 
    562 int ki_socketpair(int domain, int type, int protocol, int* sv) {
    563   ON_NOSYS_RETURN(-1);
    564   return s_state.kp->socketpair(domain, type, protocol, sv);
    565 }
    566 #endif  // PROVIDES_SOCKET_API
    567