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