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