1 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */ 2 /* 3 * Syscall definitions for NOLIBC (those in man(2)) 4 * Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu> 5 */ 6 7 #ifndef _NOLIBC_SYS_H 8 #define _NOLIBC_SYS_H 9 10 #include "std.h" 11 12 /* system includes */ 13 #include <linux/unistd.h> 14 #include <linux/signal.h> /* for SIGCHLD */ 15 #include <linux/termios.h> 16 #include <linux/mman.h> 17 #include <linux/fs.h> 18 #include <linux/loop.h> 19 #include <linux/time.h> 20 #include <linux/auxvec.h> 21 #include <linux/fcntl.h> /* for O_* and AT_* */ 22 #include <linux/stat.h> /* for statx() */ 23 #include <linux/prctl.h> 24 #include <linux/resource.h> 25 #include <linux/utsname.h> 26 27 #include "arch.h" 28 #include "errno.h" 29 #include "stdarg.h" 30 #include "types.h" 31 32 33 /* Syscall return helper: takes the syscall value in argument and checks for an 34 * error in it. This may only be used with signed returns (int or long), but 35 * not with pointers. An error is any value < 0. When an error is encountered, 36 * -ret is set into errno and -1 is returned. Otherwise the returned value is 37 * passed as-is with its type preserved. 38 */ 39 40 #define __sysret(arg) \ 41 ({ \ 42 __typeof__(arg) __sysret_arg = (arg); \ 43 (__sysret_arg < 0) /* error ? */ \ 44 ? (({ SET_ERRNO(-__sysret_arg); }), -1) /* ret -1 with errno = -arg */ \ 45 : __sysret_arg; /* return original value */ \ 46 }) 47 48 /* Syscall ENOSYS helper: Avoids unused-parameter warnings and provides a 49 * debugging hook. 50 */ 51 52 static __inline__ int __nolibc_enosys(const char *syscall, ...) 53 { 54 (void)syscall; 55 return -ENOSYS; 56 } 57 58 59 /* Functions in this file only describe syscalls. They're declared static so 60 * that the compiler usually decides to inline them while still being allowed 61 * to pass a pointer to one of their instances. Each syscall exists in two 62 * versions: 63 * - the "internal" ones, which matches the raw syscall interface at the 64 * kernel level, which may sometimes slightly differ from the documented 65 * libc-level ones. For example most of them return either a valid value 66 * or -errno. All of these are prefixed with "sys_". They may be called 67 * by non-portable applications if desired. 68 * 69 * - the "exported" ones, whose interface must closely match the one 70 * documented in man(2), that applications are supposed to expect. These 71 * ones rely on the internal ones, and set errno. 72 * 73 * Each syscall will be defined with the two functions, sorted in alphabetical 74 * order applied to the exported names. 75 * 76 * In case of doubt about the relevance of a function here, only those which 77 * set errno should be defined here. Wrappers like those appearing in man(3) 78 * should not be placed here. 79 */ 80 81 82 /* 83 * int brk(void *addr); 84 * void *sbrk(intptr_t inc) 85 */ 86 87 static __attribute__((unused)) 88 void *sys_brk(void *addr) 89 { 90 return (void *)my_syscall1(__NR_brk, addr); 91 } 92 93 static __attribute__((unused)) 94 int brk(void *addr) 95 { 96 void *ret = sys_brk(addr); 97 98 if (!ret) { 99 SET_ERRNO(ENOMEM); 100 return -1; 101 } 102 return 0; 103 } 104 105 static __attribute__((unused)) 106 void *sbrk(intptr_t inc) 107 { 108 /* first call to find current end */ 109 void *ret = sys_brk(0); 110 111 if (ret && sys_brk(ret + inc) == ret + inc) 112 return ret + inc; 113 114 SET_ERRNO(ENOMEM); 115 return (void *)-1; 116 } 117 118 119 /* 120 * int chdir(const char *path); 121 */ 122 123 static __attribute__((unused)) 124 int sys_chdir(const char *path) 125 { 126 return my_syscall1(__NR_chdir, path); 127 } 128 129 static __attribute__((unused)) 130 int chdir(const char *path) 131 { 132 return __sysret(sys_chdir(path)); 133 } 134 135 136 /* 137 * int chmod(const char *path, mode_t mode); 138 */ 139 140 static __attribute__((unused)) 141 int sys_chmod(const char *path, mode_t mode) 142 { 143 #ifdef __NR_fchmodat 144 return my_syscall4(__NR_fchmodat, AT_FDCWD, path, mode, 0); 145 #elif defined(__NR_chmod) 146 return my_syscall2(__NR_chmod, path, mode); 147 #else 148 return __nolibc_enosys(__func__, path, mode); 149 #endif 150 } 151 152 static __attribute__((unused)) 153 int chmod(const char *path, mode_t mode) 154 { 155 return __sysret(sys_chmod(path, mode)); 156 } 157 158 159 /* 160 * int chown(const char *path, uid_t owner, gid_t group); 161 */ 162 163 static __attribute__((unused)) 164 int sys_chown(const char *path, uid_t owner, gid_t group) 165 { 166 #ifdef __NR_fchownat 167 return my_syscall5(__NR_fchownat, AT_FDCWD, path, owner, group, 0); 168 #elif defined(__NR_chown) 169 return my_syscall3(__NR_chown, path, owner, group); 170 #else 171 return __nolibc_enosys(__func__, path, owner, group); 172 #endif 173 } 174 175 static __attribute__((unused)) 176 int chown(const char *path, uid_t owner, gid_t group) 177 { 178 return __sysret(sys_chown(path, owner, group)); 179 } 180 181 182 /* 183 * int chroot(const char *path); 184 */ 185 186 static __attribute__((unused)) 187 int sys_chroot(const char *path) 188 { 189 return my_syscall1(__NR_chroot, path); 190 } 191 192 static __attribute__((unused)) 193 int chroot(const char *path) 194 { 195 return __sysret(sys_chroot(path)); 196 } 197 198 199 /* 200 * int close(int fd); 201 */ 202 203 static __attribute__((unused)) 204 int sys_close(int fd) 205 { 206 return my_syscall1(__NR_close, fd); 207 } 208 209 static __attribute__((unused)) 210 int close(int fd) 211 { 212 return __sysret(sys_close(fd)); 213 } 214 215 216 /* 217 * int dup(int fd); 218 */ 219 220 static __attribute__((unused)) 221 int sys_dup(int fd) 222 { 223 return my_syscall1(__NR_dup, fd); 224 } 225 226 static __attribute__((unused)) 227 int dup(int fd) 228 { 229 return __sysret(sys_dup(fd)); 230 } 231 232 233 /* 234 * int dup2(int old, int new); 235 */ 236 237 static __attribute__((unused)) 238 int sys_dup2(int old, int new) 239 { 240 #ifdef __NR_dup3 241 return my_syscall3(__NR_dup3, old, new, 0); 242 #elif defined(__NR_dup2) 243 return my_syscall2(__NR_dup2, old, new); 244 #else 245 return __nolibc_enosys(__func__, old, new); 246 #endif 247 } 248 249 static __attribute__((unused)) 250 int dup2(int old, int new) 251 { 252 return __sysret(sys_dup2(old, new)); 253 } 254 255 256 /* 257 * int dup3(int old, int new, int flags); 258 */ 259 260 #ifdef __NR_dup3 261 static __attribute__((unused)) 262 int sys_dup3(int old, int new, int flags) 263 { 264 return my_syscall3(__NR_dup3, old, new, flags); 265 } 266 267 static __attribute__((unused)) 268 int dup3(int old, int new, int flags) 269 { 270 return __sysret(sys_dup3(old, new, flags)); 271 } 272 #endif 273 274 275 /* 276 * int execve(const char *filename, char *const argv[], char *const envp[]); 277 */ 278 279 static __attribute__((unused)) 280 int sys_execve(const char *filename, char *const argv[], char *const envp[]) 281 { 282 return my_syscall3(__NR_execve, filename, argv, envp); 283 } 284 285 static __attribute__((unused)) 286 int execve(const char *filename, char *const argv[], char *const envp[]) 287 { 288 return __sysret(sys_execve(filename, argv, envp)); 289 } 290 291 292 /* 293 * void exit(int status); 294 */ 295 296 static __attribute__((noreturn,unused)) 297 void sys_exit(int status) 298 { 299 my_syscall1(__NR_exit, status & 255); 300 while(1); /* shut the "noreturn" warnings. */ 301 } 302 303 static __attribute__((noreturn,unused)) 304 void exit(int status) 305 { 306 sys_exit(status); 307 } 308 309 310 /* 311 * pid_t fork(void); 312 */ 313 314 #ifndef sys_fork 315 static __attribute__((unused)) 316 pid_t sys_fork(void) 317 { 318 #ifdef __NR_clone 319 /* note: some archs only have clone() and not fork(). Different archs 320 * have a different API, but most archs have the flags on first arg and 321 * will not use the rest with no other flag. 322 */ 323 return my_syscall5(__NR_clone, SIGCHLD, 0, 0, 0, 0); 324 #elif defined(__NR_fork) 325 return my_syscall0(__NR_fork); 326 #else 327 return __nolibc_enosys(__func__); 328 #endif 329 } 330 #endif 331 332 static __attribute__((unused)) 333 pid_t fork(void) 334 { 335 return __sysret(sys_fork()); 336 } 337 338 339 /* 340 * int fsync(int fd); 341 */ 342 343 static __attribute__((unused)) 344 int sys_fsync(int fd) 345 { 346 return my_syscall1(__NR_fsync, fd); 347 } 348 349 static __attribute__((unused)) 350 int fsync(int fd) 351 { 352 return __sysret(sys_fsync(fd)); 353 } 354 355 356 /* 357 * int getdents64(int fd, struct linux_dirent64 *dirp, int count); 358 */ 359 360 static __attribute__((unused)) 361 int sys_getdents64(int fd, struct linux_dirent64 *dirp, int count) 362 { 363 return my_syscall3(__NR_getdents64, fd, dirp, count); 364 } 365 366 static __attribute__((unused)) 367 int getdents64(int fd, struct linux_dirent64 *dirp, int count) 368 { 369 return __sysret(sys_getdents64(fd, dirp, count)); 370 } 371 372 373 /* 374 * uid_t geteuid(void); 375 */ 376 377 static __attribute__((unused)) 378 uid_t sys_geteuid(void) 379 { 380 #ifdef __NR_geteuid32 381 return my_syscall0(__NR_geteuid32); 382 #else 383 return my_syscall0(__NR_geteuid); 384 #endif 385 } 386 387 static __attribute__((unused)) 388 uid_t geteuid(void) 389 { 390 return sys_geteuid(); 391 } 392 393 394 /* 395 * pid_t getpgid(pid_t pid); 396 */ 397 398 static __attribute__((unused)) 399 pid_t sys_getpgid(pid_t pid) 400 { 401 return my_syscall1(__NR_getpgid, pid); 402 } 403 404 static __attribute__((unused)) 405 pid_t getpgid(pid_t pid) 406 { 407 return __sysret(sys_getpgid(pid)); 408 } 409 410 411 /* 412 * pid_t getpgrp(void); 413 */ 414 415 static __attribute__((unused)) 416 pid_t sys_getpgrp(void) 417 { 418 return sys_getpgid(0); 419 } 420 421 static __attribute__((unused)) 422 pid_t getpgrp(void) 423 { 424 return sys_getpgrp(); 425 } 426 427 428 /* 429 * pid_t getpid(void); 430 */ 431 432 static __attribute__((unused)) 433 pid_t sys_getpid(void) 434 { 435 return my_syscall0(__NR_getpid); 436 } 437 438 static __attribute__((unused)) 439 pid_t getpid(void) 440 { 441 return sys_getpid(); 442 } 443 444 445 /* 446 * pid_t getppid(void); 447 */ 448 449 static __attribute__((unused)) 450 pid_t sys_getppid(void) 451 { 452 return my_syscall0(__NR_getppid); 453 } 454 455 static __attribute__((unused)) 456 pid_t getppid(void) 457 { 458 return sys_getppid(); 459 } 460 461 462 /* 463 * pid_t gettid(void); 464 */ 465 466 static __attribute__((unused)) 467 pid_t sys_gettid(void) 468 { 469 return my_syscall0(__NR_gettid); 470 } 471 472 static __attribute__((unused)) 473 pid_t gettid(void) 474 { 475 return sys_gettid(); 476 } 477 478 static unsigned long getauxval(unsigned long key); 479 480 /* 481 * int getpagesize(void); 482 */ 483 484 static __attribute__((unused)) 485 int getpagesize(void) 486 { 487 return __sysret((int)getauxval(AT_PAGESZ) ?: -ENOENT); 488 } 489 490 491 /* 492 * int gettimeofday(struct timeval *tv, struct timezone *tz); 493 */ 494 495 static __attribute__((unused)) 496 int sys_gettimeofday(struct timeval *tv, struct timezone *tz) 497 { 498 #ifdef __NR_gettimeofday 499 return my_syscall2(__NR_gettimeofday, tv, tz); 500 #else 501 return __nolibc_enosys(__func__, tv, tz); 502 #endif 503 } 504 505 static __attribute__((unused)) 506 int gettimeofday(struct timeval *tv, struct timezone *tz) 507 { 508 return __sysret(sys_gettimeofday(tv, tz)); 509 } 510 511 512 /* 513 * uid_t getuid(void); 514 */ 515 516 static __attribute__((unused)) 517 uid_t sys_getuid(void) 518 { 519 #ifdef __NR_getuid32 520 return my_syscall0(__NR_getuid32); 521 #else 522 return my_syscall0(__NR_getuid); 523 #endif 524 } 525 526 static __attribute__((unused)) 527 uid_t getuid(void) 528 { 529 return sys_getuid(); 530 } 531 532 533 /* 534 * int ioctl(int fd, unsigned long cmd, ... arg); 535 */ 536 537 static __attribute__((unused)) 538 long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) 539 { 540 return my_syscall3(__NR_ioctl, fd, cmd, arg); 541 } 542 543 #define ioctl(fd, cmd, arg) __sysret(sys_ioctl(fd, cmd, (unsigned long)(arg))) 544 545 /* 546 * int kill(pid_t pid, int signal); 547 */ 548 549 static __attribute__((unused)) 550 int sys_kill(pid_t pid, int signal) 551 { 552 return my_syscall2(__NR_kill, pid, signal); 553 } 554 555 static __attribute__((unused)) 556 int kill(pid_t pid, int signal) 557 { 558 return __sysret(sys_kill(pid, signal)); 559 } 560 561 562 /* 563 * int link(const char *old, const char *new); 564 */ 565 566 static __attribute__((unused)) 567 int sys_link(const char *old, const char *new) 568 { 569 #ifdef __NR_linkat 570 return my_syscall5(__NR_linkat, AT_FDCWD, old, AT_FDCWD, new, 0); 571 #elif defined(__NR_link) 572 return my_syscall2(__NR_link, old, new); 573 #else 574 return __nolibc_enosys(__func__, old, new); 575 #endif 576 } 577 578 static __attribute__((unused)) 579 int link(const char *old, const char *new) 580 { 581 return __sysret(sys_link(old, new)); 582 } 583 584 585 /* 586 * off_t lseek(int fd, off_t offset, int whence); 587 */ 588 589 static __attribute__((unused)) 590 off_t sys_lseek(int fd, off_t offset, int whence) 591 { 592 #ifdef __NR_lseek 593 return my_syscall3(__NR_lseek, fd, offset, whence); 594 #else 595 return __nolibc_enosys(__func__, fd, offset, whence); 596 #endif 597 } 598 599 static __attribute__((unused)) 600 int sys_llseek(int fd, unsigned long offset_high, unsigned long offset_low, 601 __kernel_loff_t *result, int whence) 602 { 603 #ifdef __NR_llseek 604 return my_syscall5(__NR_llseek, fd, offset_high, offset_low, result, whence); 605 #else 606 return __nolibc_enosys(__func__, fd, offset_high, offset_low, result, whence); 607 #endif 608 } 609 610 static __attribute__((unused)) 611 off_t lseek(int fd, off_t offset, int whence) 612 { 613 __kernel_loff_t loff = 0; 614 off_t result; 615 int ret; 616 617 result = sys_lseek(fd, offset, whence); 618 if (result == -ENOSYS) { 619 /* Only exists on 32bit where nolibc off_t is also 32bit */ 620 ret = sys_llseek(fd, 0, offset, &loff, whence); 621 if (ret < 0) 622 result = ret; 623 else if (loff != (off_t)loff) 624 result = -EOVERFLOW; 625 else 626 result = loff; 627 } 628 629 return __sysret(result); 630 } 631 632 633 /* 634 * int mkdir(const char *path, mode_t mode); 635 */ 636 637 static __attribute__((unused)) 638 int sys_mkdir(const char *path, mode_t mode) 639 { 640 #ifdef __NR_mkdirat 641 return my_syscall3(__NR_mkdirat, AT_FDCWD, path, mode); 642 #elif defined(__NR_mkdir) 643 return my_syscall2(__NR_mkdir, path, mode); 644 #else 645 return __nolibc_enosys(__func__, path, mode); 646 #endif 647 } 648 649 static __attribute__((unused)) 650 int mkdir(const char *path, mode_t mode) 651 { 652 return __sysret(sys_mkdir(path, mode)); 653 } 654 655 /* 656 * int rmdir(const char *path); 657 */ 658 659 static __attribute__((unused)) 660 int sys_rmdir(const char *path) 661 { 662 #ifdef __NR_rmdir 663 return my_syscall1(__NR_rmdir, path); 664 #elif defined(__NR_unlinkat) 665 return my_syscall3(__NR_unlinkat, AT_FDCWD, path, AT_REMOVEDIR); 666 #else 667 return __nolibc_enosys(__func__, path); 668 #endif 669 } 670 671 static __attribute__((unused)) 672 int rmdir(const char *path) 673 { 674 return __sysret(sys_rmdir(path)); 675 } 676 677 678 /* 679 * int mknod(const char *path, mode_t mode, dev_t dev); 680 */ 681 682 static __attribute__((unused)) 683 long sys_mknod(const char *path, mode_t mode, dev_t dev) 684 { 685 #ifdef __NR_mknodat 686 return my_syscall4(__NR_mknodat, AT_FDCWD, path, mode, dev); 687 #elif defined(__NR_mknod) 688 return my_syscall3(__NR_mknod, path, mode, dev); 689 #else 690 return __nolibc_enosys(__func__, path, mode, dev); 691 #endif 692 } 693 694 static __attribute__((unused)) 695 int mknod(const char *path, mode_t mode, dev_t dev) 696 { 697 return __sysret(sys_mknod(path, mode, dev)); 698 } 699 700 #ifndef sys_mmap 701 static __attribute__((unused)) 702 void *sys_mmap(void *addr, size_t length, int prot, int flags, int fd, 703 off_t offset) 704 { 705 int n; 706 707 #if defined(__NR_mmap2) 708 n = __NR_mmap2; 709 offset >>= 12; 710 #else 711 n = __NR_mmap; 712 #endif 713 714 return (void *)my_syscall6(n, addr, length, prot, flags, fd, offset); 715 } 716 #endif 717 718 /* Note that on Linux, MAP_FAILED is -1 so we can use the generic __sysret() 719 * which returns -1 upon error and still satisfy user land that checks for 720 * MAP_FAILED. 721 */ 722 723 static __attribute__((unused)) 724 void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) 725 { 726 void *ret = sys_mmap(addr, length, prot, flags, fd, offset); 727 728 if ((unsigned long)ret >= -4095UL) { 729 SET_ERRNO(-(long)ret); 730 ret = MAP_FAILED; 731 } 732 return ret; 733 } 734 735 static __attribute__((unused)) 736 int sys_munmap(void *addr, size_t length) 737 { 738 return my_syscall2(__NR_munmap, addr, length); 739 } 740 741 static __attribute__((unused)) 742 int munmap(void *addr, size_t length) 743 { 744 return __sysret(sys_munmap(addr, length)); 745 } 746 747 /* 748 * int mount(const char *source, const char *target, 749 * const char *fstype, unsigned long flags, 750 * const void *data); 751 */ 752 static __attribute__((unused)) 753 int sys_mount(const char *src, const char *tgt, const char *fst, 754 unsigned long flags, const void *data) 755 { 756 return my_syscall5(__NR_mount, src, tgt, fst, flags, data); 757 } 758 759 static __attribute__((unused)) 760 int mount(const char *src, const char *tgt, 761 const char *fst, unsigned long flags, 762 const void *data) 763 { 764 return __sysret(sys_mount(src, tgt, fst, flags, data)); 765 } 766 767 /* 768 * int openat(int dirfd, const char *path, int flags[, mode_t mode]); 769 */ 770 771 static __attribute__((unused)) 772 int sys_openat(int dirfd, const char *path, int flags, mode_t mode) 773 { 774 return my_syscall4(__NR_openat, dirfd, path, flags, mode); 775 } 776 777 static __attribute__((unused)) 778 int openat(int dirfd, const char *path, int flags, ...) 779 { 780 mode_t mode = 0; 781 782 if (flags & O_CREAT) { 783 va_list args; 784 785 va_start(args, flags); 786 mode = va_arg(args, mode_t); 787 va_end(args); 788 } 789 790 return __sysret(sys_openat(dirfd, path, flags, mode)); 791 } 792 793 /* 794 * int open(const char *path, int flags[, mode_t mode]); 795 */ 796 797 static __attribute__((unused)) 798 int sys_open(const char *path, int flags, mode_t mode) 799 { 800 return my_syscall4(__NR_openat, AT_FDCWD, path, flags, mode); 801 } 802 803 static __attribute__((unused)) 804 int open(const char *path, int flags, ...) 805 { 806 mode_t mode = 0; 807 808 if (flags & O_CREAT) { 809 va_list args; 810 811 va_start(args, flags); 812 mode = va_arg(args, mode_t); 813 va_end(args); 814 } 815 816 return __sysret(sys_open(path, flags, mode)); 817 } 818 819 820 /* 821 * int pipe2(int pipefd[2], int flags); 822 * int pipe(int pipefd[2]); 823 */ 824 825 static __attribute__((unused)) 826 int sys_pipe2(int pipefd[2], int flags) 827 { 828 return my_syscall2(__NR_pipe2, pipefd, flags); 829 } 830 831 static __attribute__((unused)) 832 int pipe2(int pipefd[2], int flags) 833 { 834 return __sysret(sys_pipe2(pipefd, flags)); 835 } 836 837 static __attribute__((unused)) 838 int pipe(int pipefd[2]) 839 { 840 return pipe2(pipefd, 0); 841 } 842 843 844 /* 845 * int prctl(int option, unsigned long arg2, unsigned long arg3, 846 * unsigned long arg4, unsigned long arg5); 847 */ 848 849 static __attribute__((unused)) 850 int sys_prctl(int option, unsigned long arg2, unsigned long arg3, 851 unsigned long arg4, unsigned long arg5) 852 { 853 return my_syscall5(__NR_prctl, option, arg2, arg3, arg4, arg5); 854 } 855 856 static __attribute__((unused)) 857 int prctl(int option, unsigned long arg2, unsigned long arg3, 858 unsigned long arg4, unsigned long arg5) 859 { 860 return __sysret(sys_prctl(option, arg2, arg3, arg4, arg5)); 861 } 862 863 864 /* 865 * int pivot_root(const char *new, const char *old); 866 */ 867 868 static __attribute__((unused)) 869 int sys_pivot_root(const char *new, const char *old) 870 { 871 return my_syscall2(__NR_pivot_root, new, old); 872 } 873 874 static __attribute__((unused)) 875 int pivot_root(const char *new, const char *old) 876 { 877 return __sysret(sys_pivot_root(new, old)); 878 } 879 880 881 /* 882 * int poll(struct pollfd *fds, int nfds, int timeout); 883 */ 884 885 static __attribute__((unused)) 886 int sys_poll(struct pollfd *fds, int nfds, int timeout) 887 { 888 #if defined(__NR_ppoll) 889 struct timespec t; 890 891 if (timeout >= 0) { 892 t.tv_sec = timeout / 1000; 893 t.tv_nsec = (timeout % 1000) * 1000000; 894 } 895 return my_syscall5(__NR_ppoll, fds, nfds, (timeout >= 0) ? &t : NULL, NULL, 0); 896 #elif defined(__NR_poll) 897 return my_syscall3(__NR_poll, fds, nfds, timeout); 898 #else 899 return __nolibc_enosys(__func__, fds, nfds, timeout); 900 #endif 901 } 902 903 static __attribute__((unused)) 904 int poll(struct pollfd *fds, int nfds, int timeout) 905 { 906 return __sysret(sys_poll(fds, nfds, timeout)); 907 } 908 909 910 /* 911 * ssize_t read(int fd, void *buf, size_t count); 912 */ 913 914 static __attribute__((unused)) 915 ssize_t sys_read(int fd, void *buf, size_t count) 916 { 917 return my_syscall3(__NR_read, fd, buf, count); 918 } 919 920 static __attribute__((unused)) 921 ssize_t read(int fd, void *buf, size_t count) 922 { 923 return __sysret(sys_read(fd, buf, count)); 924 } 925 926 927 /* 928 * int reboot(int cmd); 929 * <cmd> is among LINUX_REBOOT_CMD_* 930 */ 931 932 static __attribute__((unused)) 933 ssize_t sys_reboot(int magic1, int magic2, int cmd, void *arg) 934 { 935 return my_syscall4(__NR_reboot, magic1, magic2, cmd, arg); 936 } 937 938 static __attribute__((unused)) 939 int reboot(int cmd) 940 { 941 return __sysret(sys_reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, 0)); 942 } 943 944 945 /* 946 * int getrlimit(int resource, struct rlimit *rlim); 947 * int setrlimit(int resource, const struct rlimit *rlim); 948 */ 949 950 static __attribute__((unused)) 951 int sys_prlimit64(pid_t pid, int resource, 952 const struct rlimit64 *new_limit, struct rlimit64 *old_limit) 953 { 954 return my_syscall4(__NR_prlimit64, pid, resource, new_limit, old_limit); 955 } 956 957 static __attribute__((unused)) 958 int getrlimit(int resource, struct rlimit *rlim) 959 { 960 struct rlimit64 rlim64; 961 int ret; 962 963 ret = __sysret(sys_prlimit64(0, resource, NULL, &rlim64)); 964 rlim->rlim_cur = rlim64.rlim_cur; 965 rlim->rlim_max = rlim64.rlim_max; 966 967 return ret; 968 } 969 970 static __attribute__((unused)) 971 int setrlimit(int resource, const struct rlimit *rlim) 972 { 973 struct rlimit64 rlim64 = { 974 .rlim_cur = rlim->rlim_cur, 975 .rlim_max = rlim->rlim_max, 976 }; 977 978 return __sysret(sys_prlimit64(0, resource, &rlim64, NULL)); 979 } 980 981 982 /* 983 * int sched_yield(void); 984 */ 985 986 static __attribute__((unused)) 987 int sys_sched_yield(void) 988 { 989 return my_syscall0(__NR_sched_yield); 990 } 991 992 static __attribute__((unused)) 993 int sched_yield(void) 994 { 995 return __sysret(sys_sched_yield()); 996 } 997 998 999 /* 1000 * int select(int nfds, fd_set *read_fds, fd_set *write_fds, 1001 * fd_set *except_fds, struct timeval *timeout); 1002 */ 1003 1004 static __attribute__((unused)) 1005 int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout) 1006 { 1007 #if defined(__ARCH_WANT_SYS_OLD_SELECT) && !defined(__NR__newselect) 1008 struct sel_arg_struct { 1009 unsigned long n; 1010 fd_set *r, *w, *e; 1011 struct timeval *t; 1012 } arg = { .n = nfds, .r = rfds, .w = wfds, .e = efds, .t = timeout }; 1013 return my_syscall1(__NR_select, &arg); 1014 #elif defined(__NR__newselect) 1015 return my_syscall5(__NR__newselect, nfds, rfds, wfds, efds, timeout); 1016 #elif defined(__NR_select) 1017 return my_syscall5(__NR_select, nfds, rfds, wfds, efds, timeout); 1018 #elif defined(__NR_pselect6) 1019 struct timespec t; 1020 1021 if (timeout) { 1022 t.tv_sec = timeout->tv_sec; 1023 t.tv_nsec = timeout->tv_usec * 1000; 1024 } 1025 return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL); 1026 #else 1027 return __nolibc_enosys(__func__, nfds, rfds, wfds, efds, timeout); 1028 #endif 1029 } 1030 1031 static __attribute__((unused)) 1032 int select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout) 1033 { 1034 return __sysret(sys_select(nfds, rfds, wfds, efds, timeout)); 1035 } 1036 1037 1038 /* 1039 * int setpgid(pid_t pid, pid_t pgid); 1040 */ 1041 1042 static __attribute__((unused)) 1043 int sys_setpgid(pid_t pid, pid_t pgid) 1044 { 1045 return my_syscall2(__NR_setpgid, pid, pgid); 1046 } 1047 1048 static __attribute__((unused)) 1049 int setpgid(pid_t pid, pid_t pgid) 1050 { 1051 return __sysret(sys_setpgid(pid, pgid)); 1052 } 1053 1054 1055 /* 1056 * pid_t setsid(void); 1057 */ 1058 1059 static __attribute__((unused)) 1060 pid_t sys_setsid(void) 1061 { 1062 return my_syscall0(__NR_setsid); 1063 } 1064 1065 static __attribute__((unused)) 1066 pid_t setsid(void) 1067 { 1068 return __sysret(sys_setsid()); 1069 } 1070 1071 /* 1072 * int statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf); 1073 * int stat(const char *path, struct stat *buf); 1074 */ 1075 1076 static __attribute__((unused)) 1077 int sys_statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf) 1078 { 1079 #ifdef __NR_statx 1080 return my_syscall5(__NR_statx, fd, path, flags, mask, buf); 1081 #else 1082 return __nolibc_enosys(__func__, fd, path, flags, mask, buf); 1083 #endif 1084 } 1085 1086 static __attribute__((unused)) 1087 int statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf) 1088 { 1089 return __sysret(sys_statx(fd, path, flags, mask, buf)); 1090 } 1091 1092 1093 static __attribute__((unused)) 1094 int stat(const char *path, struct stat *buf) 1095 { 1096 struct statx statx; 1097 long ret; 1098 1099 ret = __sysret(sys_statx(AT_FDCWD, path, AT_NO_AUTOMOUNT, STATX_BASIC_STATS, &statx)); 1100 if (ret == -1) 1101 return ret; 1102 1103 buf->st_dev = ((statx.stx_dev_minor & 0xff) 1104 | (statx.stx_dev_major << 8) 1105 | ((statx.stx_dev_minor & ~0xff) << 12)); 1106 buf->st_ino = statx.stx_ino; 1107 buf->st_mode = statx.stx_mode; 1108 buf->st_nlink = statx.stx_nlink; 1109 buf->st_uid = statx.stx_uid; 1110 buf->st_gid = statx.stx_gid; 1111 buf->st_rdev = ((statx.stx_rdev_minor & 0xff) 1112 | (statx.stx_rdev_major << 8) 1113 | ((statx.stx_rdev_minor & ~0xff) << 12)); 1114 buf->st_size = statx.stx_size; 1115 buf->st_blksize = statx.stx_blksize; 1116 buf->st_blocks = statx.stx_blocks; 1117 buf->st_atim.tv_sec = statx.stx_atime.tv_sec; 1118 buf->st_atim.tv_nsec = statx.stx_atime.tv_nsec; 1119 buf->st_mtim.tv_sec = statx.stx_mtime.tv_sec; 1120 buf->st_mtim.tv_nsec = statx.stx_mtime.tv_nsec; 1121 buf->st_ctim.tv_sec = statx.stx_ctime.tv_sec; 1122 buf->st_ctim.tv_nsec = statx.stx_ctime.tv_nsec; 1123 1124 return 0; 1125 } 1126 1127 1128 /* 1129 * int symlink(const char *old, const char *new); 1130 */ 1131 1132 static __attribute__((unused)) 1133 int sys_symlink(const char *old, const char *new) 1134 { 1135 #ifdef __NR_symlinkat 1136 return my_syscall3(__NR_symlinkat, old, AT_FDCWD, new); 1137 #elif defined(__NR_symlink) 1138 return my_syscall2(__NR_symlink, old, new); 1139 #else 1140 return __nolibc_enosys(__func__, old, new); 1141 #endif 1142 } 1143 1144 static __attribute__((unused)) 1145 int symlink(const char *old, const char *new) 1146 { 1147 return __sysret(sys_symlink(old, new)); 1148 } 1149 1150 1151 /* 1152 * mode_t umask(mode_t mode); 1153 */ 1154 1155 static __attribute__((unused)) 1156 mode_t sys_umask(mode_t mode) 1157 { 1158 return my_syscall1(__NR_umask, mode); 1159 } 1160 1161 static __attribute__((unused)) 1162 mode_t umask(mode_t mode) 1163 { 1164 return sys_umask(mode); 1165 } 1166 1167 1168 /* 1169 * int umount2(const char *path, int flags); 1170 */ 1171 1172 static __attribute__((unused)) 1173 int sys_umount2(const char *path, int flags) 1174 { 1175 return my_syscall2(__NR_umount2, path, flags); 1176 } 1177 1178 static __attribute__((unused)) 1179 int umount2(const char *path, int flags) 1180 { 1181 return __sysret(sys_umount2(path, flags)); 1182 } 1183 1184 1185 /* 1186 * int uname(struct utsname *buf); 1187 */ 1188 1189 struct utsname { 1190 char sysname[65]; 1191 char nodename[65]; 1192 char release[65]; 1193 char version[65]; 1194 char machine[65]; 1195 char domainname[65]; 1196 }; 1197 1198 static __attribute__((unused)) 1199 int sys_uname(struct utsname *buf) 1200 { 1201 return my_syscall1(__NR_uname, buf); 1202 } 1203 1204 static __attribute__((unused)) 1205 int uname(struct utsname *buf) 1206 { 1207 return __sysret(sys_uname(buf)); 1208 } 1209 1210 1211 /* 1212 * int unlink(const char *path); 1213 */ 1214 1215 static __attribute__((unused)) 1216 int sys_unlink(const char *path) 1217 { 1218 #ifdef __NR_unlinkat 1219 return my_syscall3(__NR_unlinkat, AT_FDCWD, path, 0); 1220 #elif defined(__NR_unlink) 1221 return my_syscall1(__NR_unlink, path); 1222 #else 1223 return __nolibc_enosys(__func__, path); 1224 #endif 1225 } 1226 1227 static __attribute__((unused)) 1228 int unlink(const char *path) 1229 { 1230 return __sysret(sys_unlink(path)); 1231 } 1232 1233 1234 /* 1235 * pid_t wait(int *status); 1236 * pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage); 1237 * pid_t waitpid(pid_t pid, int *status, int options); 1238 */ 1239 1240 static __attribute__((unused)) 1241 pid_t sys_wait4(pid_t pid, int *status, int options, struct rusage *rusage) 1242 { 1243 #ifdef __NR_wait4 1244 return my_syscall4(__NR_wait4, pid, status, options, rusage); 1245 #else 1246 return __nolibc_enosys(__func__, pid, status, options, rusage); 1247 #endif 1248 } 1249 1250 static __attribute__((unused)) 1251 pid_t wait(int *status) 1252 { 1253 return __sysret(sys_wait4(-1, status, 0, NULL)); 1254 } 1255 1256 static __attribute__((unused)) 1257 pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage) 1258 { 1259 return __sysret(sys_wait4(pid, status, options, rusage)); 1260 } 1261 1262 1263 static __attribute__((unused)) 1264 pid_t waitpid(pid_t pid, int *status, int options) 1265 { 1266 return __sysret(sys_wait4(pid, status, options, NULL)); 1267 } 1268 1269 1270 /* 1271 * int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options); 1272 */ 1273 1274 static __attribute__((unused)) 1275 int sys_waitid(int which, pid_t pid, siginfo_t *infop, int options, struct rusage *rusage) 1276 { 1277 return my_syscall5(__NR_waitid, which, pid, infop, options, rusage); 1278 } 1279 1280 static __attribute__((unused)) 1281 int waitid(int which, pid_t pid, siginfo_t *infop, int options) 1282 { 1283 return __sysret(sys_waitid(which, pid, infop, options, NULL)); 1284 } 1285 1286 1287 /* 1288 * ssize_t write(int fd, const void *buf, size_t count); 1289 */ 1290 1291 static __attribute__((unused)) 1292 ssize_t sys_write(int fd, const void *buf, size_t count) 1293 { 1294 return my_syscall3(__NR_write, fd, buf, count); 1295 } 1296 1297 static __attribute__((unused)) 1298 ssize_t write(int fd, const void *buf, size_t count) 1299 { 1300 return __sysret(sys_write(fd, buf, count)); 1301 } 1302 1303 1304 /* 1305 * int memfd_create(const char *name, unsigned int flags); 1306 */ 1307 1308 static __attribute__((unused)) 1309 int sys_memfd_create(const char *name, unsigned int flags) 1310 { 1311 return my_syscall2(__NR_memfd_create, name, flags); 1312 } 1313 1314 static __attribute__((unused)) 1315 int memfd_create(const char *name, unsigned int flags) 1316 { 1317 return __sysret(sys_memfd_create(name, flags)); 1318 } 1319 1320 /* make sure to include all global symbols */ 1321 #include "nolibc.h" 1322 1323 #endif /* _NOLIBC_SYS_H */ 1324