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