diff mbox series

[v2,05/13] posix: Consolidate execve family of functions

Message ID c73086c71d3deb6598029f3a72810c985a148ac7.1722193092.git.fweimer@redhat.com
State New
Headers show
Series getenv/environ thread safety | expand

Commit Message

Florian Weimer July 28, 2024, 7:02 p.m. UTC
Ports only need to implement __arch_execveat going forward.
Generic code implements execve, fexecve, execveat on top of it.
The __arch_execveat/execveat split makes it easy to add
generic code to the execveat implementation, e.g., for environ
handling.

The Linux implementation prefers the execve system call if
available and keeps emulation for fexecve-style execveat,
for maximum compatibility.
---
 posix/execve.c                                | 13 +----
 posix/execveat.c                              | 12 ++---
 posix/fexecve.c                               | 13 ++---
 .../hurd/execve.c => generic/arch-execveat.h} | 21 +++------
 .../mach/hurd/{execveat.c => arch-execveat.h} | 11 ++---
 sysdeps/mach/hurd/fexecve.c                   | 47 -------------------
 .../sysv/linux/{fexecve.c => arch-execveat.h} | 38 +++++++--------
 sysdeps/unix/sysv/linux/execveat.c            | 32 -------------
 sysdeps/unix/sysv/linux/syscalls.list         |  1 -
 9 files changed, 40 insertions(+), 148 deletions(-)
 rename sysdeps/{mach/hurd/execve.c => generic/arch-execveat.h} (61%)
 rename sysdeps/mach/hurd/{execveat.c => arch-execveat.h} (90%)
 delete mode 100644 sysdeps/mach/hurd/fexecve.c
 rename sysdeps/unix/sysv/linux/{fexecve.c => arch-execveat.h} (73%)
 delete mode 100644 sysdeps/unix/sysv/linux/execveat.c
diff mbox series

Patch

diff --git a/posix/execve.c b/posix/execve.c
index c8f08658cb..6d6cefaebe 100644
--- a/posix/execve.c
+++ b/posix/execve.c
@@ -16,24 +16,15 @@ 
    <https://www.gnu.org/licenses/>.  */
 
 #include <errno.h>
-#include <stddef.h>
+#include <fcntl.h>
 #include <unistd.h>
 
-
 /* Replace the current process, executing PATH with arguments ARGV and
    environment ENVP.  ARGV and ENVP are terminated by NULL pointers.  */
 int
 __execve (const char *path, char *const argv[], char *const envp[])
 {
-  if (path == NULL || argv == NULL || envp == NULL)
-    {
-      __set_errno (EINVAL);
-      return -1;
-    }
-
-  __set_errno (ENOSYS);
-  return -1;
+  return __execveat (AT_FDCWD, path, argv, envp, 0);
 }
-stub_warning (execve)
 
 weak_alias (__execve, execve)
diff --git a/posix/execveat.c b/posix/execveat.c
index bddc4d5fb3..110177ea54 100644
--- a/posix/execveat.c
+++ b/posix/execveat.c
@@ -20,6 +20,8 @@ 
 #include <stddef.h>
 #include <unistd.h>
 
+#include <arch-execveat.h>
+
 /* Replace the current process, executing PATH relative to difrd with
    arguments argv and environment envp.
    argv and envp are terminated by NULL pointers.  */
@@ -27,15 +29,7 @@  int
 __execveat (int dirfd, const char *path, char *const argv[], char *const envp[],
             int flags)
 {
-  if (path == NULL || argv == NULL || envp == NULL)
-    {
-      __set_errno (EINVAL);
-      return -1;
-    }
-
-  __set_errno (ENOSYS);
-  return -1;
+  return __arch_execveat (dirfd, path, argv, envp, flags);
 }
-stub_warning (execveat)
 
 weak_alias (__execveat, execveat)
diff --git a/posix/fexecve.c b/posix/fexecve.c
index 04e59f97ad..3f632b3ea3 100644
--- a/posix/fexecve.c
+++ b/posix/fexecve.c
@@ -16,23 +16,20 @@ 
    <https://www.gnu.org/licenses/>.  */
 
 #include <errno.h>
-#include <stddef.h>
+#include <fcntl.h>
 #include <unistd.h>
 
