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