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_* */ 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, provides compile 49 * time validation and a debugging hook. 50 */ 51 52 #if defined(NOLIBC_COMPILE_TIME_ENOSYS) 53 static __inline__ int __nolibc_enosys(const char *syscall, ...) 54 { 55 (void)syscall; 56 return -ENOSYS; 57 } 58 59 #elif __nolibc_has_attribute(error) 60 __attribute__((error("system call not implemented"))) 61 extern int __nolibc_enosys(const char *syscall, ...); 62 63 #else 64 static __inline__ int __nolibc_enosys(const char *syscall, ...) 65 { 66 extern int __nolibc_enosys_error; 67 (void)syscall; 68 69 return __nolibc_enosys_error; 70 } 71 #endif 72 73 74 /* 75 * Helper for 32-bit machines where a 64-bit syscall arg needs to be split into 76 * two 32-bit parts while making sure the order of the low/high parts are correct 77 * for the endianness: 78 * __NOLIBC_LLARGPART(x, 0), __NOLIBC_LLARGPART(x, 1) 79 */ 80 #define __NOLIBC_LLARGPART(_arg, _part) \ 81 (((union { long long ll; long l[2]; }) { .ll = _arg }).l[_part]) 82 83 84 /* Functions in this file only describe syscalls. They're declared static so 85 * that the compiler usually decides to inline them while still being allowed 86 * to pass a pointer to one of their instances. Each syscall exists in two 87 * versions: 88 * - the "internal" ones, which matches the raw syscall interface at the 89 * kernel level, which may sometimes slightly differ from the documented 90 * libc-level ones. For example most of them return either a valid value 91 * or -errno. All of these are prefixed with "_sys_". They may be called 92 * by non-portable applications if desired. 93 * 94 * - the "exported" ones, whose interface must closely match the one 95 * documented in man(2), that applications are supposed to expect. These 96 * ones rely on the internal ones, and set errno. 97 * 98 * Each syscall will be defined with the two functions, sorted in alphabetical 99 * order applied to the exported names. 100 * 101 * In case of doubt about the relevance of a function here, only those which 102 * set errno should be defined here. Wrappers like those appearing in man(3) 103 * should not be placed here. 104 */ 105 106 107 /* 108 * int brk(void *addr); 109 * void *sbrk(intptr_t inc) 110 */ 111 112 static __attribute__((unused)) 113 void *_sys_brk(void *addr) 114 { 115 return (void *)(unsigned long)__nolibc_syscall1(__NR_brk, addr); 116 } 117 118 static __attribute__((unused)) 119 int brk(void *addr) 120 { 121 void *ret = _sys_brk(addr); 122 123 if (!ret) { 124 SET_ERRNO(ENOMEM); 125 return -1; 126 } 127 return 0; 128 } 129 130 static __attribute__((unused)) 131 void *sbrk(intptr_t inc) 132 { 133 /* first call to find current end */ 134 void *ret = _sys_brk(NULL); 135 136 if (ret && _sys_brk(ret + inc) == ret + inc) 137 return ret + inc; 138 139 SET_ERRNO(ENOMEM); 140 return (void *)-1; 141 } 142 143 144 /* 145 * int chdir(const char *path); 146 * int fchdir(int fildes); 147 */ 148 149 static __attribute__((unused)) 150 int _sys_chdir(const char *path) 151 { 152 return __nolibc_syscall1(__NR_chdir, path); 153 } 154 155 static __attribute__((unused)) 156 int chdir(const char *path) 157 { 158 return __sysret(_sys_chdir(path)); 159 } 160 161 static __attribute__((unused)) 162 int _sys_fchdir(int fildes) 163 { 164 return __nolibc_syscall1(__NR_fchdir, fildes); 165 } 166 167 static __attribute__((unused)) 168 int fchdir(int fildes) 169 { 170 return __sysret(_sys_fchdir(fildes)); 171 } 172 173 174 /* 175 * int chmod(const char *path, mode_t mode); 176 */ 177 178 static __attribute__((unused)) 179 int _sys_chmod(const char *path, mode_t mode) 180 { 181 #if defined(__NR_fchmodat) 182 return __nolibc_syscall4(__NR_fchmodat, AT_FDCWD, path, mode, 0); 183 #else 184 return __nolibc_syscall2(__NR_chmod, path, mode); 185 #endif 186 } 187 188 static __attribute__((unused)) 189 int chmod(const char *path, mode_t mode) 190 { 191 return __sysret(_sys_chmod(path, mode)); 192 } 193 194 195 /* 196 * int chown(const char *path, uid_t owner, gid_t group); 197 */ 198 199 static __attribute__((unused)) 200 int _sys_chown(const char *path, uid_t owner, gid_t group) 201 { 202 #if defined(__NR_fchownat) 203 return __nolibc_syscall5(__NR_fchownat, AT_FDCWD, path, owner, group, 0); 204 #else 205 return __nolibc_syscall3(__NR_chown, path, owner, group); 206 #endif 207 } 208 209 static __attribute__((unused)) 210 int chown(const char *path, uid_t owner, gid_t group) 211 { 212 return __sysret(_sys_chown(path, owner, group)); 213 } 214 215 216 /* 217 * int chroot(const char *path); 218 */ 219 220 static __attribute__((unused)) 221 int _sys_chroot(const char *path) 222 { 223 return __nolibc_syscall1(__NR_chroot, path); 224 } 225 226 static __attribute__((unused)) 227 int chroot(const char *path) 228 { 229 return __sysret(_sys_chroot(path)); 230 } 231 232 233 /* 234 * int close(int fd); 235 */ 236 237 static __attribute__((unused)) 238 int _sys_close(int fd) 239 { 240 return __nolibc_syscall1(__NR_close, fd); 241 } 242 243 static __attribute__((unused)) 244 int close(int fd) 245 { 246 return __sysret(_sys_close(fd)); 247 } 248 249 250 /* 251 * int dup(int fd); 252 */ 253 254 static __attribute__((unused)) 255 int _sys_dup(int fd) 256 { 257 return __nolibc_syscall1(__NR_dup, fd); 258 } 259 260 static __attribute__((unused)) 261 int dup(int fd) 262 { 263 return __sysret(_sys_dup(fd)); 264 } 265 266 267 /* 268 * int dup2(int old, int new); 269 */ 270 271 static __attribute__((unused)) 272 int _sys_dup2(int old, int new) 273 { 274 #if defined(__NR_dup3) 275 int ret, nr_fcntl; 276 277 #ifdef __NR_fcntl64 278 nr_fcntl = __NR_fcntl64; 279 #else 280 nr_fcntl = __NR_fcntl; 281 #endif 282 283 if (old == new) { 284 ret = __nolibc_syscall2(nr_fcntl, old, F_GETFD); 285 return ret < 0 ? ret : old; 286 } 287 288 return __nolibc_syscall3(__NR_dup3, old, new, 0); 289 #else 290 return __nolibc_syscall2(__NR_dup2, old, new); 291 #endif 292 } 293 294 static __attribute__((unused)) 295 int dup2(int old, int new) 296 { 297 return __sysret(_sys_dup2(old, new)); 298 } 299 300 301 /* 302 * int dup3(int old, int new, int flags); 303 */ 304 305 #if defined(__NR_dup3) 306 static __attribute__((unused)) 307 int _sys_dup3(int old, int new, int flags) 308 { 309 return __nolibc_syscall3(__NR_dup3, old, new, flags); 310 } 311 312 static __attribute__((unused)) 313 int dup3(int old, int new, int flags) 314 { 315 return __sysret(_sys_dup3(old, new, flags)); 316 } 317 #endif 318 319 320 /* 321 * int execve(const char *filename, char *const argv[], char *const envp[]); 322 */ 323 324 static __attribute__((unused)) 325 int _sys_execve(const char *filename, char *const argv[], char *const envp[]) 326 { 327 return __nolibc_syscall3(__NR_execve, filename, argv, envp); 328 } 329 330 static __attribute__((unused)) 331 int execve(const char *filename, char *const argv[], char *const envp[]) 332 { 333 return __sysret(_sys_execve(filename, argv, envp)); 334 } 335 336 337 /* 338 * void exit(int status); 339 */ 340 341 static __attribute__((noreturn,unused)) 342 void _sys_exit(int status) 343 { 344 __nolibc_syscall1(__NR_exit, status & 255); 345 while(1); /* shut the "noreturn" warnings. */ 346 } 347 348 static __attribute__((noreturn,unused)) 349 void _exit(int status) 350 { 351 _sys_exit(status); 352 } 353 354 static __attribute__((noreturn,unused)) 355 void exit(int status) 356 { 357 _exit(status); 358 } 359 360 361 /* 362 * pid_t fork(void); 363 */ 364 365 #ifndef _sys_fork 366 static __attribute__((unused)) 367 pid_t _sys_fork(void) 368 { 369 #if defined(__NR_clone) 370 /* note: some archs only have clone() and not fork(). Different archs 371 * have a different API, but most archs have the flags on first arg and 372 * will not use the rest with no other flag. 373 */ 374 return __nolibc_syscall5(__NR_clone, SIGCHLD, 0, 0, 0, 0); 375 #else 376 return __nolibc_syscall0(__NR_fork); 377 #endif 378 } 379 #endif 380 381 static __attribute__((unused)) 382 pid_t fork(void) 383 { 384 return __sysret(_sys_fork()); 385 } 386 387 #ifndef _sys_vfork 388 static __attribute__((unused)) 389 pid_t _sys_vfork(void) 390 { 391 #if defined(__NR_clone) 392 /* See the note in _sys_fork(). */ 393 return __nolibc_syscall5(__NR_clone, CLONE_VM | CLONE_VFORK | SIGCHLD, 0, 0, 0, 0); 394 #elif defined(__NR_vfork) 395 return __nolibc_syscall0(__NR_vfork); 396 #endif 397 } 398 #endif 399 400 static __attribute__((unused)) 401 pid_t vfork(void) 402 { 403 return __sysret(_sys_vfork()); 404 } 405 406 /* 407 * int fsync(int fd); 408 */ 409 410 static __attribute__((unused)) 411 int _sys_fsync(int fd) 412 { 413 return __nolibc_syscall1(__NR_fsync, fd); 414 } 415 416 static __attribute__((unused)) 417 int fsync(int fd) 418 { 419 return __sysret(_sys_fsync(fd)); 420 } 421 422 423 /* 424 * int getdents64(int fd, struct linux_dirent64 *dirp, int count); 425 */ 426 427 static __attribute__((unused)) 428 int _sys_getdents64(int fd, struct linux_dirent64 *dirp, int count) 429 { 430 return __nolibc_syscall3(__NR_getdents64, fd, dirp, count); 431 } 432 433 static __attribute__((unused)) 434 int getdents64(int fd, struct linux_dirent64 *dirp, int count) 435 { 436 return __sysret(_sys_getdents64(fd, dirp, count)); 437 } 438 439 440 /* 441 * uid_t geteuid(void); 442 */ 443 444 static __attribute__((unused)) 445 uid_t _sys_geteuid(void) 446 { 447 #if defined(__NR_geteuid32) 448 return __nolibc_syscall0(__NR_geteuid32); 449 #else 450 return __nolibc_syscall0(__NR_geteuid); 451 #endif 452 } 453 454 static __attribute__((unused)) 455 uid_t geteuid(void) 456 { 457 return _sys_geteuid(); 458 } 459 460 461 /* 462 * pid_t getpgid(pid_t pid); 463 */ 464 465 static __attribute__((unused)) 466 pid_t _sys_getpgid(pid_t pid) 467 { 468 return __nolibc_syscall1(__NR_getpgid, pid); 469 } 470 471 static __attribute__((unused)) 472 pid_t getpgid(pid_t pid) 473 { 474 return __sysret(_sys_getpgid(pid)); 475 } 476 477 478 /* 479 * pid_t getpgrp(void); 480 */ 481 482 static __attribute__((unused)) 483 pid_t _sys_getpgrp(void) 484 { 485 return _sys_getpgid(0); 486 } 487 488 static __attribute__((unused)) 489 pid_t getpgrp(void) 490 { 491 return _sys_getpgrp(); 492 } 493 494 495 /* 496 * pid_t getpid(void); 497 */ 498 499 static __attribute__((unused)) 500 pid_t _sys_getpid(void) 501 { 502 return __nolibc_syscall0(__NR_getpid); 503 } 504 505 static __attribute__((unused)) 506 pid_t getpid(void) 507 { 508 return _sys_getpid(); 509 } 510 511 512 /* 513 * pid_t getppid(void); 514 */ 515 516 static __attribute__((unused)) 517 pid_t _sys_getppid(void) 518 { 519 return __nolibc_syscall0(__NR_getppid); 520 } 521 522 static __attribute__((unused)) 523 pid_t getppid(void) 524 { 525 return _sys_getppid(); 526 } 527 528 529 /* 530 * pid_t gettid(void); 531 */ 532 533 static __attribute__((unused)) 534 pid_t _sys_gettid(void) 535 { 536 return __nolibc_syscall0(__NR_gettid); 537 } 538 539 static __attribute__((unused)) 540 pid_t gettid(void) 541 { 542 return _sys_gettid(); 543 } 544 545 #ifndef NOLIBC_NO_RUNTIME 546 static unsigned long getauxval(unsigned long key); 547 548 /* 549 * int getpagesize(void); 550 */ 551 552 static __attribute__((unused)) 553 int getpagesize(void) 554 { 555 return __sysret((int)getauxval(AT_PAGESZ) ?: -ENOENT); 556 } 557 #endif /* NOLIBC_NO_RUNTIME */ 558 559 /* 560 * uid_t getuid(void); 561 */ 562 563 static __attribute__((unused)) 564 uid_t _sys_getuid(void) 565 { 566 #if defined(__NR_getuid32) 567 return __nolibc_syscall0(__NR_getuid32); 568 #else 569 return __nolibc_syscall0(__NR_getuid); 570 #endif 571 } 572 573 static __attribute__((unused)) 574 uid_t getuid(void) 575 { 576 return _sys_getuid(); 577 } 578 579 580 /* 581 * int kill(pid_t pid, int signal); 582 */ 583 584 static __attribute__((unused)) 585 int _sys_kill(pid_t pid, int signal) 586 { 587 return __nolibc_syscall2(__NR_kill, pid, signal); 588 } 589 590 static __attribute__((unused)) 591 int kill(pid_t pid, int signal) 592 { 593 return __sysret(_sys_kill(pid, signal)); 594 } 595 596 597 /* 598 * int link(const char *old, const char *new); 599 */ 600 601 static __attribute__((unused)) 602 int _sys_link(const char *old, const char *new) 603 { 604 #if defined(__NR_linkat) 605 return __nolibc_syscall5(__NR_linkat, AT_FDCWD, old, AT_FDCWD, new, 0); 606 #else 607 return __nolibc_syscall2(__NR_link, old, new); 608 #endif 609 } 610 611 static __attribute__((unused)) 612 int link(const char *old, const char *new) 613 { 614 return __sysret(_sys_link(old, new)); 615 } 616 617 618 /* 619 * off_t lseek(int fd, off_t offset, int whence); 620 */ 621 622 static __attribute__((unused)) 623 off_t _sys_lseek(int fd, off_t offset, int whence) 624 { 625 #if defined(__NR_llseek) || defined(__NR__llseek) 626 __kernel_loff_t loff = 0; 627 int ret, nr_llseek; 628 off_t result; 629 630 #if defined(__NR_llseek) 631 nr_llseek = __NR_llseek; 632 #else 633 nr_llseek = __NR__llseek; 634 #endif 635 636 ret = __nolibc_syscall5(nr_llseek, fd, offset >> 32, (uint32_t)offset, &loff, whence); 637 if (ret < 0) 638 result = ret; 639 else 640 result = loff; 641 642 return result; 643 #else 644 return __nolibc_syscall3(__NR_lseek, fd, offset, whence); 645 #endif 646 } 647 648 static __attribute__((unused)) 649 off_t lseek(int fd, off_t offset, int whence) 650 { 651 return __sysret(_sys_lseek(fd, offset, whence)); 652 } 653 654 655 /* 656 * int mkdir(const char *path, mode_t mode); 657 */ 658 659 static __attribute__((unused)) 660 int _sys_mkdir(const char *path, mode_t mode) 661 { 662 #if defined(__NR_mkdirat) 663 return __nolibc_syscall3(__NR_mkdirat, AT_FDCWD, path, mode); 664 #else 665 return __nolibc_syscall2(__NR_mkdir, path, mode); 666 #endif 667 } 668 669 static __attribute__((unused)) 670 int mkdir(const char *path, mode_t mode) 671 { 672 return __sysret(_sys_mkdir(path, mode)); 673 } 674 675 /* 676 * int rmdir(const char *path); 677 */ 678 679 static __attribute__((unused)) 680 int _sys_rmdir(const char *path) 681 { 682 #if defined(__NR_rmdir) 683 return __nolibc_syscall1(__NR_rmdir, path); 684 #else 685 return __nolibc_syscall3(__NR_unlinkat, AT_FDCWD, path, AT_REMOVEDIR); 686 #endif 687 } 688 689 static __attribute__((unused)) 690 int rmdir(const char *path) 691 { 692 return __sysret(_sys_rmdir(path)); 693 } 694 695 696 /* 697 * int mknod(const char *path, mode_t mode, dev_t dev); 698 */ 699 700 static __attribute__((unused)) 701 long _sys_mknod(const char *path, mode_t mode, dev_t dev) 702 { 703 #if defined(__NR_mknodat) 704 return __nolibc_syscall4(__NR_mknodat, AT_FDCWD, path, mode, dev); 705 #else 706 return __nolibc_syscall3(__NR_mknod, path, mode, dev); 707 #endif 708 } 709 710 static __attribute__((unused)) 711 int mknod(const char *path, mode_t mode, dev_t dev) 712 { 713 return __sysret(_sys_mknod(path, mode, dev)); 714 } 715 716 717 /* 718 * int pipe2(int pipefd[2], int flags); 719 * int pipe(int pipefd[2]); 720 */ 721 722 static __attribute__((unused)) 723 int _sys_pipe2(int pipefd[2], int flags) 724 { 725 return __nolibc_syscall2(__NR_pipe2, pipefd, flags); 726 } 727 728 static __attribute__((unused)) 729 int pipe2(int pipefd[2], int flags) 730 { 731 return __sysret(_sys_pipe2(pipefd, flags)); 732 } 733 734 static __attribute__((unused)) 735 int pipe(int pipefd[2]) 736 { 737 return pipe2(pipefd, 0); 738 } 739 740 741 /* 742 * int pivot_root(const char *new, const char *old); 743 */ 744 745 static __attribute__((unused)) 746 int _sys_pivot_root(const char *new, const char *old) 747 { 748 return __nolibc_syscall2(__NR_pivot_root, new, old); 749 } 750 751 static __attribute__((unused)) 752 int pivot_root(const char *new, const char *old) 753 { 754 return __sysret(_sys_pivot_root(new, old)); 755 } 756 757 758 /* 759 * ssize_t read(int fd, void *buf, size_t count); 760 */ 761 762 static __attribute__((unused)) 763 ssize_t _sys_read(int fd, void *buf, size_t count) 764 { 765 return __nolibc_syscall3(__NR_read, fd, buf, count); 766 } 767 768 static __attribute__((unused)) 769 ssize_t read(int fd, void *buf, size_t count) 770 { 771 return __sysret(_sys_read(fd, buf, count)); 772 } 773 774 775 /* 776 * int sched_yield(void); 777 */ 778 779 static __attribute__((unused)) 780 int _sys_sched_yield(void) 781 { 782 return __nolibc_syscall0(__NR_sched_yield); 783 } 784 785 static __attribute__((unused)) 786 int sched_yield(void) 787 { 788 return __sysret(_sys_sched_yield()); 789 } 790 791 792 /* 793 * int setpgid(pid_t pid, pid_t pgid); 794 */ 795 796 static __attribute__((unused)) 797 int _sys_setpgid(pid_t pid, pid_t pgid) 798 { 799 return __nolibc_syscall2(__NR_setpgid, pid, pgid); 800 } 801 802 static __attribute__((unused)) 803 int setpgid(pid_t pid, pid_t pgid) 804 { 805 return __sysret(_sys_setpgid(pid, pgid)); 806 } 807 808 /* 809 * pid_t setpgrp(void) 810 */ 811 812 static __attribute__((unused)) 813 pid_t setpgrp(void) 814 { 815 return setpgid(0, 0); 816 } 817 818 819 /* 820 * pid_t setsid(void); 821 */ 822 823 static __attribute__((unused)) 824 pid_t _sys_setsid(void) 825 { 826 return __nolibc_syscall0(__NR_setsid); 827 } 828 829 static __attribute__((unused)) 830 pid_t setsid(void) 831 { 832 return __sysret(_sys_setsid()); 833 } 834 835 836 /* 837 * int symlink(const char *old, const char *new); 838 */ 839 840 static __attribute__((unused)) 841 int _sys_symlink(const char *old, const char *new) 842 { 843 #if defined(__NR_symlinkat) 844 return __nolibc_syscall3(__NR_symlinkat, old, AT_FDCWD, new); 845 #else 846 return __nolibc_syscall2(__NR_symlink, old, new); 847 #endif 848 } 849 850 static __attribute__((unused)) 851 int symlink(const char *old, const char *new) 852 { 853 return __sysret(_sys_symlink(old, new)); 854 } 855 856 857 /* 858 * mode_t umask(mode_t mode); 859 */ 860 861 static __attribute__((unused)) 862 mode_t _sys_umask(mode_t mode) 863 { 864 return __nolibc_syscall1(__NR_umask, mode); 865 } 866 867 static __attribute__((unused)) 868 mode_t umask(mode_t mode) 869 { 870 return _sys_umask(mode); 871 } 872 873 874 /* 875 * int umount2(const char *path, int flags); 876 */ 877 878 static __attribute__((unused)) 879 int _sys_umount2(const char *path, int flags) 880 { 881 return __nolibc_syscall2(__NR_umount2, path, flags); 882 } 883 884 static __attribute__((unused)) 885 int umount2(const char *path, int flags) 886 { 887 return __sysret(_sys_umount2(path, flags)); 888 } 889 890 891 /* 892 * int unlink(const char *path); 893 */ 894 895 static __attribute__((unused)) 896 int _sys_unlink(const char *path) 897 { 898 #if defined(__NR_unlinkat) 899 return __nolibc_syscall3(__NR_unlinkat, AT_FDCWD, path, 0); 900 #else 901 return __nolibc_syscall1(__NR_unlink, path); 902 #endif 903 } 904 905 static __attribute__((unused)) 906 int unlink(const char *path) 907 { 908 return __sysret(_sys_unlink(path)); 909 } 910 911 912 /* 913 * ssize_t write(int fd, const void *buf, size_t count); 914 */ 915 916 static __attribute__((unused)) 917 ssize_t _sys_write(int fd, const void *buf, size_t count) 918 { 919 return __nolibc_syscall3(__NR_write, fd, buf, count); 920 } 921 922 static __attribute__((unused)) 923 ssize_t write(int fd, const void *buf, size_t count) 924 { 925 return __sysret(_sys_write(fd, buf, count)); 926 } 927 928 929 /* 930 * int memfd_create(const char *name, unsigned int flags); 931 */ 932 933 static __attribute__((unused)) 934 int _sys_memfd_create(const char *name, unsigned int flags) 935 { 936 return __nolibc_syscall2(__NR_memfd_create, name, flags); 937 } 938 939 static __attribute__((unused)) 940 int memfd_create(const char *name, unsigned int flags) 941 { 942 return __sysret(_sys_memfd_create(name, flags)); 943 } 944 945 #endif /* _NOLIBC_SYS_H */ 946