-
 /* Execute the file FD refers to, overlaying the running program image.
    ARGV and ENVP are passed to the new program, as for `execve'.  */
 int
 fexecve (int fd, char *const argv[], char *const envp[])
 {
-  if (fd < 0 || argv == NULL || envp == NULL)
+  /* Avoid unexpected behavior of execveat with AT_FDCWD.  */
+  if (fd < 0)
     {
-      __set_errno (EINVAL);
+      __set_errno (EBADF);
       return -1;
     }
 
-  __set_errno (ENOSYS);
-  return -1;
+  return __execveat (fd, "", argv, envp, AT_EMPTY_PATH);
 }
-
-stub_warning (fexecve)
diff --git a/sysdeps/mach/hurd/execve.c b/sysdeps/generic/arch-execveat.h
similarity index 61%
rename from sysdeps/mach/hurd/execve.c
rename to sysdeps/generic/arch-execveat.h
index 11e3f34b39..cd064df28f 100644
--- a/sysdeps/mach/hurd/execve.c
+++ b/sysdeps/generic/arch-execveat.h
@@ -1,4 +1,5 @@ 
-/* Copyright (C) 1991-2024 Free Software Foundation, Inc.
+/* Architecture-specific execveat implementation.  Stub version.
+   Copyright (C) 2024 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
@@ -15,18 +16,10 @@ 
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <unistd.h>
-#include <hurd.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-/* Replace the current process, executing FILE_NAME with arguments ARGV and
-   environment ENVP.  ARGV and ENVP are terminated by NULL pointers.  */
-int
-__execve (const char *file_name, char *const argv[], char *const envp[])
+static int
+__arch_execveat (int dirfd, const char *path, char *const argv,
+                 char *const envp, int flags)
 {
-  return __execveat (AT_FDCWD, file_name, argv, envp, 0);
+  __set_errno (ENOSYS);
+  return -1;
 }
-
-weak_alias (__execve, execve)
diff --git a/sysdeps/mach/hurd/execveat.c b/sysdeps/mach/hurd/arch-execveat.h
similarity index 90%
rename from sysdeps/mach/hurd/execveat.c
rename to sysdeps/mach/hurd/arch-execveat.h
index f24dd7b62f..999779cbd5 100644
--- a/sysdeps/mach/hurd/execveat.c
+++ b/sysdeps/mach/hurd/arch-execveat.h
@@ -1,4 +1,5 @@ 
-/* Copyright (C) 1991-2024 Free Software Foundation, Inc.
+/* Execute program relative to a directory file descriptor.  Hurd version.
+   Copyright (C) 1991-2024 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
@@ -25,9 +26,9 @@ 
 
 /* Replace the current process, executing FILE_NAME with arguments ARGV and
    environment ENVP.  ARGV and ENVP are terminated by NULL pointers.  */
