[v2] Use execveat syscall in fexecve

Message ID mvmr2vdbkky.fsf_-_@suse.de
State New, archived
Headers

Commit Message

Andreas Schwab Sept. 11, 2017, 10:23 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.
	* 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
  

Comments

Adhemerval Zanella Netto Sept. 11, 2017, 8:29 p.m. UTC | #1
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
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <unistd.h>
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <sys/wait.h>
> +
> +#include <support/check.h>
> +
> +/* 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 <support/test-driver.c>
> 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);

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
>
  
Joseph Myers Sept. 11, 2017, 8:38 p.m. UTC | #2
On Mon, 11 Sep 2017, Adhemerval Zanella wrote:

> > +# 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.

We have the ENOSYS code there and the subsequent fallback that will 
eventually need cleaning up *anyway*.  Having the __ASSUME_* macro makes 
it obvious in future exactly what changes should be made for the cleanup 
and exactly when it is possible to do that cleanup.  I think having such 
macros for any case with fallback code that can be cleaned up in future is 
a good idea for that reason.
  
Florian Weimer Sept. 11, 2017, 8:59 p.m. UTC | #3
* Joseph Myers:

> We have the ENOSYS code there and the subsequent fallback that will 
> eventually need cleaning up *anyway*.  Having the __ASSUME_* macro makes 
> it obvious in future exactly what changes should be made for the cleanup 
> and exactly when it is possible to do that cleanup.  I think having such 
> macros for any case with fallback code that can be cleaned up in future is 
> a good idea for that reason.

Agreed.  As long as there is an expectation that we will eventually
bump the minimum kernel requirement, __ASSUME_* macros are the way to
go.
  
Adhemerval Zanella Netto Sept. 11, 2017, 10:58 p.m. UTC | #4
On 11/09/2017 17:59, Florian Weimer wrote:
> * Joseph Myers:
> 
>> We have the ENOSYS code there and the subsequent fallback that will 
>> eventually need cleaning up *anyway*.  Having the __ASSUME_* macro makes 
>> it obvious in future exactly what changes should be made for the cleanup 
>> and exactly when it is possible to do that cleanup.  I think having such 
>> macros for any case with fallback code that can be cleaned up in future is 
>> a good idea for that reason.
> 
> Agreed.  As long as there is an expectation that we will eventually
> bump the minimum kernel requirement, __ASSUME_* macros are the way to
> go.
> 

Fair enough then.
  
Andreas Schwab Sept. 14, 2017, 8:04 a.m. UTC | #5
On Sep 11 2017, Adhemerval Zanella <adhemerval.zanella@linaro.org> wrote:

> 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

No, that would be wrong.  Either the exec succeeds, then errno no longer
exits, otherwise errno needs to be set before we return.

Andreas.
  
Adhemerval Zanella Netto Sept. 14, 2017, 1:44 p.m. UTC | #6
On 14/09/2017 05:04, Andreas Schwab wrote:
> On Sep 11 2017, Adhemerval Zanella <adhemerval.zanella@linaro.org> wrote:
> 
>> 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
> 
> No, that would be wrong.  Either the exec succeeds, then errno no longer
> exits, otherwise errno needs to be set before we return.
> 
> Andreas.
> 

Right, errno does need to be setup (I misread the man for some reason).
  

Patch

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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+
+#include <support/check.h>
+
+/* 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 <support/test-driver.c>
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