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