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