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