diff mbox series

[v2,03/13] Linux: Introduce __do_fexecve in fexecve

Message ID 49be319a6cc60341a437ba186ef701b9095e00d7.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
Call the execve system call directly, in preparation of
wrapping environ access in the *execve* family of function.

Make handling of errno more explicit on the fallback path
by using INTERNAL_SYSCALL_CALL.
---
 sysdeps/unix/sysv/linux/fexecve.c | 53 ++++++++++++++++---------------
 1 file changed, 28 insertions(+), 25 deletions(-)

Comments

Adhemerval Zanella Netto Oct. 15, 2024, 7:51 p.m. UTC | #1
On 28/07/24 16:02, Florian Weimer wrote:
> Call the execve system call directly, in preparation of
> wrapping environ access in the *execve* family of function.
> 
> Make handling of errno more explicit on the fallback path
> by using INTERNAL_SYSCALL_CALL.

LGTM, thanks.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>

> ---
>  sysdeps/unix/sysv/linux/fexecve.c | 53 ++++++++++++++++---------------
>  1 file changed, 28 insertions(+), 25 deletions(-)
> 
> diff --git a/sysdeps/unix/sysv/linux/fexecve.c b/sysdeps/unix/sysv/linux/fexecve.c
> index e0e5566fd7..46c8170092 100644
> --- a/sysdeps/unix/sysv/linux/fexecve.c
> +++ b/sysdeps/unix/sysv/linux/fexecve.c
> @@ -27,6 +27,33 @@
>  #include <sys/syscall.h>
>  #include <kernel-features.h>
>  
> +static int
> +__do_fexecve (int fd, char *const argv[], char *const envp[])
> +{
> +  /* Avoid implicit array coercion in syscall macros.  */
> +  int err = -INTERNAL_SYSCALL_CALL (execveat, fd, "", &argv[0], &envp[0],
> +                                    AT_EMPTY_PATH);
> +
> +#ifndef __ASSUME_EXECVEAT
> +  if (err == ENOSYS)
> +    {
> +      /* We use the /proc filesystem to get the information.  If it is not
> +         mounted we fail.  We do not need the return value.  */
> +      struct fd_to_filename filename;
> +      const char *path = __fd_to_filename (fd, &filename);
> +      err = -INTERNAL_SYSCALL_CALL (execve, path, &argv[0], &envp[0]);
> +
> +      /* We come here only if the 'execve' call fails.  Determine whether
> +         /proc is mounted.  If not we return ENOSYS.  */
> +      if (INTERNAL_SYSCALL_CALL (faccessat, AT_FDCWD, "/proc/self/fd", 0)
> +          == -ENOENT)
> +        err = ENOSYS;

Ok, replace stat with faccessat (I had to remind myself that only faccessat2
accepts a flag). 

> +    }
> +#endif /* __ASSUME_EXECVEAT */
> +
> +  __set_errno (err);
> +  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'.  */
> @@ -39,29 +66,5 @@ fexecve (int fd, char *const argv[], char *const envp[])
>        return -1;
>      }
>  
> -  /* Avoid implicit array coercion in syscall macros.  */
> -  INLINE_SYSCALL (execveat, 5, fd, "", &argv[0], &envp[0], AT_EMPTY_PATH);
> -#ifndef __ASSUME_EXECVEAT
> -  if (errno != ENOSYS)
> -    return -1;
> -#endif
> -
> -#ifndef __ASSUME_EXECVEAT
> -  /* We use the /proc filesystem to get the information.  If it is not
> -     mounted we fail.  We do not need the return value.  */
> -  struct fd_to_filename filename;
> -  __execve (__fd_to_filename (fd, &filename), argv, envp);
> -
> -  int save = errno;
> -
> -  /* We come here only if the 'execve' call fails.  Determine whether
> -     /proc is mounted.  If not we return ENOSYS.  */
> -  struct __stat64_t64 st;
> -  if (__stat64_time64 ("/proc/self/fd", &st) != 0 && errno == ENOENT)
> -    save = ENOSYS;
> -
> -  __set_errno (save);
> -#endif
> -
> -  return -1;
> +  return __do_fexecve (fd, argv, envp);
>  }
diff mbox series

Patch

diff --git a/sysdeps/unix/sysv/linux/fexecve.c b/sysdeps/unix/sysv/linux/fexecve.c
index e0e5566fd7..46c8170092 100644
--- a/sysdeps/unix/sysv/linux/fexecve.c
+++ b/sysdeps/unix/sysv/linux/fexecve.c
@@ -27,6 +27,33 @@ 
 #include <sys/syscall.h>
 #include <kernel-features.h>
 
+static int
+__do_fexecve (int fd, char *const argv[], char *const envp[])
+{
+  /* Avoid implicit array coercion in syscall macros.  */
+  int err = -INTERNAL_SYSCALL_CALL (execveat, fd, "", &argv[0], &envp[0],
+                                    AT_EMPTY_PATH);
+
+#ifndef __ASSUME_EXECVEAT
+  if (err == ENOSYS)
+    {
+      /* We use the /proc filesystem to get the information.  If it is not
+         mounted we fail.  We do not need the return value.  */
+      struct fd_to_filename filename;
+      const char *path = __fd_to_filename (fd, &filename);
+      err = -INTERNAL_SYSCALL_CALL (execve, path, &argv[0], &envp[0]);
+
+      /* We come here only if the 'execve' call fails.  Determine whether
+         /proc is mounted.  If not we return ENOSYS.  */
+      if (INTERNAL_SYSCALL_CALL (faccessat, AT_FDCWD, "/proc/self/fd", 0)
+          == -ENOENT)
+        err = ENOSYS;
+    }
+#endif /* __ASSUME_EXECVEAT */
+
+  __set_errno (err);
+  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'.  */
@@ -39,29 +66,5 @@  fexecve (int fd, char *const argv[], char *const envp[])
       return -1;
     }
 
-  /* Avoid implicit array coercion in syscall macros.  */
-  INLINE_SYSCALL (execveat, 5, fd, "", &argv[0], &envp[0], AT_EMPTY_PATH);
-#ifndef __ASSUME_EXECVEAT
-  if (errno != ENOSYS)
-    return -1;
-#endif
-
-#ifndef __ASSUME_EXECVEAT
-  /* We use the /proc filesystem to get the information.  If it is not
-     mounted we fail.  We do not need the return value.  */
-  struct fd_to_filename filename;
-  __execve (__fd_to_filename (fd, &filename), argv, envp);
-
-  int save = errno;
-
-  /* We come here only if the 'execve' call fails.  Determine whether
-     /proc is mounted.  If not we return ENOSYS.  */
-  struct __stat64_t64 st;
-  if (__stat64_time64 ("/proc/self/fd", &st) != 0 && errno == ENOENT)
-    save = ENOSYS;
-
-  __set_errno (save);
-#endif
-
-  return -1;
+  return __do_fexecve (fd, argv, envp);
 }