Message ID | 2142860d3f3a6a56fc393f1c0ccc3f859601e06f.1722193092.git.fweimer@redhat.com |
---|---|
State | New |
Headers | show |
Series | getenv/environ thread safety | expand |
On 28/07/24 16:02, Florian Weimer wrote: > Do not check argv and envp for null, for consistency with > execveat and execve. An invalid descriptor should result in > EBADF, not EINVAL. > > In the fallback code, if the file descriptor is not valid, > return EBADF, not ENOENT. LGTM, thanks. Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> > --- > posix/tst-fexecve.c | 14 ++++++++++++++ > sysdeps/unix/sysv/linux/fexecve.c | 20 +++++++++++++++----- > 2 files changed, 29 insertions(+), 5 deletions(-) > > diff --git a/posix/tst-fexecve.c b/posix/tst-fexecve.c > index 9c528fe8d9..c8e772afb6 100644 > --- a/posix/tst-fexecve.c > +++ b/posix/tst-fexecve.c > @@ -82,6 +82,20 @@ do_test (void) > close (fd); > #endif > > + /* Now fd is not open, so fexecve is expected to fail with EBADF. */ > + static const char *const argv[] = { > + "/bin/sh", "-c", "false", NULL > + }; > + errno = -1; > + TEST_COMPARE (fexecve (fd, (char **const) argv, environ), -1); > + TEST_COMPARE (errno, EBADF); > + > + /* Likewise for negative descriptors. */ > + TEST_VERIFY (AT_FDCWD != -1); > + errno = -1; > + TEST_COMPARE (fexecve (-1, (char **const) argv, environ), -1); > + TEST_COMPARE (errno, EBADF); > + > return ret; > } > > diff --git a/sysdeps/unix/sysv/linux/fexecve.c b/sysdeps/unix/sysv/linux/fexecve.c > index 46c8170092..c2303735de 100644 > --- a/sysdeps/unix/sysv/linux/fexecve.c > +++ b/sysdeps/unix/sysv/linux/fexecve.c > @@ -45,9 +45,18 @@ __do_fexecve (int fd, char *const argv[], char *const envp[]) > > /* 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; > + if (err == ENOENT) > + { > + if (INTERNAL_SYSCALL_CALL (faccessat, AT_FDCWD, "/proc/self/fd", 0) > + == -ENOENT) > + err = ENOSYS; > + else if (INTERNAL_SYSCALL_CALL (faccessat, AT_FDCWD, path, 0) > + == -ENOENT) > + /* The file descriptor does not exist, but /proc is mounted. */ > + err = EBADF; > + /* Otherwise ENOENT comes from an invalid program > + interpreter or some other property of the file. */ > + } > } > #endif /* __ASSUME_EXECVEAT */ > > @@ -60,9 +69,10 @@ __do_fexecve (int fd, char *const argv[], char *const envp[]) > 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; > } >
diff --git a/posix/tst-fexecve.c b/posix/tst-fexecve.c index 9c528fe8d9..c8e772afb6 100644 --- a/posix/tst-fexecve.c +++ b/posix/tst-fexecve.c @@ -82,6 +82,20 @@ do_test (void) close (fd); #endif + /* Now fd is not open, so fexecve is expected to fail with EBADF. */ + static const char *const argv[] = { + "/bin/sh", "-c", "false", NULL + }; + errno = -1; + TEST_COMPARE (fexecve (fd, (char **const) argv, environ), -1); + TEST_COMPARE (errno, EBADF); + + /* Likewise for negative descriptors. */ + TEST_VERIFY (AT_FDCWD != -1); + errno = -1; + TEST_COMPARE (fexecve (-1, (char **const) argv, environ), -1); + TEST_COMPARE (errno, EBADF); + return ret; } diff --git a/sysdeps/unix/sysv/linux/fexecve.c b/sysdeps/unix/sysv/linux/fexecve.c index 46c8170092..c2303735de 100644 --- a/sysdeps/unix/sysv/linux/fexecve.c +++ b/sysdeps/unix/sysv/linux/fexecve.c @@ -45,9 +45,18 @@ __do_fexecve (int fd, char *const argv[], char *const envp[]) /* 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; + if (err == ENOENT) + { + if (INTERNAL_SYSCALL_CALL (faccessat, AT_FDCWD, "/proc/self/fd", 0) + == -ENOENT) + err = ENOSYS; + else if (INTERNAL_SYSCALL_CALL (faccessat, AT_FDCWD, path, 0) + == -ENOENT) + /* The file descriptor does not exist, but /proc is mounted. */ + err = EBADF; + /* Otherwise ENOENT comes from an invalid program + interpreter or some other property of the file. */ + } } #endif /* __ASSUME_EXECVEAT */ @@ -60,9 +69,10 @@ __do_fexecve (int fd, char *const argv[], char *const envp[]) 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; }