Bug 17100 - secure_getenv() does not seem to properly detect if an environment is secure
Summary: secure_getenv() does not seem to properly detect if an environment is secure
Status: NEW
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: 2.19
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-06-29 03:16 UTC by Brent Cook
Modified: 2014-06-29 15:20 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Brent Cook 2014-06-29 03:16:36 UTC
Until getauxval(AT_SECURE) was added, there did not appear to be a good way to detect if a process is running setuid/setgid or not. You can find various discussions about how to implement the BSD issetugid() function on Linux for reference.

Checks like (uid==euid||gid==egid) can fail in various ways, e.g. it cannot detect if a process has changed its uid/gid back, it is racy in multi-threaded contexts, among other issues. I think that future glibc versions should only use AT_SECURE, removing the getuid/geteuid check. If AT_SECURE is unavailable, just assume the worst.

<snip>
     case AT_SECURE:
   seen = -1;
   __libc_enable_secure = av->a_un.a_val;
   __libc_enable_secure_decided = 1;

<snip>
__libc_init_secure (void)
{
 if (__libc_enable_secure_decided == 0)
   __libc_enable_secure = (__geteuid () != __getuid ()
               || __getegid () != __getgid ());
}

<snip>
char *
__libc_secure_getenv (name)
    const char *name;
{
 return __libc_enable_secure ? NULL : getenv (name);
}
Comment 1 Andreas Schwab 2014-06-29 07:40:23 UTC
__libc_enable_secure is computed by the libc initializer before any application code is run.  No multi threading, no setuid/setgid calls.
Comment 2 joseph@codesourcery.com 2014-06-29 11:55:12 UTC
On Sun, 29 Jun 2014, busterb at gmail dot com wrote:

> contexts, among other issues. I think that future glibc versions should only
> use AT_SECURE, removing the getuid/geteuid check. If AT_SECURE is unavailable,
> just assume the worst.

AT_SECURE is always available, since we removed support for pre-2.6 
kernels.
Comment 3 Florian Weimer 2014-06-29 12:17:08 UTC
Should we add a check which aborts if AT_SECURE is not present?  Beyond that, there isn't anything libc can do here.
Comment 4 Brent Cook 2014-06-29 13:36:02 UTC
Thank you for the clarification.

Though AT_SECURE is available in all kernels that glibc supports, is there be any way for an adversary to cause the fallback case to be triggered through external means?

That there is a fallback case is a little misleading since it does not also perform the capabilities checks that the kernel does, so I don't think one would want it to inadvertently execute on any kernel that implements capabilities:

http://lxr.free-electrons.com/source/security/commoncap.c#L590
Comment 5 Florian Weimer 2014-06-29 13:52:28 UTC
(In reply to Brent Cook from comment #4)
> Though AT_SECURE is available in all kernels that glibc supports, is there
> be any way for an adversary to cause the fallback case to be triggered
> through external means?

No, the kernel prepares the aux vector as part of the execve implementation.  It is possible to invoke the new process through userspace emulation, supplying a bogus aux vector, but then, no privilege transition occurs, so there is no security impact.
Comment 6 Brent Cook 2014-06-29 14:04:16 UTC
So at worst, the fallback case is a vestigial tail?

It would seem to be ready for the chopping block if so.
Comment 7 joseph@codesourcery.com 2014-06-29 15:20:03 UTC
elf/enbl-secure.c is used on Hurd as well as Linux, but I suppose that 
part of the code ought to be disabled if HAVE_AUX_SECURE.