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