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 <asm/unistd.h> 14 #include <asm/signal.h> /* for SIGCHLD */ 15 #include <asm/ioctls.h> 16 #include <asm/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 req, void *value); 535 */ 536 537 static __attribute__((unused)) 538 int sys_ioctl(int fd, unsigned long req, void *value) 539 { 540 return my_syscall3(__NR_ioctl, fd, req, value); 541 } 542 543 static __attribute__((unused)) 544 int ioctl(int fd, unsigned long req, void *value) 545 { 546 return __sysret(sys_ioctl(fd, req, value)); 547 } 548 549 /* 550 * int kill(pid_t pid, int signal); 551 */ 552 553 static __attribute__((unused)) 554 int sys_kill(pid_t pid, int signal) 555 { 556 return my_syscall2(__NR_kill, pid, signal); 557 } 558 559 static __attribute__((unused)) 560 int kill(pid_t pid, int signal) 561 { 562 return __sysret(sys_kill(pid, signal)); 563 } 564 565 566 /* 567 * int link(const char *old, const char *new); 568 */ 569 570 static __attribute__((unused)) 571 int sys_link(const char *old, const char *new) 572 { 573 #ifdef __NR_linkat 574 return my_syscall5(__NR_linkat, AT_FDCWD, old, AT_FDCWD, new, 0); 575 #elif defined(__NR_link) 576 return my_syscall2(__NR_link, old, new); 577 #else 578 return __nolibc_enosys(__func__, old, new); 579 #endif 580 } 581 582 static __attribute__((unused)) 583 int link(const char *old, const char *new) 584 { 585 return __sysret(sys_link(old, new)); 586 } 587 588 589 /* 590 * off_t lseek(int fd, off_t offset, int whence); 591 */ 592 593 static __attribute__((unused)) 594 off_t sys_lseek(int fd, off_t offset, int whence) 595 { 596 #ifdef __NR_lseek 597 return my_syscall3(__NR_lseek, fd, offset, whence); 598 #else 599 return __nolibc_enosys(__func__, fd, offset, whence); 600 #endif 601 } 602 603 static __attribute__((unused)) 604 off_t lseek(int fd, off_t offset, int whence) 605 { 606 return __sysret(sys_lseek(fd, offset, whence)); 607 } 608 609 610 /* 611 * int mkdir(const char *path, mode_t mode); 612 */ 613 614 static __attribute__((unused)) 615 int sys_mkdir(const char *path, mode_t mode) 616 { 617 #ifdef __NR_mkdirat 618 return my_syscall3(__NR_mkdirat, AT_FDCWD, path, mode); 619 #elif defined(__NR_mkdir) 620 return my_syscall2(__NR_mkdir, path, mode); 621 #else 622 return __nolibc_enosys(__func__, path, mode); 623 #endif 624 } 625 626 static __attribute__((unused)) 627 int mkdir(const char *path, mode_t mode) 628 { 629 return __sysret(sys_mkdir(path, mode)); 630 } 631 632 /* 633 * int rmdir(const char *path); 634 */ 635 636 static __attribute__((unused)) 637 int sys_rmdir(const char *path) 638 { 639 #ifdef __NR_rmdir 640 return my_syscall1(__NR_rmdir, path); 641 #elif defined(__NR_unlinkat) 642 return my_syscall3(__NR_unlinkat, AT_FDCWD, path, AT_REMOVEDIR); 643 #else 644 return __nolibc_enosys(__func__, path); 645 #endif 646 } 647 648 static __attribute__((unused)) 649 int rmdir(const char *path) 650 { 651 return __sysret(sys_rmdir(path)); 652 } 653 654 655 /* 656 * int mknod(const char *path, mode_t mode, dev_t dev); 657 */ 658 659 static __attribute__((unused)) 660 long sys_mknod(const char *path, mode_t mode, dev_t dev) 661 { 662 #ifdef __NR_mknodat 663 return my_syscall4(__NR_mknodat, AT_FDCWD, path, mode, dev); 664 #elif defined(__NR_mknod) 665 return my_syscall3(__NR_mknod, path, mode, dev); 666 #else 667 return __nolibc_enosys(__func__, path, mode, dev); 668 #endif 669 } 670 671 static __attribute__((unused)) 672 int mknod(const char *path, mode_t mode, dev_t dev) 673 { 674 return __sysret(sys_mknod(path, mode, dev)); 675 } 676 677 #ifndef sys_mmap 678 static __attribute__((unused)) 679 void *sys_mmap(void *addr, size_t length, int prot, int flags, int fd, 680 off_t offset) 681 { 682 int n; 683 684 #if defined(__NR_mmap2) 685 n = __NR_mmap2; 686 offset >>= 12; 687 #else 688 n = __NR_mmap; 689 #endif 690 691 return (void *)my_syscall6(n, addr, length, prot, flags, fd, offset); 692 } 693 #endif 694 695 /* Note that on Linux, MAP_FAILED is -1 so we can use the generic __sysret() 696 * which returns -1 upon error and still satisfy user land that checks for 697 * MAP_FAILED. 698 */ 699 700 static __attribute__((unused)) 701 void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) 702 { 703 void *ret = sys_mmap(addr, length, prot, flags, fd, offset); 704 705 if ((unsigned long)ret >= -4095UL) { 706 SET_ERRNO(-(long)ret); 707 ret = MAP_FAILED; 708 } 709 return ret; 710 } 711 712 static __attribute__((unused)) 713 int sys_munmap(void *addr, size_t length) 714 { 715 return my_syscall2(__NR_munmap, addr, length); 716 } 717 718 static __attribute__((unused)) 719 int munmap(void *addr, size_t length) 720 { 721 return __sysret(sys_munmap(addr, length)); 722 } 723 724 /* 725 * int mount(const char *source, const char *target, 726 * const char *fstype, unsigned long flags, 727 * const void *data); 728 */ 729 static __attribute__((unused)) 730 int sys_mount(const char *src, const char *tgt, const char *fst, 731 unsigned long flags, const void *data) 732 { 733 return my_syscall5(__NR_mount, src, tgt, fst, flags, data); 734 } 735 736 static __attribute__((unused)) 737 int mount(const char *src, const char *tgt, 738 const char *fst, unsigned long flags, 739 const void *data) 740 { 741 return __sysret(sys_mount(src, tgt, fst, flags, data)); 742 } 743 744 745 /* 746 * int open(const char *path, int flags[, mode_t mode]); 747 */ 748 749 static __attribute__((unused)) 750 int sys_open(const char *path, int flags, mode_t mode) 751 { 752 #ifdef __NR_openat 753 return my_syscall4(__NR_openat, AT_FDCWD, path, flags, mode); 754 #elif defined(__NR_open) 755 return my_syscall3(__NR_open, path, flags, mode); 756 #else 757 return __nolibc_enosys(__func__, path, flags, mode); 758 #endif 759 } 760 761 static __attribute__((unused)) 762 int open(const char *path, int flags, ...) 763 { 764 mode_t mode = 0; 765 766 if (flags & O_CREAT) { 767 va_list args; 768 769 va_start(args, flags); 770 mode = va_arg(args, int); 771 va_end(args); 772 } 773 774 return __sysret(sys_open(path, flags, mode)); 775 } 776 777 778 /* 779 * int pipe2(int pipefd[2], int flags); 780 * int pipe(int pipefd[2]); 781 */ 782 783 static __attribute__((unused)) 784 int sys_pipe2(int pipefd[2], int flags) 785 { 786 return my_syscall2(__NR_pipe2, pipefd, flags); 787 } 788 789 static __attribute__((unused)) 790 int pipe2(int pipefd[2], int flags) 791 { 792 return __sysret(sys_pipe2(pipefd, flags)); 793 } 794 795 static __attribute__((unused)) 796 int pipe(int pipefd[2]) 797 { 798 return pipe2(pipefd, 0); 799 } 800 801 802 /* 803 * int prctl(int option, unsigned long arg2, unsigned long arg3, 804 * unsigned long arg4, unsigned long arg5); 805 */ 806 807 static __attribute__((unused)) 808 int sys_prctl(int option, unsigned long arg2, unsigned long arg3, 809 unsigned long arg4, unsigned long arg5) 810 { 811 return my_syscall5(__NR_prctl, option, arg2, arg3, arg4, arg5); 812 } 813 814 static __attribute__((unused)) 815 int prctl(int option, unsigned long arg2, unsigned long arg3, 816 unsigned long arg4, unsigned long arg5) 817 { 818 return __sysret(sys_prctl(option, arg2, arg3, arg4, arg5)); 819 } 820 821 822 /* 823 * int pivot_root(const char *new, const char *old); 824 */ 825 826 static __attribute__((unused)) 827 int sys_pivot_root(const char *new, const char *old) 828 { 829 return my_syscall2(__NR_pivot_root, new, old); 830 } 831 832 static __attribute__((unused)) 833 int pivot_root(const char *new, const char *old) 834 { 835 return __sysret(sys_pivot_root(new, old)); 836 } 837 838 839 /* 840 * int poll(struct pollfd *fds, int nfds, int timeout); 841 */ 842 843 static __attribute__((unused)) 844 int sys_poll(struct pollfd *fds, int nfds, int timeout) 845 { 846 #if defined(__NR_ppoll) 847 struct timespec t; 848 849 if (timeout >= 0) { 850 t.tv_sec = timeout / 1000; 851 t.tv_nsec = (timeout % 1000) * 1000000; 852 } 853 return my_syscall5(__NR_ppoll, fds, nfds, (timeout >= 0) ? &t : NULL, NULL, 0); 854 #elif defined(__NR_poll) 855 return my_syscall3(__NR_poll, fds, nfds, timeout); 856 #else 857 return __nolibc_enosys(__func__, fds, nfds, timeout); 858 #endif 859 } 860 861 static __attribute__((unused)) 862 int poll(struct pollfd *fds, int nfds, int timeout) 863 { 864 return __sysret(sys_poll(fds, nfds, timeout)); 865 } 866 867 868 /* 869 * ssize_t read(int fd, void *buf, size_t count); 870 */ 871 872 static __attribute__((unused)) 873 ssize_t sys_read(int fd, void *buf, size_t count) 874 { 875 return my_syscall3(__NR_read, fd, buf, count); 876 } 877 878 static __attribute__((unused)) 879 ssize_t read(int fd, void *buf, size_t count) 880 { 881 return __sysret(sys_read(fd, buf, count)); 882 } 883 884 885 /* 886 * int reboot(int cmd); 887 * <cmd> is among LINUX_REBOOT_CMD_* 888 */ 889 890 static __attribute__((unused)) 891 ssize_t sys_reboot(int magic1, int magic2, int cmd, void *arg) 892 { 893 return my_syscall4(__NR_reboot, magic1, magic2, cmd, arg); 894 } 895 896 static __attribute__((unused)) 897 int reboot(int cmd) 898 { 899 return __sysret(sys_reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, 0)); 900 } 901 902 903 /* 904 * int getrlimit(int resource, struct rlimit *rlim); 905 * int setrlimit(int resource, const struct rlimit *rlim); 906 */ 907 908 static __attribute__((unused)) 909 int sys_prlimit64(pid_t pid, int resource, 910 const struct rlimit64 *new_limit, struct rlimit64 *old_limit) 911 { 912 return my_syscall4(__NR_prlimit64, pid, resource, new_limit, old_limit); 913 } 914 915 static __attribute__((unused)) 916 int getrlimit(int resource, struct rlimit *rlim) 917 { 918 struct rlimit64 rlim64; 919 int ret; 920 921 ret = __sysret(sys_prlimit64(0, resource, NULL, &rlim64)); 922 rlim->rlim_cur = rlim64.rlim_cur; 923 rlim->rlim_max = rlim64.rlim_max; 924 925 return ret; 926 } 927 928 static __attribute__((unused)) 929 int setrlimit(int resource, const struct rlimit *rlim) 930 { 931 struct rlimit64 rlim64 = { 932 .rlim_cur = rlim->rlim_cur, 933 .rlim_max = rlim->rlim_max, 934 }; 935 936 return __sysret(sys_prlimit64(0, resource, &rlim64, NULL)); 937 } 938 939 940 /* 941 * int sched_yield(void); 942 */ 943 944 static __attribute__((unused)) 945 int sys_sched_yield(void) 946 { 947 return my_syscall0(__NR_sched_yield); 948 } 949 950 static __attribute__((unused)) 951 int sched_yield(void) 952 { 953 return __sysret(sys_sched_yield()); 954 } 955 956 957 /* 958 * int select(int nfds, fd_set *read_fds, fd_set *write_fds, 959 * fd_set *except_fds, struct timeval *timeout); 960 */ 961 962 static __attribute__((unused)) 963 int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout) 964 { 965 #if defined(__ARCH_WANT_SYS_OLD_SELECT) && !defined(__NR__newselect) 966 struct sel_arg_struct { 967 unsigned long n; 968 fd_set *r, *w, *e; 969 struct timeval *t; 970 } arg = { .n = nfds, .r = rfds, .w = wfds, .e = efds, .t = timeout }; 971 return my_syscall1(__NR_select, &arg); 972 #elif defined(__NR__newselect) 973 return my_syscall5(__NR__newselect, nfds, rfds, wfds, efds, timeout); 974 #elif defined(__NR_select) 975 return my_syscall5(__NR_select, nfds, rfds, wfds, efds, timeout); 976 #elif defined(__NR_pselect6) 977 struct timespec t; 978 979 if (timeout) { 980 t.tv_sec = timeout->tv_sec; 981 t.tv_nsec = timeout->tv_usec * 1000; 982 } 983 return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL); 984 #else 985 return __nolibc_enosys(__func__, nfds, rfds, wfds, efds, timeout); 986 #endif 987 } 988 989 static __attribute__((unused)) 990 int select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout) 991 { 992 return __sysret(sys_select(nfds, rfds, wfds, efds, timeout)); 993 } 994 995 996 /* 997 * int setpgid(pid_t pid, pid_t pgid); 998 */ 999 1000 static __attribute__((unused)) 1001 int sys_setpgid(pid_t pid, pid_t pgid) 1002 { 1003 return my_syscall2(__NR_setpgid, pid, pgid); 1004 } 1005 1006 static __attribute__((unused)) 1007 int setpgid(pid_t pid, pid_t pgid) 1008 { 1009 return __sysret(sys_setpgid(pid, pgid)); 1010 } 1011 1012 1013 /* 1014 * pid_t setsid(void); 1015 */ 1016 1017 static __attribute__((unused)) 1018 pid_t sys_setsid(void) 1019 { 1020 return my_syscall0(__NR_setsid); 1021 } 1022 1023 static __attribute__((unused)) 1024 pid_t setsid(void) 1025 { 1026 return __sysret(sys_setsid()); 1027 } 1028 1029 /* 1030 * int statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf); 1031 * int stat(const char *path, struct stat *buf); 1032 */ 1033 1034 static __attribute__((unused)) 1035 int sys_statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf) 1036 { 1037 #ifdef __NR_statx 1038 return my_syscall5(__NR_statx, fd, path, flags, mask, buf); 1039 #else 1040 return __nolibc_enosys(__func__, fd, path, flags, mask, buf); 1041 #endif 1042 } 1043 1044 static __attribute__((unused)) 1045 int statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf) 1046 { 1047 return __sysret(sys_statx(fd, path, flags, mask, buf)); 1048 } 1049 1050 1051 static __attribute__((unused)) 1052 int stat(const char *path, struct stat *buf) 1053 { 1054 struct statx statx; 1055 long ret; 1056 1057 ret = __sysret(sys_statx(AT_FDCWD, path, AT_NO_AUTOMOUNT, STATX_BASIC_STATS, &statx)); 1058 if (ret == -1) 1059 return ret; 1060 1061 buf->st_dev = ((statx.stx_dev_minor & 0xff) 1062 | (statx.stx_dev_major << 8) 1063 | ((statx.stx_dev_minor & ~0xff) << 12)); 1064 buf->st_ino = statx.stx_ino; 1065 buf->st_mode = statx.stx_mode; 1066 buf->st_nlink = statx.stx_nlink; 1067 buf->st_uid = statx.stx_uid; 1068 buf->st_gid = statx.stx_gid; 1069 buf->st_rdev = ((statx.stx_rdev_minor & 0xff) 1070 | (statx.stx_rdev_major << 8) 1071 | ((statx.stx_rdev_minor & ~0xff) << 12)); 1072 buf->st_size = statx.stx_size; 1073 buf->st_blksize = statx.stx_blksize; 1074 buf->st_blocks = statx.stx_blocks; 1075 buf->st_atim.tv_sec = statx.stx_atime.tv_sec; 1076 buf->st_atim.tv_nsec = statx.stx_atime.tv_nsec; 1077 buf->st_mtim.tv_sec = statx.stx_mtime.tv_sec; 1078 buf->st_mtim.tv_nsec = statx.stx_mtime.tv_nsec; 1079 buf->st_ctim.tv_sec = statx.stx_ctime.tv_sec; 1080 buf->st_ctim.tv_nsec = statx.stx_ctime.tv_nsec; 1081 1082 return 0; 1083 } 1084 1085 1086 /* 1087 * int symlink(const char *old, const char *new); 1088 */ 1089 1090 static __attribute__((unused)) 1091 int sys_symlink(const char *old, const char *new) 1092 { 1093 #ifdef __NR_symlinkat 1094 return my_syscall3(__NR_symlinkat, old, AT_FDCWD, new); 1095 #elif defined(__NR_symlink) 1096 return my_syscall2(__NR_symlink, old, new); 1097 #else 1098 return __nolibc_enosys(__func__, old, new); 1099 #endif 1100 } 1101 1102 static __attribute__((unused)) 1103 int symlink(const char *old, const char *new) 1104 { 1105 return __sysret(sys_symlink(old, new)); 1106 } 1107 1108 1109 /* 1110 * mode_t umask(mode_t mode); 1111 */ 1112 1113 static __attribute__((unused)) 1114 mode_t sys_umask(mode_t mode) 1115 { 1116 return my_syscall1(__NR_umask, mode); 1117 } 1118 1119 static __attribute__((unused)) 1120 mode_t umask(mode_t mode) 1121 { 1122 return sys_umask(mode); 1123 } 1124 1125 1126 /* 1127 * int umount2(const char *path, int flags); 1128 */ 1129 1130 static __attribute__((unused)) 1131 int sys_umount2(const char *path, int flags) 1132 { 1133 return my_syscall2(__NR_umount2, path, flags); 1134 } 1135 1136 static __attribute__((unused)) 1137 int umount2(const char *path, int flags) 1138 { 1139 return __sysret(sys_umount2(path, flags)); 1140 } 1141 1142 1143 /* 1144 * int uname(struct utsname *buf); 1145 */ 1146 1147 struct utsname { 1148 char sysname[65]; 1149 char nodename[65]; 1150 char release[65]; 1151 char version[65]; 1152 char machine[65]; 1153 char domainname[65]; 1154 }; 1155 1156 static __attribute__((unused)) 1157 int sys_uname(struct utsname *buf) 1158 { 1159 return my_syscall1(__NR_uname, buf); 1160 } 1161 1162 static __attribute__((unused)) 1163 int uname(struct utsname *buf) 1164 { 1165 return __sysret(sys_uname(buf)); 1166 } 1167 1168 1169 /* 1170 * int unlink(const char *path); 1171 */ 1172 1173 static __attribute__((unused)) 1174 int sys_unlink(const char *path) 1175 { 1176 #ifdef __NR_unlinkat 1177 return my_syscall3(__NR_unlinkat, AT_FDCWD, path, 0); 1178 #elif defined(__NR_unlink) 1179 return my_syscall1(__NR_unlink, path); 1180 #else 1181 return __nolibc_enosys(__func__, path); 1182 #endif 1183 } 1184 1185 static __attribute__((unused)) 1186 int unlink(const char *path) 1187 { 1188 return __sysret(sys_unlink(path)); 1189 } 1190 1191 1192 /* 1193 * pid_t wait(int *status); 1194 * pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage); 1195 * pid_t waitpid(pid_t pid, int *status, int options); 1196 */ 1197 1198 static __attribute__((unused)) 1199 pid_t sys_wait4(pid_t pid, int *status, int options, struct rusage *rusage) 1200 { 1201 #ifdef __NR_wait4 1202 return my_syscall4(__NR_wait4, pid, status, options, rusage); 1203 #else 1204 return __nolibc_enosys(__func__, pid, status, options, rusage); 1205 #endif 1206 } 1207 1208 static __attribute__((unused)) 1209 pid_t wait(int *status) 1210 { 1211 return __sysret(sys_wait4(-1, status, 0, NULL)); 1212 } 1213 1214 static __attribute__((unused)) 1215 pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage) 1216 { 1217 return __sysret(sys_wait4(pid, status, options, rusage)); 1218 } 1219 1220 1221 static __attribute__((unused)) 1222 pid_t waitpid(pid_t pid, int *status, int options) 1223 { 1224 return __sysret(sys_wait4(pid, status, options, NULL)); 1225 } 1226 1227 1228 /* 1229 * ssize_t write(int fd, const void *buf, size_t count); 1230 */ 1231 1232 static __attribute__((unused)) 1233 ssize_t sys_write(int fd, const void *buf, size_t count) 1234 { 1235 return my_syscall3(__NR_write, fd, buf, count); 1236 } 1237 1238 static __attribute__((unused)) 1239 ssize_t write(int fd, const void *buf, size_t count) 1240 { 1241 return __sysret(sys_write(fd, buf, count)); 1242 } 1243 1244 1245 /* 1246 * int memfd_create(const char *name, unsigned int flags); 1247 */ 1248 1249 static __attribute__((unused)) 1250 int sys_memfd_create(const char *name, unsigned int flags) 1251 { 1252 return my_syscall2(__NR_memfd_create, name, flags); 1253 } 1254 1255 static __attribute__((unused)) 1256 int memfd_create(const char *name, unsigned int flags) 1257 { 1258 return __sysret(sys_memfd_create(name, flags)); 1259 } 1260 1261 /* make sure to include all global symbols */ 1262 #include "nolibc.h" 1263 1264 #endif /* _NOLIBC_SYS_H */ 1265