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