Fix third argument to setresgid call while setting $(.
authorLeon Timmermans <fawaka@gmail.com>
Tue, 13 Sep 2011 20:04:23 +0000 (22:04 +0200)
committerCraig A. Berry <craigberry@mac.com>
Mon, 31 Oct 2011 23:57:56 +0000 (18:57 -0500)
[Committer's note: discussion on perl5-security-report concluded that
exploitability was low to nonexistent because any system that has setresgid
but not setregid will pretend to have the latter and define it in terms
of the former (see "#ifndef HAS_SETREGID" in perl.h).  But the bug should
be fixed in case that code gets exposed in the future.  The approach
taken in perl.h was also called into question and may elicit further
discussion and patching.]

Note: bug this only affects systems that have setresgid but not setregid
(since that codepath prefers the latter over the former). To the best of
my knowledge, no such systems exists (nor would it make much sense) so
this bug is probably not exploitable, but I can't guarantee that.

When the effective group is set using setresgid, it does this:
  setresgid((Gid_t)PL_gid, (Gid_t)-1, (Gid_t) 1);
That last 1 should have been a -1. Instead of leaving the saved GID
unchanged it sets it to to 1. This means privileges are not permanently
dropped, but instead the GID is set to 1 (if possible). The program can
thereafter change it's effective and real GIDs to 1.

mg.c

diff --git a/mg.c b/mg.c
index 8c986a5..5c2628b 100644 (file)
--- a/mg.c
+++ b/mg.c
@@ -2820,7 +2820,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
        (void)setregid((Gid_t)PL_gid, (Gid_t)-1);
 #else
 #ifdef HAS_SETRESGID
-      (void)setresgid((Gid_t)PL_gid, (Gid_t)-1, (Gid_t) 1);
+      (void)setresgid((Gid_t)PL_gid, (Gid_t)-1, (Gid_t) -1);
 #else
        if (PL_gid == PL_egid)                  /* special case $( = $) */
            (void)PerlProc_setgid(PL_gid);