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.
5 #include <sys/types.h> // Include something that will define __GLIBC__.
7 // The entire file is wrapped in this #if. We do this so this .cc file can be
8 // compiled, even on a non-glibc build.
9 #if defined(__native_client__) && defined(__GLIBC__)
11 #include "nacl_io/kernel_wrap.h"
18 #include <irt_syscalls.h>
19 #include <nacl_stat.h>
24 #include "nacl_io/kernel_intercept.h"
25 #include "nacl_io/kernel_wrap_real.h"
26 #include "nacl_io/log.h"
27 #include "nacl_io/osmman.h"
28 #include "nacl_io/ostime.h"
32 void stat_to_nacl_stat(const struct stat
* buf
, nacl_abi_stat
* nacl_buf
) {
33 memset(nacl_buf
, 0, sizeof(struct nacl_abi_stat
));
34 nacl_buf
->nacl_abi_st_dev
= buf
->st_dev
;
35 nacl_buf
->nacl_abi_st_ino
= buf
->st_ino
;
36 nacl_buf
->nacl_abi_st_mode
= buf
->st_mode
;
37 nacl_buf
->nacl_abi_st_nlink
= buf
->st_nlink
;
38 nacl_buf
->nacl_abi_st_uid
= buf
->st_uid
;
39 nacl_buf
->nacl_abi_st_gid
= buf
->st_gid
;
40 nacl_buf
->nacl_abi_st_rdev
= buf
->st_rdev
;
41 nacl_buf
->nacl_abi_st_size
= buf
->st_size
;
42 nacl_buf
->nacl_abi_st_blksize
= buf
->st_blksize
;
43 nacl_buf
->nacl_abi_st_blocks
= buf
->st_blocks
;
44 nacl_buf
->nacl_abi_st_atime
= buf
->st_atime
;
45 nacl_buf
->nacl_abi_st_atimensec
= buf
->st_atimensec
;
46 nacl_buf
->nacl_abi_st_mtime
= buf
->st_mtime
;
47 nacl_buf
->nacl_abi_st_mtimensec
= buf
->st_mtimensec
;
48 nacl_buf
->nacl_abi_st_ctime
= buf
->st_ctime
;
49 nacl_buf
->nacl_abi_st_ctimensec
= buf
->st_ctimensec
;
52 void nacl_stat_to_stat(const nacl_abi_stat
* nacl_buf
, struct stat
* buf
) {
53 memset(buf
, 0, sizeof(struct stat
));
54 buf
->st_dev
= nacl_buf
->nacl_abi_st_dev
;
55 buf
->st_ino
= nacl_buf
->nacl_abi_st_ino
;
56 buf
->st_mode
= nacl_buf
->nacl_abi_st_mode
;
57 buf
->st_nlink
= nacl_buf
->nacl_abi_st_nlink
;
58 buf
->st_uid
= nacl_buf
->nacl_abi_st_uid
;
59 buf
->st_gid
= nacl_buf
->nacl_abi_st_gid
;
60 buf
->st_rdev
= nacl_buf
->nacl_abi_st_rdev
;
61 buf
->st_size
= nacl_buf
->nacl_abi_st_size
;
62 buf
->st_blksize
= nacl_buf
->nacl_abi_st_blksize
;
63 buf
->st_blocks
= nacl_buf
->nacl_abi_st_blocks
;
64 buf
->st_atime
= nacl_buf
->nacl_abi_st_atime
;
65 buf
->st_atimensec
= nacl_buf
->nacl_abi_st_atimensec
;
66 buf
->st_mtime
= nacl_buf
->nacl_abi_st_mtime
;
67 buf
->st_mtimensec
= nacl_buf
->nacl_abi_st_mtimensec
;
68 buf
->st_ctime
= nacl_buf
->nacl_abi_st_ctime
;
69 buf
->st_ctimensec
= nacl_buf
->nacl_abi_st_ctimensec
;
74 // From native_client/src/trusted/service_runtime/include/sys/dirent.h
76 #ifndef nacl_abi___ino_t_defined
77 #define nacl_abi___ino_t_defined
78 typedef int64_t nacl_abi___ino_t
;
79 typedef nacl_abi___ino_t nacl_abi_ino_t
;
82 #ifndef nacl_abi___off_t_defined
83 #define nacl_abi___off_t_defined
84 typedef int64_t nacl_abi__off_t
;
85 typedef nacl_abi__off_t nacl_abi_off_t
;
88 /* We need a way to define the maximum size of a name. */
91 # define MAXNAMLEN NAME_MAX
93 # define MAXNAMLEN 255
97 struct nacl_abi_dirent
{
98 nacl_abi_ino_t nacl_abi_d_ino
;
99 nacl_abi_off_t nacl_abi_d_off
;
100 uint16_t nacl_abi_d_reclen
;
101 char nacl_abi_d_name
[MAXNAMLEN
+ 1];
104 static const int d_name_shift
= offsetof (dirent
, d_name
) -
105 offsetof (struct nacl_abi_dirent
, nacl_abi_d_name
);
109 // Macro to get the REAL function pointer
110 #define REAL(name) __nacl_irt_##name##_real
112 // Macro to get the WRAP function
113 #define WRAP(name) __nacl_irt_##name##_wrap
115 // Declare REAL function pointer.
116 #define DECLARE_REAL_PTR(name) typeof(__nacl_irt_##name) REAL(name);
118 // Assign the REAL function pointer.
119 #define ASSIGN_REAL_PTR(name) \
120 assert(__nacl_irt_##name != NULL); \
121 REAL(name) = __nacl_irt_##name;
123 // Switch IRT's pointer to the REAL pointer
124 #define USE_REAL(name) __nacl_irt_##name = (typeof(__nacl_irt_##name))REAL(name)
126 // Switch IRT's pointer to the WRAP function
127 #define USE_WRAP(name) __nacl_irt_##name = (typeof(__nacl_irt_##name))WRAP(name)
129 #define EXPAND_SYMBOL_LIST_OPERATION(OP) \
182 // TODO(bradnelson): Add these as well.
184 // OP(epoll_create1);
190 EXPAND_SYMBOL_LIST_OPERATION(DECLARE_REAL_PTR
);
192 int WRAP(chdir
)(const char* pathname
) {
193 ERRNO_RTN(ki_chdir(pathname
));
196 int WRAP(close
)(int fd
) {
197 ERRNO_RTN(ki_close(fd
));
200 int WRAP(dup
)(int fd
, int* newfd
) NOTHROW
{
202 RTN_ERRNO_IF(*newfd
< 0);
206 int WRAP(dup2
)(int fd
, int newfd
) NOTHROW
{
207 ERRNO_RTN(ki_dup2(fd
, newfd
));
210 void WRAP(exit
)(int status
) {
214 int WRAP(fstat
)(int fd
, struct nacl_abi_stat
* nacl_buf
) {
216 memset(&buf
, 0, sizeof(struct stat
));
217 int res
= ki_fstat(fd
, &buf
);
218 RTN_ERRNO_IF(res
< 0);
219 stat_to_nacl_stat(&buf
, nacl_buf
);
223 int WRAP(getcwd
)(char* buf
, size_t size
) {
224 RTN_ERRNO_IF(ki_getcwd(buf
, size
) == NULL
);
228 int WRAP(getdents
)(int fd
, dirent
* nacl_buf
, size_t nacl_count
, size_t* nread
) {
230 // "buf" contains dirent(s); "nacl_buf" contains nacl_abi_dirent(s).
231 // nacl_abi_dirent(s) are smaller than dirent(s), so nacl_count bytes buffer
233 char* buf
= (char*)alloca(nacl_count
);
237 count
= ki_getdents(fd
, buf
, nacl_count
);
238 RTN_ERRNO_IF(count
< 0);
240 while (offset
< count
) {
241 dirent
* d
= (dirent
*)(buf
+ offset
);
242 nacl_abi_dirent
* nacl_d
= (nacl_abi_dirent
*)((char*)nacl_buf
+ nacl_offset
);
243 nacl_d
->nacl_abi_d_ino
= d
->d_ino
;
244 nacl_d
->nacl_abi_d_off
= d
->d_off
;
245 nacl_d
->nacl_abi_d_reclen
= d
->d_reclen
- d_name_shift
;
246 size_t d_name_len
= d
->d_reclen
- offsetof(dirent
, d_name
);
247 memcpy(nacl_d
->nacl_abi_d_name
, d
->d_name
, d_name_len
);
249 offset
+= d
->d_reclen
;
250 nacl_offset
+= nacl_d
->nacl_abi_d_reclen
;
253 *nread
= nacl_offset
;
257 int WRAP(mkdir
)(const char* pathname
, mode_t mode
) {
258 RTN_ERRNO_IF(ki_mkdir(pathname
, mode
) < 0);
262 int WRAP(mmap
)(void** addr
,
268 if (flags
& MAP_ANONYMOUS
)
269 return REAL(mmap
)(addr
, length
, prot
, flags
, fd
, offset
);
271 *addr
= ki_mmap(*addr
, length
, prot
, flags
, fd
, offset
);
272 RTN_ERRNO_IF(*addr
== (void*)-1);
276 int WRAP(munmap
)(void* addr
, size_t length
) {
277 // Always let the real munmap run on the address range. It is not an error if
278 // there are no mapped pages in that range.
279 ki_munmap(addr
, length
);
280 return REAL(munmap
)(addr
, length
);
283 int WRAP(open
)(const char* pathname
, int oflag
, mode_t mode
, int* newfd
) {
284 *newfd
= ki_open(pathname
, oflag
, mode
);
285 RTN_ERRNO_IF(*newfd
< 0);
289 int WRAP(open_resource
)(const char* file
, int* fd
) {
290 *fd
= ki_open_resource(file
);
291 RTN_ERRNO_IF(*fd
< 0);
295 int WRAP(poll
)(struct pollfd
* fds
, nfds_t nfds
, int timeout
, int* count
) {
296 *count
= ki_poll(fds
, nfds
, timeout
);
297 RTN_ERRNO_IF(*count
< 0);
301 int WRAP(read
)(int fd
, void* buf
, size_t count
, size_t* nread
) {
302 ssize_t signed_nread
= ki_read(fd
, buf
, count
);
303 *nread
= static_cast<size_t>(signed_nread
);
304 RTN_ERRNO_IF(signed_nread
< 0);
308 int WRAP(rmdir
)(const char* pathname
) {
309 RTN_ERRNO_IF(ki_rmdir(pathname
) < 0);
313 int WRAP(seek
)(int fd
, off_t offset
, int whence
, off_t
* new_offset
) {
314 *new_offset
= ki_lseek(fd
, offset
, whence
);
315 RTN_ERRNO_IF(*new_offset
< 0);
319 int WRAP(select
)(int nfds
,
323 struct timeval
* timeout
,
325 *count
= ki_select(nfds
, readfds
, writefds
, exceptfds
, timeout
);
326 RTN_ERRNO_IF(*count
< 0);
330 int WRAP(stat
)(const char* pathname
, struct nacl_abi_stat
* nacl_buf
) {
332 memset(&buf
, 0, sizeof(struct stat
));
333 int res
= ki_stat(pathname
, &buf
);
334 RTN_ERRNO_IF(res
< 0);
335 stat_to_nacl_stat(&buf
, nacl_buf
);
339 int WRAP(lstat
)(const char* pathname
, struct nacl_abi_stat
* nacl_buf
) {
341 memset(&buf
, 0, sizeof(struct stat
));
342 int res
= ki_lstat(pathname
, &buf
);
343 RTN_ERRNO_IF(res
< 0);
344 stat_to_nacl_stat(&buf
, nacl_buf
);
348 int WRAP(link
)(const char* pathname
, const char* newpath
) {
349 ERRNO_RTN(ki_link(pathname
, newpath
));
352 int WRAP(rename
)(const char* pathname
, const char* newpath
) {
353 ERRNO_RTN(ki_rename(pathname
, newpath
));
356 int WRAP(readlink
)(const char* pathname
,
360 int rtn
= ki_readlink(pathname
, buf
, count
);
361 RTN_ERRNO_IF(rtn
< 0);
366 int WRAP(utimes
)(const char *filename
, const struct timeval
*times
) {
367 ERRNO_RTN(ki_utimes(filename
, times
));
370 int WRAP(chmod
)(const char* pathname
, mode_t mode
) {
371 ERRNO_RTN(ki_chmod(pathname
, mode
));
374 int WRAP(access
)(const char* pathname
, int amode
) {
375 ERRNO_RTN(ki_access(pathname
, amode
));
378 int WRAP(unlink
)(const char* pathname
) {
379 ERRNO_RTN(ki_unlink(pathname
));
382 int WRAP(fchdir
)(int fd
) {
383 ERRNO_RTN(ki_fchdir(fd
));
386 int WRAP(fchmod
)(int fd
, mode_t mode
) {
387 ERRNO_RTN(ki_fchmod(fd
, mode
));
390 int WRAP(fsync
)(int fd
) {
391 ERRNO_RTN(ki_fsync(fd
));
394 int WRAP(fdatasync
)(int fd
) {
395 ERRNO_RTN(ki_fdatasync(fd
));
398 int WRAP(write
)(int fd
, const void* buf
, size_t count
, size_t* nwrote
) {
399 ssize_t signed_nwrote
= ki_write(fd
, buf
, count
);
400 *nwrote
= static_cast<size_t>(signed_nwrote
);
401 RTN_ERRNO_IF(signed_nwrote
< 0);
405 int WRAP(accept
)(int sockfd
,
406 struct sockaddr
* addr
,
409 *sd
= ki_accept(sockfd
, addr
, addrlen
);
410 RTN_ERRNO_IF(*sd
< 0);
414 int WRAP(bind
)(int sockfd
, const struct sockaddr
* addr
, socklen_t addrlen
) {
415 ERRNO_RTN(ki_bind(sockfd
, addr
, addrlen
));
418 int WRAP(connect
)(int sockfd
, const struct sockaddr
* addr
, socklen_t addrlen
) {
419 ERRNO_RTN(ki_connect(sockfd
, addr
, addrlen
));
422 int WRAP(getpeername
)(int sockfd
, struct sockaddr
* addr
, socklen_t
* addrlen
) {
423 ERRNO_RTN(ki_getpeername(sockfd
, addr
, addrlen
));
426 int WRAP(getsockname
)(int sockfd
, struct sockaddr
* addr
, socklen_t
* addrlen
) {
427 ERRNO_RTN(ki_getsockname(sockfd
, addr
, addrlen
));
430 int WRAP(getsockopt
)(int sockfd
,
435 ERRNO_RTN(ki_getsockopt(sockfd
, level
, optname
, optval
, optlen
));
438 int WRAP(setsockopt
)(int sockfd
,
443 ERRNO_RTN(ki_setsockopt(sockfd
, level
, optname
, optval
, optlen
));
446 int WRAP(listen
)(int sockfd
, int backlog
) {
447 ERRNO_RTN(ki_listen(sockfd
, backlog
));
450 int WRAP(recv
)(int sockfd
, void* buf
, size_t len
, int flags
, int* count
) {
451 ssize_t signed_nread
= ki_recv(sockfd
, buf
, len
, flags
);
452 *count
= static_cast<int>(signed_nread
);
453 RTN_ERRNO_IF(signed_nread
< 0);
457 int WRAP(recvfrom
)(int sockfd
,
461 struct sockaddr
* addr
,
464 ssize_t signed_nread
= ki_recvfrom(sockfd
, buf
, len
, flags
, addr
, addrlen
);
465 *count
= static_cast<int>(signed_nread
);
466 RTN_ERRNO_IF(signed_nread
< 0);
470 int WRAP(recvmsg
)(int sockfd
, struct msghdr
* msg
, int flags
, int* count
) {
471 ssize_t signed_nread
= ki_recvmsg(sockfd
, msg
, flags
);
472 *count
= static_cast<int>(signed_nread
);
473 RTN_ERRNO_IF(signed_nread
< 0);
477 ssize_t
WRAP(send
)(int sockfd
, const void* buf
, size_t len
, int flags
,
479 ssize_t signed_nread
= ki_send(sockfd
, buf
, len
, flags
);
480 *count
= static_cast<int>(signed_nread
);
481 RTN_ERRNO_IF(signed_nread
< 0);
485 ssize_t
WRAP(sendto
)(int sockfd
,
489 const struct sockaddr
* addr
,
492 ssize_t signed_nread
= ki_sendto(sockfd
, buf
, len
, flags
, addr
, addrlen
);
493 *count
= static_cast<int>(signed_nread
);
494 RTN_ERRNO_IF(signed_nread
< 0);
498 ssize_t
WRAP(sendmsg
)(int sockfd
,
499 const struct msghdr
* msg
,
502 ssize_t signed_nread
= ki_sendmsg(sockfd
, msg
, flags
);
503 *count
= static_cast<int>(signed_nread
);
504 RTN_ERRNO_IF(signed_nread
< 0);
508 int WRAP(shutdown
)(int sockfd
, int how
) {
509 RTN_ERRNO_IF(ki_shutdown(sockfd
, how
) < 0);
513 int WRAP(socket
)(int domain
, int type
, int protocol
, int* sd
) {
514 *sd
= ki_socket(domain
, type
, protocol
);
515 RTN_ERRNO_IF(*sd
< 0);
519 int WRAP(socketpair
)(int domain
, int type
, int protocol
, int* sv
) {
520 RTN_ERRNO_IF(ki_socketpair(domain
, type
, protocol
, sv
) < 0);
524 static void assign_real_pointers() {
525 static bool assigned
= false;
527 EXPAND_SYMBOL_LIST_OPERATION(ASSIGN_REAL_PTR
)
532 #define CHECK_REAL(func) \
534 assign_real_pointers(); \
539 // "real" functions, i.e. the unwrapped original functions.
541 int _real_close(int fd
) {
543 return REAL(close
)(fd
);
546 void _real_exit(int status
) {
548 assign_real_pointers();
552 int _real_fstat(int fd
, struct stat
* buf
) {
553 struct nacl_abi_stat st
;
555 int err
= REAL(fstat
)(fd
, &st
);
561 nacl_stat_to_stat(&st
, buf
);
565 int _real_getdents(int fd
, void* buf
, size_t count
, size_t* nread
) {
566 // "buf" contains dirent(s); "nacl_buf" contains nacl_abi_dirent(s).
567 // See WRAP(getdents) above.
568 char* nacl_buf
= (char*)alloca(count
);
570 size_t nacl_offset
= 0;
572 CHECK_REAL(getdents
);
573 int err
= REAL(getdents
)(fd
, (dirent
*)nacl_buf
, count
, &nacl_nread
);
577 while (nacl_offset
< nacl_nread
) {
578 dirent
* d
= (dirent
*)((char*)buf
+ offset
);
579 nacl_abi_dirent
* nacl_d
= (nacl_abi_dirent
*)(nacl_buf
+ nacl_offset
);
580 d
->d_ino
= nacl_d
->nacl_abi_d_ino
;
581 d
->d_off
= nacl_d
->nacl_abi_d_off
;
582 d
->d_reclen
= nacl_d
->nacl_abi_d_reclen
+ d_name_shift
;
584 nacl_d
->nacl_abi_d_reclen
- offsetof(nacl_abi_dirent
, nacl_abi_d_name
);
585 memcpy(d
->d_name
, nacl_d
->nacl_abi_d_name
, d_name_len
);
587 offset
+= d
->d_reclen
;
588 offset
+= nacl_d
->nacl_abi_d_reclen
;
595 int _real_lseek(int fd
, off_t offset
, int whence
, off_t
* new_offset
) {
597 return REAL(seek
)(fd
, offset
, whence
, new_offset
);
600 int _real_mkdir(const char* pathname
, mode_t mode
) {
602 return REAL(mkdir
)(pathname
, mode
);
605 int _real_mmap(void** addr
,
612 return REAL(mmap
)(addr
, length
, prot
, flags
, fd
, offset
);
615 int _real_munmap(void* addr
, size_t length
) {
617 return REAL(munmap
)(addr
, length
);
620 int _real_open(const char* pathname
, int oflag
, mode_t mode
, int* newfd
) {
622 return REAL(open
)(pathname
, oflag
, mode
, newfd
);
625 int _real_open_resource(const char* file
, int* fd
) {
626 CHECK_REAL(open_resource
);
627 return REAL(open_resource
)(file
, fd
);
630 int _real_read(int fd
, void* buf
, size_t count
, size_t* nread
) {
632 return REAL(read
)(fd
, buf
, count
, nread
);
635 int _real_rmdir(const char* pathname
) {
637 return REAL(rmdir
)(pathname
);
640 int _real_write(int fd
, const void* buf
, size_t count
, size_t* nwrote
) {
642 return REAL(write
)(fd
, buf
, count
, nwrote
);
645 int _real_getcwd(char* pathname
, size_t len
) {
647 return REAL(getcwd
)(pathname
, len
);
650 static bool s_wrapped
= false;
651 void kernel_wrap_init() {
653 LOG_TRACE("kernel_wrap_init");
654 assign_real_pointers();
655 EXPAND_SYMBOL_LIST_OPERATION(USE_WRAP
)
660 void kernel_wrap_uninit() {
662 LOG_TRACE("kernel_wrap_uninit");
663 EXPAND_SYMBOL_LIST_OPERATION(USE_REAL
)
670 #endif // defined(__native_client__) && defined(__GLIBC__)