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"
27 * The following macros are used to interfact with IRT interfaces.
29 /* This macro defines an interfact structure, use as a regular type. */
30 #define NACL_IRT_INTERFACE(interface_type) \
31 struct nacl_io_##interface_type { \
32 const char *query_string; \
35 struct interface_type interface; \
38 /* This macro unconditionally initializes an interface (do not use directly). */
39 #define INIT_INTERFACE_BARE(interface_struct) \
40 if (!interface_struct.queried) { \
41 const size_t bytes __attribute__((unused)) = \
42 nacl_interface_query(interface_struct.query_string, \
43 &interface_struct.interface, \
44 sizeof(interface_struct.interface)); \
45 interface_struct.queried = true; \
46 interface_struct.initialized = \
47 (bytes == sizeof(interface_struct.interface)); \
50 /* This macro initializes an interface and does not handle errors. */
51 #define INIT_INTERFACE(interface_struct) \
53 INIT_INTERFACE_BARE(interface_struct); \
56 /* This macro initializes an interface and returns ENOSYS on failure. */
57 #define INIT_INTERFACE_ENOSYS(interface_struct) \
59 INIT_INTERFACE_BARE(interface_struct); \
60 if (!interface_struct.initialized) \
64 /* This macro initializes an interface and asserts on failure. */
65 #define INIT_INTERFACE_ASSERT(interface_struct) \
67 INIT_INTERFACE_BARE(interface_struct); \
68 assert(interface_struct.initialized); \
71 /* This macro supplies an IRT Extension interface and asserts on failure. */
72 #define EXT_SUPPLY_INTERFACE_ASSERT(interface_struct, supplied_struct) \
74 const size_t bytes __attribute__((unused)) = \
75 nacl_interface_ext_supply(interface_struct.query_string, \
77 sizeof(supplied_struct)); \
78 assert(bytes == sizeof(supplied_struct)); \
82 * IRT interfaces as declared in irt.h.
84 static NACL_IRT_INTERFACE(nacl_irt_basic
) s_irt_basic
= {
88 static NACL_IRT_INTERFACE(nacl_irt_fdio
) s_irt_fdio
= {
92 static NACL_IRT_INTERFACE(nacl_irt_memory
) s_irt_memory
= {
96 static NACL_IRT_INTERFACE(nacl_irt_resource_open
) s_irt_resource_open
= {
97 NACL_IRT_RESOURCE_OPEN_v0_1
,
101 * IRT Dev interfaces as declared in irt_dev.h.
103 static NACL_IRT_INTERFACE(nacl_irt_dev_fdio
) s_irt_dev_fdio
= {
104 NACL_IRT_DEV_FDIO_v0_3
,
107 static NACL_IRT_INTERFACE(nacl_irt_dev_filename
) s_irt_dev_filename
= {
108 NACL_IRT_DEV_FILENAME_v0_3
,
111 static bool s_wrapped
= false;
114 * Functions for the nacl_irt_dev_fdio interface.
116 static int ext_close(int fd
) {
117 ERRNO_RTN(ki_close(fd
));
120 static int ext_dup(int fd
, int *newfd
) {
125 static int ext_dup2(int fd
, int newfd
) {
126 newfd
= ki_dup2(fd
, newfd
);
130 static int ext_read(int fd
, void *buf
, size_t count
, size_t *nread
) {
131 ssize_t signed_nread
= ki_read(fd
, buf
, count
);
132 *nread
= (size_t) signed_nread
;
133 ERRNO_RTN(signed_nread
);
136 static int ext_write(int fd
, const void *buf
, size_t count
, size_t *nwrote
) {
137 ssize_t signed_nwrote
= ki_write(fd
, buf
, count
);
138 *nwrote
= (size_t) signed_nwrote
;
139 ERRNO_RTN(signed_nwrote
);
142 static int ext_seek(int fd
, nacl_irt_off_t offset
, int whence
,
143 nacl_irt_off_t
*new_offset
) {
144 *new_offset
= ki_lseek(fd
, offset
, whence
);
145 ERRNO_RTN(*new_offset
);
148 static int ext_fstat(int fd
, struct stat
*buf
) {
149 ERRNO_RTN(ki_fstat(fd
, buf
));
152 static int ext_getdents(int fd
, struct dirent
*ents
, size_t count
,
154 int rtn
= ki_getdents(fd
, ents
, count
);
155 RTN_ERRNO_IF(rtn
< 0);
161 * Functions for the nacl_irt_memory interface.
163 static int ext_mmap(void **addr
, size_t len
, int prot
, int flags
, int fd
,
164 nacl_irt_off_t off
) {
165 if (flags
& MAP_ANONYMOUS
)
166 return s_irt_memory
.interface
.mmap(addr
, len
, prot
, flags
, fd
, off
);
168 *addr
= ki_mmap(*addr
, len
, prot
, flags
, fd
, off
);
169 RTN_ERRNO_IF(*addr
== (void*)-1);
173 static int ext_munmap(void *addr
, size_t length
) {
175 * Always let the real munmap run on the address range. It is not an error if
176 * there are no mapped pages in that range.
178 ki_munmap(addr
, length
);
179 return s_irt_memory
.interface
.munmap(addr
, length
);
183 * Extra functions for the nacl_irt_dev_fdio interface.
185 static int ext_fchdir(int fd
) {
186 ERRNO_RTN(ki_fchdir(fd
));
189 static int ext_fchmod(int fd
, mode_t mode
) {
190 ERRNO_RTN(ki_fchmod(fd
, mode
));
193 static int ext_fsync(int fd
) {
194 ERRNO_RTN(ki_fsync(fd
));
197 static int ext_fdatasync(int fd
) {
198 ERRNO_RTN(ki_fdatasync(fd
));
201 static int ext_ftruncate(int fd
, nacl_irt_off_t length
) {
202 ERRNO_RTN(ki_ftruncate(fd
, length
));
205 static int ext_isatty(int fd
, int *result
) {
206 *result
= ki_isatty(fd
);
207 RTN_ERRNO_IF(*result
== 0);
212 * Functions for the nacl_irt_dev_filename interface.
214 static int ext_open(const char *pathname
, int oflag
, mode_t cmode
, int *newfd
) {
215 *newfd
= ki_open(pathname
, oflag
, cmode
);
219 static int ext_stat(const char *pathname
, struct stat
*buf
) {
220 ERRNO_RTN(ki_stat(pathname
, buf
));
223 static int ext_mkdir(const char *pathname
, mode_t mode
) {
224 ERRNO_RTN(ki_mkdir(pathname
, mode
));
227 static int ext_rmdir(const char *pathname
) {
228 ERRNO_RTN(ki_rmdir(pathname
));
231 static int ext_chdir(const char *pathname
) {
232 ERRNO_RTN(ki_chdir(pathname
));
235 static int ext_getcwd(char *pathname
, size_t len
) {
236 char *rtn
= ki_getcwd(pathname
, len
);
237 RTN_ERRNO_IF(NULL
== rtn
);
241 static int ext_unlink(const char *pathname
) {
242 ERRNO_RTN(ki_unlink(pathname
));
245 static int ext_truncate(const char *pathname
, nacl_irt_off_t length
) {
246 ERRNO_RTN(ki_truncate(pathname
, length
));
249 static int ext_lstat(const char *pathname
, struct stat
*buf
) {
250 ERRNO_RTN(ki_lstat(pathname
, buf
));
253 static int ext_link(const char *pathname
, const char *newpath
) {
254 ERRNO_RTN(ki_link(pathname
, newpath
));
257 static int ext_rename(const char *pathname
, const char *newpath
) {
258 ERRNO_RTN(ki_rename(pathname
, newpath
));
261 static int ext_symlink(const char *pathname
, const char *newpath
) {
262 ERRNO_RTN(ki_symlink(pathname
, newpath
));
265 static int ext_chmod(const char *pathname
, mode_t mode
) {
266 ERRNO_RTN(ki_chmod(pathname
, mode
));
269 static int ext_access(const char *pathname
, int amode
) {
270 ERRNO_RTN(ki_access(pathname
, amode
));
273 static int ext_readlink(const char *pathname
, char *buf
, size_t count
,
275 int rtn
= ki_readlink(pathname
, buf
, count
);
276 RTN_ERRNO_IF(rtn
< 0);
281 static int ext_utimes(const char *pathname
, const struct timeval
*times
) {
282 ERRNO_RTN(ki_utimes(pathname
, times
));
286 * Functions declared inside of kernel_wrap_real.h.
289 int _real_close(int fd
) {
290 INIT_INTERFACE_ENOSYS(s_irt_fdio
);
291 return s_irt_fdio
.interface
.close(fd
);
294 void _real_exit(int status
) {
295 INIT_INTERFACE_ASSERT(s_irt_basic
);
296 return s_irt_basic
.interface
.exit(status
);
299 int _real_fstat(int fd
, struct stat
*buf
) {
300 INIT_INTERFACE_ENOSYS(s_irt_fdio
);
301 return s_irt_fdio
.interface
.fstat(fd
, buf
);
304 int _real_getdents(int fd
, void *nacl_buf
, size_t nacl_count
, size_t *nread
) {
305 INIT_INTERFACE_ENOSYS(s_irt_fdio
);
306 return s_irt_fdio
.interface
.getdents(fd
, (struct dirent
*) nacl_buf
,
310 int _real_isatty(int fd
, int *result
) {
311 INIT_INTERFACE_ENOSYS(s_irt_dev_fdio
);
312 return s_irt_dev_fdio
.interface
.isatty(fd
, result
);
315 int _real_lseek(int fd
, int64_t offset
, int whence
, int64_t *new_offset
) {
316 INIT_INTERFACE_ENOSYS(s_irt_fdio
);
317 return s_irt_fdio
.interface
.seek(fd
, offset
, whence
, new_offset
);
320 int _real_mkdir(const char *pathname
, mode_t mode
) {
321 INIT_INTERFACE_ENOSYS(s_irt_dev_filename
);
322 return s_irt_dev_filename
.interface
.mkdir(pathname
, mode
);
325 int _real_mmap(void **addr
,
331 INIT_INTERFACE_ENOSYS(s_irt_memory
);
332 return s_irt_memory
.interface
.mmap(addr
, length
, prot
, flags
, fd
, offset
);
335 int _real_munmap(void *addr
, size_t length
) {
336 INIT_INTERFACE_ENOSYS(s_irt_memory
);
337 return s_irt_memory
.interface
.munmap(addr
, length
);
340 int _real_open(const char *pathname
, int oflag
, mode_t mode
, int *newfd
) {
341 INIT_INTERFACE_ENOSYS(s_irt_dev_filename
);
342 return s_irt_dev_filename
.interface
.open(pathname
, oflag
, mode
, newfd
);
345 int _real_open_resource(const char *file
, int *fd
) {
346 INIT_INTERFACE_ENOSYS(s_irt_resource_open
);
347 return s_irt_resource_open
.interface
.open_resource(file
, fd
);
350 int _real_read(int fd
, void *buf
, size_t count
, size_t *nread
) {
351 INIT_INTERFACE_ENOSYS(s_irt_fdio
);
352 return s_irt_fdio
.interface
.read(fd
, buf
, count
, nread
);
355 int _real_rmdir(const char *pathname
) {
356 INIT_INTERFACE_ENOSYS(s_irt_dev_filename
);
357 return s_irt_dev_filename
.interface
.rmdir(pathname
);
360 int _real_write(int fd
, const void *buf
, size_t count
, size_t *nwrote
) {
361 INIT_INTERFACE_ENOSYS(s_irt_fdio
);
362 return s_irt_fdio
.interface
.write(fd
, buf
, count
, nwrote
);
365 int _real_getcwd(char *pathname
, size_t len
) {
366 INIT_INTERFACE_ENOSYS(s_irt_dev_filename
);
367 return s_irt_dev_filename
.interface
.getcwd(pathname
, len
);
371 * Kernel Wrap init/uninit functions declared in kernel_wrap.h.
373 void kernel_wrap_init() {
375 LOG_TRACE("kernel_wrap_init");
378 * Register interfaces as listed in irt.h.
381 /* Register nacl_irt_basic interface. */
382 INIT_INTERFACE_ASSERT(s_irt_basic
);
383 struct nacl_irt_basic basic_calls
= {
385 s_irt_basic
.interface
.gettod
,
386 s_irt_basic
.interface
.clock
,
387 s_irt_basic
.interface
.nanosleep
,
388 s_irt_basic
.interface
.sched_yield
,
389 s_irt_basic
.interface
.sysconf
,
391 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_basic
, basic_calls
);
393 /* Register nacl_irt_fdio interface. */
394 INIT_INTERFACE(s_irt_fdio
);
395 struct nacl_irt_fdio fdio
= {
405 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_fdio
, fdio
);
407 /* Register nacl_irt_memory interface. */
408 INIT_INTERFACE_ASSERT(s_irt_memory
);
409 struct nacl_irt_memory mem
= {
412 s_irt_memory
.interface
.mprotect
,
414 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_memory
, mem
);
417 * Register interfaces as listed in irt_dev.h.
420 /* Register nacl_irt_dev_fdio interface. */
421 INIT_INTERFACE(s_irt_dev_fdio
);
422 struct nacl_irt_dev_fdio dev_fdio
= {
438 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_dev_fdio
, dev_fdio
);
440 /* Register nacl_irt_dev_filename interface. */
441 INIT_INTERFACE(s_irt_dev_filename
);
442 struct nacl_irt_dev_filename dev_filename
= {
460 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_dev_filename
, dev_filename
);
466 void kernel_wrap_uninit() {
468 LOG_TRACE("kernel_wrap_uninit");
470 /* Register original IRT interfaces in irt.h. */
471 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_basic
,
472 s_irt_basic
.interface
);
474 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_fdio
,
475 s_irt_fdio
.interface
);
477 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_memory
,
478 s_irt_memory
.interface
);
481 * Register optional original IRT dev interfaces in irt_dev.h, these
482 * may or may not exist since they are dev interfaces. If they do not
483 * exist go ahead and supply an empty interface as that's what they
484 * were originally before we supplied any extension interfaces.
486 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_dev_fdio
,
487 s_irt_dev_fdio
.interface
);
489 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_dev_filename
,
490 s_irt_dev_filename
.interface
);