Bug 92127

Summary: setuid to current euid fails with EPERM
Product: [Retired] Red Hat Linux Reporter: Damien Miller <djm>
Component: kernelAssignee: Arjan van de Ven <arjanv>
Status: CLOSED NOTABUG QA Contact: Brian Brock <bbrock>
Severity: medium Docs Contact:
Priority: medium    
Version: 9CC: alan, mitr
Target Milestone: ---   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2003-06-03 10:00:53 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
Example program none

Description Damien Miller 2003-06-02 23:48:31 UTC
A common idiom to drop all user privileges is to do a seteuid(new_uid) followed
by a setuid(new_uid). The two steps are done to ensure that the saved uid is
also set to new_uid on some (stupid) platforms.

Unfortunately this doesn't work on Linux. A setuid(geteuid()) call will fail
when the euid != cuid.

I am not sure what the motivation for this check is, as it doesn't seems to add
any security (one already has the euid privileges, or lack thereof). To make
matters doubly confusing, the same restriction is *not* applied to setgid, where
setgid(getegid()) works fine.

Comment 1 Damien Miller 2003-06-02 23:50:23 UTC
Created attachment 92099 [details]
Example program

Here is a simple example illustrating the issue. Run this with (uid, euid) as
root, the setuid call will fail.

If one replaces the setuid and seteuid with setgid and setegid, the second call
will succeed.

Comment 2 Alan Cox 2003-06-03 10:00:53 UTC
Your test program is buggy. When you seteuid() you are no longer effectively
root so you lose the capability to setuid() to someone else.

setuid(), then seteuid() 

Alternatively for more flexibility and BSD like behaviour you can use
setreuid()/setresuid()


Comment 3 Damien Miller 2003-06-03 10:45:55 UTC
> Your test program is buggy. When you seteuid() you 
> are no longer effectively root so you lose the 
> capability to setuid() to someone else.

Well, you are not setuid()ing to someone else. You are setuid()ing 
to your current euid. Seeing as how you already have these privileges, 
I can't see how such a restriction could possibly be useful.

I am aware of setresuid(), it is nice but non-standard and not widely 
supported. setreuid() is ambiguous as to the behaviour wrt saved UIDs 
so IMO can't be trusted for portable software.

BSD allows the order shown in the test program and many BSD programs 
use that order to drop privs. This seems like a break in portability 
for zero gain. 


Comment 4 Alan Cox 2003-06-03 11:12:59 UTC
Linux implements POSIX/SYS5 semantics for setuid/setuid and BSD semantics for
the BSD extensions. It has always taken this approach. For portable code you
should only rely on POSIX and SUS defined behaviour I agree.