From patchwork Mon Sep 11 10:23:09 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Schwab X-Patchwork-Id: 22823 Received: (qmail 60814 invoked by alias); 11 Sep 2017 10:23:14 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 60801 invoked by uid 89); 11 Sep 2017 10:23:14 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RP_MATCHES_RCVD, SPF_PASS autolearn=ham version=3.3.2 spammy=Hx-languages-length:7517 X-HELO: mx1.suse.de From: Andreas Schwab To: libc-alpha@sourceware.org Subject: [PATCH v2] Use execveat syscall in fexecve References: <87bmmmlpe1.fsf@mid.deneb.enyo.de> X-Yow: Should I do my BOBBIE VINTON medley? Date: Mon, 11 Sep 2017 12:23:09 +0200 In-Reply-To: <87bmmmlpe1.fsf@mid.deneb.enyo.de> (Florian Weimer's message of "Thu, 07 Sep 2017 13:27:50 +0200") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.2 (gnu/linux) MIME-Version: 1.0 By using execveat we no longer depend on /proc. The execveat syscall was introduced in 3.19, except for a few late comers. * sysdeps/unix/sysv/linux/fexecve.c (fexecve) [__NR_execveat]: Try execveat first. [!__ASSUME_EXECVEAT]: Fall back to /proc if execveat is unimplemented. * sysdeps/unix/sysv/linux/kernel-features.h (__ASSUME_EXECVEAT) [__LINUX_KERNEL_VERSION >= 0x031300]: Define. * sysdeps/unix/sysv/linux/alpha/kernel-features.h (__ASSUME_EXECVEAT) [__LINUX_KERNEL_VERSION < 0x040200]: Undef. * sysdeps/unix/sysv/linux/hppa/kernel-features.h (__ASSUME_EXECVEAT) [__LINUX_KERNEL_VERSION < 0x040000]: Undef. * sysdeps/unix/sysv/linux/microblaze/kernel-features.h (__ASSUME_EXECVEAT) [__LINUX_KERNEL_VERSION < 0x040000]: Undef. * posix/Makefile (tests): Add tst-fexecve. * posix/tst-fexecve.c: New file. --- posix/Makefile | 2 +- posix/tst-fexecve.c | 88 ++++++++++++++++++++++ sysdeps/unix/sysv/linux/alpha/kernel-features.h | 5 ++ sysdeps/unix/sysv/linux/fexecve.c | 15 ++++ sysdeps/unix/sysv/linux/hppa/kernel-features.h | 5 ++ sysdeps/unix/sysv/linux/kernel-features.h | 5 ++ .../unix/sysv/linux/microblaze/kernel-features.h | 5 ++ 7 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 posix/tst-fexecve.c diff --git a/posix/Makefile b/posix/Makefile index 4021e4f19e..75d905b922 100644 --- a/posix/Makefile +++ b/posix/Makefile @@ -94,7 +94,7 @@ tests := test-errno tstgetopt testfnm runtests runptests \ tst-fnmatch4 tst-fnmatch5 \ tst-posix_spawn-fd tst-posix_spawn-setsid \ tst-posix_fadvise tst-posix_fadvise64 \ - tst-sysconf-empty-chroot + tst-sysconf-empty-chroot tst-fexecve tests-internal := bug-regex5 bug-regex20 bug-regex33 \ tst-rfc3484 tst-rfc3484-2 tst-rfc3484-3 xtests := bug-ga2 diff --git a/posix/tst-fexecve.c b/posix/tst-fexecve.c new file mode 100644 index 0000000000..2409102e21 --- /dev/null +++ b/posix/tst-fexecve.c @@ -0,0 +1,88 @@ +/* Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include + +#include + +/* Try executing "/bin/sh -c true", using FD opened on /bin/sh. */ +static int +try_fexecve (int fd) +{ + pid_t pid = fork (); + + if (pid == 0) + { + static const char *const argv[] = { + "/bin/sh", "-c", "true", NULL + }; + fexecve (fd, (char *const *) argv, environ); + _exit (errno); + } + if (pid < 0) + FAIL_RET ("fork failed: %m"); + + pid_t termpid; + int status; + termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)); + if (termpid == -1) + FAIL_RET ("waitpid failed: %m"); + if (termpid != pid) + FAIL_RET ("waitpid returned %ld != %ld", + (long int) termpid, (long int) pid); + if (!WIFEXITED (status)) + FAIL_RET ("child hasn't exited normally"); + + /* If fexecve is unimplemented mark this test as UNSUPPORTED. */ + if (WEXITSTATUS (status) == ENOSYS) + FAIL_UNSUPPORTED ("fexecve is unimplemented"); + + if (WEXITSTATUS (status) != 0) + { + errno = WEXITSTATUS (status); + FAIL_RET ("fexecve failed: %m"); + } + return 0; +} + +static int +do_test (void) +{ + int fd; + int ret; + + fd = open ("/bin/sh", O_RDONLY); + if (fd < 0) + FAIL_UNSUPPORTED ("/bin/sh cannot be opened: %m"); + ret = try_fexecve (fd); + close (fd); + +#ifdef O_PATH + fd = open ("/bin/sh", O_RDONLY | O_PATH); + if (fd < 0) + FAIL_UNSUPPORTED ("/bin/sh cannot be opened (O_PATH): %m"); + ret |= try_fexecve (fd); + close (fd); +#endif + + return ret; +} + +#include diff --git a/sysdeps/unix/sysv/linux/alpha/kernel-features.h b/sysdeps/unix/sysv/linux/alpha/kernel-features.h index 53f7611f93..5bc2ddb713 100644 --- a/sysdeps/unix/sysv/linux/alpha/kernel-features.h +++ b/sysdeps/unix/sysv/linux/alpha/kernel-features.h @@ -35,4 +35,9 @@ #define __ASSUME_RECV_SYSCALL 1 #define __ASSUME_SEND_SYSCALL 1 +/* Support for the execveat syscall was added in 4.2. */ +#if __LINUX_KERNEL_VERSION < 0x040200 +# undef __ASSUME_EXECVEAT +#endif + #endif /* _KERNEL_FEATURES_H */ diff --git a/sysdeps/unix/sysv/linux/fexecve.c b/sysdeps/unix/sysv/linux/fexecve.c index 30fa719b56..3bf5de507f 100644 --- a/sysdeps/unix/sysv/linux/fexecve.c +++ b/sysdeps/unix/sysv/linux/fexecve.c @@ -19,8 +19,13 @@ #include #include #include +#include #include +#include +#include +#include + /* Execute the file FD refers to, overlaying the running program image. ARGV and ENVP are passed to the new program, as for `execve'. */ @@ -33,6 +38,15 @@ fexecve (int fd, char *const argv[], char *const envp[]) return -1; } +#ifdef __NR_execveat + INLINE_SYSCALL (execveat, 5, fd, "", argv, envp, AT_EMPTY_PATH); +# ifndef __ASSUME_EXECVEAT + if (errno != ENOSYS) + return -1; +# endif +#endif + +#ifndef __ASSUME_EXECVEAT /* We use the /proc filesystem to get the information. If it is not mounted we fail. */ char buf[sizeof "/proc/self/fd/" + sizeof (int) * 3]; @@ -50,6 +64,7 @@ fexecve (int fd, char *const argv[], char *const envp[]) save = ENOSYS; __set_errno (save); +#endif return -1; } diff --git a/sysdeps/unix/sysv/linux/hppa/kernel-features.h b/sysdeps/unix/sysv/linux/hppa/kernel-features.h index 0e73a5c0df..f25a840040 100644 --- a/sysdeps/unix/sysv/linux/hppa/kernel-features.h +++ b/sysdeps/unix/sysv/linux/hppa/kernel-features.h @@ -27,3 +27,8 @@ #define __ASSUME_RECV_SYSCALL 1 #define __ASSUME_SEND_SYSCALL 1 + +/* Support for the execveat syscall was added in 4.0. */ +#if __LINUX_KERNEL_VERSION < 0x040000 +# undef __ASSUME_EXECVEAT +#endif diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h index 9495db4fef..2e1fe6597a 100644 --- a/sysdeps/unix/sysv/linux/kernel-features.h +++ b/sysdeps/unix/sysv/linux/kernel-features.h @@ -102,3 +102,8 @@ implementation does not assume the __ASSUME_* and instead use a fallback implementation based on p{read,write}v and returning an error for non supported flags. */ + +/* Support for the execveat syscall was added in 3.19. */ +#if __LINUX_KERNEL_VERSION >= 0x031300 +# define __ASSUME_EXECVEAT 1 +#endif diff --git a/sysdeps/unix/sysv/linux/microblaze/kernel-features.h b/sysdeps/unix/sysv/linux/microblaze/kernel-features.h index 0257524777..6575df2a95 100644 --- a/sysdeps/unix/sysv/linux/microblaze/kernel-features.h +++ b/sysdeps/unix/sysv/linux/microblaze/kernel-features.h @@ -47,3 +47,8 @@ #if __LINUX_KERNEL_VERSION < 0x030300 # undef __ASSUME_SENDMMSG_SYSCALL #endif + +/* Support for the execveat syscall was added in 4.0. */ +#if __LINUX_KERNEL_VERSION < 0x040000 +# undef __ASSUME_EXECVEAT +#endif