Description of problem:
Linux currently lacks a proper fexecve() system call, so fexecve() is
implemented as a glibc library call that looks up the file to execute in
/proc/self/fds and calls execve(). However, if a program that starts as root
drops root privileges by calling setuid() or seteuid() before calling fexecve()
(for instance, in order to execute a program as another user), then it no longer
has read access to /proc/self/fds, and fexecve() fails.
The man page for fexecve() does not mention this failure mode. (Incidentally,
the man page for fexecve() in not included in FC5.)
Version-Release number of selected component (if applicable):
This bug occurs in glibc-2.4-11 from FC5. Since sysdeps/unix/sysv/linux/fexec.c
in the glibc sources (the file implementing the fexecve() emulation) hasn't
changed, I expect that this issue occurs in all versions of glibc that implement
Steps to Reproduce:
Run the attached program *as root*. (If user id 99 doesn't exist on your
system, change the arguments of the setuid() or seteuid() call a user id that
does exist.) It should produce no output and return 0, but it instead prints
"fexecve() failed; errno = 13" and returns 255, indicating that the call to
fexecve() failed. (errno code 13 is EACCES). If the setuid() and seteuid()
calls are both commented out, the program works as expected.
I don't think that this can be fixed in libc; we need a proper kernel
implementation. A work-around is to use execve() directly, but this leads to
race conditions under some circumstances (such as when trying to execute a file
with the file owner's permissions).
Created attachment 155559 [details]
A program that demonstrates the bug.
Then why are you filling that against glibc?
(In reply to comment #2)
> Then why are you filling that against glibc?
Because fexecve() is currently implemented there. At the very least, this issue
should be added to the glibc documentation as a known bug, and the glibc wrapper
will need to be fixed when a better solution becomes available. There is also a
possibility that the glibc gurus can come up with a better way of implementing
fexecve() in userspace.
The kernel bug is that fexecve() isn't implemented, not that it doesn't work
I just discovered that a patch was added to the kernel as of 2.6.22-rc1 that
allows access to /proc/self/fd/ by programs that have called setuid(). This may
solve this issue; I don't currently have a system lying around that I want to
test a pre-release kernel on.
This is exclusively a kernel issue and is at least in F7 fixed.