Wireshark-dev: Re: [Wireshark-dev] [Wireshark-bugs] [Bug 1741] Privilege separation patch

From: Gerald Combs <gerald@xxxxxxxxxxxxx>
Date: Wed, 15 Aug 2007 15:27:21 -0700
Guy Harris wrote:
> setuid() *should*, at least according to the Single UNIX Specification, 
> set the real, effective, and set-user ID if the process is running with 
> appropriate privileges.  The same applies, *mutatis mutandis*, to setgid().

According to "Setuid Demystified", this may not work in some cases.  The
paper is 5 years old now, so I'm not sure how much of it still applies.
 However, uidswap.c:permanently_drop_suid() in the OpenSSH distribution
seems to prefer setresuid() over setuid():

void
permanently_drop_suid(uid_t uid)
{
	uid_t old_uid = getuid();

	debug("permanently_drop_suid: %u", (u_int)uid);
#if defined(HAVE_SETRESUID) && !defined(BROKEN_SETRESUID)
	if (setresuid(uid, uid, uid) < 0)
		fatal("setresuid %u: %.100s", (u_int)uid, strerror(errno));
#elif defined(HAVE_SETREUID) && !defined(BROKEN_SETREUID)
	if (setreuid(uid, uid) < 0)
		fatal("setreuid %u: %.100s", (u_int)uid, strerror(errno));
#else
# ifndef SETEUID_BREAKS_SETUID
	if (seteuid(uid) < 0)
		fatal("seteuid %u: %.100s", (u_int)uid, strerror(errno));
# endif
	if (setuid(uid) < 0)
		fatal("setuid %u: %.100s", (u_int)uid, strerror(errno));
#endif

#ifndef HAVE_CYGWIN
	/* Try restoration of UID if changed (test clearing of saved uid) */
	if (old_uid != uid &&
	    (setuid(old_uid) != -1 || seteuid(old_uid) != -1))
		fatal("%s: was able to restore old [e]uid", __func__);
#endif

	/* Verify UID drop was successful */
	if (getuid() != uid || geteuid() != uid) {
		fatal("%s: euid incorrect uid:%u euid:%u (should be %u)",
		    __func__, (u_int)getuid(), (u_int)geteuid(), (u_int)uid);
	}
}

BROKEN_SETRESUID, BROKEN_SETREUID, and SETEUID_BREAKS_SETUID are defined
at configure time using OS pattern matching.

> In Mac OS X 10.4 and later, a process can, in effect, belong to a bigger 
> group set than just the group set that fits in the credentials (checks 
> whether a process's group set includes a given group are done by sending 
> a message to memberd).  As I remember, the right way to change the group 
> set of a process is to call initgroups(), passing it the user name of 
> the user whose group set you want the process to pick up and that user's 
> primary group ID.  initgroups() is a BSDism, and has been picked up by 
> other OSes, so it's not OS X-only; we should probably use it if available.
> 
> Should the group set be changed *before* setting the effective user ID?
> _______________________________________________
> Wireshark-dev mailing list
> Wireshark-dev@xxxxxxxxxxxxx
> http://www.wireshark.org/mailman/listinfo/wireshark-dev