1 /* Copyright 2014 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 /* NACL_IO_IRT_EXT is defined in this header */
6 #include "nacl_io/kernel_wrap.h"
7 
8 /*
9  * The entire file is wrapped in this #if. We do this so this .c file can
10  * always be compiled.
11  */
12 #if defined(NACL_IO_IRT_EXT)
13 
14 #include <assert.h>
15 #include <errno.h>
16 #include <irt.h>
17 #include <irt_dev.h>
18 #include <irt_extension.h>
19 #include <stdbool.h>
20 #include <string.h>
21 #include <sys/mman.h>
22 
23 #include "nacl_io/kernel_intercept.h"
24 #include "nacl_io/log.h"
25 #include "nacl_io/nacl_abi_types.h"
26 
27 /*
28  * The following macros are used to interfact with IRT interfaces.
29  */
30 /* This macro defines an interfact structure, use as a regular type. */
31 #define NACL_IRT_INTERFACE(interface_type) \
32   struct nacl_io_##interface_type {        \
33     const char *query_string;              \
34     bool queried;                          \
35     bool initialized;                      \
36     struct interface_type interface;       \
37   }
38 
39 /* This macro unconditionally initializes an interface (do not use directly). */
40 #define INIT_INTERFACE_BARE(interface_struct)                   \
41   if (!interface_struct.queried) {                              \
42     const size_t bytes __attribute__((unused)) =                \
43       nacl_interface_query(interface_struct.query_string,       \
44                            &interface_struct.interface,         \
45                            sizeof(interface_struct.interface)); \
46     interface_struct.queried = true;                            \
47     interface_struct.initialized =                              \
48       (bytes == sizeof(interface_struct.interface));            \
49   }
50 
51 /* This macro initializes an interface and does not handle errors. */
52 #define INIT_INTERFACE(interface_struct)   \
53   do {                                     \
54     INIT_INTERFACE_BARE(interface_struct); \
55   } while (false)
56 
57 /* This macro initializes an interface and returns ENOSYS on failure. */
58 #define INIT_INTERFACE_ENOSYS(interface_struct) \
59   do {                                          \
60     INIT_INTERFACE_BARE(interface_struct);      \
61     if (!interface_struct.initialized)          \
62       return ENOSYS;                            \
63   } while (false)
64 
65 /* This macro initializes an interface and asserts on failure. */
66 #define INIT_INTERFACE_ASSERT(interface_struct) \
67   do {                                          \
68     INIT_INTERFACE_BARE(interface_struct);      \
69     assert(interface_struct.initialized);       \
70   } while (false)
71 
72 /* This macro supplies an IRT Extension interface and asserts on failure. */
73 #define EXT_SUPPLY_INTERFACE_ASSERT(interface_struct, supplied_struct) \
74   do {                                                                 \
75     const size_t bytes __attribute__((unused)) =                       \
76       nacl_interface_ext_supply(interface_struct.query_string,         \
77                                 &supplied_struct,                      \
78                                 sizeof(supplied_struct));              \
79     assert(bytes == sizeof(supplied_struct));                          \
80   } while (false)
81 
82 
stat_to_nacl_stat(const struct stat * buf,nacl_irt_stat_t * nacl_buf)83 void stat_to_nacl_stat(const struct stat* buf, nacl_irt_stat_t* nacl_buf) {
84   memset(nacl_buf, 0, sizeof(struct nacl_abi_stat));
85   nacl_buf->nacl_abi_st_dev = buf->st_dev;
86   nacl_buf->nacl_abi_st_ino = buf->st_ino;
87   nacl_buf->nacl_abi_st_mode = buf->st_mode;
88   nacl_buf->nacl_abi_st_nlink = buf->st_nlink;
89   nacl_buf->nacl_abi_st_uid = buf->st_uid;
90   nacl_buf->nacl_abi_st_gid = buf->st_gid;
91   nacl_buf->nacl_abi_st_rdev = buf->st_rdev;
92   nacl_buf->nacl_abi_st_size = buf->st_size;
93   nacl_buf->nacl_abi_st_blksize = buf->st_blksize;
94   nacl_buf->nacl_abi_st_blocks = buf->st_blocks;
95   nacl_buf->nacl_abi_st_atime = buf->st_atim.tv_sec;
96   nacl_buf->nacl_abi_st_atimensec = buf->st_atim.tv_nsec;
97   nacl_buf->nacl_abi_st_mtime = buf->st_mtim.tv_sec;
98   nacl_buf->nacl_abi_st_mtimensec = buf->st_mtim.tv_nsec;
99   nacl_buf->nacl_abi_st_ctime = buf->st_ctim.tv_sec;
100   nacl_buf->nacl_abi_st_ctimensec = buf->st_ctim.tv_nsec;
101 }
102 
nacl_stat_to_stat(const nacl_irt_stat_t * nacl_buf,struct stat * buf)103 void nacl_stat_to_stat(const nacl_irt_stat_t* nacl_buf, struct stat* buf) {
104   memset(buf, 0, sizeof(struct stat));
105   buf->st_dev = nacl_buf->nacl_abi_st_dev;
106   buf->st_ino = nacl_buf->nacl_abi_st_ino;
107   buf->st_mode = nacl_buf->nacl_abi_st_mode;
108   buf->st_nlink = nacl_buf->nacl_abi_st_nlink;
109   buf->st_uid = nacl_buf->nacl_abi_st_uid;
110   buf->st_gid = nacl_buf->nacl_abi_st_gid;
111   buf->st_rdev = nacl_buf->nacl_abi_st_rdev;
112   buf->st_size = nacl_buf->nacl_abi_st_size;
113   buf->st_blksize = nacl_buf->nacl_abi_st_blksize;
114   buf->st_blocks = nacl_buf->nacl_abi_st_blocks;
115   buf->st_atim.tv_sec = nacl_buf->nacl_abi_st_atime;
116   buf->st_atim.tv_nsec = nacl_buf->nacl_abi_st_atimensec;
117   buf->st_mtim.tv_sec = nacl_buf->nacl_abi_st_mtime;
118   buf->st_mtim.tv_nsec = nacl_buf->nacl_abi_st_mtimensec;
119   buf->st_ctim.tv_sec = nacl_buf->nacl_abi_st_ctime;
120   buf->st_ctim.tv_nsec = nacl_buf->nacl_abi_st_ctimensec;
121 }
122 
123 /*
124  * IRT interfaces as declared in irt.h.
125  */
126 static NACL_IRT_INTERFACE(nacl_irt_basic) s_irt_basic = {
127   NACL_IRT_BASIC_v0_1,
128 };
129 
130 static NACL_IRT_INTERFACE(nacl_irt_fdio) s_irt_fdio = {
131   NACL_IRT_FDIO_v0_1,
132 };
133 
134 static NACL_IRT_INTERFACE(nacl_irt_memory) s_irt_memory = {
135   NACL_IRT_MEMORY_v0_3,
136 };
137 
138 static NACL_IRT_INTERFACE(nacl_irt_resource_open) s_irt_resource_open = {
139   NACL_IRT_RESOURCE_OPEN_v0_1,
140 };
141 
142 /*
143  * IRT Dev interfaces as declared in irt_dev.h.
144  */
145 static NACL_IRT_INTERFACE(nacl_irt_dev_fdio) s_irt_dev_fdio = {
146   NACL_IRT_DEV_FDIO_v0_3,
147 };
148 
149 static NACL_IRT_INTERFACE(nacl_irt_dev_filename) s_irt_dev_filename = {
150   NACL_IRT_DEV_FILENAME_v0_3,
151 };
152 
153 static bool s_wrapped = false;
154 
155 /*
156  * Functions for the nacl_irt_dev_fdio interface.
157  */
ext_close(int fd)158 static int ext_close(int fd) {
159   ERRNO_RTN(ki_close(fd));
160 }
161 
ext_dup(int fd,int * newfd)162 static int ext_dup(int fd, int *newfd) {
163   *newfd = ki_dup(fd);
164   ERRNO_RTN(*newfd);
165 }
166 
ext_dup2(int fd,int newfd)167 static int ext_dup2(int fd, int newfd) {
168   newfd = ki_dup2(fd, newfd);
169   ERRNO_RTN(newfd);
170 }
171 
ext_read(int fd,void * buf,size_t count,size_t * nread)172 static int ext_read(int fd, void *buf, size_t count, size_t *nread) {
173   ssize_t signed_nread = ki_read(fd, buf, count);
174   *nread = (size_t) signed_nread;
175   ERRNO_RTN(signed_nread);
176 }
177 
ext_write(int fd,const void * buf,size_t count,size_t * nwrote)178 static int ext_write(int fd, const void *buf, size_t count, size_t *nwrote) {
179   ssize_t signed_nwrote = ki_write(fd, buf, count);
180   *nwrote = (size_t) signed_nwrote;
181   ERRNO_RTN(signed_nwrote);
182 }
183 
ext_seek(int fd,nacl_irt_off_t offset,int whence,nacl_irt_off_t * new_offset)184 static int ext_seek(int fd, nacl_irt_off_t offset, int whence,
185                     nacl_irt_off_t *new_offset) {
186   *new_offset = ki_lseek(fd, offset, whence);
187   ERRNO_RTN(*new_offset);
188 }
189 
ext_fstat(int fd,nacl_irt_stat_t * nacl_buf)190 static int ext_fstat(int fd, nacl_irt_stat_t *nacl_buf) {
191   struct stat buf;
192   if (ki_fstat(fd, &buf)) {
193     return errno;
194   }
195   stat_to_nacl_stat(&buf, nacl_buf);
196   return 0;
197 }
198 
ext_getdents(int fd,struct dirent * ents,size_t count,size_t * nread)199 static int ext_getdents(int fd, struct dirent *ents, size_t count,
200                         size_t *nread) {
201   int rtn = ki_getdents(fd, ents, count);
202   RTN_ERRNO_IF(rtn < 0);
203   *nread = rtn;
204   return 0;
205 }
206 
207 /*
208  * Functions for the nacl_irt_memory interface.
209  */
ext_mmap(void ** addr,size_t len,int prot,int flags,int fd,nacl_irt_off_t off)210 static int ext_mmap(void **addr, size_t len, int prot, int flags, int fd,
211                     nacl_irt_off_t off) {
212   if (flags & MAP_ANONYMOUS)
213     return s_irt_memory.interface.mmap(addr, len, prot, flags, fd, off);
214 
215   *addr = ki_mmap(*addr, len, prot, flags, fd, off);
216   RTN_ERRNO_IF(*addr == (void*)-1);
217   return 0;
218 }
219 
ext_munmap(void * addr,size_t length)220 static int ext_munmap(void *addr, size_t length) {
221   /*
222    * Always let the real munmap run on the address range. It is not an error if
223    * there are no mapped pages in that range.
224    */
225   ki_munmap(addr, length);
226   return s_irt_memory.interface.munmap(addr, length);
227 }
228 
229 /*
230  * Extra functions for the nacl_irt_dev_fdio interface.
231  */
ext_fchdir(int fd)232 static int ext_fchdir(int fd) {
233   ERRNO_RTN(ki_fchdir(fd));
234 }
235 
ext_fchmod(int fd,mode_t mode)236 static int ext_fchmod(int fd, mode_t mode) {
237   ERRNO_RTN(ki_fchmod(fd, mode));
238 }
239 
ext_fsync(int fd)240 static int ext_fsync(int fd) {
241   ERRNO_RTN(ki_fsync(fd));
242 }
243 
ext_fdatasync(int fd)244 static int ext_fdatasync(int fd) {
245   ERRNO_RTN(ki_fdatasync(fd));
246 }
247 
ext_ftruncate(int fd,nacl_irt_off_t length)248 static int ext_ftruncate(int fd, nacl_irt_off_t length) {
249   ERRNO_RTN(ki_ftruncate(fd, length));
250 }
251 
ext_isatty(int fd,int * result)252 static int ext_isatty(int fd, int *result) {
253   *result = ki_isatty(fd);
254   RTN_ERRNO_IF(*result == 0);
255   return 0;
256 }
257 
258 /*
259  * Functions for the nacl_irt_dev_filename interface.
260  */
ext_open(const char * pathname,int oflag,mode_t cmode,int * newfd)261 static int ext_open(const char *pathname, int oflag, mode_t cmode, int *newfd) {
262   *newfd = ki_open(pathname, oflag, cmode);
263   ERRNO_RTN(*newfd);
264 }
265 
ext_stat(const char * pathname,nacl_irt_stat_t * nacl_buf)266 static int ext_stat(const char *pathname, nacl_irt_stat_t *nacl_buf) {
267   struct stat buf;
268   if (ki_stat(pathname, &buf)) {
269     return errno;
270   }
271   stat_to_nacl_stat(&buf, nacl_buf);
272   return 0;
273 }
274 
ext_mkdir(const char * pathname,mode_t mode)275 static int ext_mkdir(const char *pathname, mode_t mode) {
276   ERRNO_RTN(ki_mkdir(pathname, mode));
277 }
278 
ext_rmdir(const char * pathname)279 static int ext_rmdir(const char *pathname) {
280   ERRNO_RTN(ki_rmdir(pathname));
281 }
282 
ext_chdir(const char * pathname)283 static int ext_chdir(const char *pathname) {
284   ERRNO_RTN(ki_chdir(pathname));
285 }
286 
ext_getcwd(char * pathname,size_t len)287 static int ext_getcwd(char *pathname, size_t len) {
288   char *rtn = ki_getcwd(pathname, len);
289   RTN_ERRNO_IF(NULL == rtn);
290   return 0;
291 }
292 
ext_unlink(const char * pathname)293 static int ext_unlink(const char *pathname) {
294   ERRNO_RTN(ki_unlink(pathname));
295 }
296 
ext_truncate(const char * pathname,nacl_irt_off_t length)297 static int ext_truncate(const char *pathname, nacl_irt_off_t length) {
298   ERRNO_RTN(ki_truncate(pathname, length));
299 }
300 
ext_lstat(const char * pathname,nacl_irt_stat_t * nacl_buf)301 static int ext_lstat(const char *pathname, nacl_irt_stat_t *nacl_buf) {
302   struct stat buf;
303   if (ki_lstat(pathname, &buf)) {
304     return errno;
305   }
306   stat_to_nacl_stat(&buf, nacl_buf);
307   return 0;
308 }
309 
ext_link(const char * pathname,const char * newpath)310 static int ext_link(const char *pathname, const char *newpath) {
311   ERRNO_RTN(ki_link(pathname, newpath));
312 }
313 
ext_rename(const char * pathname,const char * newpath)314 static int ext_rename(const char *pathname, const char *newpath) {
315   ERRNO_RTN(ki_rename(pathname, newpath));
316 }
317 
ext_symlink(const char * pathname,const char * newpath)318 static int ext_symlink(const char *pathname, const char *newpath) {
319   ERRNO_RTN(ki_symlink(pathname, newpath));
320 }
321 
ext_chmod(const char * pathname,mode_t mode)322 static int ext_chmod(const char *pathname, mode_t mode) {
323   ERRNO_RTN(ki_chmod(pathname, mode));
324 }
325 
ext_access(const char * pathname,int amode)326 static int ext_access(const char *pathname, int amode) {
327   ERRNO_RTN(ki_access(pathname, amode));
328 }
329 
ext_readlink(const char * pathname,char * buf,size_t count,size_t * nread)330 static int ext_readlink(const char *pathname, char *buf, size_t count,
331                         size_t *nread) {
332   int rtn = ki_readlink(pathname, buf, count);
333   RTN_ERRNO_IF(rtn < 0);
334   *nread = rtn;
335   return 0;
336 }
337 
ext_utimes(const char * pathname,const struct timeval * times)338 static int ext_utimes(const char *pathname, const struct timeval *times) {
339   ERRNO_RTN(ki_utimes(pathname, times));
340 }
341 
342 /*
343  * Functions declared inside of kernel_wrap_real.h.
344  */
345 
_real_close(int fd)346 int _real_close(int fd) {
347   INIT_INTERFACE_ENOSYS(s_irt_fdio);
348   return s_irt_fdio.interface.close(fd);
349 }
350 
_real_exit(int status)351 void _real_exit(int status) {
352   INIT_INTERFACE_ASSERT(s_irt_basic);
353   return s_irt_basic.interface.exit(status);
354 }
355 
_real_fstat(int fd,struct stat * buf)356 int _real_fstat(int fd, struct stat *buf) {
357   INIT_INTERFACE_ENOSYS(s_irt_fdio);
358   nacl_irt_stat_t nacl_buf;
359   int err = s_irt_fdio.interface.fstat(fd, &nacl_buf);
360   if (err) {
361     errno = err;
362     return -1;
363   }
364   nacl_stat_to_stat(&nacl_buf, buf);
365   return 0;
366 }
367 
_real_getdents(int fd,void * nacl_buf,size_t nacl_count,size_t * nread)368 int _real_getdents(int fd, void *nacl_buf, size_t nacl_count, size_t *nread) {
369   INIT_INTERFACE_ENOSYS(s_irt_fdio);
370   return s_irt_fdio.interface.getdents(fd, (struct dirent *) nacl_buf,
371                                        nacl_count, nread);
372 }
373 
_real_isatty(int fd,int * result)374 int _real_isatty(int fd, int *result) {
375   INIT_INTERFACE_ENOSYS(s_irt_dev_fdio);
376   return s_irt_dev_fdio.interface.isatty(fd, result);
377 }
378 
_real_lseek(int fd,int64_t offset,int whence,int64_t * new_offset)379 int _real_lseek(int fd, int64_t offset, int whence, int64_t *new_offset) {
380   INIT_INTERFACE_ENOSYS(s_irt_fdio);
381   return s_irt_fdio.interface.seek(fd, offset, whence, new_offset);
382 }
383 
_real_mkdir(const char * pathname,mode_t mode)384 int _real_mkdir(const char *pathname, mode_t mode) {
385   INIT_INTERFACE_ENOSYS(s_irt_dev_filename);
386   return s_irt_dev_filename.interface.mkdir(pathname, mode);
387 }
388 
_real_mmap(void ** addr,size_t length,int prot,int flags,int fd,int64_t offset)389 int _real_mmap(void **addr,
390                size_t length,
391                int prot,
392                int flags,
393                int fd,
394                int64_t offset) {
395   INIT_INTERFACE_ENOSYS(s_irt_memory);
396   return s_irt_memory.interface.mmap(addr, length, prot, flags, fd, offset);
397 }
398 
_real_munmap(void * addr,size_t length)399 int _real_munmap(void *addr, size_t length) {
400   INIT_INTERFACE_ENOSYS(s_irt_memory);
401   return s_irt_memory.interface.munmap(addr, length);
402 }
403 
_real_open(const char * pathname,int oflag,mode_t mode,int * newfd)404 int _real_open(const char *pathname, int oflag, mode_t mode, int *newfd) {
405   INIT_INTERFACE_ENOSYS(s_irt_dev_filename);
406   return s_irt_dev_filename.interface.open(pathname, oflag, mode, newfd);
407 }
408 
_real_open_resource(const char * file,int * fd)409 int _real_open_resource(const char *file, int *fd) {
410   INIT_INTERFACE_ENOSYS(s_irt_resource_open);
411   return s_irt_resource_open.interface.open_resource(file, fd);
412 }
413 
_real_read(int fd,void * buf,size_t count,size_t * nread)414 int _real_read(int fd, void *buf, size_t count, size_t *nread) {
415   INIT_INTERFACE_ENOSYS(s_irt_fdio);
416   return s_irt_fdio.interface.read(fd, buf, count, nread);
417 }
418 
_real_rmdir(const char * pathname)419 int _real_rmdir(const char *pathname) {
420   INIT_INTERFACE_ENOSYS(s_irt_dev_filename);
421   return s_irt_dev_filename.interface.rmdir(pathname);
422 }
423 
_real_write(int fd,const void * buf,size_t count,size_t * nwrote)424 int _real_write(int fd, const void *buf, size_t count, size_t *nwrote) {
425   INIT_INTERFACE_ENOSYS(s_irt_fdio);
426   return s_irt_fdio.interface.write(fd, buf, count, nwrote);
427 }
428 
_real_getcwd(char * pathname,size_t len)429 int _real_getcwd(char *pathname, size_t len) {
430   INIT_INTERFACE_ENOSYS(s_irt_dev_filename);
431   return s_irt_dev_filename.interface.getcwd(pathname, len);
432 }
433 
434 /*
435  * Kernel Wrap init/uninit functions declared in kernel_wrap.h.
436  */
kernel_wrap_init()437 void kernel_wrap_init() {
438   if (!s_wrapped) {
439     LOG_TRACE("kernel_wrap_init");
440 
441     /*
442      * Register interfaces as listed in irt.h.
443      */
444 
445     /* Register nacl_irt_basic interface. */
446     INIT_INTERFACE_ASSERT(s_irt_basic);
447     struct nacl_irt_basic basic_calls = {
448       ki_exit,
449       s_irt_basic.interface.gettod,
450       s_irt_basic.interface.clock,
451       s_irt_basic.interface.nanosleep,
452       s_irt_basic.interface.sched_yield,
453       s_irt_basic.interface.sysconf,
454     };
455     EXT_SUPPLY_INTERFACE_ASSERT(s_irt_basic, basic_calls);
456 
457     /* Register nacl_irt_fdio interface. */
458     INIT_INTERFACE(s_irt_fdio);
459     struct nacl_irt_fdio fdio = {
460       ext_close,
461       ext_dup,
462       ext_dup2,
463       ext_read,
464       ext_write,
465       ext_seek,
466       ext_fstat,
467       ext_getdents,
468     };
469     EXT_SUPPLY_INTERFACE_ASSERT(s_irt_fdio, fdio);
470 
471     /* Register nacl_irt_memory interface. */
472     INIT_INTERFACE_ASSERT(s_irt_memory);
473     struct nacl_irt_memory mem = {
474       ext_mmap,
475       ext_munmap,
476       s_irt_memory.interface.mprotect,
477     };
478     EXT_SUPPLY_INTERFACE_ASSERT(s_irt_memory, mem);
479 
480     /*
481      * Register interfaces as listed in irt_dev.h.
482      */
483 
484     /* Register nacl_irt_dev_fdio interface. */
485     INIT_INTERFACE(s_irt_dev_fdio);
486     struct nacl_irt_dev_fdio dev_fdio = {
487       ext_close,
488       ext_dup,
489       ext_dup2,
490       ext_read,
491       ext_write,
492       ext_seek,
493       ext_fstat,
494       ext_getdents,
495       ext_fchdir,
496       ext_fchmod,
497       ext_fsync,
498       ext_fdatasync,
499       ext_ftruncate,
500       ext_isatty,
501     };
502     EXT_SUPPLY_INTERFACE_ASSERT(s_irt_dev_fdio, dev_fdio);
503 
504     /* Register nacl_irt_dev_filename interface. */
505     INIT_INTERFACE(s_irt_dev_filename);
506     struct nacl_irt_dev_filename dev_filename = {
507       ext_open,
508       ext_stat,
509       ext_mkdir,
510       ext_rmdir,
511       ext_chdir,
512       ext_getcwd,
513       ext_unlink,
514       ext_truncate,
515       ext_lstat,
516       ext_link,
517       ext_rename,
518       ext_symlink,
519       ext_chmod,
520       ext_access,
521       ext_readlink,
522       ext_utimes,
523     };
524     EXT_SUPPLY_INTERFACE_ASSERT(s_irt_dev_filename, dev_filename);
525 
526     s_wrapped = true;
527   }
528 }
529 
kernel_wrap_uninit()530 void kernel_wrap_uninit() {
531   if (s_wrapped) {
532     LOG_TRACE("kernel_wrap_uninit");
533 
534     /* Register original IRT interfaces in irt.h. */
535     EXT_SUPPLY_INTERFACE_ASSERT(s_irt_basic,
536                                 s_irt_basic.interface);
537 
538     EXT_SUPPLY_INTERFACE_ASSERT(s_irt_fdio,
539                                 s_irt_fdio.interface);
540 
541     EXT_SUPPLY_INTERFACE_ASSERT(s_irt_memory,
542                                 s_irt_memory.interface);
543 
544     /*
545      * Register optional original IRT dev interfaces in irt_dev.h, these
546      * may or may not exist since they are dev interfaces. If they do not
547      * exist go ahead and supply an empty interface as that's what they
548      * were originally before we supplied any extension interfaces.
549      */
550     EXT_SUPPLY_INTERFACE_ASSERT(s_irt_dev_fdio,
551                                 s_irt_dev_fdio.interface);
552 
553     EXT_SUPPLY_INTERFACE_ASSERT(s_irt_dev_filename,
554                                 s_irt_dev_filename.interface);
555 
556     s_wrapped = false;
557   }
558 }
559 
560 #endif
561