at master 17 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/* make sure to include all global symbols */ 8#include "nolibc.h" 9 10#ifndef _NOLIBC_SYS_H 11#define _NOLIBC_SYS_H 12 13#include "std.h" 14 15/* system includes */ 16#include <linux/unistd.h> 17#include <linux/signal.h> /* for SIGCHLD */ 18#include <linux/termios.h> 19#include <linux/mman.h> 20#include <linux/fs.h> 21#include <linux/loop.h> 22#include <linux/time.h> 23#include <linux/auxvec.h> 24#include <linux/fcntl.h> /* for O_* and AT_* */ 25#include <linux/sched.h> /* for clone_args */ 26#include <linux/stat.h> /* for statx() */ 27 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(NULL); 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 * int fchdir(int fildes); 122 */ 123 124static __attribute__((unused)) 125int sys_chdir(const char *path) 126{ 127 return my_syscall1(__NR_chdir, path); 128} 129 130static __attribute__((unused)) 131int chdir(const char *path) 132{ 133 return __sysret(sys_chdir(path)); 134} 135 136static __attribute__((unused)) 137int sys_fchdir(int fildes) 138{ 139 return my_syscall1(__NR_fchdir, fildes); 140} 141 142static __attribute__((unused)) 143int fchdir(int fildes) 144{ 145 return __sysret(sys_fchdir(fildes)); 146} 147 148 149/* 150 * int chmod(const char *path, mode_t mode); 151 */ 152 153static __attribute__((unused)) 154int sys_chmod(const char *path, mode_t mode) 155{ 156#if defined(__NR_fchmodat) 157 return my_syscall4(__NR_fchmodat, AT_FDCWD, path, mode, 0); 158#else 159 return my_syscall2(__NR_chmod, path, mode); 160#endif 161} 162 163static __attribute__((unused)) 164int chmod(const char *path, mode_t mode) 165{ 166 return __sysret(sys_chmod(path, mode)); 167} 168 169 170/* 171 * int chown(const char *path, uid_t owner, gid_t group); 172 */ 173 174static __attribute__((unused)) 175int sys_chown(const char *path, uid_t owner, gid_t group) 176{ 177#if defined(__NR_fchownat) 178 return my_syscall5(__NR_fchownat, AT_FDCWD, path, owner, group, 0); 179#else 180 return my_syscall3(__NR_chown, path, owner, group); 181#endif 182} 183 184static __attribute__((unused)) 185int chown(const char *path, uid_t owner, gid_t group) 186{ 187 return __sysret(sys_chown(path, owner, group)); 188} 189 190 191/* 192 * int chroot(const char *path); 193 */ 194 195static __attribute__((unused)) 196int sys_chroot(const char *path) 197{ 198 return my_syscall1(__NR_chroot, path); 199} 200 201static __attribute__((unused)) 202int chroot(const char *path) 203{ 204 return __sysret(sys_chroot(path)); 205} 206 207 208/* 209 * int close(int fd); 210 */ 211 212static __attribute__((unused)) 213int sys_close(int fd) 214{ 215 return my_syscall1(__NR_close, fd); 216} 217 218static __attribute__((unused)) 219int close(int fd) 220{ 221 return __sysret(sys_close(fd)); 222} 223 224 225/* 226 * int dup(int fd); 227 */ 228 229static __attribute__((unused)) 230int sys_dup(int fd) 231{ 232 return my_syscall1(__NR_dup, fd); 233} 234 235static __attribute__((unused)) 236int dup(int fd) 237{ 238 return __sysret(sys_dup(fd)); 239} 240 241 242/* 243 * int dup2(int old, int new); 244 */ 245 246static __attribute__((unused)) 247int sys_dup2(int old, int new) 248{ 249#if defined(__NR_dup3) 250 int ret, nr_fcntl; 251 252#ifdef __NR_fcntl64 253 nr_fcntl = __NR_fcntl64; 254#else 255 nr_fcntl = __NR_fcntl; 256#endif 257 258 if (old == new) { 259 ret = my_syscall2(nr_fcntl, old, F_GETFD); 260 return ret < 0 ? ret : old; 261 } 262 263 return my_syscall3(__NR_dup3, old, new, 0); 264#else 265 return my_syscall2(__NR_dup2, old, new); 266#endif 267} 268 269static __attribute__((unused)) 270int dup2(int old, int new) 271{ 272 return __sysret(sys_dup2(old, new)); 273} 274 275 276/* 277 * int dup3(int old, int new, int flags); 278 */ 279 280#if defined(__NR_dup3) 281static __attribute__((unused)) 282int sys_dup3(int old, int new, int flags) 283{ 284 return my_syscall3(__NR_dup3, old, new, flags); 285} 286 287static __attribute__((unused)) 288int dup3(int old, int new, int flags) 289{ 290 return __sysret(sys_dup3(old, new, flags)); 291} 292#endif 293 294 295/* 296 * int execve(const char *filename, char *const argv[], char *const envp[]); 297 */ 298 299static __attribute__((unused)) 300int sys_execve(const char *filename, char *const argv[], char *const envp[]) 301{ 302 return my_syscall3(__NR_execve, filename, argv, envp); 303} 304 305static __attribute__((unused)) 306int execve(const char *filename, char *const argv[], char *const envp[]) 307{ 308 return __sysret(sys_execve(filename, argv, envp)); 309} 310 311 312/* 313 * void exit(int status); 314 */ 315 316static __attribute__((noreturn,unused)) 317void sys_exit(int status) 318{ 319 my_syscall1(__NR_exit, status & 255); 320 while(1); /* shut the "noreturn" warnings. */ 321} 322 323static __attribute__((noreturn,unused)) 324void _exit(int status) 325{ 326 sys_exit(status); 327} 328 329static __attribute__((noreturn,unused)) 330void exit(int status) 331{ 332 _exit(status); 333} 334 335 336/* 337 * pid_t fork(void); 338 */ 339 340#ifndef sys_fork 341static __attribute__((unused)) 342pid_t sys_fork(void) 343{ 344#if defined(__NR_clone) 345 /* note: some archs only have clone() and not fork(). Different archs 346 * have a different API, but most archs have the flags on first arg and 347 * will not use the rest with no other flag. 348 */ 349 return my_syscall5(__NR_clone, SIGCHLD, 0, 0, 0, 0); 350#else 351 return my_syscall0(__NR_fork); 352#endif 353} 354#endif 355 356static __attribute__((unused)) 357pid_t fork(void) 358{ 359 return __sysret(sys_fork()); 360} 361 362#ifndef sys_vfork 363static __attribute__((unused)) 364pid_t sys_vfork(void) 365{ 366#if defined(__NR_vfork) 367 return my_syscall0(__NR_vfork); 368#else 369 /* 370 * clone() could be used but has different argument orders per 371 * architecture. 372 */ 373 struct clone_args args = { 374 .flags = CLONE_VM | CLONE_VFORK, 375 .exit_signal = SIGCHLD, 376 }; 377 378 return my_syscall2(__NR_clone3, &args, sizeof(args)); 379#endif 380} 381#endif 382 383static __attribute__((unused)) 384pid_t vfork(void) 385{ 386 return __sysret(sys_vfork()); 387} 388 389/* 390 * int fsync(int fd); 391 */ 392 393static __attribute__((unused)) 394int sys_fsync(int fd) 395{ 396 return my_syscall1(__NR_fsync, fd); 397} 398 399static __attribute__((unused)) 400int fsync(int fd) 401{ 402 return __sysret(sys_fsync(fd)); 403} 404 405 406/* 407 * int getdents64(int fd, struct linux_dirent64 *dirp, int count); 408 */ 409 410static __attribute__((unused)) 411int sys_getdents64(int fd, struct linux_dirent64 *dirp, int count) 412{ 413 return my_syscall3(__NR_getdents64, fd, dirp, count); 414} 415 416static __attribute__((unused)) 417int getdents64(int fd, struct linux_dirent64 *dirp, int count) 418{ 419 return __sysret(sys_getdents64(fd, dirp, count)); 420} 421 422 423/* 424 * uid_t geteuid(void); 425 */ 426 427static __attribute__((unused)) 428uid_t sys_geteuid(void) 429{ 430#if defined(__NR_geteuid32) 431 return my_syscall0(__NR_geteuid32); 432#else 433 return my_syscall0(__NR_geteuid); 434#endif 435} 436 437static __attribute__((unused)) 438uid_t geteuid(void) 439{ 440 return sys_geteuid(); 441} 442 443 444/* 445 * pid_t getpgid(pid_t pid); 446 */ 447 448static __attribute__((unused)) 449pid_t sys_getpgid(pid_t pid) 450{ 451 return my_syscall1(__NR_getpgid, pid); 452} 453 454static __attribute__((unused)) 455pid_t getpgid(pid_t pid) 456{ 457 return __sysret(sys_getpgid(pid)); 458} 459 460 461/* 462 * pid_t getpgrp(void); 463 */ 464 465static __attribute__((unused)) 466pid_t sys_getpgrp(void) 467{ 468 return sys_getpgid(0); 469} 470 471static __attribute__((unused)) 472pid_t getpgrp(void) 473{ 474 return sys_getpgrp(); 475} 476 477 478/* 479 * pid_t getpid(void); 480 */ 481 482static __attribute__((unused)) 483pid_t sys_getpid(void) 484{ 485 return my_syscall0(__NR_getpid); 486} 487 488static __attribute__((unused)) 489pid_t getpid(void) 490{ 491 return sys_getpid(); 492} 493 494 495/* 496 * pid_t getppid(void); 497 */ 498 499static __attribute__((unused)) 500pid_t sys_getppid(void) 501{ 502 return my_syscall0(__NR_getppid); 503} 504 505static __attribute__((unused)) 506pid_t getppid(void) 507{ 508 return sys_getppid(); 509} 510 511 512/* 513 * pid_t gettid(void); 514 */ 515 516static __attribute__((unused)) 517pid_t sys_gettid(void) 518{ 519 return my_syscall0(__NR_gettid); 520} 521 522static __attribute__((unused)) 523pid_t gettid(void) 524{ 525 return sys_gettid(); 526} 527 528#ifndef NOLIBC_NO_RUNTIME 529static unsigned long getauxval(unsigned long key); 530 531/* 532 * int getpagesize(void); 533 */ 534 535static __attribute__((unused)) 536int getpagesize(void) 537{ 538 return __sysret((int)getauxval(AT_PAGESZ) ?: -ENOENT); 539} 540#endif /* NOLIBC_NO_RUNTIME */ 541 542/* 543 * uid_t getuid(void); 544 */ 545 546static __attribute__((unused)) 547uid_t sys_getuid(void) 548{ 549#if defined(__NR_getuid32) 550 return my_syscall0(__NR_getuid32); 551#else 552 return my_syscall0(__NR_getuid); 553#endif 554} 555 556static __attribute__((unused)) 557uid_t getuid(void) 558{ 559 return sys_getuid(); 560} 561 562 563/* 564 * int kill(pid_t pid, int signal); 565 */ 566 567static __attribute__((unused)) 568int sys_kill(pid_t pid, int signal) 569{ 570 return my_syscall2(__NR_kill, pid, signal); 571} 572 573static __attribute__((unused)) 574int kill(pid_t pid, int signal) 575{ 576 return __sysret(sys_kill(pid, signal)); 577} 578 579 580/* 581 * int link(const char *old, const char *new); 582 */ 583 584static __attribute__((unused)) 585int sys_link(const char *old, const char *new) 586{ 587#if defined(__NR_linkat) 588 return my_syscall5(__NR_linkat, AT_FDCWD, old, AT_FDCWD, new, 0); 589#else 590 return my_syscall2(__NR_link, old, new); 591#endif 592} 593 594static __attribute__((unused)) 595int link(const char *old, const char *new) 596{ 597 return __sysret(sys_link(old, new)); 598} 599 600 601/* 602 * off_t lseek(int fd, off_t offset, int whence); 603 */ 604 605static __attribute__((unused)) 606off_t sys_lseek(int fd, off_t offset, int whence) 607{ 608#if defined(__NR_llseek) 609 __kernel_loff_t loff = 0; 610 off_t result; 611 int ret; 612 613 ret = my_syscall5(__NR_llseek, fd, offset >> 32, (uint32_t)offset, &loff, whence); 614 if (ret < 0) 615 result = ret; 616 else 617 result = loff; 618 619 return result; 620#else 621 return my_syscall3(__NR_lseek, fd, offset, whence); 622#endif 623} 624 625static __attribute__((unused)) 626off_t lseek(int fd, off_t offset, int whence) 627{ 628 return __sysret(sys_lseek(fd, offset, whence)); 629} 630 631 632/* 633 * int mkdir(const char *path, mode_t mode); 634 */ 635 636static __attribute__((unused)) 637int sys_mkdir(const char *path, mode_t mode) 638{ 639#if defined(__NR_mkdirat) 640 return my_syscall3(__NR_mkdirat, AT_FDCWD, path, mode); 641#else 642 return my_syscall2(__NR_mkdir, path, mode); 643#endif 644} 645 646static __attribute__((unused)) 647int mkdir(const char *path, mode_t mode) 648{ 649 return __sysret(sys_mkdir(path, mode)); 650} 651 652/* 653 * int rmdir(const char *path); 654 */ 655 656static __attribute__((unused)) 657int sys_rmdir(const char *path) 658{ 659#if defined(__NR_rmdir) 660 return my_syscall1(__NR_rmdir, path); 661#else 662 return my_syscall3(__NR_unlinkat, AT_FDCWD, path, AT_REMOVEDIR); 663#endif 664} 665 666static __attribute__((unused)) 667int rmdir(const char *path) 668{ 669 return __sysret(sys_rmdir(path)); 670} 671 672 673/* 674 * int mknod(const char *path, mode_t mode, dev_t dev); 675 */ 676 677static __attribute__((unused)) 678long sys_mknod(const char *path, mode_t mode, dev_t dev) 679{ 680#if defined(__NR_mknodat) 681 return my_syscall4(__NR_mknodat, AT_FDCWD, path, mode, dev); 682#else 683 return my_syscall3(__NR_mknod, path, mode, dev); 684#endif 685} 686 687static __attribute__((unused)) 688int mknod(const char *path, mode_t mode, dev_t dev) 689{ 690 return __sysret(sys_mknod(path, mode, dev)); 691} 692 693 694/* 695 * int pipe2(int pipefd[2], int flags); 696 * int pipe(int pipefd[2]); 697 */ 698 699static __attribute__((unused)) 700int sys_pipe2(int pipefd[2], int flags) 701{ 702 return my_syscall2(__NR_pipe2, pipefd, flags); 703} 704 705static __attribute__((unused)) 706int pipe2(int pipefd[2], int flags) 707{ 708 return __sysret(sys_pipe2(pipefd, flags)); 709} 710 711static __attribute__((unused)) 712int pipe(int pipefd[2]) 713{ 714 return pipe2(pipefd, 0); 715} 716 717 718/* 719 * int pivot_root(const char *new, const char *old); 720 */ 721 722static __attribute__((unused)) 723int sys_pivot_root(const char *new, const char *old) 724{ 725 return my_syscall2(__NR_pivot_root, new, old); 726} 727 728static __attribute__((unused)) 729int pivot_root(const char *new, const char *old) 730{ 731 return __sysret(sys_pivot_root(new, old)); 732} 733 734 735/* 736 * ssize_t read(int fd, void *buf, size_t count); 737 */ 738 739static __attribute__((unused)) 740ssize_t sys_read(int fd, void *buf, size_t count) 741{ 742 return my_syscall3(__NR_read, fd, buf, count); 743} 744 745static __attribute__((unused)) 746ssize_t read(int fd, void *buf, size_t count) 747{ 748 return __sysret(sys_read(fd, buf, count)); 749} 750 751 752/* 753 * int sched_yield(void); 754 */ 755 756static __attribute__((unused)) 757int sys_sched_yield(void) 758{ 759 return my_syscall0(__NR_sched_yield); 760} 761 762static __attribute__((unused)) 763int sched_yield(void) 764{ 765 return __sysret(sys_sched_yield()); 766} 767 768 769/* 770 * int setpgid(pid_t pid, pid_t pgid); 771 */ 772 773static __attribute__((unused)) 774int sys_setpgid(pid_t pid, pid_t pgid) 775{ 776 return my_syscall2(__NR_setpgid, pid, pgid); 777} 778 779static __attribute__((unused)) 780int setpgid(pid_t pid, pid_t pgid) 781{ 782 return __sysret(sys_setpgid(pid, pgid)); 783} 784 785/* 786 * pid_t setpgrp(void) 787 */ 788 789static __attribute__((unused)) 790pid_t setpgrp(void) 791{ 792 return setpgid(0, 0); 793} 794 795 796/* 797 * pid_t setsid(void); 798 */ 799 800static __attribute__((unused)) 801pid_t sys_setsid(void) 802{ 803 return my_syscall0(__NR_setsid); 804} 805 806static __attribute__((unused)) 807pid_t setsid(void) 808{ 809 return __sysret(sys_setsid()); 810} 811 812 813/* 814 * int symlink(const char *old, const char *new); 815 */ 816 817static __attribute__((unused)) 818int sys_symlink(const char *old, const char *new) 819{ 820#if defined(__NR_symlinkat) 821 return my_syscall3(__NR_symlinkat, old, AT_FDCWD, new); 822#else 823 return my_syscall2(__NR_symlink, old, new); 824#endif 825} 826 827static __attribute__((unused)) 828int symlink(const char *old, const char *new) 829{ 830 return __sysret(sys_symlink(old, new)); 831} 832 833 834/* 835 * mode_t umask(mode_t mode); 836 */ 837 838static __attribute__((unused)) 839mode_t sys_umask(mode_t mode) 840{ 841 return my_syscall1(__NR_umask, mode); 842} 843 844static __attribute__((unused)) 845mode_t umask(mode_t mode) 846{ 847 return sys_umask(mode); 848} 849 850 851/* 852 * int umount2(const char *path, int flags); 853 */ 854 855static __attribute__((unused)) 856int sys_umount2(const char *path, int flags) 857{ 858 return my_syscall2(__NR_umount2, path, flags); 859} 860 861static __attribute__((unused)) 862int umount2(const char *path, int flags) 863{ 864 return __sysret(sys_umount2(path, flags)); 865} 866 867 868/* 869 * int unlink(const char *path); 870 */ 871 872static __attribute__((unused)) 873int sys_unlink(const char *path) 874{ 875#if defined(__NR_unlinkat) 876 return my_syscall3(__NR_unlinkat, AT_FDCWD, path, 0); 877#else 878 return my_syscall1(__NR_unlink, path); 879#endif 880} 881 882static __attribute__((unused)) 883int unlink(const char *path) 884{ 885 return __sysret(sys_unlink(path)); 886} 887 888 889/* 890 * ssize_t write(int fd, const void *buf, size_t count); 891 */ 892 893static __attribute__((unused)) 894ssize_t sys_write(int fd, const void *buf, size_t count) 895{ 896 return my_syscall3(__NR_write, fd, buf, count); 897} 898 899static __attribute__((unused)) 900ssize_t write(int fd, const void *buf, size_t count) 901{ 902 return __sysret(sys_write(fd, buf, count)); 903} 904 905 906/* 907 * int memfd_create(const char *name, unsigned int flags); 908 */ 909 910static __attribute__((unused)) 911int sys_memfd_create(const char *name, unsigned int flags) 912{ 913 return my_syscall2(__NR_memfd_create, name, flags); 914} 915 916static __attribute__((unused)) 917int memfd_create(const char *name, unsigned int flags) 918{ 919 return __sysret(sys_memfd_create(name, flags)); 920} 921 922#endif /* _NOLIBC_SYS_H */