* gnu/packages/patches/perl-CVE-2016-2381.patch: New file. * gnu-system.am (dist_patch_DATA): Add it. * gnu/packages/perl.scm (perl)[replacement]: New field. (perl-fixed): New variable. * gnu/packages/commencement.scm (perl-boot0)[replacement]: New field.
		
			
				
	
	
		
			116 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			116 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| Fix CVE-2016-2381 (ambiguous handling of duplicated environment variables).
 | |
| 
 | |
| Copied from upstream:
 | |
| http://perl5.git.perl.org/perl.git/commit/ae37b791a73a9e78dedb89fb2429d2628cf58076
 | |
| 
 | |
| References:
 | |
| https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-2381
 | |
| http://www.nntp.perl.org/group/perl.perl5.porters/2016/03/msg234747.html
 | |
| https://security-tracker.debian.org/tracker/CVE-2016-2381
 | |
| 
 | |
| ---
 | |
| 
 | |
| From 1237ea93fb2475a5ae576d5ee1358a5bb4ebe426 Mon Sep 17 00:00:00 2001
 | |
| From: Tony Cook <tony@develop-help.com>
 | |
| Date: Wed, 27 Jan 2016 11:52:15 +1100
 | |
| Subject: 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.
 | |
| 
 | |
| Patch-Name: fixes/CVE-2016-2381_duplicate_env.diff
 | |
| ---
 | |
|  perl.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++--
 | |
|  1 file changed, 49 insertions(+), 2 deletions(-)
 | |
| 
 | |
| diff --git a/perl.c b/perl.c
 | |
| index 67d32ce..26aeb91 100644
 | |
| --- a/perl.c
 | |
| +++ b/perl.c
 | |
| @@ -4277,23 +4277,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 */
 |