Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
|
Sam Clegg
2014/09/30 20:49:03
You're not going to like this but... do you think
David Yen
2014/09/30 21:37:36
Okay, I will do this as separate patches so as to
David Yen
2014/10/01 20:01:44
Done.
| |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include <sys/types.h> // Include something that will define __GLIBC__. | |
| 6 #include "nacl_io/kernel_wrap.h" // IRT_EXT is turned on in this header. | |
| 7 | |
| 8 // The entire file is wrapped in this #if. We do this so this .cc file can | |
| 9 // always be compiled. | |
| 10 #if defined(__NACL_IO_IRT_EXT__) | |
| 11 | |
| 12 #include <errno.h> | |
| 13 #include <string.h> | |
| 14 #include <sys/mman.h> | |
| 15 | |
| 16 #include "nacl_io/kernel_intercept.h" | |
| 17 #include "nacl_io/log.h" | |
| 18 #include "native_client/src/untrusted/irt/irt.h" | |
| 19 #include "native_client/src/untrusted/irt/irt_dev.h" | |
| 20 #include "native_client/src/untrusted/irt/irt_extension.h" | |
| 21 | |
| 22 #define CHECK_CALL(call) \ | |
| 23 do { \ | |
| 24 const bool ret = call; \ | |
| 25 (void) ret; \ | |
|
Sam Clegg
2014/09/30 20:49:03
Use __attribute__ unused?
David Yen
2014/09/30 21:37:36
Done.
| |
| 26 assert(ret); \ | |
| 27 } while(false) | |
| 28 | |
| 29 template<typename T> | |
| 30 struct nacl_irt_interface { | |
| 31 bool initialized; | |
| 32 const char* query_string; | |
| 33 T interface; | |
| 34 | |
| 35 nacl_irt_interface(const char* query) | |
| 36 : initialized(false), | |
| 37 query_string(query) { | |
| 38 memset(&interface, 0, sizeof(interface)); | |
| 39 } | |
| 40 | |
| 41 bool Initialized() const { | |
| 42 return initialized; | |
| 43 } | |
| 44 | |
| 45 bool Initialize() { | |
| 46 if (Initialized()) | |
| 47 return true; | |
| 48 | |
| 49 size_t bytes = nacl_interface_query(query_string, | |
| 50 &interface, | |
| 51 sizeof(interface)); | |
| 52 initialized = (bytes == sizeof(interface)); | |
| 53 return initialized; | |
| 54 } | |
| 55 | |
| 56 bool IRTExtSupply(const T& new_interface) const { | |
| 57 size_t bytes = nacl_interface_ext_supply(query_string, | |
| 58 &new_interface, | |
| 59 sizeof(new_interface)); | |
| 60 return (bytes == sizeof(interface)); | |
| 61 } | |
| 62 | |
| 63 bool RevertIRTExtSupply(bool force_revert = false) { | |
| 64 if (!Initialize() && !force_revert) | |
| 65 return false; | |
| 66 | |
| 67 size_t bytes = nacl_interface_ext_supply(query_string, | |
| 68 &interface, | |
| 69 sizeof(interface)); | |
| 70 return (bytes == sizeof(interface)); | |
| 71 } | |
| 72 }; | |
| 73 | |
| 74 // IRT interfaces as declared in irt.h. | |
| 75 static nacl_irt_interface<nacl_irt_basic> s_irt_basic(NACL_IRT_BASIC_v0_1); | |
| 76 static nacl_irt_interface<nacl_irt_fdio> s_irt_fdio(NACL_IRT_FDIO_v0_1); | |
| 77 static nacl_irt_interface<nacl_irt_memory> s_irt_memory(NACL_IRT_MEMORY_v0_3); | |
| 78 static nacl_irt_interface<nacl_irt_resource_open> s_irt_resource_open( | |
| 79 NACL_IRT_RESOURCE_OPEN_v0_1); | |
| 80 | |
| 81 // IRT Dev interfaces as declared in irt_dev.h. | |
| 82 static nacl_irt_interface<nacl_irt_dev_fdio> s_irt_dev_fdio( | |
| 83 NACL_IRT_DEV_FDIO_v0_3); | |
| 84 static nacl_irt_interface<nacl_irt_dev_filename> s_irt_dev_filename( | |
| 85 NACL_IRT_DEV_FILENAME_v0_3); | |
| 86 | |
| 87 static bool s_wrapped = false; | |
| 88 | |
| 89 // Functions for the nacl_irt_dev_fdio interface. | |
| 90 static int ext_close(int fd) { | |
| 91 ERRNO_RTN(ki_close(fd)); | |
| 92 } | |
| 93 | |
| 94 static int ext_dup(int fd, int *newfd) { | |
| 95 *newfd = ki_dup(fd); | |
| 96 ERRNO_RTN(*newfd); | |
| 97 } | |
| 98 | |
| 99 static int ext_dup2(int fd, int newfd) { | |
| 100 newfd = ki_dup2(fd, newfd); | |
| 101 ERRNO_RTN(newfd); | |
| 102 } | |
| 103 | |
| 104 static int ext_read(int fd, void *buf, size_t count, size_t *nread) { | |
| 105 ssize_t signed_nread = ki_read(fd, buf, count); | |
| 106 *nread = static_cast<size_t>(signed_nread); | |
| 107 ERRNO_RTN(signed_nread); | |
| 108 } | |
| 109 | |
| 110 static int ext_write(int fd, const void *buf, size_t count, size_t *nwrote) { | |
| 111 ssize_t signed_nwrote = ki_write(fd, buf, count); | |
| 112 *nwrote = static_cast<size_t>(signed_nwrote); | |
| 113 ERRNO_RTN(signed_nwrote); | |
| 114 } | |
| 115 | |
| 116 static int ext_seek(int fd, nacl_irt_off_t offset, int whence, | |
| 117 nacl_irt_off_t *new_offset) { | |
| 118 *new_offset = ki_lseek(fd, offset, whence); | |
| 119 ERRNO_RTN(*new_offset); | |
| 120 } | |
| 121 | |
| 122 static int ext_fstat(int fd, struct stat *buf) { | |
| 123 ERRNO_RTN(ki_fstat(fd, buf)); | |
| 124 } | |
| 125 | |
| 126 static int ext_getdents(int fd, struct dirent *ents, size_t count, | |
| 127 size_t *nread) { | |
| 128 int rtn = ki_getdents(fd, ents, count); | |
| 129 RTN_ERRNO_IF(rtn < 0); | |
| 130 *nread = rtn; | |
| 131 return 0; | |
| 132 } | |
| 133 | |
| 134 // Functions for the nacl_irt_memory interface. | |
| 135 static int ext_mmap(void **addr, size_t len, int prot, int flags, int fd, | |
| 136 nacl_irt_off_t off) { | |
| 137 if (flags & MAP_ANONYMOUS) | |
| 138 return s_irt_memory.interface.mmap(addr, len, prot, flags, fd, off); | |
| 139 | |
| 140 *addr = ki_mmap(*addr, len, prot, flags, fd, off); | |
| 141 RTN_ERRNO_IF(*addr == (void*)-1); | |
| 142 return 0; | |
| 143 } | |
| 144 | |
| 145 // Extra functions for the nacl_irt_fdio interface. | |
| 146 static int ext_fchdir(int fd) { | |
| 147 ERRNO_RTN(ki_fchdir(fd)); | |
| 148 } | |
| 149 | |
| 150 static int ext_fchmod(int fd, mode_t mode) { | |
| 151 ERRNO_RTN(ki_fchmod(fd, mode)); | |
| 152 } | |
| 153 | |
| 154 static int ext_fsync(int fd) { | |
| 155 ERRNO_RTN(ki_fsync(fd)); | |
| 156 } | |
| 157 | |
| 158 static int ext_fdatasync(int fd) { | |
| 159 ERRNO_RTN(ki_fdatasync(fd)); | |
| 160 } | |
| 161 | |
| 162 static int ext_ftruncate(int fd, nacl_irt_off_t length) { | |
| 163 ERRNO_RTN(ki_ftruncate(fd, length)); | |
| 164 } | |
| 165 | |
| 166 static int ext_isatty(int fd, int *result) { | |
| 167 *result = ki_isatty(fd); | |
| 168 RTN_ERRNO_IF(*result == 0); | |
| 169 return 0; | |
| 170 } | |
| 171 | |
| 172 static int ext_munmap(void *addr, size_t length) { | |
| 173 // Always let the real munmap run on the address range. It is not an error if | |
| 174 // there are no mapped pages in that range. | |
| 175 ki_munmap(addr, length); | |
| 176 return s_irt_memory.interface.munmap(addr, length); | |
| 177 } | |
| 178 | |
| 179 static int ext_mprotect(void *addr, size_t len, int prot) { | |
| 180 return ENOSYS; | |
| 181 } | |
| 182 | |
| 183 // Functions for the nacl_irt_dev_filename interface. | |
| 184 static int ext_open(const char *pathname, int oflag, mode_t cmode, int *newfd) { | |
| 185 *newfd = ki_open(pathname, oflag, cmode); | |
| 186 ERRNO_RTN(*newfd); | |
| 187 } | |
| 188 | |
| 189 static int ext_stat(const char *pathname, struct stat *buf) { | |
| 190 ERRNO_RTN(ki_stat(pathname, buf)); | |
| 191 } | |
| 192 | |
| 193 static int ext_mkdir(const char *pathname, mode_t mode) { | |
| 194 ERRNO_RTN(ki_mkdir(pathname, mode)); | |
| 195 } | |
| 196 | |
| 197 static int ext_rmdir(const char *pathname) { | |
| 198 ERRNO_RTN(ki_rmdir(pathname)); | |
| 199 } | |
| 200 | |
| 201 static int ext_chdir(const char *pathname) { | |
| 202 ERRNO_RTN(ki_chdir(pathname)); | |
| 203 } | |
| 204 | |
| 205 static int ext_getcwd(char *pathname, size_t len) { | |
| 206 char* rtn = ki_getcwd(pathname, len); | |
| 207 RTN_ERRNO_IF(NULL == rtn); | |
| 208 return 0; | |
| 209 } | |
| 210 | |
| 211 static int ext_unlink(const char *pathname) { | |
| 212 ERRNO_RTN(ki_unlink(pathname)); | |
| 213 } | |
| 214 | |
| 215 static int ext_truncate(const char *pathname, nacl_irt_off_t length) { | |
| 216 ERRNO_RTN(ki_truncate(pathname, length)); | |
| 217 } | |
| 218 | |
| 219 static int ext_lstat(const char *pathname, struct stat *buf) { | |
| 220 ERRNO_RTN(ki_lstat(pathname, buf)); | |
| 221 } | |
| 222 | |
| 223 static int ext_link(const char *pathname, const char *newpath) { | |
| 224 ERRNO_RTN(ki_link(pathname, newpath)); | |
| 225 } | |
| 226 | |
| 227 static int ext_rename(const char *pathname, const char *newpath) { | |
| 228 ERRNO_RTN(ki_rename(pathname, newpath)); | |
| 229 } | |
| 230 | |
| 231 static int ext_symlink(const char *pathname, const char *newpath) { | |
| 232 ERRNO_RTN(ki_symlink(pathname, newpath)); | |
| 233 } | |
| 234 | |
| 235 static int ext_chmod(const char *pathname, mode_t mode) { | |
| 236 ERRNO_RTN(ki_chmod(pathname, mode)); | |
| 237 } | |
| 238 | |
| 239 static int ext_access(const char *pathname, int amode) { | |
| 240 ERRNO_RTN(ki_access(pathname, amode)); | |
| 241 } | |
| 242 | |
| 243 static int ext_readlink(const char *pathname, char *buf, size_t count, | |
| 244 size_t *nread) { | |
| 245 int rtn = ki_readlink(pathname, buf, count); | |
| 246 RTN_ERRNO_IF(rtn < 0); | |
| 247 *nread = rtn; | |
| 248 return 0; | |
| 249 } | |
| 250 | |
| 251 static int ext_utimes(const char *pathname, const struct timeval *times) { | |
| 252 ERRNO_RTN(ki_utimes(pathname, times)); | |
| 253 } | |
| 254 | |
| 255 // Functions declared inside of kernel_wrap_real.h. | |
| 256 EXTERN_C_BEGIN | |
| 257 | |
| 258 int _real_close(int fd) { | |
| 259 if (!s_irt_fdio.Initialize()) | |
| 260 return ENOSYS; | |
| 261 return s_irt_fdio.interface.close(fd); | |
| 262 } | |
| 263 | |
| 264 void _real_exit(int status) { | |
| 265 CHECK_CALL(s_irt_basic.Initialize()); | |
| 266 return s_irt_basic.interface.exit(status); | |
| 267 } | |
| 268 | |
| 269 int _real_fstat(int fd, struct stat* buf) { | |
| 270 if (!s_irt_fdio.Initialize()) | |
| 271 return ENOSYS; | |
| 272 return s_irt_fdio.interface.fstat(fd, buf); | |
| 273 } | |
| 274 | |
| 275 int _real_getdents(int fd, void* nacl_buf, size_t nacl_count, size_t* nread) { | |
| 276 if (!s_irt_fdio.Initialize()) | |
| 277 return ENOSYS; | |
| 278 return s_irt_fdio.interface.getdents(fd, static_cast<dirent*>(nacl_buf), | |
| 279 nacl_count, nread); | |
| 280 } | |
| 281 | |
| 282 int _real_isatty(int fd, int* result) { | |
| 283 if (!s_irt_dev_fdio.Initialize()) | |
| 284 return ENOSYS; | |
| 285 return s_irt_dev_fdio.interface.isatty(fd, result); | |
| 286 } | |
| 287 | |
| 288 int _real_lseek(int fd, int64_t offset, int whence, int64_t* new_offset) { | |
| 289 if (!s_irt_fdio.Initialize()) | |
| 290 return ENOSYS; | |
| 291 return s_irt_fdio.interface.seek(fd, offset, whence, new_offset); | |
| 292 } | |
| 293 | |
| 294 int _real_mkdir(const char* pathname, mode_t mode) { | |
| 295 if (!s_irt_dev_filename.Initialize()) | |
| 296 return ENOSYS; | |
| 297 return s_irt_dev_filename.interface.mkdir(pathname, mode); | |
| 298 } | |
| 299 | |
| 300 int _real_mmap(void** addr, | |
| 301 size_t length, | |
| 302 int prot, | |
| 303 int flags, | |
| 304 int fd, | |
| 305 int64_t offset) { | |
| 306 if (!s_irt_memory.Initialize()) | |
| 307 return ENOSYS; | |
| 308 return s_irt_memory.interface.mmap(addr, length, prot, flags, fd, offset); | |
| 309 } | |
| 310 | |
| 311 int _real_munmap(void* addr, size_t length) { | |
| 312 if (!s_irt_memory.Initialize()) | |
| 313 return ENOSYS; | |
| 314 return s_irt_memory.interface.munmap(addr, length); | |
| 315 } | |
| 316 | |
| 317 int _real_open(const char* pathname, int oflag, mode_t mode, int* newfd) { | |
| 318 if (!s_irt_dev_filename.Initialize()) | |
| 319 return ENOSYS; | |
| 320 return s_irt_dev_filename.interface.open(pathname, oflag, mode, newfd); | |
| 321 } | |
| 322 | |
| 323 int _real_open_resource(const char* file, int* fd) { | |
| 324 if (!s_irt_resource_open.Initialize()) | |
| 325 return ENOSYS; | |
| 326 return s_irt_resource_open.interface.open_resource(file, fd); | |
| 327 } | |
| 328 | |
| 329 int _real_read(int fd, void* buf, size_t count, size_t* nread) { | |
| 330 if (!s_irt_fdio.Initialize()) | |
| 331 return ENOSYS; | |
| 332 return s_irt_fdio.interface.read(fd, buf, count, nread); | |
| 333 } | |
| 334 | |
| 335 int _real_rmdir(const char* pathname) { | |
| 336 if (!s_irt_dev_filename.Initialize()) | |
| 337 return ENOSYS; | |
| 338 return s_irt_dev_filename.interface.rmdir(pathname); | |
| 339 } | |
| 340 | |
| 341 int _real_write(int fd, const void* buf, size_t count, size_t* nwrote) { | |
| 342 if (!s_irt_fdio.Initialize()) | |
| 343 return ENOSYS; | |
| 344 return s_irt_fdio.interface.write(fd, buf, count, nwrote); | |
| 345 } | |
| 346 | |
| 347 int _real_getcwd(char* pathname, size_t len) { | |
| 348 if (!s_irt_dev_filename.Initialize()) | |
| 349 return ENOSYS; | |
| 350 return s_irt_dev_filename.interface.getcwd(pathname, len); | |
| 351 } | |
| 352 | |
| 353 // Kernel Wrap init/uninit functions declared in kernel_wrap.h. | |
| 354 void kernel_wrap_init() { | |
| 355 if (!s_wrapped) { | |
| 356 LOG_TRACE("kernel_wrap_init"); | |
| 357 | |
| 358 // Register interfaces as listed in irt.h. | |
| 359 | |
| 360 // Register nacl_irt_basic interface. | |
| 361 CHECK_CALL(s_irt_basic.Initialize()); | |
| 362 struct nacl_irt_basic basic_calls = { | |
| 363 ki_exit, | |
| 364 s_irt_basic.interface.gettod, | |
| 365 s_irt_basic.interface.clock, | |
| 366 s_irt_basic.interface.nanosleep, | |
| 367 s_irt_basic.interface.sched_yield, | |
| 368 s_irt_basic.interface.sysconf, | |
| 369 }; | |
| 370 CHECK_CALL(s_irt_basic.IRTExtSupply(basic_calls)); | |
| 371 | |
| 372 // Register nacl_irt_fdio interface. | |
| 373 struct nacl_irt_fdio fdio = { | |
| 374 ext_close, | |
| 375 ext_dup, | |
| 376 ext_dup2, | |
| 377 ext_read, | |
| 378 ext_write, | |
| 379 ext_seek, | |
| 380 ext_fstat, | |
| 381 ext_getdents, | |
| 382 }; | |
| 383 CHECK_CALL(s_irt_fdio.IRTExtSupply(fdio)); | |
| 384 | |
| 385 // Register nacl_irt_memory interface. | |
| 386 struct nacl_irt_memory mem = { | |
| 387 ext_mmap, | |
| 388 ext_munmap, | |
| 389 ext_mprotect, | |
| 390 }; | |
| 391 CHECK_CALL(s_irt_memory.IRTExtSupply(mem)); | |
| 392 | |
| 393 // Register interfaces as listed in irt_dev.h. | |
| 394 | |
| 395 // Register nacl_irt_dev_fdio interface. | |
| 396 struct nacl_irt_dev_fdio dev_fdio = { | |
| 397 ext_close, | |
| 398 ext_dup, | |
| 399 ext_dup2, | |
| 400 ext_read, | |
| 401 ext_write, | |
| 402 ext_seek, | |
| 403 ext_fstat, | |
| 404 ext_getdents, | |
| 405 ext_fchdir, | |
| 406 ext_fchmod, | |
| 407 ext_fsync, | |
| 408 ext_fdatasync, | |
| 409 ext_ftruncate, | |
| 410 ext_isatty, | |
| 411 }; | |
| 412 CHECK_CALL(s_irt_dev_fdio.IRTExtSupply(dev_fdio)); | |
| 413 | |
| 414 // Register nacl_irt_dev_filename interface. | |
| 415 struct nacl_irt_dev_filename dev_filename = { | |
| 416 ext_open, | |
| 417 ext_stat, | |
| 418 ext_mkdir, | |
| 419 ext_rmdir, | |
| 420 ext_chdir, | |
| 421 ext_getcwd, | |
| 422 ext_unlink, | |
| 423 ext_truncate, | |
| 424 ext_lstat, | |
| 425 ext_link, | |
| 426 ext_rename, | |
| 427 ext_symlink, | |
| 428 ext_chmod, | |
| 429 ext_access, | |
| 430 ext_readlink, | |
| 431 ext_utimes, | |
| 432 }; | |
| 433 CHECK_CALL(s_irt_dev_filename.IRTExtSupply(dev_filename)); | |
| 434 | |
| 435 s_wrapped = true; | |
| 436 } | |
| 437 } | |
| 438 | |
| 439 void kernel_wrap_uninit() { | |
| 440 if (s_wrapped) { | |
| 441 LOG_TRACE("kernel_wrap_uninit"); | |
| 442 | |
| 443 // Register original IRT interfaces in irt.h. | |
| 444 CHECK_CALL(s_irt_basic.RevertIRTExtSupply()); | |
| 445 CHECK_CALL(s_irt_fdio.RevertIRTExtSupply()); | |
| 446 CHECK_CALL(s_irt_memory.RevertIRTExtSupply()); | |
| 447 | |
| 448 // Register optional original IRT dev interfaces in irt_dev.h. | |
| 449 s_irt_dev_fdio.RevertIRTExtSupply(true); | |
| 450 s_irt_dev_filename.RevertIRTExtSupply(true); | |
| 451 | |
| 452 s_wrapped = false; | |
| 453 } | |
| 454 } | |
| 455 | |
| 456 EXTERN_C_END | |
| 457 | |
| 458 #endif // defined(__NACL_IO_IRT_EXT__) | |
| OLD | NEW |