Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 18 Apr 2016 11:20:10 +0000 (UTC)
From:      Mathieu Arnold <mat@FreeBSD.org>
To:        ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org
Subject:   svn commit: r413567 - in head/lang: perl5.18 perl5.18/files perl5.20 perl5.20/files perl5.22 perl5.22/files
Message-ID:  <201604181120.u3IBKACj028429@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mat
Date: Mon Apr 18 11:20:10 2016
New Revision: 413567
URL: https://svnweb.freebsd.org/changeset/ports/413567

Log:
  Fix a Perl security issue.
  
  PR:		208879
  Reported by:	Sevan Janiyan
  Security:	CVE-2016-2381
  Sponsored by:	Absolight

Added:
  head/lang/perl5.18/files/patch-7098eff   (contents, props changed)
  head/lang/perl5.20/files/patch-7098eff   (contents, props changed)
  head/lang/perl5.22/files/patch-58eaa11   (contents, props changed)
Modified:
  head/lang/perl5.18/Makefile   (contents, props changed)
  head/lang/perl5.20/Makefile   (contents, props changed)
  head/lang/perl5.22/Makefile   (contents, props changed)

Modified: head/lang/perl5.18/Makefile
==============================================================================
--- head/lang/perl5.18/Makefile	Mon Apr 18 10:11:26 2016	(r413566)
+++ head/lang/perl5.18/Makefile	Mon Apr 18 11:20:10 2016	(r413567)
@@ -3,7 +3,7 @@
 
 PORTNAME=	perl
 PORTVERSION=	${PERL_VERSION}
-PORTREVISION=	20
+PORTREVISION=	21
 CATEGORIES=	lang devel perl5
 MASTER_SITES=	CPAN/../../src/5.0
 DIST_SUBDIR=	perl

Added: head/lang/perl5.18/files/patch-7098eff
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lang/perl5.18/files/patch-7098eff	Mon Apr 18 11:20:10 2016	(r413567)
@@ -0,0 +1,98 @@
+commit 7098efff946437a2db6013d12c4fc3193fc328ce
+Author: Tony Cook <tony@develop-help.com>
+Date:   2016-01-27 11:52:15 +1100
+
+    remove duplicate environment variables from environ
+    
+    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.
+
+--- perl.c.orig	2014-10-01 01:33:00 UTC
++++ perl.c
+@@ -4272,23 +4272,70 @@ S_init_postdump_symbols(pTHX_ int argc, 
+ 	}
+ 	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 */

Modified: head/lang/perl5.20/Makefile
==============================================================================
--- head/lang/perl5.20/Makefile	Mon Apr 18 10:11:26 2016	(r413566)
+++ head/lang/perl5.20/Makefile	Mon Apr 18 11:20:10 2016	(r413567)
@@ -3,7 +3,7 @@
 
 PORTNAME=	perl
 PORTVERSION=	${PERL_VERSION}
-PORTREVISION=	11
+PORTREVISION=	12
 CATEGORIES=	lang devel perl5
 MASTER_SITES=	CPAN/../../src/5.0
 DIST_SUBDIR=	perl

Added: head/lang/perl5.20/files/patch-7098eff
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lang/perl5.20/files/patch-7098eff	Mon Apr 18 11:20:10 2016	(r413567)
@@ -0,0 +1,100 @@
+commit 7098efff946437a2db6013d12c4fc3193fc328ce
+Author: Tony Cook <tony@develop-help.com>
+Date:   2016-01-27 11:52:15 +1100
+
+    remove duplicate environment variables from environ
+    
+    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.
+
+diff --git perl.c perl.c
+index d3e378f..25e2075 100644
+--- perl.c
++++ perl.c
+@@ -4281,23 +4281,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 */

Modified: head/lang/perl5.22/Makefile
==============================================================================
--- head/lang/perl5.22/Makefile	Mon Apr 18 10:11:26 2016	(r413566)
+++ head/lang/perl5.22/Makefile	Mon Apr 18 11:20:10 2016	(r413567)
@@ -3,7 +3,7 @@
 
 PORTNAME=	perl
 DISTVERSION=	${PERL_VERSION}
-PORTREVISION=	7
+PORTREVISION=	8
 CATEGORIES=	lang devel perl5
 MASTER_SITES=	CPAN/../../src/5.0 CPAN/../by-authors/id/S/SH/SHAY
 DIST_SUBDIR=	perl

Added: head/lang/perl5.22/files/patch-58eaa11
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lang/perl5.22/files/patch-58eaa11	Mon Apr 18 11:20:10 2016	(r413567)
@@ -0,0 +1,100 @@
+commit 58eaa1131a38c16ee4a66d0bc36288cfde1a39bf
+Author: Tony Cook <tony@develop-help.com>
+Date:   2016-01-27 11:52:15 +1100
+
+    remove duplicate environment variables from environ
+    
+    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.
+
+diff --git perl.c perl.c
+index 16a6ca4..8ef7474 100644
+--- perl.c
++++ perl.c
+@@ -4298,23 +4298,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 */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201604181120.u3IBKACj028429>