-int
-__execveat (int dirfd, const char *file_name, char *const argv[],
-            char *const envp[], int flags)
+static int
+__arch_execveat (int dirfd, const char *file_name, char *const argv[],
+		 char *const envp[], int flags)
 {
   error_t err;
   char *concat_name = NULL;
@@ -88,5 +89,3 @@  __execveat (int dirfd, const char *file_name, char *const argv[],
 
   return __hurd_fail (err);
 }
-
-weak_alias (__execveat, execveat)
diff --git a/sysdeps/mach/hurd/fexecve.c b/sysdeps/mach/hurd/fexecve.c
deleted file mode 100644
index 50472d5ca5..0000000000
--- a/sysdeps/mach/hurd/fexecve.c
+++ /dev/null
@@ -1,47 +0,0 @@ 
-/* Copyright (C) 1993-2024 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
-   <https://www.gnu.org/licenses/>.  */
-
-#include <unistd.h>
-#include <hurd.h>
-#include <hurd/fd.h>
-#include <errno.h>
-
-/* Execute the file FD refers to, overlaying the running program image.  */
-
-int
-fexecve (int fd, char *const argv[], char *const envp[])
-{
-  file_t file;
-  error_t err;
-  enum retry_type doretry;
-  char retryname[1024];
-
-  err = HURD_DPORT_USE (fd,
-      __dir_lookup (port, "", O_EXEC, 0, &doretry, retryname, &file));
-
-  if (! err && (doretry != FS_RETRY_NORMAL || retryname[0] != '\0'))
-    err = EGRATUITOUS;
-  if (err)
-    return __hurd_fail(err);
-
-  err = _hurd_exec_paths (__mach_task_self (), file, NULL, NULL, argv, envp);
-  if (! err)
-    err = EGRATUITOUS;
-
-  __mach_port_deallocate (__mach_task_self (), file);
-  return __hurd_fail (err);
-}
diff --git a/sysdeps/unix/sysv/linux/fexecve.c b/sysdeps/unix/sysv/linux/arch-execveat.h
similarity index 73%
rename from sysdeps/unix/sysv/linux/fexecve.c
rename to sysdeps/unix/sysv/linux/arch-execveat.h
index c2303735de..b6bc286829 100644
--- a/sysdeps/unix/sysv/linux/fexecve.c
+++ b/sysdeps/unix/sysv/linux/arch-execveat.h
@@ -1,4 +1,5 @@ 
-/* Copyright (C) 1994-2024 Free Software Foundation, Inc.
+/* Execute program relative to a directory file descriptor.  Linux version.
+   Copyright (C) 1994-2024 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
@@ -15,17 +16,11 @@ 
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <errno.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <unistd.h>
 #include <fcntl.h>
-#include <sys/stat.h>
-
 #include <fd_to_filename.h>
-#include <sysdep.h>
-#include <sys/syscall.h>
 #include <kernel-features.h>
+#include <sys/syscall.h>
+#include <sysdep.h>
 
 static int
 __do_fexecve (int fd, char *const argv[], char *const envp[])
@@ -64,17 +59,20 @@  __do_fexecve (int fd, char *const argv[], char *const envp[])
   return -1;
 }
 
-/* Execute the file FD refers to, overlaying the running program image.
-   ARGV and ENVP are passed to the new program, as for `execve'.  */
-int
-fexecve (int fd, char *const argv[], char *const envp[])
+static int
+__arch_execveat (int dirfd, const char *path, char *const *argv,
+                 char *const *envp, int flags)
 {
-  /* Avoid unexpected behavior of execveat with AT_FDCWD.  */
-  if (fd < 0)
-    {
-      __set_errno (EBADF);
-      return -1;
-    }
+  /* Use execve if possible, to preserve the historic system call
+     profile.  */
+  if (dirfd == AT_FDCWD && flags == 0)
+    return INLINE_SYSCALL_CALL (execve, path, argv, envp, flags);
+
+  /* Provide emulation for an fexecve-style execveat call.  */
+  if (dirfd >= 0 && flags == AT_EMPTY_PATH && path[0] == '\0')
+    return __do_fexecve (dirfd, argv, envp);
 
-  return __do_fexecve (fd, argv, envp);
+  /* Otherwise perform the system call without emulation.  */
+  return INLINE_SYSCALL_CALL (execveat, dirfd, path, &argv[0], &envp[0],
+                              flags);
 }
diff --git a/sysdeps/unix/sysv/linux/execveat.c b/sysdeps/unix/sysv/linux/execveat.c
deleted file mode 100644
index e1d68b9043..0000000000
--- a/sysdeps/unix/sysv/linux/execveat.c
+++ /dev/null
@@ -1,32 +0,0 @@ 
-/* Execute program relative to a directory file descriptor.
-   Copyright (C) 2021-2024 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
-   <https://www.gnu.org/licenses/>.  */
-
-#include <fd_to_filename.h>
-#include <sysdep.h>
-#include <unistd.h>
-
-/* Execute the file FD refers to, overlaying the running program image.
-   ARGV and ENVP are passed to the new program, as for 'execve'.  */
-int
-execveat (int dirfd, const char *path, char *const argv[], char *const envp[],
-          int flags)
-{
-  /* Avoid implicit array coercion in syscall macros.  */
-  return INLINE_SYSCALL_CALL (execveat, dirfd, path, &argv[0], &envp[0],
-			      flags);
-}
diff --git a/sysdeps/unix/sysv/linux/syscalls.list b/sysdeps/unix/sysv/linux/syscalls.list
index 9ac42c3436..14bbb5fe6e 100644
--- a/sysdeps/unix/sysv/linux/syscalls.list
+++ b/sysdeps/unix/sysv/linux/syscalls.list
@@ -9,7 +9,6 @@  delete_module	EXTRA	delete_module	3	delete_module
 epoll_create1	EXTRA	epoll_create1	i:i	epoll_create1
 epoll_ctl	EXTRA	epoll_ctl	i:iiip	epoll_ctl
 eventfd		EXTRA	eventfd2	i:ii	eventfd
-execve		-	execve		i:spp	__execve	execve
 flock		-	flock		i:ii	__flock		flock
 fsconfig	EXTRA	fsconfig	i:iUsNi	fsconfig
 fsmount		EXTRA	fsmount		i:iUU	fsmount