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. */
5 /* NACL_IO_IRT_EXT is defined in this header */
6 #include "nacl_io/kernel_wrap.h"
9 * The entire file is wrapped in this #if. We do this so this .c file can
12 #if defined(NACL_IO_IRT_EXT)
18 #include <irt_extension.h>
23 #include "nacl_io/kernel_intercept.h"
24 #include "nacl_io/log.h"
25 #include "nacl_io/nacl_abi_types.h"
28 * The following macros are used to interfact with IRT interfaces.
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; \
36 struct interface_type interface; \
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)); \
51 /* This macro initializes an interface and does not handle errors. */
52 #define INIT_INTERFACE(interface_struct) \
54 INIT_INTERFACE_BARE(interface_struct); \
57 /* This macro initializes an interface and returns ENOSYS on failure. */
58 #define INIT_INTERFACE_ENOSYS(interface_struct) \
60 INIT_INTERFACE_BARE(interface_struct); \
61 if (!interface_struct.initialized) \
65 /* This macro initializes an interface and asserts on failure. */
66 #define INIT_INTERFACE_ASSERT(interface_struct) \
68 INIT_INTERFACE_BARE(interface_struct); \
69 assert(interface_struct.initialized); \
72 /* This macro supplies an IRT Extension interface and asserts on failure. */
73 #define EXT_SUPPLY_INTERFACE_ASSERT(interface_struct, supplied_struct) \
75 const size_t bytes __attribute__((unused)) = \
76 nacl_interface_ext_supply(interface_struct.query_string, \
78 sizeof(supplied_struct)); \
79 assert(bytes == sizeof(supplied_struct)); \
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
;
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
;
124 * IRT interfaces as declared in irt.h.
126 static NACL_IRT_INTERFACE(nacl_irt_basic
) s_irt_basic
= {
130 static NACL_IRT_INTERFACE(nacl_irt_fdio
) s_irt_fdio
= {
134 static NACL_IRT_INTERFACE(nacl_irt_memory
) s_irt_memory
= {
135 NACL_IRT_MEMORY_v0_3
,
138 static NACL_IRT_INTERFACE(nacl_irt_resource_open
) s_irt_resource_open
= {
139 NACL_IRT_RESOURCE_OPEN_v0_1
,
143 * IRT Dev interfaces as declared in irt_dev.h.
145 static NACL_IRT_INTERFACE(nacl_irt_dev_fdio
) s_irt_dev_fdio
= {
146 NACL_IRT_DEV_FDIO_v0_3
,
149 static NACL_IRT_INTERFACE(nacl_irt_dev_filename
) s_irt_dev_filename
= {
150 NACL_IRT_DEV_FILENAME_v0_3
,
153 static bool s_wrapped
= false;
156 * Functions for the nacl_irt_dev_fdio interface.
158 static int ext_close(int fd
) {
159 ERRNO_RTN(ki_close(fd
));
162 static int ext_dup(int fd
, int *newfd
) {
167 static int ext_dup2(int fd
, int newfd
) {
168 newfd
= ki_dup2(fd
, newfd
);
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
);
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
);
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
);
190 static int ext_fstat(int fd
, nacl_irt_stat_t
*nacl_buf
) {
192 if (ki_fstat(fd
, &buf
)) {
195 stat_to_nacl_stat(&buf
, nacl_buf
);
199 static int ext_getdents(int fd
, struct dirent
*ents
, size_t count
,
201 int rtn
= ki_getdents(fd
, ents
, count
);
202 RTN_ERRNO_IF(rtn
< 0);
208 * Functions for the nacl_irt_memory interface.
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
);
215 *addr
= ki_mmap(*addr
, len
, prot
, flags
, fd
, off
);
216 RTN_ERRNO_IF(*addr
== (void*)-1);
220 static int ext_munmap(void *addr
, size_t length
) {
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.
225 ki_munmap(addr
, length
);
226 return s_irt_memory
.interface
.munmap(addr
, length
);
230 * Extra functions for the nacl_irt_dev_fdio interface.
232 static int ext_fchdir(int fd
) {
233 ERRNO_RTN(ki_fchdir(fd
));
236 static int ext_fchmod(int fd
, mode_t mode
) {
237 ERRNO_RTN(ki_fchmod(fd
, mode
));
240 static int ext_fsync(int fd
) {
241 ERRNO_RTN(ki_fsync(fd
));
244 static int ext_fdatasync(int fd
) {
245 ERRNO_RTN(ki_fdatasync(fd
));
248 static int ext_ftruncate(int fd
, nacl_irt_off_t length
) {
249 ERRNO_RTN(ki_ftruncate(fd
, length
));
252 static int ext_isatty(int fd
, int *result
) {
253 *result
= ki_isatty(fd
);
254 RTN_ERRNO_IF(*result
== 0);
259 * Functions for the nacl_irt_dev_filename interface.
261 static int ext_open(const char *pathname
, int oflag
, mode_t cmode
, int *newfd
) {
262 *newfd
= ki_open(pathname
, oflag
, cmode
);
266 static int ext_stat(const char *pathname
, nacl_irt_stat_t
*nacl_buf
) {
268 if (ki_stat(pathname
, &buf
)) {
271 stat_to_nacl_stat(&buf
, nacl_buf
);
275 static int ext_mkdir(const char *pathname
, mode_t mode
) {
276 ERRNO_RTN(ki_mkdir(pathname
, mode
));
279 static int ext_rmdir(const char *pathname
) {
280 ERRNO_RTN(ki_rmdir(pathname
));
283 static int ext_chdir(const char *pathname
) {
284 ERRNO_RTN(ki_chdir(pathname
));
287 static int ext_getcwd(char *pathname
, size_t len
) {
288 char *rtn
= ki_getcwd(pathname
, len
);
289 RTN_ERRNO_IF(NULL
== rtn
);
293 static int ext_unlink(const char *pathname
) {
294 ERRNO_RTN(ki_unlink(pathname
));
297 static int ext_truncate(const char *pathname
, nacl_irt_off_t length
) {
298 ERRNO_RTN(ki_truncate(pathname
, length
));
301 static int ext_lstat(const char *pathname
, nacl_irt_stat_t
*nacl_buf
) {
303 if (ki_lstat(pathname
, &buf
)) {
306 stat_to_nacl_stat(&buf
, nacl_buf
);
310 static int ext_link(const char *pathname
, const char *newpath
) {
311 ERRNO_RTN(ki_link(pathname
, newpath
));
314 static int ext_rename(const char *pathname
, const char *newpath
) {
315 ERRNO_RTN(ki_rename(pathname
, newpath
));
318 static int ext_symlink(const char *pathname
, const char *newpath
) {
319 ERRNO_RTN(ki_symlink(pathname
, newpath
));
322 static int ext_chmod(const char *pathname
, mode_t mode
) {
323 ERRNO_RTN(ki_chmod(pathname
, mode
));
326 static int ext_access(const char *pathname
, int amode
) {
327 ERRNO_RTN(ki_access(pathname
, amode
));
330 static int ext_readlink(const char *pathname
, char *buf
, size_t count
,
332 int rtn
= ki_readlink(pathname
, buf
, count
);
333 RTN_ERRNO_IF(rtn
< 0);
338 static int ext_utimes(const char *pathname
, const struct timeval
*times
) {
339 ERRNO_RTN(ki_utimes(pathname
, times
));
343 * Functions declared inside of kernel_wrap_real.h.
346 int _real_close(int fd
) {
347 INIT_INTERFACE_ENOSYS(s_irt_fdio
);
348 return s_irt_fdio
.interface
.close(fd
);
351 void _real_exit(int status
) {
352 INIT_INTERFACE_ASSERT(s_irt_basic
);
353 return s_irt_basic
.interface
.exit(status
);
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
);
364 nacl_stat_to_stat(&nacl_buf
, buf
);
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
,
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
);
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
);
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
);
389 int _real_mmap(void **addr
,
395 INIT_INTERFACE_ENOSYS(s_irt_memory
);
396 return s_irt_memory
.interface
.mmap(addr
, length
, prot
, flags
, fd
, offset
);
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
);
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
);
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
);
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
);
419 int _real_rmdir(const char *pathname
) {
420 INIT_INTERFACE_ENOSYS(s_irt_dev_filename
);
421 return s_irt_dev_filename
.interface
.rmdir(pathname
);
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
);
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
);
435 * Kernel Wrap init/uninit functions declared in kernel_wrap.h.
437 void kernel_wrap_init() {
439 LOG_TRACE("kernel_wrap_init");
442 * Register interfaces as listed in irt.h.
445 /* Register nacl_irt_basic interface. */
446 INIT_INTERFACE_ASSERT(s_irt_basic
);
447 struct nacl_irt_basic basic_calls
= {
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
,
455 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_basic
, basic_calls
);
457 /* Register nacl_irt_fdio interface. */
458 INIT_INTERFACE(s_irt_fdio
);
459 struct nacl_irt_fdio fdio
= {
469 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_fdio
, fdio
);
471 /* Register nacl_irt_memory interface. */
472 INIT_INTERFACE_ASSERT(s_irt_memory
);
473 struct nacl_irt_memory mem
= {
476 s_irt_memory
.interface
.mprotect
,
478 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_memory
, mem
);
481 * Register interfaces as listed in irt_dev.h.
484 /* Register nacl_irt_dev_fdio interface. */
485 INIT_INTERFACE(s_irt_dev_fdio
);
486 struct nacl_irt_dev_fdio dev_fdio
= {
502 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_dev_fdio
, dev_fdio
);
504 /* Register nacl_irt_dev_filename interface. */
505 INIT_INTERFACE(s_irt_dev_filename
);
506 struct nacl_irt_dev_filename dev_filename
= {
524 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_dev_filename
, dev_filename
);
530 void kernel_wrap_uninit() {
532 LOG_TRACE("kernel_wrap_uninit");
534 /* Register original IRT interfaces in irt.h. */
535 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_basic
,
536 s_irt_basic
.interface
);
538 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_fdio
,
539 s_irt_fdio
.interface
);
541 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_memory
,
542 s_irt_memory
.interface
);
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.
550 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_dev_fdio
,
551 s_irt_dev_fdio
.interface
);
553 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_dev_filename
,
554 s_irt_dev_filename
.interface
);