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