• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2012, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <portability.h>
18 #include <unistd.h>
19 #include <stdarg.h>
20 #include <signal.h>
21 #include <signal_portable.h>
22 #include <time.h>
23 #include <errno.h>
24 #include <errno_portable.h>
25 #include <eventfd_portable.h>
26 #include <filefd_portable.h>
27 #include <inotify_portable.h>
28 #include <timerfd_portable.h>
29 #include <asm/unistd-portable.h>
30 #include <asm/unistd.h>
31 
32 #define PORTABLE_TAG "syscall_portable"
33 #include <log_portable.h>
34 
35 #if __NR_gettimeofday_portable == __NR_gettimeofday
36 #error "Bad build environment"
37 #endif
38 
39 /*
40  * Minimal syscall support for LTP testing.
41  * These are the system calls that LTP references explicitly.
42  * Not all of them are exported via bionic header so use #ifdef.
43  *
44  * TODO:
45  *    Add existing portable system calls currently redirected from
46  *    experimental Bionic linker code so that calls to them via
47  *    syscall() are also processed. For example, LTP only calls open()
48  *    directly and never does a syscall(__NR_open, ...).
49  */
50 
51 
52 extern int REAL(syscall)(int, ...);
53 
54 #define MAXARGS 8
55 
WRAP(syscall)56 int WRAP(syscall)(int portable_number, ...)
57 {
58     va_list ap;
59     int native_number, ret;
60     int i, nargs, args[MAXARGS];
61 
62     ALOGV(" ");
63     ALOGV("%s(portable_number:%d, ...) {", __func__, portable_number);
64 
65     switch (portable_number) {
66 #ifdef __NR_add_key_portable
67     case __NR_add_key_portable: native_number = __NR_add_key; break;
68 #endif
69 
70 #ifdef __NR_cacheflush_portable
71     case __NR_cacheflush_portable: {
72         long start, end, flags;
73 
74         va_start(ap, portable_number);
75         start = va_arg(ap, long);
76         end = va_arg(ap, long);
77         flags = va_arg(ap, long);
78         va_end(ap);
79 
80         ret = cacheflush(start, end, flags);
81         goto done;
82     }
83 #endif
84 
85 #ifdef __NR_capget_portable
86     case __NR_capget_portable: native_number = __NR_capget; break;
87 #endif
88 
89 #ifdef __NR_capset_portable
90     case __NR_capset_portable: native_number = __NR_capset; break;
91 #endif
92 
93 #ifdef __NR_clock_getres_portable
94     case __NR_clock_getres_portable: native_number = __NR_clock_getres; break;
95 #endif
96 
97 #ifdef __NR_clock_nanosleep
98     case __NR_clock_nanosleep_portable: native_number = __NR_clock_nanosleep; break;
99 #endif
100 
101 #ifdef __NR_dup3_portable
102     case __NR_dup3_portable: native_number = __NR_dup3; break;
103 #endif
104 
105 #ifdef __NR_epoll_create_portable
106     case __NR_epoll_create_portable: native_number = __NR_epoll_create; break;
107 #endif
108 
109 #ifdef __NR_epoll_create1_portable
110     case __NR_epoll_create1_portable: native_number = __NR_epoll_create1; break;
111 #endif
112 
113 #ifdef __NR_eventfd_portable
114     /*
115      * Prior to 2.6.27 we only had this system call,
116      * which didn't have a flags argument. The kernel
117      * just provides a zero for flags when this system
118      * call number is used.
119      */
120     case __NR_eventfd_portable: {
121         unsigned int initval;                        /* 64-bit counter initial value */
122         int flags = 0;
123 
124         va_start(ap, portable_number);
125 
126         initval  = va_arg(ap, int);
127 
128         va_end(ap);
129 
130         ret = WRAP(eventfd)(initval, flags);      /* Android uses __NR_eventfd2 in eventfd() */
131         goto done;
132     }
133 #endif
134 
135 #ifdef __NR_eventfd2_portable
136     /*
137      * Starting with Linux 2.6.27 a flags argument was added.
138      * Both Bionic and glibc implement the eventfd() now with
139      * the additional flags argument.
140      */
141     case __NR_eventfd2_portable: {
142         unsigned int initval;                        /* 64-bit counter initial value */
143         int flags;
144 
145         va_start(ap, portable_number);
146 
147         initval  = va_arg(ap, int);
148         flags = va_arg(ap, int);
149 
150         va_end(ap);
151 
152         ret = WRAP(eventfd)(initval, flags);      /* Android uses __NR_eventfd2 in eventfd() */
153         goto done;
154     }
155 #endif
156 
157 #ifdef __NR_exit_group_portable
158     case __NR_exit_group_portable: native_number = __NR_exit_group; break;
159 #endif
160 
161 #ifdef __NR_faccessat_portable
162     case __NR_faccessat_portable: native_number = __NR_faccessat; break;
163 #endif
164 
165 #ifdef __NR_fallocate_portable
166     case __NR_fallocate_portable: native_number = __NR_fallocate; break;
167 #endif
168 
169 #ifdef __NR_fchmodat_portable
170     case __NR_fchmodat_portable: native_number = __NR_fchmodat; break;
171 #endif
172 
173 #ifdef __NR_fchownat_portable
174     case __NR_fchownat_portable: native_number = __NR_fchownat; break;
175 #endif
176 
177 #ifdef __NR_fstatat64_portable
178     case __NR_fstatat64_portable: native_number = __NR_fstatat64; break;
179 #endif
180 
181 #ifdef __NR_futimesat_portable
182     case __NR_futimesat_portable: native_number = __NR_futimesat; break;
183 #endif
184 
185 #ifdef __NR_getegid_portable
186     case __NR_getegid_portable: native_number = __NR_getegid; break;
187 #endif
188 
189 #ifdef __NR_geteuid_portable
190     case __NR_geteuid_portable: native_number = __NR_geteuid; break;
191 #endif
192 
193 #ifdef __NR_getgid_portable
194     case __NR_getgid_portable: native_number = __NR_getgid; break;
195 #endif
196 
197 #ifdef __NR_get_mempolicy_portable
198     case __NR_get_mempolicy_portable: native_number = __NR_get_mempolicy; break;
199 #endif
200 
201 #ifdef __NR_get_robust_list_portable
202     case __NR_get_robust_list_portable: native_number = __NR_get_robust_list; break;
203 #endif
204 
205 #ifdef __NR_gettid_portable
206     case __NR_gettid_portable: native_number = __NR_gettid; break;
207 #endif
208 
209 #ifdef __NR_gettimeofday_portable
210     case __NR_gettimeofday_portable: native_number = __NR_gettimeofday; break;
211 #endif
212 
213 #ifdef __NR_getuid_portable
214     case __NR_getuid_portable: native_number = __NR_getuid; break;
215 #endif
216 
217 #ifdef __NR_inotify_init_portable
218     case __NR_inotify_init_portable: native_number = __NR_inotify_init; break;
219 #endif
220 
221 #ifdef __NR_inotify_add_watch_portable
222     case __NR_inotify_add_watch_portable: native_number = __NR_inotify_add_watch; break;
223 #endif
224 
225 #ifdef __NR_inotify_init1_portable
226     case __NR_inotify_init1_portable: {
227         int portable_flags;
228 
229         va_start(ap, portable_number);
230         portable_flags = va_arg(ap, int);
231         va_end(ap);
232 
233         ret = WRAP(inotify_init1)(portable_flags);
234         goto done;
235     }
236 #endif
237 
238 #ifdef __NR_keyctl_portable
239     case __NR_keyctl_portable: native_number = __NR_keyctl; break;
240 #endif
241 
242 #ifdef __NR_linkat
243     case __NR_linkat_portable: native_number = __NR_linkat; break;
244 #endif
245 
246 #ifdef __NR_mbind_portable
247     case __NR_mbind_portable: native_number = __NR_mbind; break;
248 #endif
249 
250 #ifdef __NR_mkdirat_portable
251     case __NR_mkdirat_portable: native_number = __NR_mkdirat; break;
252 #endif
253 
254 #ifdef __NR_mknodat_portable
255     case __NR_mknodat_portable: native_number = __NR_mknodat; break;
256 #endif
257 
258 #ifdef __NR_openat_portable
259     case __NR_openat_portable: native_number = __NR_openat; break;
260 #endif
261 
262 #ifdef __NR_pipe2_portable
263     case __NR_pipe2_portable: {
264         int *pipefd_ptr;
265         int portable_flags;
266 
267         va_start(ap, portable_number);
268         pipefd_ptr = va_arg(ap, int *);
269         portable_flags = va_arg(ap, int);
270         va_end(ap);
271 
272         ret = WRAP(pipe2)(pipefd_ptr, portable_flags);
273         goto done;
274     }
275 #endif
276 
277 #ifdef __NR_readahead_portable
278     case __NR_readahead_portable: native_number = __NR_readahead; break;
279 #endif
280 
281 #ifdef __NR_readlinkat_portable
282     case __NR_readlinkat_portable: native_number = __NR_readlinkat; break;
283 #endif
284 
285 #ifdef __NR_renameat_portable
286     case __NR_renameat_portable: native_number = __NR_renameat; break;
287 #endif
288 
289 #ifdef __NR_rt_sigaction_portable
290     case __NR_rt_sigaction_portable: {
291         int sig;
292         struct sigaction_portable *act;
293         struct sigaction_portable *oact;
294         size_t sigsetsize;
295 
296         va_start(ap, portable_number);
297         sig = va_arg(ap, int);
298         act = va_arg(ap, struct sigaction_portable *);
299         oact = va_arg(ap, struct sigaction_portable *);
300         sigsetsize = va_arg(ap, size_t);
301         va_end(ap);
302         return WRAP(__rt_sigaction)(sig, act, oact, sigsetsize);
303     }
304 #endif
305 
306 #ifdef __NR_rt_sigprocmask_portable
307     case __NR_rt_sigprocmask_portable: {
308         int how;
309         const sigset_portable_t *set;
310         sigset_portable_t *oset;
311         size_t sigsetsize;
312 
313         va_start(ap, portable_number);
314         how = va_arg(ap, int);
315         set = va_arg(ap, sigset_portable_t *);
316         oset = va_arg(ap, sigset_portable_t *);
317         sigsetsize = va_arg(ap, size_t);
318         va_end(ap);
319 
320         ret = WRAP(__rt_sigprocmask)(how, set, oset, sigsetsize);
321         goto done;
322     }
323 #endif
324 
325 #ifdef __NR_rt_sigtimedwait_portable
326     case __NR_rt_sigtimedwait_portable: {
327         const sigset_portable_t *set;
328         siginfo_portable_t *info;
329         const struct timespec *timeout;
330         size_t sigsetsize;
331 
332         va_start(ap, portable_number);
333         set = va_arg(ap, sigset_portable_t *);
334         info = va_arg(ap, siginfo_portable_t *);
335         timeout = va_arg(ap, struct timespec *);
336         sigsetsize = va_arg(ap, size_t);
337         va_end(ap);
338 
339         ret = WRAP(__rt_sigtimedwait)(set, info, timeout, sigsetsize);
340         goto done;
341     }
342 #endif
343 
344 #ifdef __NR_rt_sigqueueinfo_portable
345     case __NR_rt_sigqueueinfo_portable: {
346         pid_t pid;
347         int sig;
348         siginfo_portable_t *uinfo;
349 
350         va_start(ap, portable_number);
351         pid = va_arg(ap, pid_t);
352         sig = va_arg(ap, int);
353         uinfo = va_arg(ap, siginfo_portable_t *);
354         va_end(ap);
355 
356         ret = WRAP(rt_sigqueueinfo)(pid, sig, uinfo);
357         goto done;
358     }
359 #endif
360 
361 #ifdef __NR_setgid_portable
362     case __NR_setgid_portable: native_number = __NR_setgid; break;
363 #endif
364 
365 #ifdef __NR_set_mempolicy_portable
366     case __NR_set_mempolicy_portable: native_number = __NR_set_mempolicy; break;
367 #endif
368 
369 #ifdef __NR_set_robust_list_portable
370     case __NR_set_robust_list_portable: native_number = __NR_set_robust_list; break;
371 #endif
372 
373 #ifdef __NR_set_tid_address_portable
374     case __NR_set_tid_address_portable: native_number = __NR_set_tid_address; break;
375 #endif
376 
377 #ifdef __NR_sgetmask_portable
378     case __NR_sgetmask_portable: native_number = __NR_sgetmask; break;
379 #endif
380 
381 #ifdef __NR_signalfd4_portable
382     case __NR_signalfd4_portable: {
383         int fd;
384         sigset_portable_t *portable_sigmask;
385         int sigsetsize;
386         int flags;
387 
388         va_start(ap, portable_number);
389 
390         fd = va_arg(ap, int);
391         portable_sigmask = va_arg(ap, sigset_portable_t *);
392         sigsetsize = va_arg(ap, int);
393         flags = va_arg(ap, int);
394 
395         va_end(ap);
396 
397         ret = do_signalfd4_portable(fd, (const sigset_portable_t *) portable_sigmask, sigsetsize,
398                                     flags);
399         goto done;
400     }
401 #endif
402 
403 #ifdef __NR_socketcall_portable
404     case __NR_socketcall_portable: native_number = __NR_socketcall; break;
405 #endif
406 
407 #ifdef __NR_splice_portable
408     case __NR_splice_portable: native_number = __NR_splice; break;
409 #endif
410 
411 /* REMIND - DOUBLE CHECK THIS ONE */
412 #ifdef __NR_ssetmask_portable
413     case __NR_ssetmask_portable: native_number = __NR_ssetmask; break;
414 #endif
415 
416 #ifdef __NR_swapoff_portable
417     case __NR_swapoff_portable: native_number = __NR_swapoff; break;
418 #endif
419 
420 #ifdef __NR_swapon_portable
421     case __NR_swapon_portable: native_number = __NR_swapon; break;
422 #endif
423 
424 #ifdef __NR_symlinkat_portable
425     case __NR_symlinkat_portable: native_number = __NR_symlinkat; break;
426 #endif
427 
428 /*
429  * ARM uses the new, version 2, form of sync_file_range() which
430  * doesn't waste 32 bits between the 32 bit arg and the 64 bit arg.
431  * It does this by moving the last 32 bit arg and placing it with
432  * the 1st 32 bit arg.
433  *
434  * Here's the trivial mapping function in the kernel ARM code:
435  *
436  *   sync_file_range2(int fd, unsigned int flags, loff_t offset, loff_t nbytes) {
437  *       return sys_sync_file_range(fd, offset, nbytes, flags);
438  *   }
439  *
440  * For portability we have to do a similar mapping for the native/MIPS system
441  * call but have to provide the alignment padding expected by the sync_file_range()
442  * system call. We avoid alignment issues while using varargs by avoiding the use
443  * of 64 bit args.
444  */
445 #if defined( __NR_arm_sync_file_range_portable)
446     case __NR_arm_sync_file_range_portable: native_number = __NR_sync_file_range; {
447         int fd;
448         int flags;
449         int offset_low, offset_high;
450         int nbytes_low, nbytes_high;
451         int align_fill = 0;
452 
453 
454         va_start(ap, portable_number);
455         fd = va_arg(ap, int);
456         flags = va_arg(ap, int);
457         offset_low = va_arg(ap, int);
458         offset_high = va_arg(ap, int);
459         nbytes_low = va_arg(ap, int);
460         nbytes_high = va_arg(ap, int);
461         va_end(ap);
462 
463         ALOGV("%s: Calling syscall(native_number:%d:'sync_file_range', fd:%d, "
464               "align_fill:0x%x, offset_low:0x%x, offset_high:0x%x, "
465               "nbytes_low:0x%x, nbytes_high:0x%x, flags:0x%x);", __func__,
466               native_number, fd, align_fill, offset_low, offset_high,
467               nbytes_low, nbytes_high, flags);
468 
469         ret = REAL(syscall)(native_number, fd, align_fill, offset_low, offset_high,
470                       nbytes_low, nbytes_high, flags);
471 
472         goto done;
473     }
474 #endif
475 
476 
477 #ifdef __NR__sysctl_portable
478     case __NR__sysctl_portable: native_number = __NR__sysctl; break;
479 #endif
480 
481 #ifdef __NR_sysfs_portable
482     case __NR_sysfs_portable: native_number = __NR_sysfs; break;
483 #endif
484 
485 #ifdef __NR_syslog_portable
486     case __NR_syslog_portable: native_number = __NR_syslog; break;
487 #endif
488 
489 #ifdef __NR_tee_portable
490     case __NR_tee_portable: native_number = __NR_tee; break;
491 #endif
492 
493 #ifdef __NR_timer_create_portable
494     case __NR_timer_create_portable: {
495         clockid_t clockid;
496         struct sigevent *evp;
497         timer_t *timerid;
498 
499         va_start(ap, portable_number);
500         clockid = va_arg(ap, clockid_t);
501         evp = va_arg(ap, struct sigevent *);
502         timerid = va_arg(ap, timer_t *);
503         va_end(ap);
504 
505         ret = WRAP(timer_create)(clockid, evp, timerid);
506         goto done;
507     }
508 #endif
509 
510 #ifdef __NR_timerfd_create_portable
511     case __NR_timerfd_create_portable: {
512         int clockid;
513         int flags;
514 
515         va_start(ap, portable_number);
516         clockid = va_arg(ap, int);              /* clockid is portable */
517         flags = va_arg(ap, int);                /* flags need to be mapped */
518         va_end(ap);
519 
520         ret = WRAP(timerfd_create)(clockid, flags);
521         goto done;
522     }
523 #endif
524 
525 #ifdef __NR_timerfd_gettime_portable
526     case __NR_timerfd_gettime_portable: native_number = __NR_timerfd_gettime; break;
527 #endif
528 
529 #ifdef __NR_timerfd_settime_portable
530     case __NR_timerfd_settime_portable: native_number = __NR_timerfd_settime; break;
531 #endif
532 
533 #ifdef __NR_timer_getoverrun_portable
534     case __NR_timer_getoverrun_portable: native_number = __NR_timer_getoverrun; break;
535 #endif
536 
537 #ifdef __NR_timer_gettime_portable
538     case __NR_timer_gettime_portable: native_number = __NR_timer_gettime; break;
539 #endif
540 
541 #ifdef __NR_timer_settime_portable
542     case __NR_timer_settime_portable: native_number = __NR_timer_settime; break;
543 #endif
544 
545 #ifdef __NR_rt_tgsigqueueinfo_portable
546     case __NR_rt_tgsigqueueinfo_portable: {
547         pid_t tgid;
548         pid_t pid;
549         int sig;
550         siginfo_portable_t *uinfo;
551 
552         va_start(ap, portable_number);
553         tgid = va_arg(ap, pid_t);
554         pid = va_arg(ap, pid_t);
555         sig = va_arg(ap, int);
556         uinfo = va_arg(ap, siginfo_portable_t *);
557         va_end(ap);
558 
559         ret = WRAP(rt_tgsigqueueinfo)(tgid, pid, sig, uinfo);
560         goto done;
561     }
562 #endif
563 
564 #ifdef __NR_tkill_portable
565     case __NR_tkill_portable: {
566         int tid, sig;
567 
568         va_start(ap, portable_number);
569         tid = va_arg(ap, int);
570         sig = va_arg(ap, int);
571         va_end(ap);
572 
573         ret = WRAP(tkill)(tid, sig);
574         goto done;
575     }
576 #endif
577 
578 #ifdef __NR_uname_portable
579     case __NR_uname_portable: native_number = __NR_uname; break;
580 #endif
581 
582 #ifdef __NR_vmsplice_portable
583     case __NR_vmsplice_portable: native_number = __NR_vmsplice; break;
584 #endif
585 
586     default:
587         ALOGV("%s(portable_number:%d,  ...): case default; native_number = -1; "
588               "[ERROR: ADD MISSING SYSTEM CALL]", __func__, portable_number);
589 
590         native_number = -1;
591         break;
592     }
593 
594     ALOGV("%s: native_number = %d", __func__, native_number);
595 
596     if (native_number <= 0) {
597         ALOGV("%s: native_number:%d <= 0; ret = -1; [ERROR: FIX SYSTEM CALL]", __func__,
598                    native_number);
599 
600         *REAL(__errno)() = ENOSYS;
601         ret = -1;
602         goto done;
603     }
604 
605     /*
606      * Get the argument list
607      * This is pretty crappy:
608      *   It assumes that the portable and native arguments are compatible
609      *   It assumes that no more than MAXARGS arguments are passed
610      *
611      * Possible changes:
612      *  o include the argument count for each mapped system call
613      *  o map the syscall into the equivalent library call:
614      *    eg syscall(__NR_gettimeofday_portable, struct timeval *tv, struct timezone *tz) =>
615      *       gettimeofday(struct timeval *tv, struct timezone *tz)
616      *
617      * second option is probably best as it allows argument remapping to take place if needed
618      *
619      */
620     va_start(ap, portable_number);
621     /* For now assume all syscalls take MAXARGS arguments. */
622     nargs = MAXARGS;
623     for (i = 0; i < nargs; i++)
624         args[i] = va_arg(ap, int);
625     va_end(ap);
626 
627     ALOGV("%s: Calling syscall(%d, %d, %d, %d, %d, %d, %d, %d, %d);", __func__,
628           native_number, args[0], args[1], args[2], args[3], args[4],
629           args[5], args[6], args[7]);
630 
631     ret = REAL(syscall)(native_number, args[0], args[1], args[2], args[3],
632                   args[4], args[5], args[6], args[7]);
633 
634 done:
635     if (ret == -1) {
636         ALOGV("%s: ret == -1; errno:%d;", __func__, *REAL(__errno)());
637     }
638     ALOGV("%s: return(ret:%d); }", __func__, ret);
639     return ret;
640 }
641