at v6.15 1323 lines 27 kB view raw
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 52static __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 87static __attribute__((unused)) 88void *sys_brk(void *addr) 89{ 90 return (void *)my_syscall1(__NR_brk, addr); 91} 92 93static __attribute__((unused)) 94int 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 105static __attribute__((unused)) 106void *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 123static __attribute__((unused)) 124int sys_chdir(const char *path) 125{ 126 return my_syscall1(__NR_chdir, path); 127} 128 129static __attribute__((unused)) 130int 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 140static __attribute__((unused)) 141int 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 152static __attribute__((unused)) 153int 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 163static __attribute__((unused)) 164int 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 175static __attribute__((unused)) 176int 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 186static __attribute__((unused)) 187int sys_chroot(const char *path) 188{ 189 return my_syscall1(__NR_chroot, path); 190} 191 192static __attribute__((unused)) 193int chroot(const char *path) 194{ 195 return __sysret(sys_chroot(path)); 196} 197 198 199/* 200 * int close(int fd); 201 */ 202 203static __attribute__((unused)) 204int sys_close(int fd) 205{ 206 return my_syscall1(__NR_close, fd); 207} 208 209static __attribute__((unused)) 210int close(int fd) 211{ 212 return __sysret(sys_close(fd)); 213} 214 215 216/* 217 * int dup(int fd); 218 */ 219 220static __attribute__((unused)) 221int sys_dup(int fd) 222{ 223 return my_syscall1(__NR_dup, fd); 224} 225 226static __attribute__((unused)) 227int dup(int fd) 228{ 229 return __sysret(sys_dup(fd)); 230} 231 232 233/* 234 * int dup2(int old, int new); 235 */ 236 237static __attribute__((unused)) 238int 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 249static __attribute__((unused)) 250int 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 261static __attribute__((unused)) 262int sys_dup3(int old, int new, int flags) 263{ 264 return my_syscall3(__NR_dup3, old, new, flags); 265} 266 267static __attribute__((unused)) 268int 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 279static __attribute__((unused)) 280int sys_execve(const char *filename, char *const argv[], char *const envp[]) 281{ 282 return my_syscall3(__NR_execve, filename, argv, envp); 283} 284 285static __attribute__((unused)) 286int 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 296static __attribute__((noreturn,unused)) 297void sys_exit(int status) 298{ 299 my_syscall1(__NR_exit, status & 255); 300 while(1); /* shut the "noreturn" warnings. */ 301} 302 303static __attribute__((noreturn,unused)) 304void exit(int status) 305{ 306 sys_exit(status); 307} 308 309 310/* 311 * pid_t fork(void); 312 */ 313 314#ifndef sys_fork 315static __attribute__((unused)) 316pid_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 332static __attribute__((unused)) 333pid_t fork(void) 334{ 335 return __sysret(sys_fork()); 336} 337 338 339/* 340 * int fsync(int fd); 341 */ 342 343static __attribute__((unused)) 344int sys_fsync(int fd) 345{ 346 return my_syscall1(__NR_fsync, fd); 347} 348 349static __attribute__((unused)) 350int 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 360static __attribute__((unused)) 361int sys_getdents64(int fd, struct linux_dirent64 *dirp, int count) 362{ 363 return my_syscall3(__NR_getdents64, fd, dirp, count); 364} 365 366static __attribute__((unused)) 367int 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 377static __attribute__((unused)) 378uid_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 387static __attribute__((unused)) 388uid_t geteuid(void) 389{ 390 return sys_geteuid(); 391} 392 393 394/* 395 * pid_t getpgid(pid_t pid); 396 */ 397 398static __attribute__((unused)) 399pid_t sys_getpgid(pid_t pid) 400{ 401 return my_syscall1(__NR_getpgid, pid); 402} 403 404static __attribute__((unused)) 405pid_t getpgid(pid_t pid) 406{ 407 return __sysret(sys_getpgid(pid)); 408} 409 410 411/* 412 * pid_t getpgrp(void); 413 */ 414 415static __attribute__((unused)) 416pid_t sys_getpgrp(void) 417{ 418 return sys_getpgid(0); 419} 420 421static __attribute__((unused)) 422pid_t getpgrp(void) 423{ 424 return sys_getpgrp(); 425} 426 427 428/* 429 * pid_t getpid(void); 430 */ 431 432static __attribute__((unused)) 433pid_t sys_getpid(void) 434{ 435 return my_syscall0(__NR_getpid); 436} 437 438static __attribute__((unused)) 439pid_t getpid(void) 440{ 441 return sys_getpid(); 442} 443 444 445/* 446 * pid_t getppid(void); 447 */ 448 449static __attribute__((unused)) 450pid_t sys_getppid(void) 451{ 452 return my_syscall0(__NR_getppid); 453} 454 455static __attribute__((unused)) 456pid_t getppid(void) 457{ 458 return sys_getppid(); 459} 460 461 462/* 463 * pid_t gettid(void); 464 */ 465 466static __attribute__((unused)) 467pid_t sys_gettid(void) 468{ 469 return my_syscall0(__NR_gettid); 470} 471 472static __attribute__((unused)) 473pid_t gettid(void) 474{ 475 return sys_gettid(); 476} 477 478static unsigned long getauxval(unsigned long key); 479 480/* 481 * int getpagesize(void); 482 */ 483 484static __attribute__((unused)) 485int 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 495static __attribute__((unused)) 496int 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 505static __attribute__((unused)) 506int 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 516static __attribute__((unused)) 517uid_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 526static __attribute__((unused)) 527uid_t getuid(void) 528{ 529 return sys_getuid(); 530} 531 532 533/* 534 * int ioctl(int fd, unsigned long cmd, ... arg); 535 */ 536 537static __attribute__((unused)) 538long 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 549static __attribute__((unused)) 550int sys_kill(pid_t pid, int signal) 551{ 552 return my_syscall2(__NR_kill, pid, signal); 553} 554 555static __attribute__((unused)) 556int 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 566static __attribute__((unused)) 567int 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 578static __attribute__((unused)) 579int 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 589static __attribute__((unused)) 590off_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 599static __attribute__((unused)) 600int 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 610static __attribute__((unused)) 611off_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 637static __attribute__((unused)) 638int 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 649static __attribute__((unused)) 650int 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 659static __attribute__((unused)) 660int 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 671static __attribute__((unused)) 672int 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 682static __attribute__((unused)) 683long 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 694static __attribute__((unused)) 695int 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 701static __attribute__((unused)) 702void *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 723static __attribute__((unused)) 724void *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 735static __attribute__((unused)) 736int sys_munmap(void *addr, size_t length) 737{ 738 return my_syscall2(__NR_munmap, addr, length); 739} 740 741static __attribute__((unused)) 742int 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 */ 752static __attribute__((unused)) 753int 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 759static __attribute__((unused)) 760int 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 771static __attribute__((unused)) 772int 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 777static __attribute__((unused)) 778int 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 797static __attribute__((unused)) 798int sys_open(const char *path, int flags, mode_t mode) 799{ 800 return my_syscall4(__NR_openat, AT_FDCWD, path, flags, mode); 801} 802 803static __attribute__((unused)) 804int 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 825static __attribute__((unused)) 826int sys_pipe2(int pipefd[2], int flags) 827{ 828 return my_syscall2(__NR_pipe2, pipefd, flags); 829} 830 831static __attribute__((unused)) 832int pipe2(int pipefd[2], int flags) 833{ 834 return __sysret(sys_pipe2(pipefd, flags)); 835} 836 837static __attribute__((unused)) 838int 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 849static __attribute__((unused)) 850int 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 856static __attribute__((unused)) 857int 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 868static __attribute__((unused)) 869int sys_pivot_root(const char *new, const char *old) 870{ 871 return my_syscall2(__NR_pivot_root, new, old); 872} 873 874static __attribute__((unused)) 875int 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 885static __attribute__((unused)) 886int 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 903static __attribute__((unused)) 904int 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 914static __attribute__((unused)) 915ssize_t sys_read(int fd, void *buf, size_t count) 916{ 917 return my_syscall3(__NR_read, fd, buf, count); 918} 919 920static __attribute__((unused)) 921ssize_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 932static __attribute__((unused)) 933ssize_t sys_reboot(int magic1, int magic2, int cmd, void *arg) 934{ 935 return my_syscall4(__NR_reboot, magic1, magic2, cmd, arg); 936} 937 938static __attribute__((unused)) 939int 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 950static __attribute__((unused)) 951int 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 957static __attribute__((unused)) 958int 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 970static __attribute__((unused)) 971int 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 986static __attribute__((unused)) 987int sys_sched_yield(void) 988{ 989 return my_syscall0(__NR_sched_yield); 990} 991 992static __attribute__((unused)) 993int 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 1004static __attribute__((unused)) 1005int 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 1031static __attribute__((unused)) 1032int 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 1042static __attribute__((unused)) 1043int sys_setpgid(pid_t pid, pid_t pgid) 1044{ 1045 return my_syscall2(__NR_setpgid, pid, pgid); 1046} 1047 1048static __attribute__((unused)) 1049int 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 1059static __attribute__((unused)) 1060pid_t sys_setsid(void) 1061{ 1062 return my_syscall0(__NR_setsid); 1063} 1064 1065static __attribute__((unused)) 1066pid_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 1076static __attribute__((unused)) 1077int 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 1086static __attribute__((unused)) 1087int 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 1093static __attribute__((unused)) 1094int 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 1132static __attribute__((unused)) 1133int 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 1144static __attribute__((unused)) 1145int 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 1155static __attribute__((unused)) 1156mode_t sys_umask(mode_t mode) 1157{ 1158 return my_syscall1(__NR_umask, mode); 1159} 1160 1161static __attribute__((unused)) 1162mode_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 1172static __attribute__((unused)) 1173int sys_umount2(const char *path, int flags) 1174{ 1175 return my_syscall2(__NR_umount2, path, flags); 1176} 1177 1178static __attribute__((unused)) 1179int 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 1189struct 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 1198static __attribute__((unused)) 1199int sys_uname(struct utsname *buf) 1200{ 1201 return my_syscall1(__NR_uname, buf); 1202} 1203 1204static __attribute__((unused)) 1205int uname(struct utsname *buf) 1206{ 1207 return __sysret(sys_uname(buf)); 1208} 1209 1210 1211/* 1212 * int unlink(const char *path); 1213 */ 1214 1215static __attribute__((unused)) 1216int 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 1227static __attribute__((unused)) 1228int 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 1240static __attribute__((unused)) 1241pid_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 1250static __attribute__((unused)) 1251pid_t wait(int *status) 1252{ 1253 return __sysret(sys_wait4(-1, status, 0, NULL)); 1254} 1255 1256static __attribute__((unused)) 1257pid_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 1263static __attribute__((unused)) 1264pid_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 1274static __attribute__((unused)) 1275int 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 1280static __attribute__((unused)) 1281int 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 1291static __attribute__((unused)) 1292ssize_t sys_write(int fd, const void *buf, size_t count) 1293{ 1294 return my_syscall3(__NR_write, fd, buf, count); 1295} 1296 1297static __attribute__((unused)) 1298ssize_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 1308static __attribute__((unused)) 1309int sys_memfd_create(const char *name, unsigned int flags) 1310{ 1311 return my_syscall2(__NR_memfd_create, name, flags); 1312} 1313 1314static __attribute__((unused)) 1315int 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 */