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