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.
4 
5 #include <sys/types.h>  // Include something that will define __GLIBC__.
6 #include "nacl_io/kernel_wrap.h" // IRT_EXT is turned on in this header.
7 
8 // The entire file is wrapped in this #if. We do this so this .cc file can be
9 // compiled, even on a non-newlib build.
10 #if !defined(NACL_IO_IRT_EXT) && defined(__native_client__) && \
11     !defined(__GLIBC__) && !defined(__BIONIC__)
12 
13 #include <dirent.h>
14 #include <errno.h>
15 #include <irt.h>
16 #include <irt_dev.h>
17 #include <sys/mman.h>
18 #include <sys/stat.h>
19 #include <sys/time.h>
20 
21 #include "nacl_io/kernel_intercept.h"
22 #include "nacl_io/kernel_wrap_real.h"
23 #include "nacl_io/log.h"
24 
25 EXTERN_C_BEGIN
26 
27 // Macro to get the REAL function pointer
28 #define REAL(name) __nacl_irt_##name##_real
29 
30 // Macro to get the WRAP function
31 #define WRAP(name) __nacl_irt_##name##_wrap
32 
33 // Declare REAL function pointer.
34 #define DECLARE_REAL_PTR(group, name) \
35   __typeof__(__libnacl_irt_##group.name) REAL(name);
36 
37 // Assign the REAL function pointer.
38 #define ASSIGN_REAL_PTR(group, name) REAL(name) = __libnacl_irt_##group.name;
39 
40 // Switch IRT's pointer to the REAL pointer
41 #define USE_REAL(group, name) \
42   __libnacl_irt_##group.name = (__typeof__(REAL(name)))REAL(name);
43 
44 // Switch the IRT's pointer to the WRAP function
45 #define USE_WRAP(group, name) \
46   __libnacl_irt_##group.name = (__typeof__(REAL(name)))WRAP(name);
47 
48 extern void __libnacl_irt_dev_filename_init(void);
49 extern void __libnacl_irt_dev_fdio_init(void);
50 
51 extern struct nacl_irt_basic __libnacl_irt_basic;
52 extern struct nacl_irt_fdio __libnacl_irt_fdio;
53 extern struct nacl_irt_dev_fdio __libnacl_irt_dev_fdio;
54 extern struct nacl_irt_dev_filename __libnacl_irt_dev_filename;
55 extern struct nacl_irt_memory __libnacl_irt_memory;
56 
57 // Create function pointers to the REAL implementation
58 #define EXPAND_SYMBOL_LIST_OPERATION(OP) \
59   OP(basic, exit);                       \
60   OP(fdio, close);                       \
61   OP(fdio, dup);                         \
62   OP(fdio, dup2);                        \
63   OP(fdio, read);                        \
64   OP(fdio, write);                       \
65   OP(fdio, seek);                        \
66   OP(fdio, fstat);                       \
67   OP(fdio, getdents);                    \
68   OP(dev_fdio, fchdir);                  \
69   OP(dev_fdio, fchmod);                  \
70   OP(dev_fdio, fsync);                   \
71   OP(dev_fdio, fdatasync);               \
72   OP(dev_fdio, ftruncate);               \
73   OP(dev_fdio, isatty);                  \
74   OP(dev_filename, open);                \
75   OP(dev_filename, stat);                \
76   OP(dev_filename, mkdir);               \
77   OP(dev_filename, rmdir);               \
78   OP(dev_filename, chdir);               \
79   OP(dev_filename, getcwd);              \
80   OP(dev_filename, unlink);              \
81   OP(dev_filename, truncate);            \
82   OP(dev_filename, lstat);               \
83   OP(dev_filename, link);                \
84   OP(dev_filename, rename);              \
85   OP(dev_filename, symlink);             \
86   OP(dev_filename, chmod);               \
87   OP(dev_filename, access);              \
88   OP(dev_filename, readlink);            \
89   OP(dev_filename, utimes);              \
90   OP(memory, mmap);                      \
91   OP(memory, munmap);
92 
93 EXPAND_SYMBOL_LIST_OPERATION(DECLARE_REAL_PTR);
94 
WRAP(close)95 int WRAP(close)(int fd) {
96   ERRNO_RTN(ki_close(fd));
97 }
98 
WRAP(dup)99 int WRAP(dup)(int fd, int* newfd) {
100   *newfd = ki_dup(fd);
101   ERRNO_RTN(*newfd);
102 }
103 
WRAP(dup2)104 int WRAP(dup2)(int fd, int newfd) {
105   newfd = ki_dup2(fd, newfd);
106   ERRNO_RTN(newfd);
107 }
108 
WRAP(exit)109 void WRAP(exit)(int status) {
110   ki_exit(status);
111 }
112 
WRAP(read)113 int WRAP(read)(int fd, void* buf, size_t count, size_t* nread) {
114   ssize_t signed_nread = ki_read(fd, buf, count);
115   *nread = static_cast<size_t>(signed_nread);
116   ERRNO_RTN(signed_nread);
117 }
118 
WRAP(write)119 int WRAP(write)(int fd, const void* buf, size_t count, size_t* nwrote) {
120   ssize_t signed_nwrote = ki_write(fd, buf, count);
121   *nwrote = static_cast<size_t>(signed_nwrote);
122   ERRNO_RTN(signed_nwrote);
123 }
124 
WRAP(seek)125 int WRAP(seek)(int fd, off_t offset, int whence, off_t* new_offset) {
126   *new_offset = ki_lseek(fd, offset, whence);
127   ERRNO_RTN(*new_offset);
128 }
129 
WRAP(fstat)130 int WRAP(fstat)(int fd, struct stat* buf) {
131   ERRNO_RTN(ki_fstat(fd, buf));
132 }
133 
WRAP(getdents)134 int WRAP(getdents)(int fd, dirent* buf, size_t count, size_t* nread) {
135   int rtn = ki_getdents(fd, buf, count);
136   RTN_ERRNO_IF(rtn < 0);
137   *nread = rtn;
138   return 0;
139 }
140 
WRAP(fchdir)141 int WRAP(fchdir)(int fd) {
142   ERRNO_RTN(ki_fchdir(fd));
143 }
144 
WRAP(fchmod)145 int WRAP(fchmod)(int fd, mode_t mode) {
146   ERRNO_RTN(ki_fchmod(fd, mode));
147 }
148 
WRAP(fsync)149 int WRAP(fsync)(int fd) {
150   ERRNO_RTN(ki_fsync(fd));
151 }
152 
WRAP(fdatasync)153 int WRAP(fdatasync)(int fd) {
154   ERRNO_RTN(ki_fdatasync(fd));
155 }
156 
WRAP(ftruncate)157 int WRAP(ftruncate)(int fd, off_t length) {
158   ERRNO_RTN(ki_ftruncate(fd, length));
159 }
160 
WRAP(isatty)161 int WRAP(isatty)(int fd, int* result) {
162   *result = ki_isatty(fd);
163   RTN_ERRNO_IF(*result == 0);
164   return 0;
165 }
166 
WRAP(mmap)167 int WRAP(mmap)(void** addr,
168                size_t length,
169                int prot,
170                int flags,
171                int fd,
172                off_t offset) {
173   if (flags & MAP_ANONYMOUS)
174     return REAL(mmap)(addr, length, prot, flags, fd, offset);
175 
176   *addr = ki_mmap(*addr, length, prot, flags, fd, offset);
177   RTN_ERRNO_IF(*addr == (void*)-1);
178   return 0;
179 }
180 
WRAP(munmap)181 int WRAP(munmap)(void* addr, size_t length) {
182   // Always let the real munmap run on the address range. It is not an error if
183   // there are no mapped pages in that range.
184   ki_munmap(addr, length);
185   return REAL(munmap)(addr, length);
186 }
187 
WRAP(open)188 int WRAP(open)(const char* pathname, int oflag, mode_t mode, int* newfd) {
189   *newfd = ki_open(pathname, oflag, mode);
190   ERRNO_RTN(*newfd);
191 }
192 
WRAP(stat)193 int WRAP(stat)(const char* pathname, struct stat* buf) {
194   ERRNO_RTN(ki_stat(pathname, buf));
195 }
196 
WRAP(mkdir)197 int WRAP(mkdir)(const char* pathname, mode_t mode) {
198   ERRNO_RTN(ki_mkdir(pathname, mode));
199 }
200 
WRAP(rmdir)201 int WRAP(rmdir)(const char* pathname) {
202   ERRNO_RTN(ki_rmdir(pathname));
203 }
204 
WRAP(chdir)205 int WRAP(chdir)(const char* pathname) {
206   ERRNO_RTN(ki_chdir(pathname));
207 }
208 
WRAP(getcwd)209 int WRAP(getcwd)(char* pathname, size_t len) {
210   char* rtn = ki_getcwd(pathname, len);
211   RTN_ERRNO_IF(NULL == rtn);
212   return 0;
213 }
214 
WRAP(unlink)215 int WRAP(unlink)(const char* pathname) {
216   ERRNO_RTN(ki_unlink(pathname));
217 }
218 
WRAP(truncate)219 int WRAP(truncate)(const char* pathname, off_t length) {
220   ERRNO_RTN(ki_truncate(pathname, length));
221 }
222 
WRAP(lstat)223 int WRAP(lstat)(const char* pathname, struct stat* buf) {
224   ERRNO_RTN(ki_lstat(pathname, buf));
225 }
226 
WRAP(link)227 int WRAP(link)(const char* pathname, const char* newpath) {
228   ERRNO_RTN(ki_link(pathname, newpath));
229 }
230 
WRAP(rename)231 int WRAP(rename)(const char* pathname, const char* newpath) {
232   ERRNO_RTN(ki_rename(pathname, newpath));
233 }
234 
WRAP(symlink)235 int WRAP(symlink)(const char* pathname, const char* newpath) {
236   ERRNO_RTN(ki_symlink(pathname, newpath));
237 }
238 
WRAP(chmod)239 int WRAP(chmod)(const char* pathname, mode_t mode) {
240   ERRNO_RTN(ki_chmod(pathname, mode));
241 }
242 
WRAP(access)243 int WRAP(access)(const char* pathname, int amode) {
244   ERRNO_RTN(ki_access(pathname, amode));
245 }
246 
WRAP(readlink)247 int WRAP(readlink)(const char* pathname,
248                    char* buf,
249                    size_t count,
250                    size_t* nread) {
251   int rtn = ki_readlink(pathname, buf, count);
252   RTN_ERRNO_IF(rtn < 0);
253   *nread = rtn;
254   return 0;
255 }
256 
WRAP(utimes)257 int WRAP(utimes)(const char* pathname, const struct timeval times[2]) {
258   ERRNO_RTN(ki_utimes(pathname, times));
259 }
260 
assign_real_pointers()261 static void assign_real_pointers() {
262   static bool assigned = false;
263   if (!assigned) {
264     __libnacl_irt_dev_filename_init();
265     __libnacl_irt_dev_fdio_init();
266     EXPAND_SYMBOL_LIST_OPERATION(ASSIGN_REAL_PTR)
267     assigned = true;
268   }
269 }
270 
271 #define CHECK_REAL(func)    \
272   if (!REAL(func)) {        \
273     assign_real_pointers(); \
274     if (!REAL(func))        \
275       return ENOSYS;        \
276   }
277 
278 // "real" functions, i.e. the unwrapped original functions.
279 
_real_close(int fd)280 int _real_close(int fd) {
281   CHECK_REAL(close);
282   return REAL(close)(fd);
283 }
284 
_real_exit(int status)285 void _real_exit(int status) {
286   if (!REAL(exit))
287     assign_real_pointers();
288   REAL(exit)(status);
289 }
290 
_real_fstat(int fd,struct stat * buf)291 int _real_fstat(int fd, struct stat* buf) {
292   CHECK_REAL(fstat);
293   return REAL(fstat)(fd, buf);
294 }
295 
_real_isatty(int fd,int * result)296 int _real_isatty(int fd, int* result) {
297   CHECK_REAL(isatty);
298   // The real isatty function can be NULL (for example if we are running
299   // within chrome).
300   if (REAL(isatty) == NULL) {
301     *result = 0;
302     return ENOTTY;
303   }
304   return REAL(isatty)(fd, result);
305 }
306 
_real_getdents(int fd,void * nacl_buf,size_t nacl_count,size_t * nread)307 int _real_getdents(int fd, void* nacl_buf, size_t nacl_count, size_t* nread) {
308   CHECK_REAL(getdents);
309   return REAL(getdents)(fd, static_cast<dirent*>(nacl_buf), nacl_count, nread);
310 }
311 
_real_lseek(int fd,off_t offset,int whence,off_t * new_offset)312 int _real_lseek(int fd, off_t offset, int whence, off_t* new_offset) {
313   CHECK_REAL(seek);
314   return REAL(seek)(fd, offset, whence, new_offset);
315 }
316 
_real_mkdir(const char * pathname,mode_t mode)317 int _real_mkdir(const char* pathname, mode_t mode) {
318   CHECK_REAL(mkdir);
319   return REAL(mkdir)(pathname, mode);
320 }
321 
_real_mmap(void ** addr,size_t length,int prot,int flags,int fd,off_t offset)322 int _real_mmap(void** addr,
323                size_t length,
324                int prot,
325                int flags,
326                int fd,
327                off_t offset) {
328   CHECK_REAL(mmap);
329   return REAL(mmap)(addr, length, prot, flags, fd, offset);
330 }
331 
_real_munmap(void * addr,size_t length)332 int _real_munmap(void* addr, size_t length) {
333   CHECK_REAL(munmap);
334   return REAL(munmap)(addr, length);
335 }
336 
_real_open(const char * pathname,int oflag,mode_t mode,int * newfd)337 int _real_open(const char* pathname, int oflag, mode_t mode, int* newfd) {
338   CHECK_REAL(open);
339   return REAL(open)(pathname, oflag, mode, newfd);
340 }
341 
_real_open_resource(const char * file,int * fd)342 int _real_open_resource(const char* file, int* fd) {
343   return ENOSYS;
344 }
345 
_real_read(int fd,void * buf,size_t count,size_t * nread)346 int _real_read(int fd, void* buf, size_t count, size_t* nread) {
347   CHECK_REAL(read);
348   return REAL(read)(fd, buf, count, nread);
349 }
350 
_real_rmdir(const char * pathname)351 int _real_rmdir(const char* pathname) {
352   CHECK_REAL(rmdir);
353   return REAL(rmdir)(pathname);
354 }
355 
_real_write(int fd,const void * buf,size_t count,size_t * nwrote)356 int _real_write(int fd, const void* buf, size_t count, size_t* nwrote) {
357   CHECK_REAL(write);
358   return REAL(write)(fd, buf, count, nwrote);
359 }
360 
_real_getcwd(char * pathname,size_t len)361 int _real_getcwd(char* pathname, size_t len) {
362   CHECK_REAL(getcwd);
363   return REAL(getcwd)(pathname, len);
364 }
365 
366 static bool s_wrapped = false;
367 
kernel_wrap_init()368 void kernel_wrap_init() {
369   if (!s_wrapped) {
370     LOG_TRACE("kernel_wrap_init");
371     assign_real_pointers();
372     EXPAND_SYMBOL_LIST_OPERATION(USE_WRAP)
373     s_wrapped = true;
374   }
375 }
376 
kernel_wrap_uninit()377 void kernel_wrap_uninit() {
378   if (s_wrapped) {
379     LOG_TRACE("kernel_wrap_uninit");
380     EXPAND_SYMBOL_LIST_OPERATION(USE_REAL)
381     s_wrapped = false;
382   }
383 }
384 
385 EXTERN_C_END
386 
387 #endif  // defined(__native_client__) && !defined(__GLIBC__) ...
388