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-newlib build. 9 #if defined(__native_client__) && !defined(__GLIBC__) 10 11 #include "nacl_io/kernel_wrap.h" 12 #include <assert.h> 13 #include <dirent.h> 14 #include <errno.h> 15 #include <irt.h> 16 #include <sys/mman.h> 17 #include <sys/stat.h> 18 #include <sys/time.h> 19 #include "nacl_io/kernel_intercept.h" 20 21 EXTERN_C_BEGIN 22 23 // Macro to get the REAL function pointer 24 #define REAL(name) __nacl_irt_##name##_real 25 26 // Macro to get the WRAP function 27 #define WRAP(name) __nacl_irt_##name##_wrap 28 29 // Declare REAL function pointer. 30 #define DECLARE_REAL_PTR(group, name) \ 31 typeof(__libnacl_irt_##group.name) REAL(name); 32 33 // Assign the REAL function pointer. 34 #define ASSIGN_REAL_PTR(group, name) \ 35 assert(__libnacl_irt_##group.name != NULL); \ 36 REAL(name) = __libnacl_irt_##group.name; 37 38 // Switch IRT's pointer to the REAL pointer 39 #define USE_REAL(group, name) \ 40 __libnacl_irt_##group.name = (typeof(REAL(name))) REAL(name); \ 41 42 // Switch the IRT's pointer to the WRAP function 43 #define USE_WRAP(group, name) \ 44 __libnacl_irt_##group.name = (typeof(REAL(name))) WRAP(name); \ 45 46 extern void __libnacl_irt_filename_init(void); 47 48 extern struct nacl_irt_fdio __libnacl_irt_fdio; 49 extern struct nacl_irt_dev_filename __libnacl_irt_dev_filename; 50 extern struct nacl_irt_memory __libnacl_irt_memory; 51 52 // Create function pointers to the REAL implementation 53 #define EXPAND_SYMBOL_LIST_OPERATION(OP) \ 54 OP(fdio, close); \ 55 OP(fdio, dup); \ 56 OP(fdio, dup2); \ 57 OP(fdio, fstat); \ 58 OP(fdio, getdents); \ 59 OP(fdio, read); \ 60 OP(fdio, seek); \ 61 OP(fdio, write); \ 62 OP(dev_filename, open); \ 63 OP(dev_filename, stat); \ 64 OP(memory, mmap); \ 65 OP(memory, munmap); 66 67 68 EXPAND_SYMBOL_LIST_OPERATION(DECLARE_REAL_PTR); 69 70 int WRAP(close)(int fd) { 71 return (ki_close(fd) < 0) ? errno : 0; 72 } 73 74 int WRAP(dup)(int fd, int* newfd) { 75 *newfd = ki_dup(fd); 76 return (*newfd < 0) ? errno : 0; 77 } 78 79 int WRAP(dup2)(int fd, int newfd) { 80 newfd = ki_dup2(fd, newfd); 81 return (newfd < 0) ? errno : 0; 82 } 83 84 int WRAP(fstat)(int fd, struct stat* buf) { 85 return (ki_fstat(fd, buf) < 0) ? errno : 0; 86 } 87 88 int WRAP(getdents)(int fd, dirent* buf, size_t count, size_t* nread) { 89 return (ki_getdents(fd, buf, count) < 0) ? errno : 0; 90 } 91 92 int WRAP(mmap)(void** addr, size_t length, int prot, int flags, int fd, 93 off_t offset) { 94 if (flags & MAP_ANONYMOUS) 95 return REAL(mmap)(addr, length, prot, flags, fd, offset); 96 97 *addr = ki_mmap(*addr, length, prot, flags, fd, offset); 98 return *addr == (void*)-1 ? errno : 0; 99 } 100 101 int WRAP(munmap)(void* addr, size_t length) { 102 // Always let the real munmap run on the address range. It is not an error if 103 // there are no mapped pages in that range. 104 ki_munmap(addr, length); 105 return REAL(munmap)(addr, length); 106 } 107 108 int WRAP(open)(const char* pathname, int oflag, mode_t cmode, int* newfd) { 109 *newfd = ki_open(pathname, oflag); 110 return (*newfd < 0) ? errno : 0; 111 } 112 113 int WRAP(read)(int fd, void* buf, size_t count, size_t* nread) { 114 if (!ki_is_initialized()) 115 return REAL(read)(fd, buf, count, nread); 116 117 ssize_t signed_nread = ki_read(fd, buf, count); 118 *nread = static_cast<size_t>(signed_nread); 119 return (signed_nread < 0) ? errno : 0; 120 } 121 122 int WRAP(seek)(int fd, off_t offset, int whence, off_t* new_offset) { 123 *new_offset = ki_lseek(fd, offset, whence); 124 return (*new_offset < 0) ? errno : 0; 125 } 126 127 int WRAP(stat)(const char* pathname, struct stat* buf) { 128 return (ki_stat(pathname, buf) < 0) ? errno : 0; 129 } 130 131 int WRAP(write)(int fd, const void* buf, size_t count, size_t* nwrote) { 132 if (!ki_is_initialized()) 133 return REAL(write)(fd, buf, count, nwrote); 134 135 ssize_t signed_nwrote = ki_write(fd, buf, count); 136 *nwrote = static_cast<size_t>(signed_nwrote); 137 return (signed_nwrote < 0) ? errno : 0; 138 } 139 140 // "real" functions, i.e. the unwrapped original functions. 141 142 int _real_close(int fd) { 143 return REAL(close)(fd); 144 } 145 146 int _real_fstat(int fd, struct stat* buf) { 147 return REAL(fstat)(fd, buf); 148 } 149 150 int _real_getdents(int fd, dirent* nacl_buf, size_t nacl_count, size_t* nread) { 151 return REAL(getdents)(fd, nacl_buf, nacl_count, nread); 152 } 153 154 int _real_lseek(int fd, off_t offset, int whence, off_t* new_offset) { 155 return REAL(seek)(fd, offset, whence, new_offset); 156 } 157 158 int _real_mkdir(const char* pathname, mode_t mode) { 159 return ENOSYS; 160 } 161 162 int _real_mmap(void** addr, size_t length, int prot, int flags, int fd, 163 off_t offset) { 164 return REAL(mmap)(addr, length, prot, flags, fd, offset); 165 } 166 167 int _real_munmap(void* addr, size_t length) { 168 return REAL(munmap)(addr, length); 169 } 170 171 int _real_open(const char* pathname, int oflag, mode_t cmode, int* newfd) { 172 return REAL(open)(pathname, oflag, cmode, newfd); 173 } 174 175 int _real_open_resource(const char* file, int* fd) { 176 return ENOSYS; 177 } 178 179 int _real_read(int fd, void* buf, size_t count, size_t* nread) { 180 return REAL(read)(fd, buf, count, nread); 181 } 182 183 int _real_rmdir(const char* pathname) { 184 return ENOSYS; 185 } 186 187 int _real_write(int fd, const void* buf, size_t count, size_t* nwrote) { 188 return REAL(write)(fd, buf, count, nwrote); 189 } 190 191 uint64_t usec_since_epoch() { 192 struct timeval tv; 193 gettimeofday(&tv, NULL); 194 return tv.tv_usec + (tv.tv_sec * 1000000); 195 } 196 197 static bool s_wrapped = false; 198 static bool s_assigned = false; 199 void kernel_wrap_init() { 200 if (!s_wrapped) { 201 if (!s_assigned) { 202 __libnacl_irt_filename_init(); 203 EXPAND_SYMBOL_LIST_OPERATION(ASSIGN_REAL_PTR) 204 s_assigned = true; 205 } 206 EXPAND_SYMBOL_LIST_OPERATION(USE_WRAP) 207 s_wrapped = true; 208 } 209 } 210 211 void kernel_wrap_uninit() { 212 if (s_wrapped) { 213 EXPAND_SYMBOL_LIST_OPERATION(USE_REAL) 214 s_wrapped = false; 215 } 216 } 217 218 EXTERN_C_END 219 220 221 #endif // defined(__native_client__) && !defined(__GLIBC__) 222 223