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.
5 #include "nacl_io/kernel_intercept.h"
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/ostime.h"
18 #include "nacl_io/pepper_interface.h"
19 #include "nacl_io/real_pepper_interface.h"
21 using namespace nacl_io
;
23 #define ON_NOSYS_RETURN(x) \
24 if (!ki_is_initialized()) { \
29 #define TRACE_KP_CALLS 0
32 #define KP_TRACE nacl_io_log
37 #define KP_CALL(METHOD, ARGS) \
38 ON_NOSYS_RETURN(-1); \
39 int rtn = s_state.kp-> METHOD ARGS; \
40 KP_TRACE("ki_" #METHOD " -> %d\n", rtn); \
43 struct KernelInterceptState
{
45 PepperInterface
* ppapi
;
49 static KernelInterceptState s_state
;
51 // The the test code we want to be able to save the previous kernel
52 // proxy when intialising and restore it on uninit.
53 static KernelInterceptState s_saved_state
;
55 int ki_push_state_for_testing() {
56 assert(s_saved_state
.kp
== NULL
);
57 if (s_saved_state
.kp
!= NULL
)
59 s_saved_state
= s_state
;
62 s_state
.kp_owned
= false;
66 static void ki_pop_state() {
67 // Swap out the KernelProxy. This will normally reset the
68 // proxy to NULL, aside from in test code that has called
69 // ki_push_state_for_testing().
70 s_state
= s_saved_state
;
71 s_saved_state
.kp
= NULL
;
72 s_saved_state
.ppapi
= NULL
;
73 s_saved_state
.kp_owned
= false;
76 int ki_pop_state_for_testing() {
81 int ki_init(void* kp
) {
82 LOG_TRACE("ki_init: %p", kp
);
83 return ki_init_ppapi(kp
, 0, NULL
);
86 int ki_init_ppapi(void* kp
,
88 PPB_GetInterface get_browser_interface
) {
90 if (s_state
.kp
!= NULL
)
92 PepperInterface
* ppapi
= NULL
;
93 if (instance
&& get_browser_interface
) {
94 ppapi
= new RealPepperInterface(instance
, get_browser_interface
);
95 s_state
.ppapi
= ppapi
;
97 int rtn
= ki_init_interface(kp
, ppapi
);
101 int ki_init_interface(void* kp
, void* pepper_interface
) {
102 LOG_TRACE("ki_init_interface: %p %p", kp
, pepper_interface
);
104 if (s_state
.kp
!= NULL
)
106 PepperInterface
* ppapi
= static_cast<PepperInterface
*>(pepper_interface
);
110 s_state
.kp
= new KernelProxy();
111 s_state
.kp_owned
= true;
113 s_state
.kp
= static_cast<KernelProxy
*>(kp
);
114 s_state
.kp_owned
= false;
117 if (s_state
.kp
->Init(ppapi
) != 0)
123 int ki_is_initialized() {
124 return s_state
.kp
!= NULL
;
128 LOG_TRACE("ki_uninit");
130 if (s_state
.kp
== NULL
)
133 if (s_saved_state
.kp
== NULL
)
134 kernel_wrap_uninit();
136 // If we are going to delete the KernelProxy don't do it
137 // until we've swapped it out.
138 KernelInterceptState state_to_delete
= s_state
;
142 if (state_to_delete
.kp_owned
)
143 delete state_to_delete
.kp
;
145 delete state_to_delete
.ppapi
;
149 nacl_io::KernelProxy
* ki_get_proxy() {
153 void ki_exit(int status
) {
154 KP_TRACE("ki_exit\n");
155 if (ki_is_initialized())
156 s_state
.kp
->exit(status
);
161 char* ki_getcwd(char* buf
, size_t size
) {
162 ON_NOSYS_RETURN(NULL
);
163 KP_TRACE("ki_getcwd\n");
164 return s_state
.kp
->getcwd(buf
, size
);
167 char* ki_getwd(char* buf
) {
168 ON_NOSYS_RETURN(NULL
);
169 KP_TRACE("ki_getwd\n");
170 return s_state
.kp
->getwd(buf
);
173 int ki_chdir(const char* path
) {
174 KP_CALL(chdir
, (path
));
177 int ki_dup(int oldfd
) {
178 KP_CALL(dup
, (oldfd
));
181 int ki_dup2(int oldfd
, int newfd
) {
182 KP_CALL(dup2
, (oldfd
, newfd
));
185 int ki_chmod(const char* path
, mode_t mode
) {
186 KP_CALL(chmod
, (path
, mode
));
189 int ki_fchdir(int fd
) {
190 KP_CALL(fchdir
, (fd
));
193 int ki_fchmod(int fd
, mode_t mode
) {
194 KP_CALL(fchmod
, (fd
, mode
));
197 int ki_stat(const char* path
, struct stat
* buf
) {
198 KP_CALL(stat
, (path
, buf
));
201 int ki_mkdir(const char* path
, mode_t mode
) {
202 KP_CALL(mkdir
, (path
, mode
));
205 int ki_rmdir(const char* path
) {
206 KP_CALL(rmdir
, (path
));
209 int ki_mount(const char* source
,
211 const char* filesystemtype
,
212 unsigned long mountflags
,
214 KP_CALL(mount
, (source
, target
, filesystemtype
, mountflags
, data
));
217 int ki_umount(const char* path
) {
218 KP_CALL(umount
, (path
));
221 int ki_open(const char* path
, int oflag
, mode_t mode
) {
222 KP_CALL(open
, (path
, oflag
, mode
));
225 int ki_pipe(int pipefds
[2]) {
226 KP_CALL(pipe
, (pipefds
));
229 ssize_t
ki_read(int fd
, void* buf
, size_t nbyte
) {
231 KP_TRACE("ki_read\n");
232 return s_state
.kp
->read(fd
, buf
, nbyte
);
235 ssize_t
ki_write(int fd
, const void* buf
, size_t nbyte
) {
237 KP_TRACE("ki_write\n");
238 return s_state
.kp
->write(fd
, buf
, nbyte
);
241 int ki_fstat(int fd
, struct stat
* buf
) {
242 KP_CALL(fstat
, (fd
, buf
));
245 int ki_getdents(int fd
, struct dirent
* buf
, unsigned int count
) {
246 KP_CALL(getdents
, (fd
, buf
, count
));
249 int ki_ftruncate(int fd
, off_t length
) {
250 KP_CALL(ftruncate
, (fd
, length
));
253 int ki_fsync(int fd
) {
254 KP_CALL(fsync
, (fd
));
257 int ki_fdatasync(int fd
) {
258 KP_CALL(fdatasync
, (fd
));
261 int ki_isatty(int fd
) {
263 KP_TRACE("ki_isatty\n");
264 return s_state
.kp
->isatty(fd
);
267 int ki_close(int fd
) {
268 KP_CALL(close
, (fd
));
271 off_t
ki_lseek(int fd
, off_t offset
, int whence
) {
273 KP_TRACE("ki_lseek\n");
274 return s_state
.kp
->lseek(fd
, offset
, whence
);
277 int ki_remove(const char* path
) {
278 KP_CALL(remove
, (path
));
281 int ki_unlink(const char* path
) {
282 KP_CALL(unlink
, (path
));
285 int ki_truncate(const char* path
, off_t length
) {
286 KP_CALL(truncate
, (path
, length
));
289 int ki_lstat(const char* path
, struct stat
* buf
) {
290 KP_CALL(lstat
, (path
, buf
));
293 int ki_link(const char* oldpath
, const char* newpath
) {
294 KP_CALL(link
, (oldpath
, newpath
));
297 int ki_rename(const char* path
, const char* newpath
) {
298 KP_CALL(rename
, (path
, newpath
));
301 int ki_symlink(const char* oldpath
, const char* newpath
) {
302 KP_CALL(symlink
, (oldpath
, newpath
));
305 int ki_access(const char* path
, int amode
) {
306 KP_CALL(access
, (path
, amode
));
309 int ki_readlink(const char* path
, char* buf
, size_t count
) {
310 KP_CALL(readlink
, (path
, buf
, count
));
313 int ki_utimes(const char* path
, const struct timeval times
[2]) {
315 KP_TRACE("ki_utimes");
316 // Implement in terms of utimens.
318 return s_state
.kp
->utimens(path
, NULL
);
321 struct timespec ts
[2];
322 ts
[0].tv_sec
= times
[0].tv_sec
;
323 ts
[0].tv_nsec
= times
[0].tv_usec
* 1000;
324 ts
[1].tv_sec
= times
[1].tv_sec
;
325 ts
[1].tv_nsec
= times
[1].tv_usec
* 1000;
326 return s_state
.kp
->utimens(path
, ts
);
329 int ki_futimes(int fd
, const struct timeval times
[2]) {
331 KP_TRACE("ki_futimes");
332 // Implement in terms of futimens.
334 return s_state
.kp
->futimens(fd
, NULL
);
337 struct timespec ts
[2];
338 ts
[0].tv_sec
= times
[0].tv_sec
;
339 ts
[0].tv_nsec
= times
[0].tv_usec
* 1000;
340 ts
[1].tv_sec
= times
[1].tv_sec
;
341 ts
[1].tv_nsec
= times
[1].tv_usec
* 1000;
342 return s_state
.kp
->futimens(fd
, ts
);
345 void* ki_mmap(void* addr
,
351 ON_NOSYS_RETURN(MAP_FAILED
);
352 KP_TRACE("ki_mmap\n");
353 return s_state
.kp
->mmap(addr
, length
, prot
, flags
, fd
, offset
);
356 int ki_munmap(void* addr
, size_t length
) {
358 KP_TRACE("ki_munmap\n");
359 return s_state
.kp
->munmap(addr
, length
);
362 int ki_open_resource(const char* file
) {
364 KP_TRACE("ki_open_resource\n");
365 return s_state
.kp
->open_resource(file
);
368 int ki_fcntl(int d
, int request
, va_list args
) {
369 KP_CALL(fcntl
, (d
, request
, args
));
372 int ki_ioctl(int d
, int request
, va_list args
) {
373 KP_CALL(ioctl
, (d
, request
, args
));
376 int ki_chown(const char* path
, uid_t owner
, gid_t group
) {
377 KP_CALL(chown
, (path
, owner
, group
));
380 int ki_fchown(int fd
, uid_t owner
, gid_t group
) {
381 KP_CALL(fchown
, (fd
, owner
, group
));
384 int ki_lchown(const char* path
, uid_t owner
, gid_t group
) {
385 KP_CALL(lchown
, (path
, owner
, group
));
388 int ki_utime(const char* filename
, const struct utimbuf
* times
) {
390 KP_TRACE("ki_utime\n");
391 // Implement in terms of utimens.
393 return s_state
.kp
->utimens(filename
, NULL
);
396 struct timespec ts
[2];
397 ts
[0].tv_sec
= times
->actime
;
399 ts
[1].tv_sec
= times
->modtime
;
401 return s_state
.kp
->utimens(filename
, ts
);
404 int ki_futimens(int fd
, const struct timespec times
[2]) {
405 KP_CALL(futimens
, (fd
, times
));
408 mode_t
ki_umask(mode_t mask
) {
410 KP_TRACE("ki_umask\n");
411 return s_state
.kp
->umask(mask
);
414 int ki_poll(struct pollfd
* fds
, nfds_t nfds
, int timeout
) {
415 KP_CALL(poll
, (fds
, nfds
, timeout
));
418 int ki_select(int nfds
,
422 struct timeval
* timeout
) {
423 KP_CALL(select
, (nfds
, readfds
, writefds
, exceptfds
, timeout
));
426 int ki_tcflush(int fd
, int queue_selector
) {
427 KP_CALL(tcflush
, (fd
, queue_selector
));
430 int ki_tcgetattr(int fd
, struct termios
* termios_p
) {
431 KP_CALL(tcgetattr
, (fd
, termios_p
));
434 int ki_tcsetattr(int fd
,
435 int optional_actions
,
436 const struct termios
* termios_p
) {
437 KP_CALL(tcsetattr
, (fd
, optional_actions
, termios_p
));
440 int ki_kill(pid_t pid
, int sig
) {
441 KP_CALL(kill
, (pid
, sig
));
444 int ki_killpg(pid_t pid
, int sig
) {
449 int ki_sigaction(int signum
,
450 const struct sigaction
* action
,
451 struct sigaction
* oaction
) {
452 KP_CALL(sigaction
, (signum
, action
, oaction
));
455 int ki_sigpause(int sigmask
) {
460 int ki_sigpending(sigset_t
* set
) {
465 int ki_sigsuspend(const sigset_t
* set
) {
470 sighandler_t
ki_signal(int signum
, sighandler_t handler
) {
471 return ki_sigset(signum
, handler
);
474 sighandler_t
ki_sigset(int signum
, sighandler_t handler
) {
475 ON_NOSYS_RETURN(SIG_ERR
);
476 KP_TRACE("ki_sigset\n");
477 // Implement sigset(2) in terms of sigaction(2).
478 struct sigaction action
;
479 struct sigaction oaction
;
480 memset(&action
, 0, sizeof(action
));
481 memset(&oaction
, 0, sizeof(oaction
));
482 action
.sa_handler
= handler
;
483 int rtn
= s_state
.kp
->sigaction(signum
, &action
, &oaction
);
486 return oaction
.sa_handler
;
489 #ifdef PROVIDES_SOCKET_API
491 int ki_accept(int fd
, struct sockaddr
* addr
, socklen_t
* len
) {
492 KP_CALL(accept
, (fd
, addr
, len
));
495 int ki_bind(int fd
, const struct sockaddr
* addr
, socklen_t len
) {
496 KP_CALL(bind
, (fd
, addr
, len
));
499 int ki_connect(int fd
, const struct sockaddr
* addr
, socklen_t len
) {
500 KP_CALL(connect
, (fd
, addr
, len
));
503 struct hostent
* ki_gethostbyname(const char* name
) {
504 ON_NOSYS_RETURN(NULL
);
505 return s_state
.kp
->gethostbyname(name
);
508 int ki_getnameinfo(const struct sockaddr
*sa
,
514 unsigned int flags
) {
515 ON_NOSYS_RETURN(EAI_SYSTEM
);
516 KP_TRACE("ki_getnameinfo\n");
517 return s_state
.kp
->getnameinfo(sa
, salen
, host
, hostlen
, serv
, servlen
,
521 int ki_getaddrinfo(const char* node
,
523 const struct addrinfo
* hints
,
524 struct addrinfo
** res
) {
525 ON_NOSYS_RETURN(EAI_SYSTEM
);
526 KP_TRACE("ki_getaddrinfo\n");
527 return s_state
.kp
->getaddrinfo(node
, service
, hints
, res
);
530 void ki_freeaddrinfo(struct addrinfo
* res
) {
531 KP_TRACE("ki_freeaddrinfo\n");
532 s_state
.kp
->freeaddrinfo(res
);
535 int ki_getpeername(int fd
, struct sockaddr
* addr
, socklen_t
* len
) {
536 KP_CALL(getpeername
, (fd
, addr
, len
));
539 int ki_getsockname(int fd
, struct sockaddr
* addr
, socklen_t
* len
) {
540 KP_CALL(getsockname
, (fd
, addr
, len
));
543 int ki_getsockopt(int fd
, int lvl
, int optname
, void* optval
, socklen_t
* len
) {
544 KP_CALL(getsockopt
, (fd
, lvl
, optname
, optval
, len
));
547 int ki_listen(int fd
, int backlog
) {
548 KP_CALL(listen
, (fd
, backlog
));
551 ssize_t
ki_recv(int fd
, void* buf
, size_t len
, int flags
) {
553 KP_TRACE("ki_recv\n");
554 return s_state
.kp
->recv(fd
, buf
, len
, flags
);
557 ssize_t
ki_recvfrom(int fd
,
561 struct sockaddr
* addr
,
562 socklen_t
* addrlen
) {
564 KP_TRACE("ki_recvfrom\n");
565 return s_state
.kp
->recvfrom(fd
, buf
, len
, flags
, addr
, addrlen
);
568 ssize_t
ki_recvmsg(int fd
, struct msghdr
* msg
, int flags
) {
570 KP_TRACE("ki_recvmsg\n");
571 return s_state
.kp
->recvmsg(fd
, msg
, flags
);
574 ssize_t
ki_send(int fd
, const void* buf
, size_t len
, int flags
) {
576 KP_TRACE("ki_send\n");
577 return s_state
.kp
->send(fd
, buf
, len
, flags
);
580 ssize_t
ki_sendto(int fd
,
584 const struct sockaddr
* addr
,
587 KP_TRACE("ki_sendto\n");
588 return s_state
.kp
->sendto(fd
, buf
, len
, flags
, addr
, addrlen
);
591 ssize_t
ki_sendmsg(int fd
, const struct msghdr
* msg
, int flags
) {
593 KP_TRACE("ki_sendmsg\n");
594 return s_state
.kp
->sendmsg(fd
, msg
, flags
);
597 int ki_setsockopt(int fd
,
602 KP_CALL(setsockopt
, (fd
, lvl
, optname
, optval
, len
));
605 int ki_shutdown(int fd
, int how
) {
606 KP_CALL(shutdown
, (fd
, how
));
609 int ki_socket(int domain
, int type
, int protocol
) {
610 KP_CALL(socket
, (domain
, type
, protocol
));
613 int ki_socketpair(int domain
, int type
, int protocol
, int* sv
) {
614 KP_CALL(socketpair
, (domain
, type
, protocol
, sv
));
616 #endif // PROVIDES_SOCKET_API