Bug 241609

Summary: fexecve() fails after calling setuid() or seteuid()
Product: [Fedora] Fedora Reporter: Rennie deGraaf <degraaf>
Component: kernelAssignee: Kernel Maintainer List <kernel-maint>
Status: CLOSED CURRENTRELEASE QA Contact: Brian Brock <bbrock>
Severity: medium Docs Contact:
Priority: medium    
Version: 5CC: drepper
Target Milestone: ---   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: 2.6.22.1-41 Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2007-08-20 22:35:25 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
A program that demonstrates the bug. none

Description Rennie deGraaf 2007-05-28 21:12:18 UTC
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
fexecve().

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.

Additional Info:
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).

Comment 1 Rennie deGraaf 2007-05-28 21:12:18 UTC
Created attachment 155559 [details]
A program that demonstrates the bug.

Comment 2 Jakub Jelinek 2007-05-28 23:17:42 UTC
Then why are you filling that against glibc?

Comment 3 Rennie deGraaf 2007-05-28 23:33:31 UTC
(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
properly.

Comment 4 Rennie deGraaf 2007-05-29 00:49:07 UTC
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.

Comment 5 Ulrich Drepper 2007-08-20 22:35:25 UTC
This is exclusively a kernel issue and is at least in F7 fixed.