From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 39611 invoked by alias); 11 Sep 2017 20:30:00 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Received: (qmail 39583 invoked by uid 89); 11 Sep 2017 20:29:59 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.4 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RCVD_IN_DNSWL_NONE,RCVD_IN_SORBS_SPAM,SPF_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mail-qt0-f174.google.com X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-language :content-transfer-encoding; bh=XW/rrDMFUfddCBKFL5hrHZsxwEHarTPj1njuofpEYNA=; b=AifGXTQRzdfk70DoKsMW+ZKGRSdWNFc3zQihA9wTkQ/ysVwMxR2zR90fT45DqZKXqs BbIBoqQKszs/ecMM3EpHjOZ62i6xT4HID9Co12ua5ASSUQbaJsUtOaYBgKLEAw9juoVa LAKS3TUtwaNEDZB9y118fH6VBl/d7xh3FzcIrjbyefiYv/GbxTOItJ6pZ89Vqn6mM9Xc OBPqJ6NLxj4FhKW0qYdzqTOZD2dn7iAr32ClMy3hjIPc0rRp0pUrgt6C/jTn+mKej945 tvXSvg8s+TtL6ivP01MG3u/TkUurV5X1rVa4bLMkx5V1eozLT8/oFjBhQYno2vLotwmh 6dgQ== X-Gm-Message-State: AHPjjUic4yfl8oKjFUmpL+TYP1fhH8rvmIgZcrgsqrGTEeYgmQqctW3t Naofb4vqpEYDQyiOcDNnZA== X-Google-Smtp-Source: AOwi7QDzLL58ZXDExadCSbTKbC7jWbRSusgRAvPe011zItyl8KVU+2aB/pvu+bHG6R/hy36C6oca7A== X-Received: by 10.237.58.7 with SMTP id n7mr896228qte.205.1505161787347; Mon, 11 Sep 2017 13:29:47 -0700 (PDT) Subject: Re: [PATCH v2] Use execveat syscall in fexecve To: libc-alpha@sourceware.org References: <87bmmmlpe1.fsf@mid.deneb.enyo.de> From: Adhemerval Zanella Message-ID: <2a21b0d6-5f62-a711-2b4a-616ebb798963@linaro.org> Date: Mon, 11 Sep 2017 20:30:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.2.1 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-SW-Source: 2017-09/txt/msg00465.txt.bz2 On 11/09/2017 07:23, Andreas Schwab wrote: > 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); I would prefer it to use INLINE_SYSCALL_CALL. And since the idea is not to clobber errno I think we can do: #ifdef __NR_execvat INTERNAL_SYSCALL_DECL (err); int val = INTERNAL_SYSCALL_CALL (execveat, fd, argv, envp, AT_EMPTY_PATH); if (INTERNAL_SYSCALL_ERROR_P (val, err) != ENOSYS) return -1; #endif > +# ifndef __ASSUME_EXECVEAT > + if (errno != ENOSYS) > + return -1; > +# endif > +#endif Do we really need to add another __ASSUME_* that eventually we will need to cleanup? Can't we just check fo __NR_execvat, call it and if it fails with ENOSYS use the current code as fallback? The drawback would be that the fallback code would be mainly dead code for newer kernels. > + > +#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 >