OLD | NEW |
| (Empty) |
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. */ | |
4 | |
5 /* NACL_IO_IRT_EXT is defined in this header */ | |
6 #include "nacl_io/kernel_wrap.h" | |
7 | |
8 /* | |
9 * The entire file is wrapped in this #if. We do this so this .c file can | |
10 * always be compiled. | |
11 */ | |
12 #if defined(NACL_IO_IRT_EXT) | |
13 | |
14 #include <assert.h> | |
15 #include <errno.h> | |
16 #include <irt.h> | |
17 #include <irt_dev.h> | |
18 #include <irt_extension.h> | |
19 #include <stdbool.h> | |
20 #include <string.h> | |
21 #include <sys/mman.h> | |
22 | |
23 #include "nacl_io/kernel_intercept.h" | |
24 #include "nacl_io/log.h" | |
25 | |
26 /* | |
27 * The following macros are used to interfact with IRT interfaces. | |
28 */ | |
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; \ | |
33 bool queried; \ | |
34 bool initialized; \ | |
35 struct interface_type interface; \ | |
36 } | |
37 | |
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)); \ | |
48 } | |
49 | |
50 /* This macro initializes an interface and does not handle errors. */ | |
51 #define INIT_INTERFACE(interface_struct) \ | |
52 do { \ | |
53 INIT_INTERFACE_BARE(interface_struct); \ | |
54 } while (false) | |
55 | |
56 /* This macro initializes an interface and returns ENOSYS on failure. */ | |
57 #define INIT_INTERFACE_ENOSYS(interface_struct) \ | |
58 do { \ | |
59 INIT_INTERFACE_BARE(interface_struct); \ | |
60 if (!interface_struct.initialized) \ | |
61 return ENOSYS; \ | |
62 } while (false) | |
63 | |
64 /* This macro initializes an interface and asserts on failure. */ | |
65 #define INIT_INTERFACE_ASSERT(interface_struct) \ | |
66 do { \ | |
67 INIT_INTERFACE_BARE(interface_struct); \ | |
68 assert(interface_struct.initialized); \ | |
69 } while (false) | |
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 NACL_IRT_BASIC_v0_1, | |
86 }; | |
87 | |
88 static NACL_IRT_INTERFACE(nacl_irt_fdio) s_irt_fdio = { | |
89 NACL_IRT_FDIO_v0_1, | |
90 }; | |
91 | |
92 static NACL_IRT_INTERFACE(nacl_irt_memory) s_irt_memory = { | |
93 NACL_IRT_MEMORY_v0_3, | |
94 }; | |
95 | |
96 static NACL_IRT_INTERFACE(nacl_irt_resource_open) s_irt_resource_open = { | |
97 NACL_IRT_RESOURCE_OPEN_v0_1, | |
98 }; | |
99 | |
100 /* | |
101 * IRT Dev interfaces as declared in irt_dev.h. | |
102 */ | |
103 static NACL_IRT_INTERFACE(nacl_irt_dev_fdio) s_irt_dev_fdio = { | |
104 NACL_IRT_DEV_FDIO_v0_3, | |
105 }; | |
106 | |
107 static NACL_IRT_INTERFACE(nacl_irt_dev_filename) s_irt_dev_filename = { | |
108 NACL_IRT_DEV_FILENAME_v0_3, | |
109 }; | |
110 | |
111 static bool s_wrapped = false; | |
112 | |
113 /* | |
114 * Functions for the nacl_irt_dev_fdio interface. | |
115 */ | |
116 static int ext_close(int fd) { | |
117 ERRNO_RTN(ki_close(fd)); | |
118 } | |
119 | |
120 static int ext_dup(int fd, int *newfd) { | |
121 *newfd = ki_dup(fd); | |
122 ERRNO_RTN(*newfd); | |
123 } | |
124 | |
125 static int ext_dup2(int fd, int newfd) { | |
126 newfd = ki_dup2(fd, newfd); | |
127 ERRNO_RTN(newfd); | |
128 } | |
129 | |
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); | |
134 } | |
135 | |
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); | |
140 } | |
141 | |
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); | |
146 } | |
147 | |
148 static int ext_fstat(int fd, struct stat *buf) { | |
149 ERRNO_RTN(ki_fstat(fd, buf)); | |
150 } | |
151 | |
152 static int ext_getdents(int fd, struct dirent *ents, size_t count, | |
153 size_t *nread) { | |
154 int rtn = ki_getdents(fd, ents, count); | |
155 RTN_ERRNO_IF(rtn < 0); | |
156 *nread = rtn; | |
157 return 0; | |
158 } | |
159 | |
160 /* | |
161 * Functions for the nacl_irt_memory interface. | |
162 */ | |
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); | |
167 | |
168 *addr = ki_mmap(*addr, len, prot, flags, fd, off); | |
169 RTN_ERRNO_IF(*addr == (void*)-1); | |
170 return 0; | |
171 } | |
172 | |
173 static int ext_munmap(void *addr, size_t length) { | |
174 /* | |
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. | |
177 */ | |
178 ki_munmap(addr, length); | |
179 return s_irt_memory.interface.munmap(addr, length); | |
180 } | |
181 | |
182 /* | |
183 * Extra functions for the nacl_irt_dev_fdio interface. | |
184 */ | |
185 static int ext_fchdir(int fd) { | |
186 ERRNO_RTN(ki_fchdir(fd)); | |
187 } | |
188 | |
189 static int ext_fchmod(int fd, mode_t mode) { | |
190 ERRNO_RTN(ki_fchmod(fd, mode)); | |
191 } | |
192 | |
193 static int ext_fsync(int fd) { | |
194 ERRNO_RTN(ki_fsync(fd)); | |
195 } | |
196 | |
197 static int ext_fdatasync(int fd) { | |
198 ERRNO_RTN(ki_fdatasync(fd)); | |
199 } | |
200 | |
201 static int ext_ftruncate(int fd, nacl_irt_off_t length) { | |
202 ERRNO_RTN(ki_ftruncate(fd, length)); | |
203 } | |
204 | |
205 static int ext_isatty(int fd, int *result) { | |
206 *result = ki_isatty(fd); | |
207 RTN_ERRNO_IF(*result == 0); | |
208 return 0; | |
209 } | |
210 | |
211 /* | |
212 * Functions for the nacl_irt_dev_filename interface. | |
213 */ | |
214 static int ext_open(const char *pathname, int oflag, mode_t cmode, int *newfd) { | |
215 *newfd = ki_open(pathname, oflag, cmode); | |
216 ERRNO_RTN(*newfd); | |
217 } | |
218 | |
219 static int ext_stat(const char *pathname, struct stat *buf) { | |
220 ERRNO_RTN(ki_stat(pathname, buf)); | |
221 } | |
222 | |
223 static int ext_mkdir(const char *pathname, mode_t mode) { | |
224 ERRNO_RTN(ki_mkdir(pathname, mode)); | |
225 } | |
226 | |
227 static int ext_rmdir(const char *pathname) { | |
228 ERRNO_RTN(ki_rmdir(pathname)); | |
229 } | |
230 | |
231 static int ext_chdir(const char *pathname) { | |
232 ERRNO_RTN(ki_chdir(pathname)); | |
233 } | |
234 | |
235 static int ext_getcwd(char *pathname, size_t len) { | |
236 char *rtn = ki_getcwd(pathname, len); | |
237 RTN_ERRNO_IF(NULL == rtn); | |
238 return 0; | |
239 } | |
240 | |
241 static int ext_unlink(const char *pathname) { | |
242 ERRNO_RTN(ki_unlink(pathname)); | |
243 } | |
244 | |
245 static int ext_truncate(const char *pathname, nacl_irt_off_t length) { | |
246 ERRNO_RTN(ki_truncate(pathname, length)); | |
247 } | |
248 | |
249 static int ext_lstat(const char *pathname, struct stat *buf) { | |
250 ERRNO_RTN(ki_lstat(pathname, buf)); | |
251 } | |
252 | |
253 static int ext_link(const char *pathname, const char *newpath) { | |
254 ERRNO_RTN(ki_link(pathname, newpath)); | |
255 } | |
256 | |
257 static int ext_rename(const char *pathname, const char *newpath) { | |
258 ERRNO_RTN(ki_rename(pathname, newpath)); | |
259 } | |
260 | |
261 static int ext_symlink(const char *pathname, const char *newpath) { | |
262 ERRNO_RTN(ki_symlink(pathname, newpath)); | |
263 } | |
264 | |
265 static int ext_chmod(const char *pathname, mode_t mode) { | |
266 ERRNO_RTN(ki_chmod(pathname, mode)); | |
267 } | |
268 | |
269 static int ext_access(const char *pathname, int amode) { | |
270 ERRNO_RTN(ki_access(pathname, amode)); | |
271 } | |
272 | |
273 static int ext_readlink(const char *pathname, char *buf, size_t count, | |
274 size_t *nread) { | |
275 int rtn = ki_readlink(pathname, buf, count); | |
276 RTN_ERRNO_IF(rtn < 0); | |
277 *nread = rtn; | |
278 return 0; | |
279 } | |
280 | |
281 static int ext_utimes(const char *pathname, const struct timeval *times) { | |
282 ERRNO_RTN(ki_utimes(pathname, times)); | |
283 } | |
284 | |
285 /* | |
286 * Functions declared inside of kernel_wrap_real.h. | |
287 */ | |
288 | |
289 int _real_close(int fd) { | |
290 INIT_INTERFACE_ENOSYS(s_irt_fdio); | |
291 return s_irt_fdio.interface.close(fd); | |
292 } | |
293 | |
294 void _real_exit(int status) { | |
295 INIT_INTERFACE_ASSERT(s_irt_basic); | |
296 return s_irt_basic.interface.exit(status); | |
297 } | |
298 | |
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); | |
302 } | |
303 | |
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, | |
307 nacl_count, nread); | |
308 } | |
309 | |
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); | |
313 } | |
314 | |
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); | |
318 } | |
319 | |
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); | |
323 } | |
324 | |
325 int _real_mmap(void **addr, | |
326 size_t length, | |
327 int prot, | |
328 int flags, | |
329 int fd, | |
330 int64_t offset) { | |
331 INIT_INTERFACE_ENOSYS(s_irt_memory); | |
332 return s_irt_memory.interface.mmap(addr, length, prot, flags, fd, offset); | |
333 } | |
334 | |
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); | |
338 } | |
339 | |
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); | |
343 } | |
344 | |
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); | |
348 } | |
349 | |
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); | |
353 } | |
354 | |
355 int _real_rmdir(const char *pathname) { | |
356 INIT_INTERFACE_ENOSYS(s_irt_dev_filename); | |
357 return s_irt_dev_filename.interface.rmdir(pathname); | |
358 } | |
359 | |
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); | |
363 } | |
364 | |
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); | |
368 } | |
369 | |
370 /* | |
371 * Kernel Wrap init/uninit functions declared in kernel_wrap.h. | |
372 */ | |
373 void kernel_wrap_init() { | |
374 if (!s_wrapped) { | |
375 LOG_TRACE("kernel_wrap_init"); | |
376 | |
377 /* | |
378 * Register interfaces as listed in irt.h. | |
379 */ | |
380 | |
381 /* Register nacl_irt_basic interface. */ | |
382 INIT_INTERFACE_ASSERT(s_irt_basic); | |
383 struct nacl_irt_basic basic_calls = { | |
384 ki_exit, | |
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, | |
390 }; | |
391 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_basic, basic_calls); | |
392 | |
393 /* Register nacl_irt_fdio interface. */ | |
394 INIT_INTERFACE(s_irt_fdio); | |
395 struct nacl_irt_fdio fdio = { | |
396 ext_close, | |
397 ext_dup, | |
398 ext_dup2, | |
399 ext_read, | |
400 ext_write, | |
401 ext_seek, | |
402 ext_fstat, | |
403 ext_getdents, | |
404 }; | |
405 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_fdio, fdio); | |
406 | |
407 /* Register nacl_irt_memory interface. */ | |
408 INIT_INTERFACE_ASSERT(s_irt_memory); | |
409 struct nacl_irt_memory mem = { | |
410 ext_mmap, | |
411 ext_munmap, | |
412 s_irt_memory.interface.mprotect, | |
413 }; | |
414 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_memory, mem); | |
415 | |
416 /* | |
417 * Register interfaces as listed in irt_dev.h. | |
418 */ | |
419 | |
420 /* Register nacl_irt_dev_fdio interface. */ | |
421 INIT_INTERFACE(s_irt_dev_fdio); | |
422 struct nacl_irt_dev_fdio dev_fdio = { | |
423 ext_close, | |
424 ext_dup, | |
425 ext_dup2, | |
426 ext_read, | |
427 ext_write, | |
428 ext_seek, | |
429 ext_fstat, | |
430 ext_getdents, | |
431 ext_fchdir, | |
432 ext_fchmod, | |
433 ext_fsync, | |
434 ext_fdatasync, | |
435 ext_ftruncate, | |
436 ext_isatty, | |
437 }; | |
438 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_dev_fdio, dev_fdio); | |
439 | |
440 /* Register nacl_irt_dev_filename interface. */ | |
441 INIT_INTERFACE(s_irt_dev_filename); | |
442 struct nacl_irt_dev_filename dev_filename = { | |
443 ext_open, | |
444 ext_stat, | |
445 ext_mkdir, | |
446 ext_rmdir, | |
447 ext_chdir, | |
448 ext_getcwd, | |
449 ext_unlink, | |
450 ext_truncate, | |
451 ext_lstat, | |
452 ext_link, | |
453 ext_rename, | |
454 ext_symlink, | |
455 ext_chmod, | |
456 ext_access, | |
457 ext_readlink, | |
458 ext_utimes, | |
459 }; | |
460 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_dev_filename, dev_filename); | |
461 | |
462 s_wrapped = true; | |
463 } | |
464 } | |
465 | |
466 void kernel_wrap_uninit() { | |
467 if (s_wrapped) { | |
468 LOG_TRACE("kernel_wrap_uninit"); | |
469 | |
470 /* Register original IRT interfaces in irt.h. */ | |
471 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_basic, | |
472 s_irt_basic.interface); | |
473 | |
474 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_fdio, | |
475 s_irt_fdio.interface); | |
476 | |
477 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_memory, | |
478 s_irt_memory.interface); | |
479 | |
480 /* | |
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. | |
485 */ | |
486 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_dev_fdio, | |
487 s_irt_dev_fdio.interface); | |
488 | |
489 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_dev_filename, | |
490 s_irt_dev_filename.interface); | |
491 | |
492 s_wrapped = false; | |
493 } | |
494 } | |
495 | |
496 #endif | |
OLD | NEW |