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 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_uname_portable 565 case __NR_uname_portable: native_number = __NR_uname; break; 566 #endif 567 568 #ifdef __NR_vmsplice_portable 569 case __NR_vmsplice_portable: native_number = __NR_vmsplice; break; 570 #endif 571 572 default: 573 ALOGV("%s(portable_number:%d, ...): case default; native_number = -1; " 574 "[ERROR: ADD MISSING SYSTEM CALL]", __func__, portable_number); 575 576 native_number = -1; 577 break; 578 } 579 580 ALOGV("%s: native_number = %d", __func__, native_number); 581 582 if (native_number <= 0) { 583 ALOGV("%s: native_number:%d <= 0; ret = -1; [ERROR: FIX SYSTEM CALL]", __func__, 584 native_number); 585 586 *REAL(__errno)() = ENOSYS; 587 ret = -1; 588 goto done; 589 } 590 591 /* 592 * Get the argument list 593 * This is pretty crappy: 594 * It assumes that the portable and native arguments are compatible 595 * It assumes that no more than MAXARGS arguments are passed 596 * 597 * Possible changes: 598 * o include the argument count for each mapped system call 599 * o map the syscall into the equivalent library call: 600 * eg syscall(__NR_gettimeofday_portable, struct timeval *tv, struct timezone *tz) => 601 * gettimeofday(struct timeval *tv, struct timezone *tz) 602 * 603 * second option is probably best as it allows argument remapping to take place if needed 604 * 605 */ 606 va_start(ap, portable_number); 607 /* For now assume all syscalls take MAXARGS arguments. */ 608 nargs = MAXARGS; 609 for (i = 0; i < nargs; i++) 610 args[i] = va_arg(ap, int); 611 va_end(ap); 612 613 ALOGV("%s: Calling syscall(%d, %d, %d, %d, %d, %d, %d, %d, %d);", __func__, 614 native_number, args[0], args[1], args[2], args[3], args[4], 615 args[5], args[6], args[7]); 616 617 ret = REAL(syscall)(native_number, args[0], args[1], args[2], args[3], 618 args[4], args[5], args[6], args[7]); 619 620 done: 621 if (ret == -1) { 622 ALOGV("%s: ret == -1; errno:%d;", __func__, *REAL(__errno)()); 623 } 624 ALOGV("%s: return(ret:%d); }", __func__, ret); 625 return ret; 626 } 627