Fix CVE-2016-2381 (ambiguous environment variables handling)

This commit is contained in:
Petr Písař 2016-02-17 17:14:50 +01:00
parent 760b95c162
commit e55807fcfb
2 changed files with 122 additions and 1 deletions

View File

@ -0,0 +1,112 @@
From ae37b791a73a9e78dedb89fb2429d2628cf58076 Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@develop-help.com>
Date: Wed, 27 Jan 2016 11:52:15 +1100
Subject: [PATCH] remove duplicate environment variables from environ
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
If we see duplicate environment variables while iterating over
environ[]:
a) make sure we use the same value in %ENV that getenv() returns.
Previously on a duplicate, %ENV would have the last entry for the name
from environ[], but a typical getenv() would return the first entry.
Rather than assuming all getenv() implementations return the first entry
explicitly call getenv() to ensure they agree.
b) remove duplicate entries from environ
Previously if there was a duplicate definition for a name in environ[]
setting that name in %ENV could result in an unsafe value being passed
to a child process, so ensure environ[] has no duplicates.
CVE-2016-2381
Signed-off-by: Petr Písař <ppisar@redhat.com>
---
perl.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 49 insertions(+), 2 deletions(-)
diff --git a/perl.c b/perl.c
index 4a324c6..5c71fd0 100644
--- a/perl.c
+++ b/perl.c
@@ -4329,23 +4329,70 @@ S_init_postdump_symbols(pTHX_ int argc, char **argv, char **env)
}
if (env) {
char *s, *old_var;
+ STRLEN nlen;
SV *sv;
+ HV *dups = newHV();
+
for (; *env; env++) {
old_var = *env;
if (!(s = strchr(old_var,'=')) || s == old_var)
continue;
+ nlen = s - old_var;
#if defined(MSDOS) && !defined(DJGPP)
*s = '\0';
(void)strupr(old_var);
*s = '=';
#endif
- sv = newSVpv(s+1, 0);
- (void)hv_store(hv, old_var, s - old_var, sv, 0);
+ if (hv_exists(hv, old_var, nlen)) {
+ const char *name = savepvn(old_var, nlen);
+
+ /* make sure we use the same value as getenv(), otherwise code that
+ uses getenv() (like setlocale()) might see a different value to %ENV
+ */
+ sv = newSVpv(PerlEnv_getenv(name), 0);
+
+ /* keep a count of the dups of this name so we can de-dup environ later */
+ if (hv_exists(dups, name, nlen))
+ ++SvIVX(*hv_fetch(dups, name, nlen, 0));
+ else
+ (void)hv_store(dups, name, nlen, newSViv(1), 0);
+
+ Safefree(name);
+ }
+ else {
+ sv = newSVpv(s+1, 0);
+ }
+ (void)hv_store(hv, old_var, nlen, sv, 0);
if (env_is_not_environ)
mg_set(sv);
}
+ if (HvKEYS(dups)) {
+ /* environ has some duplicate definitions, remove them */
+ HE *entry;
+ hv_iterinit(dups);
+ while ((entry = hv_iternext_flags(dups, 0))) {
+ STRLEN nlen;
+ const char *name = HePV(entry, nlen);
+ IV count = SvIV(HeVAL(entry));
+ IV i;
+ SV **valp = hv_fetch(hv, name, nlen, 0);
+
+ assert(valp);
+
+ /* try to remove any duplicate names, depending on the
+ * implementation used in my_setenv() the iteration might
+ * not be necessary, but let's be safe.
+ */
+ for (i = 0; i < count; ++i)
+ my_setenv(name, 0);
+
+ /* and set it back to the value we set $ENV{name} to */
+ my_setenv(name, SvPV_nolen(*valp));
+ }
+ }
+ SvREFCNT_dec_NN(dups);
}
#endif /* USE_ENVIRON_ARRAY */
#endif /* !PERL_MICRO */
--
2.5.0

View File

@ -29,7 +29,7 @@
Name: perl
Version: %{perl_version}
# release number must be even higher, because dual-lived modules will be broken otherwise
Release: 356%{?dist}
Release: 357%{?dist}
Epoch: %{perl_epoch}
Summary: Practical Extraction and Report Language
Group: Development/Languages
@ -91,6 +91,10 @@ Patch27: perl-5.22.0-make-PadlistNAMES-lvalue-again.patch
# Workaround for Coro, bug #1231165, CPAN RT#101063. To remove in the future.
Patch28: perl-5.22.0-Revert-const-the-core-magic-vtables.patch
# Fix CVE-2016-2381 (ambiguous environment variables handling), bug #1313702,
# in upstream after 5.23.8
Patch29: perl-5.23.8-remove-duplicate-environment-variables-from-environ.patch
# Link XS modules to libperl.so with EU::CBuilder on Linux, bug #960048
Patch200: perl-5.16.3-Link-XS-modules-to-libperl.so-with-EU-CBuilder-on-Li.patch
@ -2358,6 +2362,7 @@ Perl extension for Version Objects
%patch26 -p1
%patch27 -p1
%patch28 -p1
%patch29 -p1
%patch200 -p1
%patch201 -p1
@ -2378,6 +2383,7 @@ perl -x patchlevel.h \
'Fedora Patch26: Make *DBM_File desctructors thread-safe (RT#61912)' \
'Fedora Patch27: Make PadlistNAMES() lvalue again (CPAN RT#101063)' \
'Fedora Patch28: Make magic vtable writable as a work-around for Coro (CPAN RT#101063)' \
'Fedora Patch29: Fix CVE-2016-2381 (ambiguous environment variables handling)' \
'Fedora Patch200: Link XS modules to libperl.so with EU::CBuilder on Linux' \
'Fedora Patch201: Link XS modules to libperl.so with EU::MM on Linux' \
%{nil}
@ -4628,6 +4634,9 @@ popd
# Old changelog entries are preserved in CVS.
%changelog
* Wed Mar 02 2016 Petr Pisar <ppisar@redhat.com> - 4:5.22.1-357
- Fix CVE-2016-2381 (ambiguous environment variables handling) (bug #1313702)
* Thu Feb 04 2016 Fedora Release Engineering <releng@fedoraproject.org> - 4:5.22.1-356
- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild