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 <sys/types.h>  // Include something that will define __GLIBC__.
      6 
      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.
      9 #if defined(__native_client__) && defined(__GLIBC__)
     10 
     11 #include "nacl_io/kernel_wrap.h"
     12 
     13 #include <alloca.h>
     14 #include <assert.h>
     15 #include <dirent.h>
     16 #include <errno.h>
     17 #include <irt.h>
     18 #include <irt_syscalls.h>
     19 #include <nacl_stat.h>
     20 #include <string.h>
     21 #include <sys/stat.h>
     22 #include <sys/time.h>
     23 
     24 #include "nacl_io/kernel_intercept.h"
     25 #include "nacl_io/kernel_wrap_real.h"
     26 #include "nacl_io/log.h"
     27 #include "nacl_io/osmman.h"
     28 #include "nacl_io/ostime.h"
     29 
     30 namespace {
     31 
     32 void stat_to_nacl_stat(const struct stat* buf, nacl_abi_stat* nacl_buf) {
     33   memset(nacl_buf, 0, sizeof(struct nacl_abi_stat));
     34   nacl_buf->nacl_abi_st_dev = buf->st_dev;
     35   nacl_buf->nacl_abi_st_ino = buf->st_ino;
     36   nacl_buf->nacl_abi_st_mode = buf->st_mode;
     37   nacl_buf->nacl_abi_st_nlink = buf->st_nlink;
     38   nacl_buf->nacl_abi_st_uid = buf->st_uid;
     39   nacl_buf->nacl_abi_st_gid = buf->st_gid;
     40   nacl_buf->nacl_abi_st_rdev = buf->st_rdev;
     41   nacl_buf->nacl_abi_st_size = buf->st_size;
     42   nacl_buf->nacl_abi_st_blksize = buf->st_blksize;
     43   nacl_buf->nacl_abi_st_blocks = buf->st_blocks;
     44   nacl_buf->nacl_abi_st_atime = buf->st_atime;
     45   nacl_buf->nacl_abi_st_atimensec = buf->st_atimensec;
     46   nacl_buf->nacl_abi_st_mtime = buf->st_mtime;
     47   nacl_buf->nacl_abi_st_mtimensec = buf->st_mtimensec;
     48   nacl_buf->nacl_abi_st_ctime = buf->st_ctime;
     49   nacl_buf->nacl_abi_st_ctimensec = buf->st_ctimensec;
     50 }
     51 
     52 void nacl_stat_to_stat(const nacl_abi_stat* nacl_buf, struct stat* buf) {
     53   memset(buf, 0, sizeof(struct stat));
     54   buf->st_dev = nacl_buf->nacl_abi_st_dev;
     55   buf->st_ino = nacl_buf->nacl_abi_st_ino;
     56   buf->st_mode = nacl_buf->nacl_abi_st_mode;
     57   buf->st_nlink = nacl_buf->nacl_abi_st_nlink;
     58   buf->st_uid = nacl_buf->nacl_abi_st_uid;
     59   buf->st_gid = nacl_buf->nacl_abi_st_gid;
     60   buf->st_rdev = nacl_buf->nacl_abi_st_rdev;
     61   buf->st_size = nacl_buf->nacl_abi_st_size;
     62   buf->st_blksize = nacl_buf->nacl_abi_st_blksize;
     63   buf->st_blocks = nacl_buf->nacl_abi_st_blocks;
     64   buf->st_atime = nacl_buf->nacl_abi_st_atime;
     65   buf->st_atimensec = nacl_buf->nacl_abi_st_atimensec;
     66   buf->st_mtime = nacl_buf->nacl_abi_st_mtime;
     67   buf->st_mtimensec = nacl_buf->nacl_abi_st_mtimensec;
     68   buf->st_ctime = nacl_buf->nacl_abi_st_ctime;
     69   buf->st_ctimensec = nacl_buf->nacl_abi_st_ctimensec;
     70 }
     71 
     72 }  // namespace
     73 
     74 // From native_client/src/trusted/service_runtime/include/sys/dirent.h
     75 
     76 #ifndef nacl_abi___ino_t_defined
     77 #define nacl_abi___ino_t_defined
     78 typedef int64_t nacl_abi___ino_t;
     79 typedef nacl_abi___ino_t nacl_abi_ino_t;
     80 #endif
     81 
     82 #ifndef nacl_abi___off_t_defined
     83 #define nacl_abi___off_t_defined
     84 typedef int64_t nacl_abi__off_t;
     85 typedef nacl_abi__off_t nacl_abi_off_t;
     86 #endif
     87 
     88 /* We need a way to define the maximum size of a name. */
     89 #ifndef MAXNAMLEN
     90 # ifdef NAME_MAX
     91 #  define MAXNAMLEN NAME_MAX
     92 # else
     93 #  define MAXNAMLEN 255
     94 # endif
     95 #endif
     96 
     97 struct nacl_abi_dirent {
     98   nacl_abi_ino_t nacl_abi_d_ino;
     99   nacl_abi_off_t nacl_abi_d_off;
    100   uint16_t       nacl_abi_d_reclen;
    101   char           nacl_abi_d_name[MAXNAMLEN + 1];
    102 };
    103 
    104 static const int d_name_shift = offsetof (dirent, d_name) -
    105   offsetof (struct nacl_abi_dirent, nacl_abi_d_name);
    106 
    107 EXTERN_C_BEGIN
    108 
    109 // Macro to get the REAL function pointer
    110 #define REAL(name) __nacl_irt_##name##_real
    111 
    112 // Macro to get the WRAP function
    113 #define WRAP(name) __nacl_irt_##name##_wrap
    114 
    115 // Declare REAL function pointer.
    116 #define DECLARE_REAL_PTR(name) typeof(__nacl_irt_##name) REAL(name);
    117 
    118 // Assign the REAL function pointer.
    119 #define ASSIGN_REAL_PTR(name)        \
    120   assert(__nacl_irt_##name != NULL); \
    121   REAL(name) = __nacl_irt_##name;
    122 
    123 // Switch IRT's pointer to the REAL pointer
    124 #define USE_REAL(name) __nacl_irt_##name = (typeof(__nacl_irt_##name))REAL(name)
    125 
    126 // Switch IRT's pointer to the WRAP function
    127 #define USE_WRAP(name) __nacl_irt_##name = (typeof(__nacl_irt_##name))WRAP(name)
    128 
    129 #define EXPAND_SYMBOL_LIST_OPERATION(OP) \
    130   OP(chdir);                             \
    131   OP(close);                             \
    132   OP(dup);                               \
    133   OP(dup2);                              \
    134   OP(exit);                              \
    135   OP(fstat);                             \
    136   OP(getcwd);                            \
    137   OP(getdents);                          \
    138   OP(mkdir);                             \
    139   OP(open);                              \
    140   OP(poll);                              \
    141   OP(read);                              \
    142   OP(rmdir);                             \
    143   OP(seek);                              \
    144   OP(stat);                              \
    145   OP(select);                            \
    146   OP(write);                             \
    147   OP(mmap);                              \
    148   OP(munmap);                            \
    149   OP(open_resource);                     \
    150                                          \
    151   OP(socket);                            \
    152   OP(accept);                            \
    153   OP(bind);                              \
    154   OP(listen);                            \
    155   OP(connect);                           \
    156   OP(send);                              \
    157   OP(sendmsg);                           \
    158   OP(sendto);                            \
    159   OP(recv);                              \
    160   OP(recvmsg);                           \
    161   OP(recvfrom);                          \
    162   OP(getpeername);                       \
    163   OP(getsockname);                       \
    164   OP(getsockopt);                        \
    165   OP(setsockopt);                        \
    166   OP(socketpair);                        \
    167   OP(shutdown);                          \
    168                                          \
    169   OP(chmod);                             \
    170   OP(access);                            \
    171   OP(unlink);                            \
    172   OP(fchdir);                            \
    173   OP(fchmod);                            \
    174   OP(fsync);                             \
    175   OP(fdatasync);                         \
    176   OP(lstat);                             \
    177   OP(link);                              \
    178   OP(readlink);                          \
    179   OP(utimes);
    180 
    181 // TODO(bradnelson): Add these as well.
    182 // OP(epoll_create);
    183 // OP(epoll_create1);
    184 // OP(epoll_ctl);
    185 // OP(epoll_pwait);
    186 // OP(ppoll);
    187 // OP(pselect);
    188 
    189 EXPAND_SYMBOL_LIST_OPERATION(DECLARE_REAL_PTR);
    190 
    191 int WRAP(chdir)(const char* pathname) {
    192   ERRNO_RTN(ki_chdir(pathname));
    193 }
    194 
    195 int WRAP(close)(int fd) {
    196   ERRNO_RTN(ki_close(fd));
    197 }
    198 
    199 int WRAP(dup)(int fd, int* newfd) NOTHROW {
    200   *newfd = ki_dup(fd);
    201   RTN_ERRNO_IF(*newfd < 0);
    202   return 0;
    203 }
    204 
    205 int WRAP(dup2)(int fd, int newfd) NOTHROW {
    206   ERRNO_RTN(ki_dup2(fd, newfd));
    207 }
    208 
    209 void WRAP(exit)(int status) {
    210   ki_exit(status);
    211 }
    212 
    213 int WRAP(fstat)(int fd, struct nacl_abi_stat* nacl_buf) {
    214   struct stat buf;
    215   memset(&buf, 0, sizeof(struct stat));
    216   int res = ki_fstat(fd, &buf);
    217   RTN_ERRNO_IF(res < 0);
    218   stat_to_nacl_stat(&buf, nacl_buf);
    219   return 0;
    220 }
    221 
    222 int WRAP(getcwd)(char* buf, size_t size) {
    223   RTN_ERRNO_IF(ki_getcwd(buf, size) == NULL);
    224   return 0;
    225 }
    226 
    227 int WRAP(getdents)(int fd, dirent* nacl_buf, size_t nacl_count, size_t* nread) {
    228   int nacl_offset = 0;
    229   // "buf" contains dirent(s); "nacl_buf" contains nacl_abi_dirent(s).
    230   // nacl_abi_dirent(s) are smaller than dirent(s), so nacl_count bytes buffer
    231   // is enough
    232   char* buf = (char*)alloca(nacl_count);
    233   int offset = 0;
    234   int count;
    235 
    236   count = ki_getdents(fd, buf, nacl_count);
    237   RTN_ERRNO_IF(count < 0);
    238 
    239   while (offset < count) {
    240     dirent* d = (dirent*)(buf + offset);
    241     nacl_abi_dirent* nacl_d = (nacl_abi_dirent*)((char*)nacl_buf + nacl_offset);
    242     nacl_d->nacl_abi_d_ino = d->d_ino;
    243     nacl_d->nacl_abi_d_off = d->d_off;
    244     nacl_d->nacl_abi_d_reclen = d->d_reclen - d_name_shift;
    245     size_t d_name_len = d->d_reclen - offsetof(dirent, d_name);
    246     memcpy(nacl_d->nacl_abi_d_name, d->d_name, d_name_len);
    247 
    248     offset += d->d_reclen;
    249     nacl_offset += nacl_d->nacl_abi_d_reclen;
    250   }
    251 
    252   *nread = nacl_offset;
    253   return 0;
    254 }
    255 
    256 int WRAP(mkdir)(const char* pathname, mode_t mode) {
    257   RTN_ERRNO_IF(ki_mkdir(pathname, mode) < 0);
    258   return 0;
    259 }
    260 
    261 int WRAP(mmap)(void** addr,
    262                size_t length,
    263                int prot,
    264                int flags,
    265                int fd,
    266                off_t offset) {
    267   if (flags & MAP_ANONYMOUS)
    268     return REAL(mmap)(addr, length, prot, flags, fd, offset);
    269 
    270   *addr = ki_mmap(*addr, length, prot, flags, fd, offset);
    271   RTN_ERRNO_IF(*addr == (void*)-1);
    272   return 0;
    273 }
    274 
    275 int WRAP(munmap)(void* addr, size_t length) {
    276   // Always let the real munmap run on the address range. It is not an error if
    277   // there are no mapped pages in that range.
    278   ki_munmap(addr, length);
    279   return REAL(munmap)(addr, length);
    280 }
    281 
    282 int WRAP(open)(const char* pathname, int oflag, mode_t mode, int* newfd) {
    283   *newfd = ki_open(pathname, oflag, mode);
    284   RTN_ERRNO_IF(*newfd < 0);
    285   return 0;
    286 }
    287 
    288 int WRAP(open_resource)(const char* file, int* fd) {
    289   *fd = ki_open_resource(file);
    290   RTN_ERRNO_IF(*fd < 0);
    291   return 0;
    292 }
    293 
    294 int WRAP(poll)(struct pollfd* fds, nfds_t nfds, int timeout, int* count) {
    295   *count = ki_poll(fds, nfds, timeout);
    296   RTN_ERRNO_IF(*count < 0);
    297   return 0;
    298 }
    299 
    300 int WRAP(read)(int fd, void* buf, size_t count, size_t* nread) {
    301   ssize_t signed_nread = ki_read(fd, buf, count);
    302   *nread = static_cast<size_t>(signed_nread);
    303   RTN_ERRNO_IF(signed_nread < 0);
    304   return 0;
    305 }
    306 
    307 int WRAP(rmdir)(const char* pathname) {
    308   RTN_ERRNO_IF(ki_rmdir(pathname) < 0);
    309   return 0;
    310 }
    311 
    312 int WRAP(seek)(int fd, off_t offset, int whence, off_t* new_offset) {
    313   *new_offset = ki_lseek(fd, offset, whence);
    314   RTN_ERRNO_IF(*new_offset < 0);
    315   return 0;
    316 }
    317 
    318 int WRAP(select)(int nfds,
    319                  fd_set* readfds,
    320                  fd_set* writefds,
    321                  fd_set* exceptfds,
    322                  struct timeval* timeout,
    323                  int* count) {
    324   *count = ki_select(nfds, readfds, writefds, exceptfds, timeout);
    325   RTN_ERRNO_IF(*count < 0);
    326   return 0;
    327 }
    328 
    329 int WRAP(stat)(const char* pathname, struct nacl_abi_stat* nacl_buf) {
    330   struct stat buf;
    331   memset(&buf, 0, sizeof(struct stat));
    332   int res = ki_stat(pathname, &buf);
    333   RTN_ERRNO_IF(res < 0);
    334   stat_to_nacl_stat(&buf, nacl_buf);
    335   return 0;
    336 }
    337 
    338 int WRAP(lstat)(const char* pathname, struct nacl_abi_stat* nacl_buf) {
    339   struct stat buf;
    340   memset(&buf, 0, sizeof(struct stat));
    341   int res = ki_lstat(pathname, &buf);
    342   RTN_ERRNO_IF(res < 0);
    343   stat_to_nacl_stat(&buf, nacl_buf);
    344   return 0;
    345 }
    346 
    347 int WRAP(link)(const char* pathname, const char* newpath) {
    348   ERRNO_RTN(ki_link(pathname, newpath));
    349 }
    350 
    351 int WRAP(readlink)(const char* pathname,
    352                    char* buf,
    353                    size_t count,
    354                    size_t* nread) {
    355   int rtn = ki_readlink(pathname, buf, count);
    356   RTN_ERRNO_IF(rtn < 0);
    357   *nread = rtn;
    358   return 0;
    359 }
    360 
    361 int WRAP(utimes)(const char *filename, const struct timeval *times) {
    362   ERRNO_RTN(ki_utimes(filename, times));
    363 }
    364 
    365 int WRAP(chmod)(const char* pathname, mode_t mode) {
    366   ERRNO_RTN(ki_chmod(pathname, mode));
    367 }
    368 
    369 int WRAP(access)(const char* pathname, int amode) {
    370   ERRNO_RTN(ki_access(pathname, amode));
    371 }
    372 
    373 int WRAP(unlink)(const char* pathname) {
    374   ERRNO_RTN(ki_unlink(pathname));
    375 }
    376 
    377 int WRAP(fchdir)(int fd) {
    378   ERRNO_RTN(ki_fchdir(fd));
    379 }
    380 
    381 int WRAP(fchmod)(int fd, mode_t mode) {
    382   ERRNO_RTN(ki_fchmod(fd, mode));
    383 }
    384 
    385 int WRAP(fsync)(int fd) {
    386   ERRNO_RTN(ki_fsync(fd));
    387 }
    388 
    389 int WRAP(fdatasync)(int fd) {
    390   ERRNO_RTN(ki_fdatasync(fd));
    391 }
    392 
    393 int WRAP(write)(int fd, const void* buf, size_t count, size_t* nwrote) {
    394   ssize_t signed_nwrote = ki_write(fd, buf, count);
    395   *nwrote = static_cast<size_t>(signed_nwrote);
    396   RTN_ERRNO_IF(signed_nwrote < 0);
    397   return 0;
    398 }
    399 
    400 int WRAP(accept)(int sockfd,
    401                  struct sockaddr* addr,
    402                  socklen_t* addrlen,
    403                  int* sd) {
    404   *sd = ki_accept(sockfd, addr, addrlen);
    405   RTN_ERRNO_IF(*sd < 0);
    406   return 0;
    407 }
    408 
    409 int WRAP(bind)(int sockfd, const struct sockaddr* addr, socklen_t addrlen) {
    410   ERRNO_RTN(ki_bind(sockfd, addr, addrlen));
    411 }
    412 
    413 int WRAP(connect)(int sockfd, const struct sockaddr* addr, socklen_t addrlen) {
    414   ERRNO_RTN(ki_connect(sockfd, addr, addrlen));
    415 }
    416 
    417 int WRAP(getpeername)(int sockfd, struct sockaddr* addr, socklen_t* addrlen) {
    418   ERRNO_RTN(ki_getpeername(sockfd, addr, addrlen));
    419 }
    420 
    421 int WRAP(getsockname)(int sockfd, struct sockaddr* addr, socklen_t* addrlen) {
    422   ERRNO_RTN(ki_getsockname(sockfd, addr, addrlen));
    423 }
    424 
    425 int WRAP(getsockopt)(int sockfd,
    426                      int level,
    427                      int optname,
    428                      void* optval,
    429                      socklen_t* optlen) {
    430   ERRNO_RTN(ki_getsockopt(sockfd, level, optname, optval, optlen));
    431 }
    432 
    433 int WRAP(setsockopt)(int sockfd,
    434                      int level,
    435                      int optname,
    436                      const void* optval,
    437                      socklen_t optlen) {
    438   ERRNO_RTN(ki_setsockopt(sockfd, level, optname, optval, optlen));
    439 }
    440 
    441 int WRAP(listen)(int sockfd, int backlog) {
    442   ERRNO_RTN(ki_listen(sockfd, backlog));
    443 }
    444 
    445 int WRAP(recv)(int sockfd, void* buf, size_t len, int flags, int* count) {
    446   ssize_t signed_nread = ki_recv(sockfd, buf, len, flags);
    447   *count = static_cast<int>(signed_nread);
    448   RTN_ERRNO_IF(signed_nread < 0);
    449   return 0;
    450 }
    451 
    452 int WRAP(recvfrom)(int sockfd,
    453                    void* buf,
    454                    size_t len,
    455                    int flags,
    456                    struct sockaddr* addr,
    457                    socklen_t* addrlen,
    458                    int* count) {
    459   ssize_t signed_nread = ki_recvfrom(sockfd, buf, len, flags, addr, addrlen);
    460   *count = static_cast<int>(signed_nread);
    461   RTN_ERRNO_IF(signed_nread < 0);
    462   return 0;
    463 }
    464 
    465 int WRAP(recvmsg)(int sockfd, struct msghdr* msg, int flags, int* count) {
    466   ssize_t signed_nread = ki_recvmsg(sockfd, msg, flags);
    467   *count = static_cast<int>(signed_nread);
    468   RTN_ERRNO_IF(signed_nread < 0);
    469   return 0;
    470 }
    471 
    472 ssize_t WRAP(send)(int sockfd, const void* buf, size_t len, int flags,
    473                    int* count) {
    474   ssize_t signed_nread = ki_send(sockfd, buf, len, flags);
    475   *count = static_cast<int>(signed_nread);
    476   RTN_ERRNO_IF(signed_nread < 0);
    477   return 0;
    478 }
    479 
    480 ssize_t WRAP(sendto)(int sockfd,
    481                      const void* buf,
    482                      size_t len,
    483                      int flags,
    484                      const struct sockaddr* addr,
    485                      socklen_t addrlen,
    486                      int* count) {
    487   ssize_t signed_nread = ki_sendto(sockfd, buf, len, flags, addr, addrlen);
    488   *count = static_cast<int>(signed_nread);
    489   RTN_ERRNO_IF(signed_nread < 0);
    490   return 0;
    491 }
    492 
    493 ssize_t WRAP(sendmsg)(int sockfd,
    494                       const struct msghdr* msg,
    495                       int flags,
    496                       int* count) {
    497   ssize_t signed_nread = ki_sendmsg(sockfd, msg, flags);
    498   *count = static_cast<int>(signed_nread);
    499   RTN_ERRNO_IF(signed_nread < 0);
    500   return 0;
    501 }
    502 
    503 int WRAP(shutdown)(int sockfd, int how) {
    504   RTN_ERRNO_IF(ki_shutdown(sockfd, how) < 0);
    505   return 0;
    506 }
    507 
    508 int WRAP(socket)(int domain, int type, int protocol, int* sd) {
    509   *sd = ki_socket(domain, type, protocol);
    510   RTN_ERRNO_IF(*sd < 0);
    511   return 0;
    512 }
    513 
    514 int WRAP(socketpair)(int domain, int type, int protocol, int* sv) {
    515   RTN_ERRNO_IF(ki_socketpair(domain, type, protocol, sv) < 0);
    516   return 0;
    517 }
    518 
    519 static void assign_real_pointers() {
    520   static bool assigned = false;
    521   if (!assigned) {
    522     EXPAND_SYMBOL_LIST_OPERATION(ASSIGN_REAL_PTR)
    523     assigned = true;
    524   }
    525 }
    526 
    527 #define CHECK_REAL(func)    \
    528   if (!REAL(func)) {        \
    529     assign_real_pointers(); \
    530     if (!REAL(func))        \
    531       return ENOSYS;        \
    532   }
    533 
    534 // "real" functions, i.e. the unwrapped original functions.
    535 
    536 int _real_close(int fd) {
    537   CHECK_REAL(close);
    538   return REAL(close)(fd);
    539 }
    540 
    541 void _real_exit(int status) {
    542   if (!REAL(exit))
    543     assign_real_pointers();
    544   REAL(exit)(status);
    545 }
    546 
    547 int _real_fstat(int fd, struct stat* buf) {
    548   struct nacl_abi_stat st;
    549   CHECK_REAL(fstat);
    550   int err = REAL(fstat)(fd, &st);
    551   if (err) {
    552     errno = err;
    553     return -1;
    554   }
    555 
    556   nacl_stat_to_stat(&st, buf);
    557   return 0;
    558 }
    559 
    560 int _real_getdents(int fd, void* buf, size_t count, size_t* nread) {
    561   // "buf" contains dirent(s); "nacl_buf" contains nacl_abi_dirent(s).
    562   // See WRAP(getdents) above.
    563   char* nacl_buf = (char*)alloca(count);
    564   size_t offset = 0;
    565   size_t nacl_offset = 0;
    566   size_t nacl_nread;
    567   CHECK_REAL(getdents);
    568   int err = REAL(getdents)(fd, (dirent*)nacl_buf, count, &nacl_nread);
    569   if (err)
    570     return err;
    571 
    572   while (nacl_offset < nacl_nread) {
    573     dirent* d = (dirent*)((char*)buf + offset);
    574     nacl_abi_dirent* nacl_d = (nacl_abi_dirent*)(nacl_buf + nacl_offset);
    575     d->d_ino = nacl_d->nacl_abi_d_ino;
    576     d->d_off = nacl_d->nacl_abi_d_off;
    577     d->d_reclen = nacl_d->nacl_abi_d_reclen + d_name_shift;
    578     size_t d_name_len =
    579         nacl_d->nacl_abi_d_reclen - offsetof(nacl_abi_dirent, nacl_abi_d_name);
    580     memcpy(d->d_name, nacl_d->nacl_abi_d_name, d_name_len);
    581 
    582     offset += d->d_reclen;
    583     offset += nacl_d->nacl_abi_d_reclen;
    584   }
    585 
    586   *nread = offset;
    587   return 0;
    588 }
    589 
    590 int _real_lseek(int fd, off_t offset, int whence, off_t* new_offset) {
    591   CHECK_REAL(seek);
    592   return REAL(seek)(fd, offset, whence, new_offset);
    593 }
    594 
    595 int _real_mkdir(const char* pathname, mode_t mode) {
    596   CHECK_REAL(mkdir);
    597   return REAL(mkdir)(pathname, mode);
    598 }
    599 
    600 int _real_mmap(void** addr,
    601                size_t length,
    602                int prot,
    603                int flags,
    604                int fd,
    605                off_t offset) {
    606   CHECK_REAL(mmap);
    607   return REAL(mmap)(addr, length, prot, flags, fd, offset);
    608 }
    609 
    610 int _real_munmap(void* addr, size_t length) {
    611   CHECK_REAL(munmap);
    612   return REAL(munmap)(addr, length);
    613 }
    614 
    615 int _real_open(const char* pathname, int oflag, mode_t mode, int* newfd) {
    616   CHECK_REAL(open);
    617   return REAL(open)(pathname, oflag, mode, newfd);
    618 }
    619 
    620 int _real_open_resource(const char* file, int* fd) {
    621   CHECK_REAL(open_resource);
    622   return REAL(open_resource)(file, fd);
    623 }
    624 
    625 int _real_read(int fd, void* buf, size_t count, size_t* nread) {
    626   CHECK_REAL(read);
    627   return REAL(read)(fd, buf, count, nread);
    628 }
    629 
    630 int _real_rmdir(const char* pathname) {
    631   CHECK_REAL(rmdir);
    632   return REAL(rmdir)(pathname);
    633 }
    634 
    635 int _real_write(int fd, const void* buf, size_t count, size_t* nwrote) {
    636   CHECK_REAL(write);
    637   return REAL(write)(fd, buf, count, nwrote);
    638 }
    639 
    640 int _real_getcwd(char* pathname, size_t len) {
    641   CHECK_REAL(getcwd);
    642   return REAL(getcwd)(pathname, len);
    643 }
    644 
    645 static bool s_wrapped = false;
    646 void kernel_wrap_init() {
    647   if (!s_wrapped) {
    648     LOG_TRACE("kernel_wrap_init");
    649     assign_real_pointers();
    650     EXPAND_SYMBOL_LIST_OPERATION(USE_WRAP)
    651     s_wrapped = true;
    652   }
    653 }
    654 
    655 void kernel_wrap_uninit() {
    656   if (s_wrapped) {
    657     LOG_TRACE("kernel_wrap_uninit");
    658     EXPAND_SYMBOL_LIST_OPERATION(USE_REAL)
    659     s_wrapped = false;
    660   }
    661 }
    662 
    663 EXTERN_C_END
    664 
    665 #endif  // defined(__native_client__) && defined(__GLIBC__)
    666