blob: 7c52f4daaf90d6047ebff77adf1df53b9efeb843 [file] [log] [blame]
Ben Murdochca12bfa2013-07-23 11:17:05 +01001// 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.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004
5#include <sys/types.h> // Include something that will define __GLIBC__.
6
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__)
10
11#include "nacl_io/kernel_wrap.h"
Ben Murdoch58e6fbe2013-07-26 10:20:38 +010012
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000013#include <alloca.h>
14#include <dirent.h>
15#include <errno.h>
16#include <irt.h>
17#include <irt_syscalls.h>
18#include <nacl_stat.h>
19#include <string.h>
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000020#include <sys/stat.h>
Ben Murdochca12bfa2013-07-23 11:17:05 +010021#include <sys/time.h>
Ben Murdoch58e6fbe2013-07-26 10:20:38 +010022
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000023#include "nacl_io/kernel_intercept.h"
Ben Murdoch58e6fbe2013-07-26 10:20:38 +010024#include "nacl_io/osmman.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000025
26
27namespace {
28
29void stat_to_nacl_stat(const struct stat* buf, nacl_abi_stat* nacl_buf) {
30 memset(nacl_buf, 0, sizeof(struct nacl_abi_stat));
31 nacl_buf->nacl_abi_st_dev = buf->st_dev;
32 nacl_buf->nacl_abi_st_ino = buf->st_ino;
33 nacl_buf->nacl_abi_st_mode = buf->st_mode;
34 nacl_buf->nacl_abi_st_nlink = buf->st_nlink;
35 nacl_buf->nacl_abi_st_uid = buf->st_uid;
36 nacl_buf->nacl_abi_st_gid = buf->st_gid;
37 nacl_buf->nacl_abi_st_rdev = buf->st_rdev;
38 nacl_buf->nacl_abi_st_size = buf->st_size;
39 nacl_buf->nacl_abi_st_blksize = buf->st_blksize;
40 nacl_buf->nacl_abi_st_blocks = buf->st_blocks;
41 nacl_buf->nacl_abi_st_atime = buf->st_atime;
42 nacl_buf->nacl_abi_st_mtime = buf->st_mtime;
43 nacl_buf->nacl_abi_st_ctime = buf->st_ctime;
44}
45
46void nacl_stat_to_stat(const nacl_abi_stat* nacl_buf, struct stat* buf) {
47 memset(buf, 0, sizeof(struct stat));
48 buf->st_dev = nacl_buf->nacl_abi_st_dev;
49 buf->st_ino = nacl_buf->nacl_abi_st_ino;
50 buf->st_mode = nacl_buf->nacl_abi_st_mode;
51 buf->st_nlink = nacl_buf->nacl_abi_st_nlink;
52 buf->st_uid = nacl_buf->nacl_abi_st_uid;
53 buf->st_gid = nacl_buf->nacl_abi_st_gid;
54 buf->st_rdev = nacl_buf->nacl_abi_st_rdev;
55 buf->st_size = nacl_buf->nacl_abi_st_size ;
56 buf->st_blksize = nacl_buf->nacl_abi_st_blksize;
57 buf->st_blocks = nacl_buf->nacl_abi_st_blocks;
58 buf->st_atime = nacl_buf->nacl_abi_st_atime;
59 buf->st_mtime = nacl_buf->nacl_abi_st_mtime;
60 buf->st_ctime = nacl_buf->nacl_abi_st_ctime;
61}
62
63} // namespace
64
65// From native_client/src/trusted/service_runtime/include/sys/dirent.h
66
67#ifndef nacl_abi___ino_t_defined
68#define nacl_abi___ino_t_defined
69typedef int64_t nacl_abi___ino_t;
70typedef nacl_abi___ino_t nacl_abi_ino_t;
71#endif
72
73#ifndef nacl_abi___off_t_defined
74#define nacl_abi___off_t_defined
75typedef int64_t nacl_abi__off_t;
76typedef nacl_abi__off_t nacl_abi_off_t;
77#endif
78
79/* We need a way to define the maximum size of a name. */
80#ifndef MAXNAMLEN
81# ifdef NAME_MAX
82# define MAXNAMLEN NAME_MAX
83# else
84# define MAXNAMLEN 255
85# endif
86#endif
87
88struct nacl_abi_dirent {
89 nacl_abi_ino_t nacl_abi_d_ino;
90 nacl_abi_off_t nacl_abi_d_off;
91 uint16_t nacl_abi_d_reclen;
92 char nacl_abi_d_name[MAXNAMLEN + 1];
93};
94
95static const int d_name_shift = offsetof (dirent, d_name) -
96 offsetof (struct nacl_abi_dirent, nacl_abi_d_name);
97
98EXTERN_C_BEGIN
99
Ben Murdoch58e6fbe2013-07-26 10:20:38 +0100100// Macro to get the REAL function pointer
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000101#define REAL(name) __nacl_irt_##name##_real
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000102
Ben Murdoch58e6fbe2013-07-26 10:20:38 +0100103// Macro to get the WRAP function
104#define WRAP(name) __nacl_irt_##name##_wrap
105
106// Declare REAL function pointer and assign it the REAL function.
107#define DECLARE_REAL_PTR(name) \
108 typeof(__nacl_irt_##name) REAL(name) = __nacl_irt_##name;
109
110// Switch IRT's pointer to the REAL pointer
111#define USE_REAL(name) \
112 __nacl_irt_##name = (typeof(__nacl_irt_##name)) REAL(name)
113
114// Switch IRT's pointer to the WRAP function
115#define USE_WRAP(name) \
116 __nacl_irt_##name = (typeof(__nacl_irt_##name)) WRAP(name)
117
118
119#define EXPAND_SYMBOL_LIST_OPERATION(OP) \
120 OP(chdir); \
121 OP(close); \
122 OP(dup); \
123 OP(dup2); \
124 OP(fstat); \
125 OP(getcwd); \
126 OP(getdents); \
127 OP(mkdir); \
128 OP(open); \
Ben Murdoch32409262013-08-07 11:04:47 +0100129 OP(poll);\
Ben Murdoch58e6fbe2013-07-26 10:20:38 +0100130 OP(read); \
131 OP(rmdir); \
132 OP(seek); \
133 OP(stat); \
Ben Murdoch32409262013-08-07 11:04:47 +0100134 OP(select); \
Ben Murdoch58e6fbe2013-07-26 10:20:38 +0100135 OP(write); \
136 OP(mmap); \
137 OP(munmap); \
138 OP(open_resource);
139
140EXPAND_SYMBOL_LIST_OPERATION(DECLARE_REAL_PTR);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000141
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000142int WRAP(chdir) (const char* pathname) {
143 return (ki_chdir(pathname)) ? errno : 0;
144}
145
146int WRAP(close)(int fd) {
147 return (ki_close(fd) < 0) ? errno : 0;
148}
149
150int WRAP(dup)(int fd, int* newfd) NOTHROW {
151 *newfd = ki_dup(fd);
152 return (*newfd < 0) ? errno : 0;
153}
154
155int WRAP(dup2)(int fd, int newfd) NOTHROW {
156 return (ki_dup2(fd, newfd) < 0) ? errno : 0;
157}
158
159int WRAP(fstat)(int fd, struct nacl_abi_stat *nacl_buf) {
160 struct stat buf;
161 memset(&buf, 0, sizeof(struct stat));
162 int res = ki_fstat(fd, &buf);
163 if (res < 0)
164 return errno;
165 stat_to_nacl_stat(&buf, nacl_buf);
166 return 0;
167}
168
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000169char* WRAP(getcwd)(char* buf, size_t size) {
170 return ki_getcwd(buf, size);
171}
172
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000173int WRAP(getdents)(int fd, dirent* nacl_buf, size_t nacl_count, size_t *nread) {
174 int nacl_offset = 0;
175 // "buf" contains dirent(s); "nacl_buf" contains nacl_abi_dirent(s).
176 // nacl_abi_dirent(s) are smaller than dirent(s), so nacl_count bytes buffer
177 // is enough
178 char* buf = (char*)alloca(nacl_count);
179 int offset = 0;
180 int count;
181
182 count = ki_getdents(fd, buf, nacl_count);
183 if (count < 0)
184 return errno;
185
186 while (offset < count) {
187 dirent* d = (dirent*)(buf + offset);
188 nacl_abi_dirent* nacl_d = (nacl_abi_dirent*)((char*)nacl_buf + nacl_offset);
189 nacl_d->nacl_abi_d_ino = d->d_ino;
190 nacl_d->nacl_abi_d_off = d->d_off;
191 nacl_d->nacl_abi_d_reclen = d->d_reclen - d_name_shift;
192 size_t d_name_len = d->d_reclen - offsetof(dirent, d_name);
193 memcpy(nacl_d->nacl_abi_d_name, d->d_name, d_name_len);
194
195 offset += d->d_reclen;
196 nacl_offset += nacl_d->nacl_abi_d_reclen;
197 }
198
199 *nread = nacl_offset;
200 return 0;
201}
202
Ben Murdoch2385ea32013-08-06 11:01:04 +0100203int WRAP(mkdir)(const char* pathname, mode_t mode) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000204 return (ki_mkdir(pathname, mode)) ? errno : 0;
205}
206
207int WRAP(mmap)(void** addr, size_t length, int prot, int flags, int fd,
208 off_t offset) {
209 if (flags & MAP_ANONYMOUS)
210 return REAL(mmap)(addr, length, prot, flags, fd, offset);
211
212 *addr = ki_mmap(*addr, length, prot, flags, fd, offset);
213 return *addr == (void*)-1 ? errno : 0;
214}
215
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000216int WRAP(munmap)(void* addr, size_t length) {
217 // Always let the real munmap run on the address range. It is not an error if
218 // there are no mapped pages in that range.
Ben Murdochca12bfa2013-07-23 11:17:05 +0100219 ki_munmap(addr, length);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000220 return REAL(munmap)(addr, length);
221}
222
223int WRAP(open)(const char* pathname, int oflag, mode_t cmode, int* newfd) {
224 *newfd = ki_open(pathname, oflag);
225 return (*newfd < 0) ? errno : 0;
226}
227
228int WRAP(open_resource)(const char* file, int* fd) {
229 *fd = ki_open_resource(file);
230 return (*fd < 0) ? errno : 0;
231}
232
Ben Murdoch32409262013-08-07 11:04:47 +0100233int WRAP(poll)(struct pollfd *fds, nfds_t nfds, int timeout, int* count) {
234 *count = ki_poll(fds, nfds, timeout);
235 return (*count < 0) ? errno : 0;
236
237}
238
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000239int WRAP(read)(int fd, void *buf, size_t count, size_t *nread) {
240 if (!ki_is_initialized())
241 return REAL(read)(fd, buf, count, nread);
242
243 ssize_t signed_nread = ki_read(fd, buf, count);
244 *nread = static_cast<size_t>(signed_nread);
245 return (signed_nread < 0) ? errno : 0;
246}
247
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000248int WRAP(rmdir)(const char* pathname) {
249 return (ki_rmdir(pathname) < 0) ? errno : 0;
250}
251
252int WRAP(seek)(int fd, off_t offset, int whence, off_t* new_offset) {
253 *new_offset = ki_lseek(fd, offset, whence);
254 return (*new_offset < 0) ? errno : 0;
255}
256
Ben Murdoch32409262013-08-07 11:04:47 +0100257int WRAP(select)(int nfds, fd_set* readfds, fd_set* writefds,
258 fd_set* exceptfds, struct timeval* timeout, int* count) {
259 *count = ki_select(nfds, readfds, writefds, exceptfds, timeout);
260 return (*count < 0) ? errno : 0;
261}
262
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000263int WRAP(stat)(const char *pathname, struct nacl_abi_stat *nacl_buf) {
264 struct stat buf;
265 memset(&buf, 0, sizeof(struct stat));
266 int res = ki_stat(pathname, &buf);
267 if (res < 0)
268 return errno;
269 stat_to_nacl_stat(&buf, nacl_buf);
270 return 0;
271}
272
Ben Murdocheb525c52013-07-10 11:40:50 +0100273int WRAP(write)(int fd, const void* buf, size_t count, size_t* nwrote) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000274 if (!ki_is_initialized())
275 return REAL(write)(fd, buf, count, nwrote);
276
277 ssize_t signed_nwrote = ki_write(fd, buf, count);
278 *nwrote = static_cast<size_t>(signed_nwrote);
279 return (signed_nwrote < 0) ? errno : 0;
280}
281
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100282// Socket functions
283int accept(int fd, struct sockaddr* addr, socklen_t* len) {
284 return ki_accept(fd, addr, len);
285}
286
287int bind(int fd, const struct sockaddr* addr, socklen_t len) {
288 return ki_bind(fd, addr, len);
289}
290
291int connect(int fd, const struct sockaddr* addr, socklen_t len) {
292 return ki_connect(fd, addr, len);
293}
294
Ben Murdochbb1529c2013-08-08 10:24:53 +0100295struct hostent* gethostbyname(const char* name) {
296 return ki_gethostbyname(name);
297}
298
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100299int getpeername(int fd, struct sockaddr* addr, socklen_t* len) {
300 return ki_getpeername(fd, addr, len);
301}
302
303int getsockname(int fd, struct sockaddr* addr, socklen_t* len) {
304 return ki_getsockname(fd, addr, len);
305}
Ben Murdochbb1529c2013-08-08 10:24:53 +0100306
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100307int getsockopt(int fd, int lvl, int optname, void* optval, socklen_t* len) {
308 return ki_getsockopt(fd, lvl, optname, optval, len);
309}
310
Ben Murdochbb1529c2013-08-08 10:24:53 +0100311void herror(const char *s) {
312 return ki_herror(s);
313}
314
315const char *hstrerror(int err) {
316 return ki_hstrerror(err);
317}
318
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100319int listen(int fd, int backlog) {
320 return ki_listen(fd, backlog);
321}
322
323ssize_t recv(int fd, void* buf, size_t len, int flags) {
324 return ki_recv(fd, buf, len, flags);
325}
326
327ssize_t recvfrom(int fd, void* buf, size_t len, int flags,
328 struct sockaddr* addr, socklen_t* addrlen) {
329 return ki_recvfrom(fd, buf, len, flags, addr, addrlen);
330}
331
332ssize_t recvmsg(int fd, struct msghdr* msg, int flags) {
333 return ki_recvmsg(fd, msg, flags);
334}
335
336ssize_t send(int fd, const void* buf, size_t len, int flags) {
337 return ki_send(fd, buf, len, flags);
338}
339
340ssize_t sendto(int fd, const void* buf, size_t len, int flags,
341 const struct sockaddr* addr, socklen_t addrlen) {
342 return ki_sendto(fd, buf, len, flags, addr, addrlen);
343}
344
345ssize_t sendmsg(int fd, const struct msghdr* msg, int flags) {
346 return ki_sendmsg(fd, msg, flags);
347}
348
349int setsockopt(int fd, int lvl, int optname, const void* optval,
350 socklen_t len) {
351 return ki_setsockopt(fd, lvl, optname, optval, len);
352}
353
354int shutdown(int fd, int how) {
355 return ki_shutdown(fd, how);
356}
357
358int socket(int domain, int type, int protocol) {
359 return ki_socket(domain, type, protocol);
360}
361
362int socketpair(int domain, int type, int protocol, int* sv) {
363 return ki_socketpair(domain, type, protocol, sv);
364}
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000365
366// "real" functions, i.e. the unwrapped original functions.
367
368int _real_close(int fd) {
369 return REAL(close)(fd);
370}
371
Ben Murdocheb525c52013-07-10 11:40:50 +0100372int _real_fstat(int fd, struct stat* buf) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000373 struct nacl_abi_stat st;
374 int err = REAL(fstat)(fd, &st);
375 if (err) {
376 errno = err;
377 return -1;
378 }
379
380 nacl_stat_to_stat(&st, buf);
381 return 0;
382}
383
Ben Murdocheb525c52013-07-10 11:40:50 +0100384int _real_getdents(int fd, void* buf, size_t count, size_t* nread) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000385 // "buf" contains dirent(s); "nacl_buf" contains nacl_abi_dirent(s).
386 // See WRAP(getdents) above.
387 char* nacl_buf = (char*)alloca(count);
388 size_t offset = 0;
389 size_t nacl_offset = 0;
390 size_t nacl_nread;
391 int err = REAL(getdents)(fd, (dirent*)nacl_buf, count, &nacl_nread);
392 if (err)
393 return err;
394
395 while (nacl_offset < nacl_nread) {
396 dirent* d = (dirent*)((char*)buf + offset);
397 nacl_abi_dirent* nacl_d = (nacl_abi_dirent*)(nacl_buf + nacl_offset);
398 d->d_ino = nacl_d->nacl_abi_d_ino;
399 d->d_off = nacl_d->nacl_abi_d_off;
400 d->d_reclen = nacl_d->nacl_abi_d_reclen + d_name_shift;
401 size_t d_name_len = nacl_d->nacl_abi_d_reclen -
402 offsetof(nacl_abi_dirent, nacl_abi_d_name);
403 memcpy(d->d_name, nacl_d->nacl_abi_d_name, d_name_len);
404
405 offset += d->d_reclen;
406 offset += nacl_d->nacl_abi_d_reclen;
407 }
408
409 *nread = offset;
410 return 0;
411}
412
413int _real_lseek(int fd, off_t offset, int whence, off_t* new_offset) {
414 return REAL(seek)(fd, offset, whence, new_offset);
415}
416
417int _real_mkdir(const char* pathname, mode_t mode) {
418 return REAL(mkdir)(pathname, mode);
419}
420
421int _real_mmap(void** addr, size_t length, int prot, int flags, int fd,
422 off_t offset) {
423 return REAL(mmap)(addr, length, prot, flags, fd, offset);
424}
425
426int _real_munmap(void* addr, size_t length) {
427 return REAL(munmap)(addr, length);
428}
429
430int _real_open(const char* pathname, int oflag, mode_t cmode, int* newfd) {
431 return REAL(open)(pathname, oflag, cmode, newfd);
432}
433
434int _real_open_resource(const char* file, int* fd) {
435 return REAL(open_resource)(file, fd);
436}
437
438int _real_read(int fd, void *buf, size_t count, size_t *nread) {
439 return REAL(read)(fd, buf, count, nread);
440}
441
442int _real_rmdir(const char* pathname) {
443 return REAL(rmdir)(pathname);
444}
445
446int _real_write(int fd, const void *buf, size_t count, size_t *nwrote) {
447 return REAL(write)(fd, buf, count, nwrote);
448}
449
Ben Murdochca12bfa2013-07-23 11:17:05 +0100450uint64_t usec_since_epoch() {
451 struct timeval tv;
452 gettimeofday(&tv, NULL);
453 return tv.tv_usec + (tv.tv_sec * 1000000);
454}
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000455
Ben Murdoch58e6fbe2013-07-26 10:20:38 +0100456static bool s_wrapped = false;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000457void kernel_wrap_init() {
Ben Murdoch58e6fbe2013-07-26 10:20:38 +0100458 if (!s_wrapped) {
459 EXPAND_SYMBOL_LIST_OPERATION(USE_WRAP)
460 s_wrapped = true;
461 }
462}
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000463
Ben Murdoch58e6fbe2013-07-26 10:20:38 +0100464void kernel_wrap_uninit() {
465 if (s_wrapped) {
466 EXPAND_SYMBOL_LIST_OPERATION(USE_REAL)
467 s_wrapped = false;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000468 }
469}
470
471EXTERN_C_END
472
473
474#endif // defined(__native_client__) && defined(__GLIBC__)
Ben Murdocheb525c52013-07-10 11:40:50 +0100475