Use execveat syscall in fexecve

Message ID mvm8thqdgj1.fsf@suse.de
State New, archived
Headers

Commit Message

Andreas Schwab Sept. 7, 2017, 9:06 a.m. UTC
  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.
---
 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 +++++
 sysdeps/unix/sysv/linux/microblaze/kernel-features.h |  5 +++++
 5 files changed, 35 insertions(+)
  

Comments

Florian Weimer Sept. 7, 2017, 11:27 a.m. UTC | #1
* Andreas Schwab:

> By using execveat we no longer depend on /proc.  The execveat syscall was
> introduced in 3.19, except for a few late comers.

Ideally, this should have a test that executing “/bin/sh -c true”
works, both with an O_PATH descriptor and a regular descriptor.

The implementation itself (including the AT_EMPTY_PATH flag) and the
__ASSUME_EXECVEAT conditions look good to me.
  

Patch

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 <stddef.h>
 #include <stdio.h>
 #include <unistd.h>
+#include <fcntl.h>
 #include <sys/stat.h>
 
+#include <sysdep.h>
+#include <sys/syscall.h>
+#include <kernel-features.h>
+
 
 /* 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