This is the mail archive of the glibc-cvs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

GNU C Library master sources branch allan/2.19/backport created. glibc-2.19-31-gd75d95a


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, allan/2.19/backport has been created
        at  d75d95a7f2823ec2cf90b5fa7dafef283f49401e (commit)

- Log -----------------------------------------------------------------
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=d75d95a7f2823ec2cf90b5fa7dafef283f49401e

commit d75d95a7f2823ec2cf90b5fa7dafef283f49401e
Author: Florian Weimer <fweimer@redhat.com>
Date:   Tue Aug 26 19:38:59 2014 +0200

    __gconv_translit_find: Disable function [BZ #17187]
    
    This functionality has never worked correctly, and the implementation
    contained a security vulnerability (CVE-2014-5119).
    
    (cherry picked from commit a1a6a401ab0a3c9f15fb7eaebbdcee24192254e8)
    (cherry picked from commit f9df71e895d3552d557e783fdb9d133328195645)
    
    Conflicts:
    	NEWS

diff --git a/ChangeLog b/ChangeLog
index fec48a1..105d70c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2014-08-26  Florian Weimer  <fweimer@redhat.com>
+
+	[BZ #17187]
+	* iconv/gconv_trans.c (struct known_trans, search_tree, lock,
+	trans_compare, open_translit, __gconv_translit_find):
+	Remove module loading code.
+
 2014-08-01  Stefan Liebler  <stli@linux.vnet.ibm.com>
 
 	* NEWS: Explain the s390 jmp_buf / ucontext_t ABI change
diff --git a/NEWS b/NEWS
index 352b8a5..ebcefb5 100644
--- a/NEWS
+++ b/NEWS
@@ -10,7 +10,7 @@ Version 2.19.1
 * The following bugs are resolved with this release:
 
   15946, 16545, 16574, 16623, 16695, 16878, 16882, 16885, 16916, 16932,
-  16943, 16958, 17048, 17069, 17137.
+  16943, 16958, 17048, 17069, 17137, 17263.
 
 * Reverted change of ABI data structures for s390 and s390x:
   On s390 and s390x the size of struct ucontext and jmp_buf was increased in
@@ -37,6 +37,13 @@ Version 2.19.1
   silently replaced with the "C" locale when running in AT_SECURE mode
   (e.g., in a SUID program).  This is no longer necessary because of the
   additional checks.
+
+* Support for loadable gconv transliteration modules has been removed.
+  The support for transliteration modules has been non-functional for
+  over a decade, and the removal is prompted by security defects.  The
+  normal gconv conversion modules are still supported.  Transliteration
+  with //TRANSLIT is still possible, and the //IGNORE specifier
+  continues to be  supported. (CVE-2014-5119)
 
 Version 2.19
 
diff --git a/iconv/gconv_trans.c b/iconv/gconv_trans.c
index 1e25854..e0835fc 100644
--- a/iconv/gconv_trans.c
+++ b/iconv/gconv_trans.c
@@ -238,181 +238,12 @@ __gconv_transliterate (struct __gconv_step *step,
   return __GCONV_ILLEGAL_INPUT;
 }
 
-
-/* Structure to represent results of found (or not) transliteration
-   modules.  */
-struct known_trans
-{
-  /* This structure must remain the first member.  */
-  struct trans_struct info;
-
-  char *fname;
-  void *handle;
-  int open_count;
-};
-
-
-/* Tree with results of previous calls to __gconv_translit_find.  */
-static void *search_tree;
-
-/* We modify global data.   */
-__libc_lock_define_initialized (static, lock);
-
-
-/* Compare two transliteration entries.  */
-static int
-trans_compare (const void *p1, const void *p2)
-{
-  const struct known_trans *s1 = (const struct known_trans *) p1;
-  const struct known_trans *s2 = (const struct known_trans *) p2;
-
-  return strcmp (s1->info.name, s2->info.name);
-}
-
-
-/* Open (maybe reopen) the module named in the struct.  Get the function
-   and data structure pointers we need.  */
-static int
-open_translit (struct known_trans *trans)
-{
-  __gconv_trans_query_fct queryfct;
-
-  trans->handle = __libc_dlopen (trans->fname);
-  if (trans->handle == NULL)
-    /* Not available.  */
-    return 1;
-
-  /* Find the required symbol.  */
-  queryfct = __libc_dlsym (trans->handle, "gconv_trans_context");
-  if (queryfct == NULL)
-    {
-      /* We cannot live with that.  */
-    close_and_out:
-      __libc_dlclose (trans->handle);
-      trans->handle = NULL;
-      return 1;
-    }
-
-  /* Get the context.  */
-  if (queryfct (trans->info.name, &trans->info.csnames, &trans->info.ncsnames)
-      != 0)
-    goto close_and_out;
-
-  /* Of course we also have to have the actual function.  */
-  trans->info.trans_fct = __libc_dlsym (trans->handle, "gconv_trans");
-  if (trans->info.trans_fct == NULL)
-    goto close_and_out;
-
-  /* Now the optional functions.  */
-  trans->info.trans_init_fct =
-    __libc_dlsym (trans->handle, "gconv_trans_init");
-  trans->info.trans_context_fct =
-    __libc_dlsym (trans->handle, "gconv_trans_context");
-  trans->info.trans_end_fct =
-    __libc_dlsym (trans->handle, "gconv_trans_end");
-
-  trans->open_count = 1;
-
-  return 0;
-}
-
-
 int
 internal_function
 __gconv_translit_find (struct trans_struct *trans)
 {
-  struct known_trans **found;
-  const struct path_elem *runp;
-  int res = 1;
-
-  /* We have to have a name.  */
-  assert (trans->name != NULL);
-
-  /* Acquire the lock.  */
-  __libc_lock_lock (lock);
-
-  /* See whether we know this module already.  */
-  found = __tfind (trans, &search_tree, trans_compare);
-  if (found != NULL)
-    {
-      /* Is this module available?  */
-      if ((*found)->handle != NULL)
-	{
-	  /* Maybe we have to reopen the file.  */
-	  if ((*found)->handle != (void *) -1)
-	    /* The object is not unloaded.  */
-	    res = 0;
-	  else if (open_translit (*found) == 0)
-	    {
-	      /* Copy the data.  */
-	      *trans = (*found)->info;
-	      (*found)->open_count++;
-	      res = 0;
-	    }
-	}
-    }
-  else
-    {
-      size_t name_len = strlen (trans->name) + 1;
-      int need_so = 0;
-      struct known_trans *newp;
-
-      /* We have to continue looking for the module.  */
-      if (__gconv_path_elem == NULL)
-	__gconv_get_path ();
-
-      /* See whether we have to append .so.  */
-      if (name_len <= 4 || memcmp (&trans->name[name_len - 4], ".so", 3) != 0)
-	need_so = 1;
-
-      /* Create a new entry.  */
-      newp = (struct known_trans *) malloc (sizeof (struct known_trans)
-					    + (__gconv_max_path_elem_len
-					       + name_len + 3)
-					    + name_len);
-      if (newp != NULL)
-	{
-	  char *cp;
-
-	  /* Clear the struct.  */
-	  memset (newp, '\0', sizeof (struct known_trans));
-
-	  /* Store a copy of the module name.  */
-	  newp->info.name = cp = (char *) (newp + 1);
-	  cp = __mempcpy (cp, trans->name, name_len);
-
-	  newp->fname = cp;
-
-	  /* Search in all the directories.  */
-	  for (runp = __gconv_path_elem; runp->name != NULL; ++runp)
-	    {
-	      cp = __mempcpy (__stpcpy ((char *) newp->fname, runp->name),
-			      trans->name, name_len);
-	      if (need_so)
-		memcpy (cp, ".so", sizeof (".so"));
-
-	      if (open_translit (newp) == 0)
-		{
-		  /* We found a module.  */
-		  res = 0;
-		  break;
-		}
-	    }
-
-	  if (res)
-	    newp->fname = NULL;
-
-	  /* In any case we'll add the entry to our search tree.  */
-	  if (__tsearch (newp, &search_tree, trans_compare) == NULL)
-	    {
-	      /* Yickes, this should not happen.  Unload the object.  */
-	      res = 1;
-	      /* XXX unload here.  */
-	    }
-	}
-    }
-
-  __libc_lock_unlock (lock);
-
-  return res;
+  /* Transliteration module loading has been removed because it never
+     worked as intended and suffered from a security vulnerability.
+     Consequently, this function always fails.  */
+  return 1;
 }

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=a27eb3cfcc0cdcbf197c66bbf78ff1ec84412f22

commit a27eb3cfcc0cdcbf197c66bbf78ff1ec84412f22
Author: Stefan Liebler <stli@linux.vnet.ibm.com>
Date:   Fri Aug 1 09:48:17 2014 +0200

    NEWS: Explain the s390 jmp_buf / ucontext_t ABI change reversal.
    
    (cherry picked from commit 95ee7fb13ba99ba265b49531c57e1cb8db629bc6)
    
    Typo fix as in commit 45ef66289acbab17278a73512f9b2a9d8a7ca79d and
    NEW enty adjusted to reflect revert occuring in 2.19.1 and 2.20.
    
    Conflicts:
    	NEWS

diff --git a/ChangeLog b/ChangeLog
index 592732b..fec48a1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2014-08-01  Stefan Liebler  <stli@linux.vnet.ibm.com>
+
+	* NEWS: Explain the s390 jmp_buf / ucontext_t ABI change
+	reversal.
+
 2014-07-31  Stefan Liebler  <stli@linux.vnet.ibm.com>
 
 	* sysdeps/s390/Makefile: Delete file.
diff --git a/NEWS b/NEWS
index 71b6ad5..352b8a5 100644
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,17 @@ Version 2.19.1
   15946, 16545, 16574, 16623, 16695, 16878, 16882, 16885, 16916, 16932,
   16943, 16958, 17048, 17069, 17137.
 
+* Reverted change of ABI data structures for s390 and s390x:
+  On s390 and s390x the size of struct ucontext and jmp_buf was increased in
+  2.19. This change is reverted in 2.19.1 and 2.20. The introduced 2.19 symbol
+  versions of getcontext, setjmp, _setjmp, __sigsetjmp, longjmp, _longjmp,
+  siglongjmp are preserved pointing straight to the same implementation as the
+  old ones. Given that, new callers will simply provide a too-big buffer to
+  these functions. Any applications/libraries out there that embed jmp_buf or
+  ucontext_t in an ABI-relevant data structure that have already been rebuilt
+  against 2.19 headers will have to rebuilt again. This is necessary in any
+  case to revert the breakage in their ABI caused by the glibc change.
+
 * CVE-2014-4043 The posix_spawn_file_actions_addopen implementation did not
   copy the path argument.  This allowed programs to cause posix_spawn to
   deference a dangling pointer, or use an unexpected pathname argument if

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=19392a8ff30c913a35574f2b0875f61dfb78af46

commit 19392a8ff30c913a35574f2b0875f61dfb78af46
Author: Stefan Liebler <stli@linux.vnet.ibm.com>
Date:   Thu Aug 28 16:53:13 2014 +1000

    S/390: Revert the jmp_buf/ucontext_t ABI change
    
    Backport of commit 2f438e20ab591641760e97458d5d1569942eced5

diff --git a/ChangeLog b/ChangeLog
index 1e97f25..592732b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,74 @@
+2014-07-31  Stefan Liebler  <stli@linux.vnet.ibm.com>
+
+	* sysdeps/s390/Makefile: Delete file.
+	* sysdeps/s390/Versions (GLIBC_2.19): Remove __setjmp.
+	* sysdeps/s390/__longjmp.c: Delete file.
+	* sysdeps/s390/bits/setjmp.h (__s390_jmp_buf):
+	Remove fields __flags and __reserved.
+	* sysdeps/s390/longjmp.c: Include setjmp/longjmp.c
+	and add versioning.
+	* sysdeps/s390/rtld-__longjmp.c: Delete file.
+	* sysdeps/s390/rtld-global-offsets.sym: Likewise.
+	* sysdeps/s390/rtld-setjmp.S: Likewise.
+	* sysdeps/s390/s390-32/__longjmp-common.c: Move to ...
+	* sysdeps/s390/s390-32/__longjmp.c: ... here.
+	* sysdeps/s390/s390-32/setjmp-common.S: Move to ...
+	* sysdeps/s390/s390-32/setjmp.S: ... here.
+	Add versioning.
+	(__sigsetjmp): Remove setting __flags field.
+	* sysdeps/s390/s390-64/__longjmp-common.c:Move to ...
+	* sysdeps/s390/s390-64/__longjmp.c: ... here.
+	* sysdeps/s390/s390-64/setjmp-common.S: Move to ...
+	* sysdeps/s390/s390-64/setjmp.S: ... here.
+	Add versioning.
+	(__sigsetjmp): Remove setting __flags field.
+	* sysdeps/s390/setjmp.S: Delete file.
+	* sysdeps/s390/sigjmp.c: Likewise.
+	* sysdeps/s390/v1-longjmp.c: Likewise.
+	* sysdeps/s390/v1-setjmp.h: Likewise.
+	* sysdeps/s390/v1-sigjmp.c: Likewise.
+	* sysdeps/unix/sysv/linux/s390/Makefile (sysdep_routines):
+	Remove v1-longjmp_chk.
+	* sysdeps/unix/sysv/linux/s390/getcontext.S: Delete file.
+	* sysdeps/unix/sysv/linux/s390/longjmp_chk.c:
+	Include debug/longjmp_chk.c and add versioning.
+	* nptl/sysdeps/unix/sysv/linux/s390/pt-longjmp.c:
+	Include nptl/sysdeps/pthread/pt-longjmp.c and add versioning.
+	* sysdeps/unix/sysv/linux/s390/rtld-getcontext.S: Delete file.
+	* sysdeps/unix/sysv/linux/s390/s390-32/____longjmp_chk.c:
+	Include __longjmp.c.
+	* sysdeps/unix/sysv/linux/s390/s390-32/getcontext-common.S:
+	Move to ...
+	* sysdeps/unix/sysv/linux/s390/s390-32/getcontext.S: ... here.
+	(__getcontext): Remove setting __flags field.
+	Add versioning.
+	* sysdeps/unix/sysv/linux/s390/s390-32/setcontext.S:
+	DonÃ?t restore upper high grps.
+	* sysdeps/unix/sysv/linux/s390/s390-32/swapcontext.S:
+	Likewise.
+	(__swapcontext): Remove setting uc_flags field.
+	* sysdeps/unix/sysv/linux/s390/s390-32/ucontext_i.sym:
+	Delete file.
+	* sysdeps/unix/sysv/linux/s390/s390-64/____longjmp_chk.c:
+	Include __longjmp.c.
+	* sysdeps/unix/sysv/linux/s390/s390-64/getcontext-common.S:
+	Move to ...
+	* sysdeps/unix/sysv/linux/s390/s390-64/getcontext.S: ... here.
+	(__getcontext): Remove setting __flags field.
+	Add versioning.
+	* sysdeps/unix/sysv/linux/s390/s390-64/swapcontext.S:
+	(__swapcontext): Remove setting uc_flags field.
+	* unix/sysv/linux/s390/s390-64/ucontext_i.sym: Delete file.
+	* sysdeps/unix/sysv/linux/s390/sys/ucontext.h (ucontext):
+	Remove fields uc_high_gprs and __reserved.
+	* sysdeps/unix/sysv/linux/s390/ucontext_i.sym:
+	New file with reverted content.
+	* sysdeps/unix/sysv/linux/s390/v1-longjmp_chk.c: Delete file.
+	* sysdeps/unix/sysv/linux/s390/s390-32/nptl/libc.abilist:
+	Regenerated.
+	* sysdeps/unix/sysv/linux/s390/s390-64/nptl/libc.abilist:
+	Regenerated.
+
 2014-07-02  Florian Weimer  <fweimer@redhat.com>
 
 	* manual/locale.texi (Locale Names): New section documenting
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/pt-longjmp.c b/nptl/sysdeps/unix/sysv/linux/s390/pt-longjmp.c
index 801432c..2a71c1a 100644
--- a/nptl/sysdeps/unix/sysv/linux/s390/pt-longjmp.c
+++ b/nptl/sysdeps/unix/sysv/linux/s390/pt-longjmp.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2013 Free Software Foundation, Inc.
+/* Copyright (C) 2014 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -15,49 +15,30 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.
 
-   This is a copy of pthread/pt-longjmp.c made for extending the
-   jmpbuf structure on System z.  */
+   Versioned copy of nptl/pt-longjmp.c modified for versioning
+   the reverted jmpbuf extension.  */
 
-#include <setjmp.h>
-#include <stdlib.h>
-#include <bits/wordsize.h>
-#include "pthreadP.h"
 #include  <shlib-compat.h>
-#if defined SHARED && SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_19)
-
-/* The __v1 version prototypes are declared in v1-setjmp.h which
-   cannot be included together with setjmp.h.  So we put the
-   prototypes here manually.  */
-extern void __v1__libc_siglongjmp (sigjmp_buf env, int val)
-     __attribute__ ((noreturn));
-extern void __v1__libc_longjmp (sigjmp_buf env, int val)
-     __attribute__ ((noreturn));
-
-void __v1_siglongjmp (sigjmp_buf env, int val)
-{
-  __v1__libc_siglongjmp (env, val);
-}
-
-void __v1_longjmp (jmp_buf env, int val)
-{
-  __v1__libc_longjmp (env, val);
-}
-
-compat_symbol (libpthread, __v1_longjmp, longjmp, GLIBC_2_0);
-compat_symbol (libpthread, __v1_siglongjmp, siglongjmp, GLIBC_2_0);
-#endif /* defined SHARED && SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_19))  */
-
-void
-__v2_longjmp (jmp_buf env, int val)
-{
-  __libc_longjmp (env, val);
-}
-
-void
-__v2_siglongjmp (jmp_buf env, int val)
-{
-  __libc_siglongjmp (env, val);
-}
-
-versioned_symbol (libpthread, __v2_longjmp, longjmp, GLIBC_2_19);
-versioned_symbol (libpthread, __v2_siglongjmp, siglongjmp, GLIBC_2_19);
+
+#if defined SHARED && SHLIB_COMPAT (libpthread, GLIBC_2_19, GLIBC_2_20)
+	/* we need a unique name in case of symbol versioning.  */
+# define longjmp __v1longjmp
+#endif /* defined SHARED && SHLIB_COMPAT (libpthread, GLIBC_2_19, GLIBC_2_20))  */
+
+#include <nptl/sysdeps/pthread/pt-longjmp.c>
+
+#if defined SHARED && SHLIB_COMPAT (libpthread, GLIBC_2_19, GLIBC_2_20)
+/* In glibc release 2.19 new versions of longjmp-functions were introduced,
+   but were reverted before 2.20. Thus both versions are the same function.  */
+
+# undef longjmp
+
+strong_alias (__v1longjmp, __v2longjmp)
+versioned_symbol (libpthread, __v1longjmp, longjmp, GLIBC_2_0);
+compat_symbol (libpthread, __v2longjmp, longjmp, GLIBC_2_19);
+
+weak_alias (siglongjmp, __v1siglongjmp)
+weak_alias (siglongjmp, __v2siglongjmp)
+versioned_symbol (libpthread, __v1siglongjmp, siglongjmp, GLIBC_2_0);
+compat_symbol (libpthread, __v2siglongjmp, siglongjmp, GLIBC_2_19);
+#endif /* defined SHARED && SHLIB_COMPAT (libpthread, GLIBC_2_19, GLIBC_2_20))  */
diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile
deleted file mode 100644
index 42978dc..0000000
--- a/sysdeps/s390/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-ifeq ($(subdir),setjmp)
-ifeq (yes,$(build-shared))
-sysdep_routines += v1-longjmp v1-sigjmp
-endif
-endif
-
-ifeq ($(subdir),csu)
-gen-as-const-headers += rtld-global-offsets.sym
-endif
diff --git a/sysdeps/s390/Versions b/sysdeps/s390/Versions
index 156abc7..8417623 100644
--- a/sysdeps/s390/Versions
+++ b/sysdeps/s390/Versions
@@ -1,12 +1,8 @@
 libc {
   GLIBC_2.19 {
-    setjmp; _setjmp; __setjmp; __sigsetjmp;
+    setjmp; _setjmp; __sigsetjmp;
     longjmp; _longjmp; siglongjmp;
   }
-  GLIBC_PRIVATE {
-    __v1__libc_longjmp; __v1__libc_siglongjmp;
-    __v2__libc_longjmp; __v2__libc_siglongjmp;
-  }
 }
 
 ld {
diff --git a/sysdeps/s390/__longjmp.c b/sysdeps/s390/__longjmp.c
deleted file mode 100644
index e4acd31..0000000
--- a/sysdeps/s390/__longjmp.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Copyright (C) 2013 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <libc-symbols.h>
-#include <shlib-compat.h>
-
-#define __longjmp  __v2__longjmp
-#include "__longjmp-common.c"
-#undef __longjmp
-strong_alias (__v2__longjmp, __longjmp)
-
-#if defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_19)
-# undef __longjmp
-# define __V1_JMPBUF
-# define __longjmp  __v1__longjmp
-# include "__longjmp-common.c"
-#endif /* if defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_19) */
diff --git a/sysdeps/s390/bits/setjmp.h b/sysdeps/s390/bits/setjmp.h
index 25eaf10..0071a9d 100644
--- a/sysdeps/s390/bits/setjmp.h
+++ b/sysdeps/s390/bits/setjmp.h
@@ -40,10 +40,6 @@ typedef struct __s390_jmp_buf
   /* We save fpu registers 4 and 6.  */
   long __fpregs[4];
 # endif
-#ifndef __V1_JMPBUF
-  unsigned long __flags;
-  char __reserved[128];
-#endif
 } __jmp_buf[1];
 
 #endif
diff --git a/sysdeps/s390/longjmp.c b/sysdeps/s390/longjmp.c
index c758d14..601f077 100644
--- a/sysdeps/s390/longjmp.c
+++ b/sysdeps/s390/longjmp.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2013 Free Software Foundation, Inc.
+/* Copyright (C) 2014 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -15,50 +15,28 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.
 
-   Versioned copy of sysdeps/generic/longjmp.c modified for extended
-   jmpbuf.  */
+   Versioned copy of setjmp/longjmp.c modified for versioning
+   the reverted jmpbuf extension.  */
 
 #include <shlib-compat.h>
-#include <stddef.h>
-#include <setjmp.h>
-#include <signal.h>
 
-extern void __v2__longjmp (__jmp_buf __env, int __val)
-     __attribute__ ((__noreturn__));
-extern void __v2__libc_longjmp (sigjmp_buf env, int val)
-     __attribute__ ((__noreturn__));
-libc_hidden_proto (__v2__libc_longjmp)
-
-/* Set the signal mask to the one specified in ENV, and jump
-   to the position specified in ENV, causing the setjmp
-   call there to return VAL, or 1 if VAL is 0.  */
-void
-__v2__libc_siglongjmp (sigjmp_buf env, int val)
-{
-  /* Perform any cleanups needed by the frames being unwound.  */
-  _longjmp_unwind (env, val);
-
-  if (env[0].__mask_was_saved)
-    /* Restore the saved signal mask.  */
-    (void) __sigprocmask (SIG_SETMASK, &env[0].__saved_mask,
-			  (sigset_t *) NULL);
-
-  /* Call the machine-dependent function to restore machine state.  */
-  __v2__longjmp (env[0].__jmpbuf, val ?: 1);
-}
-
-#ifndef __v2__longjmp
-strong_alias (__v2__libc_siglongjmp, __v2__libc_longjmp)
-libc_hidden_def (__v2__libc_longjmp)
-weak_alias (__v2__libc_siglongjmp, __v2_longjmp)
-weak_alias (__v2__libc_siglongjmp, __v2longjmp)
-weak_alias (__v2__libc_siglongjmp, __v2siglongjmp)
-
-/* These will be used by libpthread only.  */
-versioned_symbol (libc, __v2__libc_longjmp, __libc_longjmp, GLIBC_PRIVATE);
-versioned_symbol (libc, __v2__libc_siglongjmp, __libc_siglongjmp, GLIBC_PRIVATE);
-
-versioned_symbol (libc, __v2_longjmp, _longjmp, GLIBC_2_19);
-versioned_symbol (libc, __v2longjmp, longjmp, GLIBC_2_19);
-versioned_symbol (libc, __v2siglongjmp, siglongjmp, GLIBC_2_19);
-#endif /* ifndef __v2__longjmp */
+#include <setjmp/longjmp.c>
+
+#if defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_19, GLIBC_2_20)
+/* In glibc release 2.19 new versions of longjmp-functions were introduced,
+   but were reverted before 2.20. Thus both versions are the same function.  */
+weak_alias (__libc_siglongjmp, __v1_longjmp)
+weak_alias (__libc_siglongjmp, __v2_longjmp)
+versioned_symbol (libc, __v1_longjmp, _longjmp, GLIBC_2_0);
+compat_symbol (libc, __v2_longjmp, _longjmp, GLIBC_2_19);
+
+weak_alias (__libc_siglongjmp, __v1longjmp)
+weak_alias (__libc_siglongjmp, __v2longjmp)
+versioned_symbol (libc, __v1longjmp, longjmp, GLIBC_2_0);
+compat_symbol (libc, __v2longjmp, longjmp, GLIBC_2_19);
+
+weak_alias (__libc_siglongjmp, __v1siglongjmp)
+weak_alias (__libc_siglongjmp, __v2siglongjmp)
+versioned_symbol (libc, __v1siglongjmp, siglongjmp, GLIBC_2_0);
+compat_symbol (libc, __v2siglongjmp, siglongjmp, GLIBC_2_19);
+#endif /* SHARED && SHLIB_COMPAT (libc, GLIBC_2_19, GLIBC_2_20)  */
diff --git a/sysdeps/s390/rtld-__longjmp.c b/sysdeps/s390/rtld-__longjmp.c
deleted file mode 100644
index 5e9f739..0000000
--- a/sysdeps/s390/rtld-__longjmp.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Copyright (C) 2013 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-/* Build a non-versioned object for rtld-*.  */
-# include "__longjmp-common.c"
diff --git a/sysdeps/s390/rtld-global-offsets.sym b/sysdeps/s390/rtld-global-offsets.sym
deleted file mode 100644
index ff4e97f..0000000
--- a/sysdeps/s390/rtld-global-offsets.sym
+++ /dev/null
@@ -1,7 +0,0 @@
-#define SHARED 1
-
-#include <ldsodefs.h>
-
-#define rtld_global_ro_offsetof(mem) offsetof (struct rtld_global_ro, mem)
-
-RTLD_GLOBAL_RO_DL_HWCAP_OFFSET	rtld_global_ro_offsetof (_dl_hwcap)
diff --git a/sysdeps/s390/rtld-setjmp.S b/sysdeps/s390/rtld-setjmp.S
deleted file mode 100644
index 4011011..0000000
--- a/sysdeps/s390/rtld-setjmp.S
+++ /dev/null
@@ -1,20 +0,0 @@
-/* Extendible version of setjmp for System z
-   Copyright (C) 2013 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-/* Build a non-versioned object for rtld-*.  */
-# include "setjmp-common.S"
diff --git a/sysdeps/s390/s390-32/__longjmp-common.c b/sysdeps/s390/s390-32/__longjmp.c
similarity index 98%
rename from sysdeps/s390/s390-32/__longjmp-common.c
rename to sysdeps/s390/s390-32/__longjmp.c
index f78ef65..5d46e21 100644
--- a/sysdeps/s390/s390-32/__longjmp-common.c
+++ b/sysdeps/s390/s390-32/__longjmp.c
@@ -25,7 +25,7 @@
 
 /* Jump to the position specified by ENV, causing the
    setjmp call there to return VAL, or 1 if VAL is 0.  */
-attribute_hidden void
+void
 __longjmp (__jmp_buf env, int val)
 {
 #ifdef PTR_DEMANGLE
diff --git a/sysdeps/s390/s390-32/setjmp-common.S b/sysdeps/s390/s390-32/setjmp.S
similarity index 54%
rename from sysdeps/s390/s390-32/setjmp-common.S
rename to sysdeps/s390/s390-32/setjmp.S
index d7bb720..e940d71 100644
--- a/sysdeps/s390/s390-32/setjmp-common.S
+++ b/sysdeps/s390/s390-32/setjmp.S
@@ -21,30 +21,38 @@
 #define _ASM
 #define _SETJMP_H
 #include <bits/setjmp.h>
+#include <shlib-compat.h>
+
+#if !defined IS_IN_rtld
+# if defined SHARED &&  SHLIB_COMPAT (libc, GLIBC_2_19, GLIBC_2_20)
+	/* we need a unique name in case of symbol versioning.  */
+#  define __sigsetjmp __v1__sigsetjmp
+# endif /* if defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_19, GLIBC_2_20)  */
+#endif /* !defined IS_IN_rtld  */
 
 	/* We include the BSD entry points here as well but we make
 	   them weak.  */
 ENTRY (setjmp)
 	.weak C_SYMBOL_NAME (setjmp)
 	lhi    %r3,1                /* second argument of one */
-	j      0f                   /* branch relativ to __sigsetjmp */
+	j      .Linternal_sigsetjmp /* branch relativ to __sigsetjmp */
 END (setjmp)
 
 	/* Binary compatibility entry point.  */
 ENTRY(_setjmp)
 	.weak  C_SYMBOL_NAME (_setjmp)
 	lhi    %r3,0                /* second argument of zero */
-	j      0f                   /* branch relativ to __sigsetjmp */
+	j      .Linternal_sigsetjmp /* branch relativ to __sigsetjmp */
 END (_setjmp)
 libc_hidden_def (_setjmp)
 
 ENTRY(__setjmp)
 	lhi    %r3,0                /* second argument of zero */
-	j      0f                   /* branch relativ to __sigsetjmp */
+	j      .Linternal_sigsetjmp /* branch relativ to __sigsetjmp */
 END (__setjmp)
 
 ENTRY(__sigsetjmp)
-0:
+.Linternal_sigsetjmp:
 #ifdef PTR_MANGLE
 	stm    %r6,%r13,0(%r2)      /* store registers in jmp_buf */
 	lr     %r4,%r14
@@ -55,10 +63,6 @@ ENTRY(__sigsetjmp)
 #else
 	stm    %r6,%r15,0(%r2)      /* store registers in jmp_buf */
 #endif
-#ifndef __V1_JMPBUF
-	lhi    %r4,0
-	st     %r4,56(%r2)         /* Set __flags to 0.  */
-#endif
 	std    %f4,40(%r2)
 	std    %f6,48(%r2)
 #if defined NOT_IN_libc && defined IS_IN_rtld
@@ -70,15 +74,38 @@ ENTRY(__sigsetjmp)
 	   we can't save and restore our caller's value.  Instead, we do an
 	   indirect jump through the GOT. */
 	basr   %r1,0
-0:      al     %r1,1f-0b(0,%r1) /* get address of global offset table */
-				/* get address of __sigjmp_save from got */
+.L0:    al     %r1,.L1 - .L0(0,%r1) /* get address of global offset table */
+				    /* get address of __sigjmp_save from got */
 	l      %r1,__sigjmp_save@GOT12(0,%r1)
 	br     %r1
-1:      .long  _GLOBAL_OFFSET_TABLE_ - 0b
+.L1:    .long  _GLOBAL_OFFSET_TABLE_ - .L0
 #else
 	basr   %r1,0
-0:      l      %r1,1f-0b(0,%r1)   /* load address of __sigjmp_save */
-	br     %r1                /* tail-call __sigjmp_save */
-1:      .long  __sigjmp_save
+.L0:    l      %r1,.L1-.L0(0,%r1)   /* load address of __sigjmp_save */
+	br     %r1                  /* tail-call __sigjmp_save */
+.L1:    .long  __sigjmp_save
 #endif
 END (__sigsetjmp)
+
+#if !defined IS_IN_rtld
+# if defined SHARED &&  SHLIB_COMPAT (libc, GLIBC_2_19, GLIBC_2_20)
+/* In glibc release 2.19 new versions of setjmp-functions were introduced,
+   but were reverted before 2.20. Thus both versions are the same function.  */
+
+#  undef __sigsetjmp
+
+weak_alias (setjmp, __v1setjmp);
+weak_alias (setjmp, __v2setjmp);
+versioned_symbol (libc, __v1setjmp, setjmp, GLIBC_2_0);
+compat_symbol (libc, __v2setjmp, setjmp, GLIBC_2_19);
+
+weak_alias (_setjmp, __v1_setjmp);
+weak_alias (_setjmp, __v2_setjmp);
+versioned_symbol (libc, __v1_setjmp, _setjmp, GLIBC_2_0);
+compat_symbol (libc, __v2_setjmp, _setjmp, GLIBC_2_19);
+
+strong_alias (__v1__sigsetjmp, __v2__sigsetjmp);
+versioned_symbol (libc, __v1__sigsetjmp, __sigsetjmp, GLIBC_2_0);
+compat_symbol (libc, __v2__sigsetjmp, __sigsetjmp, GLIBC_2_19);
+# endif /* if defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_19, GLIBC_2_20)  */
+#endif /* if !defined IS_IN_rtld  */
diff --git a/sysdeps/s390/s390-64/__longjmp-common.c b/sysdeps/s390/s390-64/__longjmp.c
similarity index 98%
rename from sysdeps/s390/s390-64/__longjmp-common.c
rename to sysdeps/s390/s390-64/__longjmp.c
index 46cabb6..168ebf5 100644
--- a/sysdeps/s390/s390-64/__longjmp-common.c
+++ b/sysdeps/s390/s390-64/__longjmp.c
@@ -25,7 +25,7 @@
 
 /* Jump to the position specified by ENV, causing the
    setjmp call there to return VAL, or 1 if VAL is 0.  */
-attribute_hidden void
+void
 __longjmp (__jmp_buf env, int val)
 {
 #ifdef PTR_DEMANGLE
diff --git a/sysdeps/s390/s390-64/setjmp-common.S b/sysdeps/s390/s390-64/setjmp.S
similarity index 60%
rename from sysdeps/s390/s390-64/setjmp-common.S
rename to sysdeps/s390/s390-64/setjmp.S
index 9cdcae4..7cbb9e8 100644
--- a/sysdeps/s390/s390-64/setjmp-common.S
+++ b/sysdeps/s390/s390-64/setjmp.S
@@ -21,30 +21,38 @@
 #define _ASM
 #define _SETJMP_H
 #include <bits/setjmp.h>
+#include <shlib-compat.h>
+
+#if !defined IS_IN_rtld
+# if defined SHARED &&  SHLIB_COMPAT (libc, GLIBC_2_19, GLIBC_2_20)
+	/* we need a unique name in case of symbol versioning.  */
+#  define __sigsetjmp __v1__sigsetjmp
+# endif /* if defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_19, GLIBC_2_20)  */
+#endif /* !defined IS_IN_rtld  */
 
 	/* We include the BSD entry points here as well but we make
 	   them weak.  */
 ENTRY (setjmp)
 	.weak C_SYMBOL_NAME (setjmp)
         lghi   %r3,1                /* Second argument of one.  */
-        j      0f                   /* Branch relativ to __sigsetjmp.  */
+        j      .Linternal_sigsetjmp /* Branch relativ to __sigsetjmp.  */
 END (setjmp)
 
 	/* Binary compatibility entry point.  */
 ENTRY(_setjmp)
         .weak  C_SYMBOL_NAME (_setjmp)
         slgr   %r3,%r3              /* Second argument of zero.  */
-        j      0f                   /* Branch relativ to __sigsetjmp.  */
+        j      .Linternal_sigsetjmp /* Branch relativ to __sigsetjmp.  */
 END (_setjmp)
 libc_hidden_def (_setjmp)
 
 ENTRY(__setjmp)
         slgr   %r3,%r3              /* Second argument of zero.  */
-        j      0f                   /* Branch relativ to __sigsetjmp.  */
+        j      .Linternal_sigsetjmp /* Branch relativ to __sigsetjmp.  */
 END (__setjmp)
 
 ENTRY(__sigsetjmp)
-0:
+.Linternal_sigsetjmp:
 #ifdef PTR_MANGLE
 	stmg   %r6,%r13,0(%r2)      /* Store registers in jmp_buf.  */
 	lgr    %r4,%r14
@@ -55,10 +63,6 @@ ENTRY(__sigsetjmp)
 #else
         stmg   %r6,%r15,0(%r2)      /* Store registers in jmp_buf.  */
 #endif
-#ifndef __V1_JMPBUF
-	lghi   %r4,0
-	stg    %r4,144(%r2)         /* Set __flags to 0.  */
-#endif
 	std    %f8,80(%r2)
 	std    %f9,88(%r2)
 	std    %f10,96(%r2)
@@ -77,3 +81,26 @@ ENTRY(__sigsetjmp)
 	jg     __sigjmp_save
 #endif
 END (__sigsetjmp)
+
+#if !defined IS_IN_rtld
+# if defined SHARED &&  SHLIB_COMPAT (libc, GLIBC_2_19, GLIBC_2_20)
+/* In glibc release 2.19 new versions of setjmp-functions were introduced,
+   but were reverted before 2.20. Thus both versions are the same function.  */
+
+#  undef __sigsetjmp
+
+weak_alias (setjmp, __v1setjmp);
+weak_alias (setjmp, __v2setjmp);
+versioned_symbol (libc, __v1setjmp, setjmp, GLIBC_2_0);
+compat_symbol (libc, __v2setjmp, setjmp, GLIBC_2_19);
+
+weak_alias (_setjmp, __v1_setjmp);
+weak_alias (_setjmp, __v2_setjmp);
+versioned_symbol (libc, __v1_setjmp, _setjmp, GLIBC_2_0);
+compat_symbol (libc, __v2_setjmp, _setjmp, GLIBC_2_19);
+
+strong_alias (__v1__sigsetjmp, __v2__sigsetjmp);
+versioned_symbol (libc, __v1__sigsetjmp, __sigsetjmp, GLIBC_2_0);
+compat_symbol (libc, __v2__sigsetjmp, __sigsetjmp, GLIBC_2_19);
+# endif /* if defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_19, GLIBC_2_20)  */
+#endif /* if !defined IS_IN_rtld  */
diff --git a/sysdeps/s390/setjmp.S b/sysdeps/s390/setjmp.S
deleted file mode 100644
index 2ec621a..0000000
--- a/sysdeps/s390/setjmp.S
+++ /dev/null
@@ -1,64 +0,0 @@
-/* Extendible version of setjmp for System z
-   Copyright (C) 2013 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <libc-symbols.h>
-#include <shlib-compat.h>
-
-versioned_symbol (libc, __v2setjmp, setjmp, GLIBC_2_19)
-versioned_symbol (libc, __v2_setjmp, _setjmp, GLIBC_2_19)
-versioned_symbol (libc, __v2__setjmp, __setjmp, GLIBC_2_19)
-versioned_symbol (libc, __v2__sigsetjmp, __sigsetjmp, GLIBC_2_19)
-#define setjmp __v2setjmp
-#define _setjmp __v2_setjmp
-#define __setjmp __v2__setjmp
-#define __sigsetjmp __v2__sigsetjmp
-#define __sigjmp_save __v2__sigjmp_save
-
-#include "setjmp-common.S"
-
-#undef setjmp
-#undef _setjmp
-#undef __setjmp
-#undef __sigsetjmp
-#undef __sigjmp_save
-libc_hidden_ver (__v2setjmp, setjmp)
-libc_hidden_ver (__v2_setjmp, _setjmp)
-libc_hidden_ver (__v2__setjmp, __setjmp)
-libc_hidden_ver (__v2__sigsetjmp, __sigsetjmp)
-
-#if defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_19)
-compat_symbol (libc, __v1setjmp, setjmp, GLIBC_2_0)
-compat_symbol (libc, __v1_setjmp, _setjmp, GLIBC_2_0)
-compat_symbol (libc, __v1__setjmp, __setjmp, GLIBC_2_0)
-compat_symbol (libc, __v1__sigsetjmp, __sigsetjmp, GLIBC_2_0)
-# define setjmp __v1setjmp
-# define _setjmp __v1_setjmp
-# define __setjmp __v1__setjmp
-# define __sigsetjmp __v1__sigsetjmp
-# define __sigjmp_save __v1__sigjmp_save
-# define __V1_JMPBUF
-
-# include "setjmp-common.S"
-
-# undef setjmp
-# undef _setjmp
-# undef __setjmp
-# undef __sigsetjmp
-# undef __sigjmp_save
-
-#endif /* if defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_19) */
diff --git a/sysdeps/s390/sigjmp.c b/sysdeps/s390/sigjmp.c
deleted file mode 100644
index f7b5a6f..0000000
--- a/sysdeps/s390/sigjmp.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Copyright (C) 1992-2013 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <stddef.h>
-#include <setjmp.h>
-#include <signal.h>
-
-/* This function is called by the `sigsetjmp' macro
-   before doing a `__setjmp' on ENV[0].__jmpbuf.
-   Always return zero.  */
-
-int
-__v2__sigjmp_save (sigjmp_buf env, int savemask)
-{
-  env[0].__mask_was_saved = (savemask &&
-			     __sigprocmask (SIG_BLOCK, (sigset_t *) NULL,
-					    &env[0].__saved_mask) == 0);
-
-  return 0;
-}
diff --git a/sysdeps/s390/v1-longjmp.c b/sysdeps/s390/v1-longjmp.c
deleted file mode 100644
index 82252c9..0000000
--- a/sysdeps/s390/v1-longjmp.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/* Copyright (C) 2013 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.
-
-   Versioned copy of sysdeps/generic/longjmp.c modified for extended
-   jmpbuf.  */
-
-#include <shlib-compat.h>
-#include <stddef.h>
-#include <signal.h>
-#include "v1-setjmp.h"
-
-#if !defined NOT_INT_libc && defined SHARED
-# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_19)
-
-void
-__v1__libc_siglongjmp (__v1__sigjmp_buf env, int val)
-{
-  /* Perform any cleanups needed by the frames being unwound.  */
-  _longjmp_unwind (env, val);
-
-  if (env[0].__mask_was_saved)
-    /* Restore the saved signal mask.  */
-    (void) __sigprocmask (SIG_SETMASK, &env[0].__saved_mask,
-			  (sigset_t *) NULL);
-
-  /* Call the machine-dependent function to restore machine state.  */
-  __v1__longjmp (env[0].__jmpbuf, val ?: 1);
-}
-
-#  ifndef __v1__longjmp
-strong_alias (__v1__libc_siglongjmp, __v1__libc_longjmp)
-libc_hidden_def (__v1__libc_longjmp)
-weak_alias (__v1__libc_siglongjmp, __v1_longjmp)
-weak_alias (__v1__libc_siglongjmp, __v1longjmp)
-weak_alias (__v1__libc_siglongjmp, __v1siglongjmp)
-
-compat_symbol (libc, __v1_longjmp, _longjmp, GLIBC_2_0);
-compat_symbol (libc, __v1longjmp, longjmp, GLIBC_2_0);
-compat_symbol (libc, __v1siglongjmp, siglongjmp, GLIBC_2_0);
-
-#  endif /* ifndef __v1__longjmp */
-# endif /* SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_19) */
-#endif /* if !defined NOT_INT_libc && defined SHARED */
diff --git a/sysdeps/s390/v1-setjmp.h b/sysdeps/s390/v1-setjmp.h
deleted file mode 100644
index a4a6b76..0000000
--- a/sysdeps/s390/v1-setjmp.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/* Copyright (C) 1991-2013 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-/*
- *	ISO C99 Standard: 7.13 Nonlocal jumps	<setjmp.h>
- */
-
-#ifndef	_V1_SETJMP_H
-#define	_V1_SETJMP_H	1
-
-#include <features.h>
-
-__BEGIN_DECLS
-
-#define __V1_JMPBUF
-#define _SETJMP_H
-#include <bits/setjmp.h>		/* Get `__jmp_buf'.  */
-
-#ifndef _ASM
-
-#include <bits/sigset.h>		/* Get `__sigset_t'.  */
-
-
-/* Calling environment, plus possibly a saved signal mask.  */
-typedef struct __v1__jmp_buf_tag
-  {
-    /* NOTE: The machine-dependent definitions of `__sigsetjmp'
-       assume that a `jmp_buf' begins with a `__jmp_buf' and that
-       `__mask_was_saved' follows it.  Do not move these members
-       or add others before it.  */
-    __jmp_buf __jmpbuf;		/* Calling environment.  */
-    int __mask_was_saved;	/* Saved the signal mask?  */
-    __sigset_t __saved_mask;	/* Saved signal mask.  */
-  } __v1__jmp_buf[1];
-
-
-/* Store the calling environment in ENV, also saving the signal mask.
-   Return 0.  */
-extern int __v1setjmp (__v1__jmp_buf __env);
-
-/* Store the calling environment in ENV, also saving the
-   signal mask if SAVEMASK is nonzero.  Return 0.
-   This is the internal name for `sigsetjmp'.  */
-extern int __v1__sigsetjmp (struct __v1__jmp_buf_tag __env[1],
-			       int __savemask);
-
-/* Store the calling environment in ENV, not saving the signal mask.
-   Return 0.  */
-extern int __v1_setjmp (struct __v1__jmp_buf_tag __env[1]);
-
-/* Jump to the environment saved in ENV, making the
-   `setjmp' call there return VAL, or 1 if VAL is 0.  */
-extern void __v1longjmp (struct __v1__jmp_buf_tag __env[1], int __val)
-     __attribute__ ((__noreturn__));
-
-/* Same.  Usually `_longjmp' is used with `_setjmp', which does not save
-   the signal mask.  But it is how ENV was saved that determines whether
-   `longjmp' restores the mask; `_longjmp' is just an alias.  */
-extern void __v1_longjmp (struct __v1__jmp_buf_tag __env[1], int __val)
-     __attribute__ ((__noreturn__));
-
-/* Use the same type for `jmp_buf' and `sigjmp_buf'.
-   The `__mask_was_saved' flag determines whether
-   or not `longjmp' will restore the signal mask.  */
-typedef struct __v1__jmp_buf_tag __v1__sigjmp_buf[1];
-
-/* Jump to the environment saved in ENV, making the
-   sigsetjmp call there return VAL, or 1 if VAL is 0.
-   Restore the signal mask if that sigsetjmp call saved it.
-   This is just an alias `longjmp'.  */
-extern void __v1siglongjmp (__v1__sigjmp_buf __env, int __val)
-     __attribute__ ((__noreturn__));
-
-/* Internal machine-dependent function to restore context sans signal mask.  */
-extern void __v1__longjmp (__jmp_buf __env, int __val)
-     __attribute__ ((__noreturn__));
-
-/* Internal function to possibly save the current mask of blocked signals
-   in ENV, and always set the flag saying whether or not it was saved.
-   This is used by the machine-dependent definition of `__sigsetjmp'.
-   Always returns zero, for convenience.  */
-extern int __v1__sigjmp_save (__v1__jmp_buf __env, int __savemask);
-
-extern void _longjmp_unwind (__v1__jmp_buf env, int val);
-
-extern void __v1__libc_siglongjmp (__v1__sigjmp_buf env, int val)
-          __attribute__ ((noreturn));
-
-extern void __v1__libc_longjmp (__v1__sigjmp_buf env, int val)
-     __attribute__ ((noreturn));
-
-libc_hidden_proto (__v1__libc_longjmp)
-libc_hidden_proto (__v1_setjmp)
-libc_hidden_proto (__v1__sigsetjmp)
-#endif /* !_ASM */
-
-#endif /* ifndef _V1_SETJMP_H */
diff --git a/sysdeps/s390/v1-sigjmp.c b/sysdeps/s390/v1-sigjmp.c
deleted file mode 100644
index b624d16..0000000
--- a/sysdeps/s390/v1-sigjmp.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/* Copyright (C) 1992-2013 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.
-
-   Copied from setjmp/sigjmp.c for extending jmp_buf.  */
-
-#include <bits/wordsize.h>
-#include <shlib-compat.h>
-
-#if !defined NOT_IN_libc && defined SHARED
-# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_19)
-#  include <stddef.h>
-#  include <v1-setjmp.h>
-#  include <signal.h>
-
-/* This function is called by the `sigsetjmp' macro
-   before doing a `__setjmp' on ENV[0].__jmpbuf.
-   Always return zero.  */
-
-int
-__v1__sigjmp_save (__v1__sigjmp_buf env, int savemask)
-{
-  env[0].__mask_was_saved = (savemask &&
-			     __sigprocmask (SIG_BLOCK, (sigset_t *) NULL,
-					    &env[0].__saved_mask) == 0);
-
-  return 0;
-}
-
-# endif /* SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_19) */
-#endif /* !NOT_IN_libc && SHARED  */
diff --git a/sysdeps/unix/sysv/linux/s390/Makefile b/sysdeps/unix/sysv/linux/s390/Makefile
index f91179d..45b1922 100644
--- a/sysdeps/unix/sysv/linux/s390/Makefile
+++ b/sysdeps/unix/sysv/linux/s390/Makefile
@@ -16,9 +16,3 @@ endif
 ifeq ($(subdir),elf)
 sysdep_routines += dl-vdso
 endif
-
-ifeq ($(subdir),debug)
-ifeq (yes,$(build-shared))
-sysdep_routines += v1-longjmp_chk
-endif
-endif
diff --git a/sysdeps/unix/sysv/linux/s390/getcontext.S b/sysdeps/unix/sysv/linux/s390/getcontext.S
deleted file mode 100644
index 5edbf95..0000000
--- a/sysdeps/unix/sysv/linux/s390/getcontext.S
+++ /dev/null
@@ -1,38 +0,0 @@
-/* Extendible version of getcontext for System z
-   Copyright (C) 2013 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <libc-symbols.h>
-#include <shlib-compat.h>
-
-versioned_symbol (libc, __v2getcontext, getcontext, GLIBC_2_19)
-#define __getcontext __v2getcontext
-
-#include "getcontext-common.S"
-
-#undef __getcontext
-
-libc_hidden_ver (__v2getcontext, getcontext)
-
-#if defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_19)
-# define __V1_UCONTEXT
-compat_symbol (libc, __v1getcontext, getcontext, GLIBC_2_1)
-# define __getcontext __v1getcontext
-# include "getcontext-common.S"
-# undef __getcontext
-
-#endif
diff --git a/sysdeps/unix/sysv/linux/s390/longjmp_chk.c b/sysdeps/unix/sysv/linux/s390/longjmp_chk.c
index 10f542d..02c96c2 100644
--- a/sysdeps/unix/sysv/linux/s390/longjmp_chk.c
+++ b/sysdeps/unix/sysv/linux/s390/longjmp_chk.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2013 Free Software Foundation, Inc.
+/* Copyright (C) 2014 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -15,30 +15,34 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.
 
-   This is a copy of debug/longjmp_chk.c extended for symbol
-   versioning.  */
+   Versioned copy of debug/longjmp_chk.c modified for versioning
+   the reverted jmpbuf extension.  */
 
 #include <shlib-compat.h>
-#include <setjmp.h>
 
-/* This place is the only user of these functions.  */
-extern void ____v2__longjmp_chk (__jmp_buf __env, int __val)
+#if !defined NOT_IN_libc && defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_19, GLIBC_2_20)
+/* this is a copy from debug/longjmp_chk.c because we need an unique name
+   for __longjmp_chk, but it is already named via a define
+   for __libc_siglongjmp in debug/longjmp_chk.c.  */
+# include <setjmp.h>
+
+// XXX Should move to include/setjmp.h
+extern void ____longjmp_chk (__jmp_buf __env, int __val)
      __attribute__ ((__noreturn__));
 
-#if defined NOT_IN_libc
+# define __longjmp ____longjmp_chk
+# define __libc_siglongjmp __v1__longjmp_chk
 
-# define __v2__longjmp ____longjmp_chk
-# define __v2__libc_siglongjmp __longjmp_chk
+# include <setjmp/longjmp.c>
 
-# include <longjmp.c>
+/* In glibc release 2.19 a new versions of __longjmp_chk was introduced,
+   but was reverted before 2.20. Thus both versions are the same function.  */
+strong_alias (__v1__longjmp_chk, __v2__longjmp_chk);
+versioned_symbol (libc, __v1__longjmp_chk, __longjmp_chk, GLIBC_2_11);
+compat_symbol (libc, __v2__longjmp_chk, __longjmp_chk, GLIBC_2_19);
 
 #else
 
-# define __v2__longjmp ____v2__longjmp_chk
-# define __v2__libc_siglongjmp __v2__libc_siglongjmp_chk
-
-# include <longjmp.c>
-
-versioned_symbol (libc, __v2__libc_siglongjmp_chk, __longjmp_chk, GLIBC_2_19);
+# include <debug/longjmp_chk.c>
 
 #endif
diff --git a/sysdeps/unix/sysv/linux/s390/rtld-getcontext.S b/sysdeps/unix/sysv/linux/s390/rtld-getcontext.S
deleted file mode 100644
index 653f2b6..0000000
--- a/sysdeps/unix/sysv/linux/s390/rtld-getcontext.S
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Copyright (C) 2013 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-/* Build a non-versioned object for rtld-*.  */
-#include "getcontext-common.S"
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/____longjmp_chk.c b/sysdeps/unix/sysv/linux/s390/s390-32/____longjmp_chk.c
index a1b7a6a..e74f335 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/____longjmp_chk.c
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/____longjmp_chk.c
@@ -26,8 +26,8 @@
 #include <stdint.h>
 #include <signal.h>
 #include <sys/syscall.h>
-#include <libc-symbols.h>
-#include <shlib-compat.h>
+
+#define __longjmp ____longjmp_chk
 
 #define CHECK_SP(env, guard) \
   do									\
@@ -51,22 +51,4 @@
 	}								\
     } while (0)
 
-
-#if defined NOT_IN_libc
-/* Build a non-versioned object for rtld-*.  */
-# define __longjmp ____longjmp_chk
-# include "__longjmp-common.c"
-
-#else /* !NOT_IN_libc */
-# define __longjmp  ____v2__longjmp_chk
-# include "__longjmp-common.c"
-
-# if defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_11, GLIBC_2_19)
-#  undef __longjmp
-#  define __V1_JMPBUF
-#  define __longjmp  ____v1__longjmp_chk
-#  include "__longjmp-common.c"
-#  undef __longjmp
-
-# endif
-#endif /* !NOT_IN_libc */
+#include "__longjmp.c"
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/getcontext-common.S b/sysdeps/unix/sysv/linux/s390/s390-32/getcontext.S
similarity index 67%
rename from sysdeps/unix/sysv/linux/s390/s390-32/getcontext-common.S
rename to sysdeps/unix/sysv/linux/s390/s390-32/getcontext.S
index 4992030..f35bc5c 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/getcontext-common.S
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/getcontext.S
@@ -19,9 +19,10 @@
 #include <sysdep.h>
 #include <features.h>
 
-#include "rtld-global-offsets.h"
 #include "ucontext_i.h"
 
+#include <shlib-compat.h>
+
 /*  __getcontext (const ucontext_t *ucp)
 
   Saves the machine context in UCP such that when it is activated,
@@ -37,7 +38,7 @@ ENTRY(__getcontext)
 	/* rt_sigprocmask (SIG_BLOCK, NULL, &sc->sc_mask, sigsetsize).  */
 	la      %r2,SIG_BLOCK
 	slr	%r3,%r3
-	la      %r4,SC_MASK(%r1)
+	la	%r4,SC_MASK(%r1)
 	lhi	%r5,_NSIG8
 	svc	SYS_ify(rt_sigprocmask)
 
@@ -60,42 +61,6 @@ ENTRY(__getcontext)
 	std     %f14,SC_FPRS+112(%r1)
 	std     %f15,SC_FPRS+120(%r1)
 
-	lhi	%r2,0
-#ifndef __V1_UCONTEXT
-	bras	%r3,0f
-# ifdef IS_IN_rtld
-  /* Within ld.so we can do slightly better by addressing dl_hwap
-     relative to GOT start.  */
-1:	.long	_GLOBAL_OFFSET_TABLE_ - 1b
-	.long	C_SYMBOL_NAME(_rtld_global_ro)@GOTOFF
-0:	l	%r4,0(%r3)
-	la	%r4,0(%r3,%r4)
-	l	%r5,4(%r3)
-	/* _dl_hwcap is 64 bit and we need the lower 32.  */
-	l	%r3,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+4(%r4,%r5)
-# elif PIC
-1:	.long	_GLOBAL_OFFSET_TABLE_ - 1b
-	.long	C_SYMBOL_NAME(_rtld_global_ro)@GOT
-0:	l	%r4,0(%r3)
-	la	%r4,0(%r3,%r4)  /* GOT pointer -> r4 */
-	l	%r5,4(%r3)      /* GOT offset -> r5 */
-	l	%r5,0(%r4,%r5)  /* GOT slot -> r5 */
-	l	%r3,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+4(%r5)
-# else
-	.long	C_SYMBOL_NAME(_dl_hwcap)
-0:	l	%r3,0(%r3)
-	l	%r3,0(%r3)
-# endif
-	tml	%r3,512 /* HWCAP_S390_HIGH_GPRS */
-	jz	2f
-	/* highgprs implies zarch so stmh/oill is ok here.  */
-	.machine "z900"
-	.machinemode "zarch_nohighgprs"
-	stmh	%r0,%r15,SC_HIGHGPRS(%r1)
-	oill	%r2,1 /* UCONTEXT_UC_FLAGS_HIGH_GPRS */
-#endif
-2:	st	%r2,SC_FLGS(%r1)
-
 	/* Set __getcontext return value to 0.  */
 	slr     %r2,%r2
 
@@ -110,3 +75,12 @@ ENTRY(__getcontext)
 END(__getcontext)
 
 weak_alias (__getcontext, getcontext)
+
+#if defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_19, GLIBC_2_20)
+/* In glibc release 2.19 a new version of getcontext was introduced,
+   but was reverted before 2.20. Thus both versions are the same function.  */
+weak_alias (__getcontext, __v1__getcontext)
+weak_alias (__getcontext, __v2__getcontext)
+versioned_symbol (libc, __v1__getcontext, getcontext, GLIBC_2_1)
+compat_symbol (libc, __v2__getcontext, getcontext, GLIBC_2_19)
+#endif
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/nptl/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/nptl/libc.abilist
index 03f2e83..0194f0b 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/nptl/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/nptl/libc.abilist
@@ -1777,7 +1777,6 @@ GLIBC_2.18
 GLIBC_2.19
  GLIBC_2.19 A
  __longjmp_chk F
- __setjmp F
  __sigsetjmp F
  _longjmp F
  _setjmp F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/setcontext.S b/sysdeps/unix/sysv/linux/s390/s390-32/setcontext.S
index fbe8b77..42839e2 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/setcontext.S
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/setcontext.S
@@ -62,16 +62,8 @@ ENTRY(__setcontext)
 	/* Don't touch %a0, used for thread purposes.  */
 	lam	%a1,%a15,SC_ACRS+4(%r1)
 
-	/* Restore the upper halfs if available.  */
-	l	%r2,SC_FLGS(%r1)
-	tml	%r2,1   /* UCONTEXT_UC_FLAGS_HIGH_GPRS */
-	jz	0f
-	.machine	"z900"
-	.machinemode	"zarch_nohighgprs"
-	lmh	%r0,%r15,SC_HIGHGPRS(%r1)
-
 	/* Load general purpose registers.  */
-0:	lm	%r0,%r15,SC_GPRS(%r1)
+	lm	%r0,%r15,SC_GPRS(%r1)
 
 	/* Return.  */
 	br	%r14
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/swapcontext.S b/sysdeps/unix/sysv/linux/s390/s390-32/swapcontext.S
index 41ede4b..9206aa3 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/swapcontext.S
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/swapcontext.S
@@ -65,31 +65,19 @@ ENTRY(__swapcontext)
 	std     %f14,SC_FPRS+112(%r1)
 	std     %f15,SC_FPRS+120(%r1)
 
-	/* Store access registers.  */
-	stam    %a0,%a15,SC_ACRS(%r1)
-
 	/* Set __swapcontext return value to 0.  */
 	slr     %r2,%r2
 
+	/* Store access registers.  */
+	stam    %a0,%a15,SC_ACRS(%r1)
+
 	/* Store general purpose registers.  */
 	stm     %r0,%r15,SC_GPRS(%r1)
 
-	/* Copy uc_flags into the new ucontext_t.  */
+	/* sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL).  */
+	la      %r2,SIG_BLOCK
 	lr	%r5,%r0
-	l	%r2,SC_FLGS(%r5)
-	st	%r2,SC_FLGS(%r1)
-
-	/* Save/restore the upper halfs if necessary.  */
-	tml	%r2,1   /* UCONTEXT_UC_FLAGS_HIGH_GPRS */
-	jz	0f
-	.machine	"z900"
-	.machinemode	"zarch_nohighgprs"
-	stmh	%r0,%r15,SC_HIGHGPRS(%r1)
-	lmh	%r0,%r15,SC_HIGHGPRS(%r5)
-
-	/* rt_sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL, sigsetsize).  */
-0:	la      %r2,SIG_BLOCK
-	la      %r3,SC_MASK(%r5)
+	la	%r3,SC_MASK(%r5)
 	slr	%r4,%r4
 	lhi	%r5,_NSIG8
 	svc	SYS_ify(rt_sigprocmask)
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/ucontext_i.sym b/sysdeps/unix/sysv/linux/s390/s390-32/ucontext_i.sym
deleted file mode 100644
index 705c7ab..0000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/ucontext_i.sym
+++ /dev/null
@@ -1,26 +0,0 @@
-#include <stddef.h>
-#include <signal.h>
-#include <sys/ucontext.h>
-
---
-
-SIG_BLOCK
-SIG_UNBLOCK
-SIG_SETMASK
-
-_NSIG8          (_NSIG / 8)
-
-#define ucontext(member)	offsetof (ucontext_t, member)
-#define mcontext(member)	ucontext (uc_mcontext.member)
-
-SC_FLGS		ucontext (uc_flags)
-SC_LINK		ucontext (uc_link)
-SC_STCK		ucontext (uc_stack.ss_sp)
-SC_STSZ		ucontext (uc_stack.ss_size)
-SC_PSW		mcontext (psw)
-SC_GPRS		mcontext (gregs)
-SC_ACRS		mcontext (aregs)
-SC_FPC		mcontext (fpregs.fpc)
-SC_FPRS		mcontext (fpregs.fprs)
-SC_MASK		ucontext (uc_sigmask)
-SC_HIGHGPRS	ucontext (uc_high_gprs)
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/____longjmp_chk.c b/sysdeps/unix/sysv/linux/s390/s390-64/____longjmp_chk.c
index bc27b08..a3b1375 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/____longjmp_chk.c
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/____longjmp_chk.c
@@ -26,8 +26,8 @@
 #include <stdint.h>
 #include <signal.h>
 #include <sys/syscall.h>
-#include <libc-symbols.h>
-#include <shlib-compat.h>
+
+#define __longjmp ____longjmp_chk
 
 #define CHECK_SP(env, guard) \
   do									\
@@ -51,23 +51,4 @@
 	}								\
     } while (0)
 
-
-#if defined NOT_IN_libc
-/* Build a non-versioned object for rtld-*.  */
-# define __longjmp ____longjmp_chk
-# include "__longjmp-common.c"
-
-#else /* !NOT_IN_libc */
-# define __longjmp  ____v2__longjmp_chk
-# include "__longjmp-common.c"
-# undef __longjmp
-
-# if defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_11, GLIBC_2_19)
-#  undef __longjmp
-#  define __V1_JMPBUF
-#  define __longjmp  ____v1__longjmp_chk
-#  include "__longjmp-common.c"
-#  undef __longjmp
-
-# endif
-#endif /* !NOT_IN_libc */
+#include "__longjmp.c"
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/getcontext-common.S b/sysdeps/unix/sysv/linux/s390/s390-64/getcontext.S
similarity index 82%
rename from sysdeps/unix/sysv/linux/s390/s390-64/getcontext-common.S
rename to sysdeps/unix/sysv/linux/s390/s390-64/getcontext.S
index 3e61e30..26a1c51 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/getcontext-common.S
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/getcontext.S
@@ -21,6 +21,8 @@
 
 #include "ucontext_i.h"
 
+#include <shlib-compat.h>
+
 /*  __getcontext (const ucontext_t *ucp)
 
   Saves the machine context in UCP such that when it is activated,
@@ -62,10 +64,6 @@ ENTRY(__getcontext)
 	/* Set __getcontext return value to 0.  */
 	slgr    %r2,%r2
 
-	/* Store the version number into the uc_flags field.  So far
-	   we do not make use of the reserved bytes so we store a zero.  */
-	stg	%r2,SC_FLGS(%r1)
-
 	/* Store access registers.  */
 	stam    %a0,%a15,SC_ACRS(%r1)
 
@@ -77,3 +75,12 @@ ENTRY(__getcontext)
 END(__getcontext)
 
 weak_alias (__getcontext, getcontext)
+
+#if defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_19, GLIBC_2_20)
+/* In glibc release 2.19 a new version of getcontext was introduced,
+   but was reverted before 2.20. Thus both versions are the same function.  */
+weak_alias (__getcontext, __v1__getcontext)
+weak_alias (__getcontext, __v2__getcontext)
+versioned_symbol (libc, __v1__getcontext, getcontext, GLIBC_2_1)
+compat_symbol (libc, __v2__getcontext, getcontext, GLIBC_2_19)
+#endif
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/nptl/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/nptl/libc.abilist
index 4576fc8..807f702 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/nptl/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/nptl/libc.abilist
@@ -98,7 +98,6 @@ GLIBC_2.18
 GLIBC_2.19
  GLIBC_2.19 A
  __longjmp_chk F
- __setjmp F
  __sigsetjmp F
  _longjmp F
  _setjmp F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/swapcontext.S b/sysdeps/unix/sysv/linux/s390/s390-64/swapcontext.S
index ac74b6b..e3e624c 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/swapcontext.S
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/swapcontext.S
@@ -65,25 +65,21 @@ ENTRY(__swapcontext)
 	std     %f14,SC_FPRS+112(%r1)
 	std     %f15,SC_FPRS+120(%r1)
 
+	/* Set __swapcontext return value to 0.  */
+	slgr     %r2,%r2
+
 	/* Store access registers.  */
 	stam    %a0,%a15,SC_ACRS(%r1)
 
-	/* Set __swapcontext return value to 0.  */
-	slgr	%r2,%r2
-
 	/* Store general purpose registers.  */
 	stmg    %r0,%r15,SC_GPRS(%r1)
 
-	/* Copy uc_flags into the new ucontext_t.  */
-	lgr	%r5,%r0
-	lg	%r2,SC_FLGS(%r5)
-	stg	%r2,SC_FLGS(%r1)
-
 	/* rt_sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL, sigsetsize).  */
 	la      %r2,SIG_BLOCK
+	lgr	%r5,%r0
 	la	%r3,SC_MASK(%r5)
-	slgr	%r4,%r4
 	lghi	%r5,_NSIG8
+	slgr	%r4,%r4
 	svc	SYS_ify(rt_sigprocmask)
 
 	/* Load fpu context.  */
diff --git a/sysdeps/unix/sysv/linux/s390/sys/ucontext.h b/sysdeps/unix/sysv/linux/s390/sys/ucontext.h
index f04bf84..d528cb1 100644
--- a/sysdeps/unix/sysv/linux/s390/sys/ucontext.h
+++ b/sysdeps/unix/sysv/linux/s390/sys/ucontext.h
@@ -64,15 +64,6 @@ typedef struct
     fpreg_t fprs[16];
   } fpregset_t;
 
-/* Bit is set if the uc_high_gprs field contains the upper halfs of
-   the 64 bit general purpose registers.  Since the uc_high_gprs field
-   is only available in the 32 bit version of ucontext_t it will never
-   be set for 64 bit.  */
-#define UCONTEXT_UC_FLAGS_HIGH_GPRS (1UL << 0)
-
-/* A new uc_flags constant will be defined when actually making use of
-   the reserved space: UCONTEXT_UCFLAGS_RESERVED (1UL << 1).  */
-
 /* Context to describe whole processor state.  */
 typedef struct
   {
@@ -90,10 +81,6 @@ struct ucontext
     stack_t uc_stack;
     mcontext_t uc_mcontext;
     __sigset_t uc_sigmask;
-#ifndef __s390x__
-    unsigned long uc_high_gprs[16];
-#endif
-    char __reserved[512];
   };
 
 
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/ucontext_i.sym b/sysdeps/unix/sysv/linux/s390/ucontext_i.sym
similarity index 100%
rename from sysdeps/unix/sysv/linux/s390/s390-64/ucontext_i.sym
rename to sysdeps/unix/sysv/linux/s390/ucontext_i.sym
diff --git a/sysdeps/unix/sysv/linux/s390/v1-longjmp_chk.c b/sysdeps/unix/sysv/linux/s390/v1-longjmp_chk.c
deleted file mode 100644
index bd80acf..0000000
--- a/sysdeps/unix/sysv/linux/s390/v1-longjmp_chk.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Copyright (C) 2013 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.
-
-   This went into a separate source file since we would otherwise be
-   needed to include two different versions of setjmp.h into the same
-   file.  */
-
-#include <shlib-compat.h>
-
-#if !defined NOT_IN_libc && defined SHARED
-# if SHLIB_COMPAT (libc, GLIBC_2_11, GLIBC_2_19)
-
-#  define __v1__longjmp ____v1__longjmp_chk
-#  define __v1__libc_siglongjmp __v1__libc_siglongjmp_chk
-
-#  include <v1-longjmp.c>
-
-compat_symbol (libc, __v1__libc_siglongjmp_chk, __longjmp_chk, GLIBC_2_11);
-
-# endif
-#endif

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=a5dd31f514e3ab41bfe60cdeacd75d875006d9cc

commit a5dd31f514e3ab41bfe60cdeacd75d875006d9cc
Author: Florian Weimer <fweimer@redhat.com>
Date:   Wed May 28 14:05:03 2014 +0200

    manual: Update the locale documentation
    
    (cherry picked from commit 585367266923156ac6fb789939a923641ba5aaf4)
    
    Conflicts:
    	manual/locale.texi

diff --git a/ChangeLog b/ChangeLog
index eb6a80d..1e97f25 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
 2014-07-02  Florian Weimer  <fweimer@redhat.com>
 
+	* manual/locale.texi (Locale Names): New section documenting
+	locale name syntax.  Adjust menu and node chaining accordingly.
+	(Choosing Locale): Reference Locale Names, Locale Categories.
+	Mention setting LC_ALL=C.  Reflect that name syntax is now
+	documented.
+	(Locale Categories): New section title.  Reference Locale Names.
+	LC_ALL is an environment variable, but not a category.
+	(Setting the Locale): Remove "locale -a" invocation and LOCPATH
+	description, now in Locale Name.  Reference that section.  Locale
+	name syntax is now documented.
+
+2014-07-02  Florian Weimer  <fweimer@redhat.com>
+
 	[BZ #17137]
 	* locale/findlocale.c (name_present, valid_locale_name): New
 	functions.
diff --git a/manual/locale.texi b/manual/locale.texi
index 8bfd653..ee1c3a1 100644
--- a/manual/locale.texi
+++ b/manual/locale.texi
@@ -29,6 +29,7 @@ will follow the conventions preferred by the user.
 * Setting the Locale::          How a program specifies the locale
                                  with library functions.
 * Standard Locales::            Locale names available on all systems.
+* Locale Names::                Format of system-specific locale names.
 * Locale Information::          How to access the information for the locale.
 * Formatting Numbers::          A dedicated function to format numbers.
 * Yes-or-No Questions::         Check a Response against the locale.
@@ -99,14 +100,16 @@ locale named @samp{espana-castellano} to use the standard conventions of
 most of Spain.
 
 The set of locales supported depends on the operating system you are
-using, and so do their names.  We can't make any promises about what
-locales will exist, except for one standard locale called @samp{C} or
-@samp{POSIX}.  Later we will describe how to construct locales.
-@comment (@pxref{Building Locale Files}).
+using, and so do their names, except that the standard locale called
+@samp{C} or @samp{POSIX} always exist.  @xref{Locale Names}.
+
+In order to force the system to always use the default locale, the
+user can set the @code{LC_ALL} environment variable to @samp{C}.
 
 @cindex combining locales
-A user also has the option of specifying different locales for different
-purposes---in effect, choosing a mixture of multiple locales.
+A user also has the option of specifying different locales for
+different purposes---in effect, choosing a mixture of multiple
+locales.  @xref{Locale Categories}.
 
 For example, the user might specify the locale @samp{espana-castellano}
 for most purposes, but specify the locale @samp{usa-english} for
@@ -120,7 +123,7 @@ which locales apply.  However, the user can choose to use each locale
 for a particular subset of those purposes.
 
 @node Locale Categories, Setting the Locale, Choosing Locale, Locales
-@section Categories of Activities that Locales Affect
+@section Locale Categories
 @cindex categories for locales
 @cindex locale categories
 
@@ -128,7 +131,11 @@ The purposes that locales serve are grouped into @dfn{categories}, so
 that a user or a program can choose the locale for each category
 independently.  Here is a table of categories; each name is both an
 environment variable that a user can set, and a macro name that you can
-use as an argument to @code{setlocale}.
+use as the first argument to @code{setlocale}.
+
+The contents of the environment variable (or the string in the second
+argument to @code{setlocale}) has to be a valid locale name.
+@xref{Locale Names}.
 
 @vtable @code
 @comment locale.h
@@ -172,7 +179,7 @@ for affirmative and negative responses.
 @comment locale.h
 @comment ISO
 @item LC_ALL
-This is not an environment variable; it is only a macro that you can use
+This is not a category; it is only a macro that you can use
 with @code{setlocale} to set a single locale for all purposes.  Setting
 this environment variable overwrites all selections by the other
 @code{LC_*} variables or @code{LANG}.
@@ -355,13 +362,7 @@ The symbols in this section are defined in the header file @file{locale.h}.
 @c   strndup @ascuheap @acsmem
 @c   strcasecmp_l ok (C locale)
 The function @code{setlocale} sets the current locale for category
-@var{category} to @var{locale}.  A list of all the locales the system
-provides can be created by running
-
-@pindex locale
-@smallexample
-  locale -a
-@end smallexample
+@var{category} to @var{locale}.
 
 If @var{category} is @code{LC_ALL}, this specifies the locale for all
 purposes.  The other possible values of @var{category} specify an
@@ -386,10 +387,9 @@ is passed in as @var{locale} parameter.
 
 When you read the current locale for category @code{LC_ALL}, the value
 encodes the entire combination of selected locales for all categories.
-In this case, the value is not just a single locale name.  In fact, we
-don't make any promises about what it looks like.  But if you specify
-the same ``locale name'' with @code{LC_ALL} in a subsequent call to
-@code{setlocale}, it restores the same combination of locale selections.
+If you specify the same ``locale name'' with @code{LC_ALL} in a
+subsequent call to @code{setlocale}, it restores the same combination
+of locale selections.
 
 To be sure you can use the returned string encoding the currently selected
 locale at a later time, you must make a copy of the string.  It is not
@@ -405,20 +405,15 @@ for @var{category}.
 If a nonempty string is given for @var{locale}, then the locale of that
 name is used if possible.
 
+The effective locale name (either the second argument to
+@code{setlocale}, or if the argument is an empty string, the name
+obtained from the process environment) must be valid locale name.
+@xref{Locale Names}.
+
 If you specify an invalid locale name, @code{setlocale} returns a null
 pointer and leaves the current locale unchanged.
 @end deftypefun
 
-The path used for finding locale data can be set using the
-@code{LOCPATH} environment variable. The default path for finding
-locale data is system specific.  It is computed from the value given
-as the prefix while configuring the C library.  This value normally is
-@file{/usr} or @file{/}.  For the former the complete path is:
-
-@smallexample
-/usr/lib/locale
-@end smallexample
-
 Here is an example showing how you might use @code{setlocale} to
 temporarily switch to a new locale.
 
@@ -458,7 +453,7 @@ locale categories, and future versions of the library will do so.  For
 portability, assume that any symbol beginning with @samp{LC_} might be
 defined in @file{locale.h}.
 
-@node Standard Locales, Locale Information, Setting the Locale, Locales
+@node Standard Locales, Locale Names, Setting the Locale, Locales
 @section Standard Locales
 
 The only locale names you can count on finding on all operating systems
@@ -492,7 +487,94 @@ with the environment, rather than trying to specify some non-standard
 locale explicitly by name.  Remember, different machines might have
 different sets of locales installed.
 
-@node Locale Information, Formatting Numbers, Standard Locales, Locales
+@node Locale Names, Locale Information, Standard Locales, Locales
+@section Locale Names
+
+The following command prints a list of locales supported by the
+system:
+
+@pindex locale
+@smallexample
+  locale -a
+@end smallexample
+
+@strong{Portability Note:} With the notable exception of the standard
+locale names @samp{C} and @samp{POSIX}, locale names are
+system-specific.
+
+Most locale names follow XPG syntax and consist of up to four parts:
+
+@smallexample
+@var{language}[_@var{territory}[.@var{codeset}]][@@@var{modifier}]
+@end smallexample
+
+Beside the first part, all of them are allowed to be missing.  If the
+full specified locale is not found, less specific ones are looked for.
+The various parts will be stripped off, in the following order:
+
+@enumerate
+@item
+codeset
+@item
+normalized codeset
+@item
+territory
+@item
+modifier
+@end enumerate
+
+For example, the locale name @samp{de_AT.iso885915@@euro} denotes a
+German-language locale for use in Austria, using the ISO-8859-15
+(Latin-9) character set, and with the Euro as the currency symbol.
+
+In addition to locale names which follow XPG syntax, systems may
+provide aliases such as @samp{german}.  Both categories of names must
+not contain the slash character @samp{/}.
+
+If the locale name starts with a slash @samp{/}, it is treated as a
+path relative to the configured locale directories; see @code{LOCPATH}
+below.  The specified path must not contain a component @samp{..}, or
+the name is invalid, and @code{setlocale} will fail.
+
+@strong{Portability Note:} POSIX suggests that if a locale name starts
+with a slash @samp{/}, it is resolved as an absolute path.  However,
+@theglibc{} treats it as a relative path under the directories listed
+in @code{LOCPATH} (or the default locale directory if @code{LOCPATH}
+is unset).
+
+Locale names which are longer than an implementation-defined limit are
+invalid and cause @code{setlocale} to fail.
+
+As a special case, locale names used with @code{LC_ALL} can combine
+several locales, reflecting different locale settings for different
+categories.  For example, you might want to use a U.S. locale with ISO
+A4 paper format, so you set @code{LANG} to @samp{en_US.UTF-8}, and
+@code{LC_PAPER} to @samp{de_DE.UTF-8}.  In this case, the
+@code{LC_ALL}-style combined locale name is
+
+@smallexample
+LC_CTYPE=en_US.UTF-8;LC_TIME=en_US.UTF-8;LC_PAPER=de_DE.UTF-8;@dots{}
+@end smallexample
+
+followed by other category settings not shown here.
+
+@vindex LOCPATH
+The path used for finding locale data can be set using the
+@code{LOCPATH} environment variable.  This variable lists the
+directories in which to search for locale definitions, separated by a
+colon @samp{:}.
+
+The default path for finding locale data is system specific.  A typical
+value for the @code{LOCPATH} default is:
+
+@smallexample
+/usr/share/locale
+@end smallexample
+
+The value of @code{LOCPATH} is ignored by privileged programs for
+security reasons, and only the default directory is used.
+
+@node Locale Information, Formatting Numbers, Locale Names, Locales
 @section Accessing Locale Information
 
 There are several ways to access locale information.  The simplest

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=d475d58097efe764e2567fca0ea194d5d80150ce

commit d475d58097efe764e2567fca0ea194d5d80150ce
Author: Florian Weimer <fweimer@redhat.com>
Date:   Mon May 12 15:24:12 2014 +0200

    _nl_find_locale: Improve handling of crafted locale names [BZ #17137]
    
    Prevent directory traversal in locale-related environment variables
    (CVE-2014-0475).
    
    (cherry picked from commit 4e8f95a0df7c2300b830ec12c0ae1e161bc8a8a3)
    
    Conflicts:
    	NEWS
    	localedata/Makefile

diff --git a/ChangeLog b/ChangeLog
index d79506f..eb6a80d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
 2014-07-02  Florian Weimer  <fweimer@redhat.com>
 
+	[BZ #17137]
+	* locale/findlocale.c (name_present, valid_locale_name): New
+	functions.
+	(_nl_find_locale): Use the loc_name variable to store name
+	candidates.  Call name_present and valid_locale_name to check and
+	validate locale names.  Return an error if the locale is invalid.
+
+2014-07-02  Florian Weimer  <fweimer@redhat.com>
+
 	* locale/setlocale.c (setlocale): Use strdup for allocating
 	composite name copy.
 
diff --git a/NEWS b/NEWS
index e84bae5..71b6ad5 100644
--- a/NEWS
+++ b/NEWS
@@ -10,13 +10,22 @@ Version 2.19.1
 * The following bugs are resolved with this release:
 
   15946, 16545, 16574, 16623, 16695, 16878, 16882, 16885, 16916, 16932,
-  16943, 16958, 17048, 17069.
+  16943, 16958, 17048, 17069, 17137.
 
 * CVE-2014-4043 The posix_spawn_file_actions_addopen implementation did not
   copy the path argument.  This allowed programs to cause posix_spawn to
   deference a dangling pointer, or use an unexpected pathname argument if
   the string was modified after the posix_spawn_file_actions_addopen
   invocation.
+
+* Locale names, including those obtained from environment variables (LANG
+  and the LC_* variables), are more tightly checked for proper syntax.
+  setlocale will now fail (with EINVAL) for locale names that are overly
+  long, contain slashes without starting with a slash, or contain ".." path
+  components. (CVE-2014-0475)  Previously, some valid locale names were
+  silently replaced with the "C" locale when running in AT_SECURE mode
+  (e.g., in a SUID program).  This is no longer necessary because of the
+  additional checks.
 
 Version 2.19
 
diff --git a/locale/findlocale.c b/locale/findlocale.c
index 0c42b99..faeee61 100644
--- a/locale/findlocale.c
+++ b/locale/findlocale.c
@@ -17,6 +17,7 @@
    <http://www.gnu.org/licenses/>.  */
 
 #include <assert.h>
+#include <errno.h>
 #include <locale.h>
 #include <stdlib.h>
 #include <string.h>
@@ -57,6 +58,45 @@ struct loaded_l10nfile *_nl_locale_file_list[__LC_LAST];
 
 const char _nl_default_locale_path[] attribute_hidden = LOCALEDIR;
 
+/* Checks if the name is actually present, that is, not NULL and not
+   empty.  */
+static inline int
+name_present (const char *name)
+{
+  return name != NULL && name[0] != '\0';
+}
+
+/* Checks that the locale name neither extremely long, nor contains a
+   ".." path component (to prevent directory traversal).  */
+static inline int
+valid_locale_name (const char *name)
+{
+  /* Not set.  */
+  size_t namelen = strlen (name);
+  /* Name too long.  The limit is arbitrary and prevents stack overflow
+     issues later.  */
+  if (__glibc_unlikely (namelen > 255))
+    return 0;
+  /* Directory traversal attempt.  */
+  static const char slashdot[4] = {'/', '.', '.', '/'};
+  if (__glibc_unlikely (memmem (name, namelen,
+				slashdot, sizeof (slashdot)) != NULL))
+    return 0;
+  if (namelen == 2 && __glibc_unlikely (name[0] == '.' && name [1] == '.'))
+    return 0;
+  if (namelen >= 3
+      && __glibc_unlikely (((name[0] == '.'
+			     && name[1] == '.'
+			     && name[2] == '/')
+			    || (name[namelen - 3] == '/'
+				&& name[namelen - 2] == '.'
+				&& name[namelen - 1] == '.'))))
+    return 0;
+  /* If there is a slash in the name, it must start with one.  */
+  if (__glibc_unlikely (memchr (name, '/', namelen) != NULL) && name[0] != '/')
+    return 0;
+  return 1;
+}
 
 struct __locale_data *
 internal_function
@@ -65,7 +105,7 @@ _nl_find_locale (const char *locale_path, size_t locale_path_len,
 {
   int mask;
   /* Name of the locale for this category.  */
-  char *loc_name;
+  char *loc_name = (char *) *name;
   const char *language;
   const char *modifier;
   const char *territory;
@@ -73,31 +113,39 @@ _nl_find_locale (const char *locale_path, size_t locale_path_len,
   const char *normalized_codeset;
   struct loaded_l10nfile *locale_file;
 
-  if ((*name)[0] == '\0')
+  if (loc_name[0] == '\0')
     {
       /* The user decides which locale to use by setting environment
 	 variables.  */
-      *name = getenv ("LC_ALL");
-      if (*name == NULL || (*name)[0] == '\0')
-	*name = getenv (_nl_category_names.str
+      loc_name = getenv ("LC_ALL");
+      if (!name_present (loc_name))
+	loc_name = getenv (_nl_category_names.str
 			+ _nl_category_name_idxs[category]);
-      if (*name == NULL || (*name)[0] == '\0')
-	*name = getenv ("LANG");
+      if (!name_present (loc_name))
+	loc_name = getenv ("LANG");
+      if (!name_present (loc_name))
+	loc_name = (char *) _nl_C_name;
     }
 
-  if (*name == NULL || (*name)[0] == '\0'
-      || (__builtin_expect (__libc_enable_secure, 0)
-	  && strchr (*name, '/') != NULL))
-    *name = (char *) _nl_C_name;
+  /* We used to fall back to the C locale if the name contains a slash
+     character '/', but we now check for directory traversal in
+     valid_locale_name, so this is no longer necessary.  */
 
-  if (__builtin_expect (strcmp (*name, _nl_C_name), 1) == 0
-      || __builtin_expect (strcmp (*name, _nl_POSIX_name), 1) == 0)
+  if (__builtin_expect (strcmp (loc_name, _nl_C_name), 1) == 0
+      || __builtin_expect (strcmp (loc_name, _nl_POSIX_name), 1) == 0)
     {
       /* We need not load anything.  The needed data is contained in
 	 the library itself.  */
       *name = (char *) _nl_C_name;
       return _nl_C[category];
     }
+  else if (!valid_locale_name (loc_name))
+    {
+      __set_errno (EINVAL);
+      return NULL;
+    }
+
+  *name = loc_name;
 
   /* We really have to load some data.  First we try the archive,
      but only if there was no LOCPATH environment variable specified.  */
diff --git a/localedata/ChangeLog b/localedata/ChangeLog
index a570767..ff7ecb6 100644
--- a/localedata/ChangeLog
+++ b/localedata/ChangeLog
@@ -1,3 +1,9 @@
+2014-07-02  Florian Weimer  <fweimer@redhat.com>
+
+	* tst-setlocale3.c: New file.
+	* Makefile (tests): Add tst-setlocale3.
+	(tst-setlocale3-ENV): New variable.
+
 2013-12-26  Chris Leonard  <cjl@sugarlabs.org>
 
 	* locales/sa_IN: Add lang_name.
diff --git a/localedata/Makefile b/localedata/Makefile
index 7d157bf..9daa470 100644
--- a/localedata/Makefile
+++ b/localedata/Makefile
@@ -77,7 +77,7 @@ locale_test_suite := tst_iswalnum tst_iswalpha tst_iswcntrl            \
 
 tests = $(locale_test_suite) tst-digits tst-setlocale bug-iconv-trans \
 	tst-leaks tst-mbswcs6 tst-xlocale1 tst-xlocale2 bug-usesetlocale \
-	tst-strfmon1 tst-sscanf bug-setlocale1 tst-setlocale2
+	tst-strfmon1 tst-sscanf bug-setlocale1 tst-setlocale2 tst-setlocale3
 tests-static = bug-setlocale1-static
 tests += $(tests-static)
 ifeq (yes,$(build-shared))
diff --git a/localedata/tst-setlocale3.c b/localedata/tst-setlocale3.c
new file mode 100644
index 0000000..e3b21a9
--- /dev/null
+++ b/localedata/tst-setlocale3.c
@@ -0,0 +1,203 @@
+/* Regression test for setlocale invalid environment variable handling.
+   Copyright (C) 2014 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* The result of setlocale may be overwritten by subsequent calls, so
+   this wrapper makes a copy.  */
+static char *
+setlocale_copy (int category, const char *locale)
+{
+  const char *result = setlocale (category, locale);
+  if (result == NULL)
+    return NULL;
+  return strdup (result);
+}
+
+static char *de_locale;
+
+static void
+setlocale_fail (const char *envstring)
+{
+  setenv ("LC_CTYPE", envstring, 1);
+  if (setlocale (LC_CTYPE, "") != NULL)
+    {
+      printf ("unexpected setlocale success for \"%s\" locale\n", envstring);
+      exit (1);
+    }
+  const char *newloc = setlocale (LC_CTYPE, NULL);
+  if (strcmp (newloc, de_locale) != 0)
+    {
+      printf ("failed setlocale call \"%s\" changed locale to \"%s\"\n",
+	      envstring, newloc);
+      exit (1);
+    }
+}
+
+static void
+setlocale_success (const char *envstring)
+{
+  setenv ("LC_CTYPE", envstring, 1);
+  char *newloc = setlocale_copy (LC_CTYPE, "");
+  if (newloc == NULL)
+    {
+      printf ("setlocale for \"%s\": %m\n", envstring);
+      exit (1);
+    }
+  if (strcmp (newloc, de_locale) == 0)
+    {
+      printf ("setlocale with LC_CTYPE=\"%s\" left locale at \"%s\"\n",
+	      envstring, de_locale);
+      exit (1);
+    }
+  if (setlocale (LC_CTYPE, de_locale) == NULL)
+    {
+      printf ("restoring locale \"%s\" with LC_CTYPE=\"%s\": %m\n",
+	      de_locale, envstring);
+      exit (1);
+    }
+  char *newloc2 = setlocale_copy (LC_CTYPE, newloc);
+  if (newloc2 == NULL)
+    {
+      printf ("restoring locale \"%s\" following \"%s\": %m\n",
+	      newloc, envstring);
+      exit (1);
+    }
+  if (strcmp (newloc, newloc2) != 0)
+    {
+      printf ("representation of locale \"%s\" changed from \"%s\" to \"%s\"",
+	      envstring, newloc, newloc2);
+      exit (1);
+    }
+  free (newloc);
+  free (newloc2);
+
+  if (setlocale (LC_CTYPE, de_locale) == NULL)
+    {
+      printf ("restoring locale \"%s\" with LC_CTYPE=\"%s\": %m\n",
+	      de_locale, envstring);
+      exit (1);
+    }
+}
+
+/* Checks that a known-good locale still works if LC_ALL contains a
+   value which should be ignored.  */
+static void
+setlocale_ignore (const char *to_ignore)
+{
+  const char *fr_locale = "fr_FR.UTF-8";
+  setenv ("LC_CTYPE", fr_locale, 1);
+  char *expected_locale = setlocale_copy (LC_CTYPE, "");
+  if (expected_locale == NULL)
+    {
+      printf ("setlocale with LC_CTYPE=\"%s\" failed: %m\n", fr_locale);
+      exit (1);
+    }
+  if (setlocale (LC_CTYPE, de_locale) == NULL)
+    {
+      printf ("failed to restore locale: %m\n");
+      exit (1);
+    }
+  unsetenv ("LC_CTYPE");
+
+  setenv ("LC_ALL", to_ignore, 1);
+  setenv ("LC_CTYPE", fr_locale, 1);
+  const char *actual_locale = setlocale (LC_CTYPE, "");
+  if (actual_locale == NULL)
+    {
+      printf ("setlocale with LC_ALL, LC_CTYPE=\"%s\" failed: %m\n",
+	      fr_locale);
+      exit (1);
+    }
+  if (strcmp (actual_locale, expected_locale) != 0)
+    {
+      printf ("setlocale under LC_ALL failed: got \"%s\", expected \"%s\"\n",
+	      actual_locale, expected_locale);
+      exit (1);
+    }
+  unsetenv ("LC_CTYPE");
+  setlocale_success (fr_locale);
+  unsetenv ("LC_ALL");
+  free (expected_locale);
+}
+
+static int
+do_test (void)
+{
+  /* The glibc test harness sets this environment variable
+     uncondionally.  */
+  unsetenv ("LC_ALL");
+
+  de_locale = setlocale_copy (LC_CTYPE, "de_DE.UTF-8");
+  if (de_locale == NULL)
+    {
+      printf ("setlocale (LC_CTYPE, \"de_DE.UTF-8\"): %m\n");
+      return 1;
+    }
+  setlocale_success ("C");
+  setlocale_success ("en_US.UTF-8");
+  setlocale_success ("/en_US.UTF-8");
+  setlocale_success ("//en_US.UTF-8");
+  setlocale_ignore ("");
+
+  setlocale_fail ("does-not-exist");
+  setlocale_fail ("/");
+  setlocale_fail ("/../localedata/en_US.UTF-8");
+  setlocale_fail ("en_US.UTF-8/");
+  setlocale_fail ("en_US.UTF-8/..");
+  setlocale_fail ("en_US.UTF-8/../en_US.UTF-8");
+  setlocale_fail ("../localedata/en_US.UTF-8");
+  {
+    size_t large_length = 1024;
+    char *large_name = malloc (large_length + 1);
+    if (large_name == NULL)
+      {
+	puts ("malloc failure");
+	return 1;
+      }
+    memset (large_name, '/', large_length);
+    const char *suffix = "en_US.UTF-8";
+    strcpy (large_name + large_length - strlen (suffix), suffix);
+    setlocale_fail (large_name);
+    free (large_name);
+  }
+  {
+    size_t huge_length = 64 * 1024 * 1024;
+    char *huge_name = malloc (huge_length + 1);
+    if (huge_name == NULL)
+      {
+	puts ("malloc failure");
+	return 1;
+      }
+    memset (huge_name, 'X', huge_length);
+    huge_name[huge_length] = '\0';
+    /* Construct a composite locale specification. */
+    const char *prefix = "LC_CTYPE=de_DE.UTF-8;LC_TIME=";
+    memcpy (huge_name, prefix, strlen (prefix));
+    setlocale_fail (huge_name);
+    free (huge_name);
+  }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=1298cdbed6596663785254f63cb92af265aee8e0

commit 1298cdbed6596663785254f63cb92af265aee8e0
Author: Florian Weimer <fweimer@redhat.com>
Date:   Wed May 28 14:41:52 2014 +0200

    setlocale: Use the heap for the copy of the locale argument
    
    This avoids alloca calls with potentially large arguments.
    
    (cherry picked from commit d183645616b0533b3acee28f1a95570bffbdf50f)

diff --git a/ChangeLog b/ChangeLog
index c0f5bb4..d79506f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2014-07-02  Florian Weimer  <fweimer@redhat.com>
+
+	* locale/setlocale.c (setlocale): Use strdup for allocating
+	composite name copy.
+
 2014-05-26  Siddhesh Poyarekar  <siddhesh@redhat.com>
 
 	[BZ #16878]
diff --git a/locale/setlocale.c b/locale/setlocale.c
index b70fa6c..a4c5983 100644
--- a/locale/setlocale.c
+++ b/locale/setlocale.c
@@ -272,6 +272,8 @@ setlocale (int category, const char *locale)
 	 of entries of the form `CATEGORY=VALUE'.  */
       const char *newnames[__LC_LAST];
       struct __locale_data *newdata[__LC_LAST];
+      /* Copy of the locale argument, for in-place splitting.  */
+      char *locale_copy = NULL;
 
       /* Set all name pointers to the argument name.  */
       for (category = 0; category < __LC_LAST; ++category)
@@ -281,7 +283,13 @@ setlocale (int category, const char *locale)
       if (__builtin_expect (strchr (locale, ';') != NULL, 0))
 	{
 	  /* This is a composite name.  Make a copy and split it up.  */
-	  char *np = strdupa (locale);
+	  locale_copy = strdup (locale);
+	  if (__glibc_unlikely (locale_copy == NULL))
+	    {
+	      __libc_rwlock_unlock (__libc_setlocale_lock);
+	      return NULL;
+	    }
+	  char *np = locale_copy;
 	  char *cp;
 	  int cnt;
 
@@ -299,6 +307,7 @@ setlocale (int category, const char *locale)
 		{
 		error_return:
 		  __libc_rwlock_unlock (__libc_setlocale_lock);
+		  free (locale_copy);
 
 		  /* Bogus category name.  */
 		  ERROR_RETURN;
@@ -391,8 +400,9 @@ setlocale (int category, const char *locale)
       /* Critical section left.  */
       __libc_rwlock_unlock (__libc_setlocale_lock);
 
-      /* Free the resources (the locale path variable).  */
+      /* Free the resources.  */
       free (locale_path);
+      free (locale_copy);
 
       return composite;
     }

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=5754d77ab9899688380da1a52b02f62815b3d34b

commit 5754d77ab9899688380da1a52b02f62815b3d34b
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date:   Mon May 26 11:40:08 2014 +0530

    Use NSS_STATUS_TRYAGAIN to indicate insufficient buffer (BZ #16878)
    
    The netgroups nss modules in the glibc tree use NSS_STATUS_UNAVAIL
    (with errno as ERANGE) when the supplied buffer does not have
    sufficient space for the result.  This is wrong, because the canonical
    way to indicate insufficient buffer is to set the errno to ERANGE and
    the status to NSS_STATUS_TRYAGAIN, as is used by all other modules.
    
    This fixes nscd behaviour when the nss_ldap module returns
    NSS_STATUS_TRYAGAIN to indicate that a netgroup entry is too long to
    fit into the supplied buffer.
    
    (cherry picked from commit c3ec475c5dd16499aa040908e11d382c3ded9692)
    
    Conflicts:
    	NEWS

diff --git a/ChangeLog b/ChangeLog
index 87e0851..c0f5bb4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2014-05-26  Siddhesh Poyarekar  <siddhesh@redhat.com>
+
+	[BZ #16878]
+	* nscd/netgroupcache.c (addgetnetgrentX): Look for
+	NSS_STATUS_TRYAGAIN to indicate insufficient buffer space.
+	* nscd/nss_files/files-netgrp.c (_nss_netgroup_parseline): Use
+	NSS_STATUS_TRYAGAIN to indicate insufficient buffer space.
+
 2014-03-12  Siddhesh Poyarekar  <siddhesh@redhat.com>
 
 	[BZ #16695]
diff --git a/NEWS b/NEWS
index 58fe721..e84bae5 100644
--- a/NEWS
+++ b/NEWS
@@ -9,8 +9,8 @@ Version 2.19.1
 
 * The following bugs are resolved with this release:
 
-  15946, 16545, 16574, 16623, 16695, 16882, 16885, 16916, 16932, 16943,
-  16958, 17048, 17069.
+  15946, 16545, 16574, 16623, 16695, 16878, 16882, 16885, 16916, 16932,
+  16943, 16958, 17048, 17069.
 
 * CVE-2014-4043 The posix_spawn_file_actions_addopen implementation did not
   copy the path argument.  This allowed programs to cause posix_spawn to
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
index fe7fc75..084f74d 100644
--- a/nscd/netgroupcache.c
+++ b/nscd/netgroupcache.c
@@ -203,11 +203,6 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
 		    int e;
 		    status = getfct.f (&data, buffer + buffilled,
 				       buflen - buffilled - req->key_len, &e);
-		    if (status == NSS_STATUS_RETURN
-			|| status == NSS_STATUS_NOTFOUND)
-		      /* This was either the last one for this group or the
-			 group was empty.  Look at next group if available.  */
-		      break;
 		    if (status == NSS_STATUS_SUCCESS)
 		      {
 			if (data.type == triple_val)
@@ -322,11 +317,18 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
 			      }
 			  }
 		      }
-		    else if (status == NSS_STATUS_UNAVAIL && e == ERANGE)
+		    else if (status == NSS_STATUS_TRYAGAIN && e == ERANGE)
 		      {
 			buflen *= 2;
 			buffer = xrealloc (buffer, buflen);
 		      }
+		    else if (status == NSS_STATUS_RETURN
+			     || status == NSS_STATUS_NOTFOUND
+			     || status == NSS_STATUS_UNAVAIL)
+		      /* This was either the last one for this group or the
+			 group was empty or the NSS module had an internal
+			 failure.  Look at next group if available.  */
+		      break;
 		  }
 
 	      enum nss_status (*endfct) (struct __netgrent *);
diff --git a/nss/nss_files/files-netgrp.c b/nss/nss_files/files-netgrp.c
index 34eae4c..bc0b367 100644
--- a/nss/nss_files/files-netgrp.c
+++ b/nss/nss_files/files-netgrp.c
@@ -252,7 +252,7 @@ _nss_netgroup_parseline (char **cursor, struct __netgrent *result,
   if (cp - host > buflen)
     {
       *errnop = ERANGE;
-      status = NSS_STATUS_UNAVAIL;
+      status = NSS_STATUS_TRYAGAIN;
     }
   else
     {

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=b5a823c6c62a05a793aa2d6ff208d1261b46f281

commit b5a823c6c62a05a793aa2d6ff208d1261b46f281
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date:   Wed Mar 12 17:27:22 2014 +0530

    Provide correct buffer length to netgroup queries in nscd (BZ #16695)
    
    The buffer to query netgroup entries is allocated sufficient space for
    the netgroup entries and the key to be appended at the end, but it
    sends in an incorrect available length to the NSS netgroup query
    functions, resulting in overflow of the buffer in some special cases.
    The fix here is to factor in the key length when sending the available
    buffer and buffer length to the query functions.
    
    (cherry picked from commit c44496df2f090a56d3bf75df930592dac6bba46f)
    
    Conflicts:
    	NEWS

diff --git a/ChangeLog b/ChangeLog
index db1d39f..87e0851 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2014-03-12  Siddhesh Poyarekar  <siddhesh@redhat.com>
+
+	[BZ #16695]
+	* nscd/netgroupcache.c (addgetnetgrentX): Factor in space for
+	key in the buffer.
+
 2014-06-20  Maciej W. Rozycki  <macro@codesourcery.com>
 
 	[BZ #16046]
diff --git a/NEWS b/NEWS
index 3f762d1..58fe721 100644
--- a/NEWS
+++ b/NEWS
@@ -9,8 +9,8 @@ Version 2.19.1
 
 * The following bugs are resolved with this release:
 
-  15946, 16545, 16574, 16623, 16882, 16885, 16916, 16932, 16943, 16958,
-  17048, 17069.
+  15946, 16545, 16574, 16623, 16695, 16882, 16885, 16916, 16932, 16943,
+  16958, 17048, 17069.
 
 * CVE-2014-4043 The posix_spawn_file_actions_addopen implementation did not
   copy the path argument.  This allowed programs to cause posix_spawn to
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
index be01fe8..fe7fc75 100644
--- a/nscd/netgroupcache.c
+++ b/nscd/netgroupcache.c
@@ -202,7 +202,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
 		  {
 		    int e;
 		    status = getfct.f (&data, buffer + buffilled,
-				       buflen - buffilled, &e);
+				       buflen - buffilled - req->key_len, &e);
 		    if (status == NSS_STATUS_RETURN
 			|| status == NSS_STATUS_NOTFOUND)
 		      /* This was either the last one for this group or the

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=9c4b0856b5627d443edc924ae972a27078c53112

commit 9c4b0856b5627d443edc924ae972a27078c53112
Author: Maciej W. Rozycki <macro@codesourcery.com>
Date:   Fri Jun 20 21:52:53 2014 +0100

    [BZ #16046] dl_iterate_phdr static executable test
    
    (cherry picked from commit 257ce7127e2f64a6a959b146786cd43de0e42b5f)

diff --git a/ChangeLog b/ChangeLog
index 49ebab5..db1d39f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2014-06-20  Maciej W. Rozycki  <macro@codesourcery.com>
+
+	[BZ #16046]
+	* elf/tst-dl-iter-static.c: New file.
+	* elf/Makefile (tests-static): Add tst-dl-iter-static.
+
 2014-06-20  Andreas Schwab  <schwab@linux-m68k.org>
 
 	[BZ #17069]
diff --git a/elf/Makefile b/elf/Makefile
index 4c58fc9..b9da0b8 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -123,7 +123,7 @@ tests = tst-tls1 tst-tls2 tst-tls9 tst-leaks1 \
 	tst-auxv
 tests-static = tst-tls1-static tst-tls2-static tst-stackguard1-static \
 	       tst-leaks1-static tst-array1-static tst-array5-static \
-	       tst-ptrguard1-static
+	       tst-ptrguard1-static tst-dl-iter-static
 ifeq (yes,$(build-shared))
 tests-static += tst-tls9-static
 tst-tls9-static-ENV = \
diff --git a/elf/tst-dl-iter-static.c b/elf/tst-dl-iter-static.c
new file mode 100644
index 0000000..7303d7c
--- /dev/null
+++ b/elf/tst-dl-iter-static.c
@@ -0,0 +1,47 @@
+/* BZ #16046 dl_iterate_phdr static executable test.
+   Copyright (C) 2014 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <link.h>
+
+/* Check that the link map of the static executable itself is iterated
+   over exactly once.  */
+
+static int
+callback (struct dl_phdr_info *info, size_t size, void *data)
+{
+  int *count = data;
+
+  if (info->dlpi_name[0] == '\0')
+    (*count)++;
+
+  return 0;
+}
+
+static int
+do_test (void)
+{
+  int count = 0;
+  int status;
+
+  status = dl_iterate_phdr (callback, &count);
+
+  return status || count != 1;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=5ec38d177c9089db1bc62546bfaf411c0cabeb6d

commit 5ec38d177c9089db1bc62546bfaf411c0cabeb6d
Author: Andreas Schwab <schwab@linux-m68k.org>
Date:   Fri Jun 20 12:41:27 2014 +0200

    Fix another memory leak in regexp compiler (BZ #17069)
    
    (cherry picked from commit aa6ec754f3b4b1df81d186480c534b6486a1e6ee)
    
    Conflicts:
    	NEWS

diff --git a/ChangeLog b/ChangeLog
index 1a3b62d..49ebab5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2014-06-20  Andreas Schwab  <schwab@linux-m68k.org>
+
+	[BZ #17069]
+	* posix/regcomp.c (parse_reg_exp): Deallocate partially
+	constructed tree before returning error.
+	* posix/bug-regexp36.c: Expand test case.
+
 2014-06-19  Andreas Schwab  <schwab@linux-m68k.org>
 
 	[BZ #17069]
diff --git a/NEWS b/NEWS
index 4eebd67..3f762d1 100644
--- a/NEWS
+++ b/NEWS
@@ -10,7 +10,7 @@ Version 2.19.1
 * The following bugs are resolved with this release:
 
   15946, 16545, 16574, 16623, 16882, 16885, 16916, 16932, 16943, 16958,
-  17048.
+  17048, 17069.
 
 * CVE-2014-4043 The posix_spawn_file_actions_addopen implementation did not
   copy the path argument.  This allowed programs to cause posix_spawn to
diff --git a/posix/bug-regex36.c b/posix/bug-regex36.c
index 3dda026..59e2b6d 100644
--- a/posix/bug-regex36.c
+++ b/posix/bug-regex36.c
@@ -1,4 +1,4 @@
-/* Test regcomp not leaking memory on invalid repetition operator
+/* Test regcomp not leaking memory on parse errors
    Copyright (C) 2014 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -24,6 +24,6 @@ main (int argc, char **argv)
 {
   regex_t r;
   mtrace ();
-  regcomp (&r, "[a]\\{-2,}", 0);
+  regcomp (&r, "[a]\\|[a]\\{-2,}", 0);
   regfree (&r);
 }
diff --git a/posix/regcomp.c b/posix/regcomp.c
index a5020be..076eca3 100644
--- a/posix/regcomp.c
+++ b/posix/regcomp.c
@@ -2154,7 +2154,11 @@ parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token,
 	{
 	  branch = parse_branch (regexp, preg, token, syntax, nest, err);
 	  if (BE (*err != REG_NOERROR && branch == NULL, 0))
-	    return NULL;
+	    {
+	      if (tree != NULL)
+		postorder (tree, free_tree, NULL);
+	      return NULL;
+	    }
 	}
       else
 	branch = NULL;

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=4498c0516d9f16feeca46820ba8ca2e62f916f82

commit 4498c0516d9f16feeca46820ba8ca2e62f916f82
Author: Andreas Schwab <schwab@linux-m68k.org>
Date:   Thu Jun 19 15:38:03 2014 +0200

    Fix memory leak in regexp compiler (BZ #17069)
    
    (cherry picked from commit 4d43ef1e7434d7d419afbcd754931cb0c794763c)
    
    Conflicts:
    	posix/Makefile

diff --git a/ChangeLog b/ChangeLog
index d833701..1a3b62d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2014-06-19  Andreas Schwab  <schwab@linux-m68k.org>
+
+	[BZ #17069]
+	* posix/regcomp.c (parse_expression): Deallocate partially
+	constructed tree before returning error.
+	* posix/Makefile.c (tests): Add bug-regex36.
+	(generated): Add bug-regex36.mtrace.
+	(tests-special): Add $(objpfx)bug-regex36-mem.out
+	(bug-regex36-ENV): New variable.
+	($(objpfx)bug-regex36-mem.out): New rule.
+	* posix/bug-regex36.c: New file.
+
 2014-06-03  Andreas Schwab  <schwab@suse.de>
 
 	[BZ #15946]
diff --git a/posix/Makefile b/posix/Makefile
index 6709900..9dd5fa4 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -86,7 +86,7 @@ tests		:= tstgetopt testfnm runtests runptests	     \
 		   tst-getaddrinfo3 tst-fnmatch2 tst-cpucount tst-cpuset \
 		   bug-getopt1 bug-getopt2 bug-getopt3 bug-getopt4 \
 		   bug-getopt5 tst-getopt_long1 bug-regex34 bug-regex35 \
-		   tst-pathconf tst-getaddrinfo4
+		   tst-pathconf tst-getaddrinfo4 bug-regex36
 xtests		:= bug-ga2
 ifeq (yes,$(build-shared))
 test-srcs	:= globtest
@@ -110,7 +110,7 @@ generated := $(addprefix wordexp-test-result, 1 2 3 4 5 6 7 8 9 10) \
 	     tst-pcre-mem tst-pcre.mtrace tst-boost-mem tst-boost.mtrace \
 	     bug-ga2.mtrace bug-ga2-mem bug-glob2.mtrace bug-glob2-mem \
 	     tst-vfork3-mem tst-vfork3.mtrace getconf.speclist \
-	     tst-fnmatch-mem tst-fnmatch.mtrace
+	     tst-fnmatch-mem tst-fnmatch.mtrace bug-regex36.mtrace
 
 include ../Rules
 
@@ -260,6 +260,12 @@ bug-regex31-ENV = MALLOC_TRACE=$(objpfx)bug-regex31.mtrace
 $(objpfx)bug-regex31-mem: $(objpfx)bug-regex31.out
 	$(common-objpfx)malloc/mtrace $(objpfx)bug-regex31.mtrace > $@
 
+bug-regex36-ENV = MALLOC_TRACE=$(objpfx)bug-regex36.mtrace
+
+$(objpfx)bug-regex36-mem.out: $(objpfx)bug-regex36.out
+	$(common-objpfx)malloc/mtrace $(objpfx)bug-regex36.mtrace > $@; \
+	$(evaluate-test)
+
 tst-vfork3-ENV = MALLOC_TRACE=$(objpfx)tst-vfork3.mtrace
 
 $(objpfx)tst-vfork3-mem: $(objpfx)tst-vfork3.out
diff --git a/posix/bug-regex36.c b/posix/bug-regex36.c
new file mode 100644
index 0000000..3dda026
--- /dev/null
+++ b/posix/bug-regex36.c
@@ -0,0 +1,29 @@
+/* Test regcomp not leaking memory on invalid repetition operator
+   Copyright (C) 2014 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <mcheck.h>
+#include <regex.h>
+
+int
+main (int argc, char **argv)
+{
+  regex_t r;
+  mtrace ();
+  regcomp (&r, "[a]\\{-2,}", 0);
+  regfree (&r);
+}
diff --git a/posix/regcomp.c b/posix/regcomp.c
index 921d0f4..a5020be 100644
--- a/posix/regcomp.c
+++ b/posix/regcomp.c
@@ -2415,14 +2415,21 @@ parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token,
   while (token->type == OP_DUP_ASTERISK || token->type == OP_DUP_PLUS
 	 || token->type == OP_DUP_QUESTION || token->type == OP_OPEN_DUP_NUM)
     {
-      tree = parse_dup_op (tree, regexp, dfa, token, syntax, err);
-      if (BE (*err != REG_NOERROR && tree == NULL, 0))
-	return NULL;
+      bin_tree_t *dup_tree = parse_dup_op (tree, regexp, dfa, token, syntax, err);
+      if (BE (*err != REG_NOERROR && dup_tree == NULL, 0))
+	{
+	  if (tree != NULL)
+	    postorder (tree, free_tree, NULL);
+	  return NULL;
+	}
+      tree = dup_tree;
       /* In BRE consecutive duplications are not allowed.  */
       if ((syntax & RE_CONTEXT_INVALID_DUP)
 	  && (token->type == OP_DUP_ASTERISK
 	      || token->type == OP_OPEN_DUP_NUM))
 	{
+	  if (tree != NULL)
+	    postorder (tree, free_tree, NULL);
 	  *err = REG_BADRPT;
 	  return NULL;
 	}

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=7b17d60f13089585c2b63d46cbc660c4b85d169d

commit 7b17d60f13089585c2b63d46cbc660c4b85d169d
Author: Andreas Schwab <schwab@suse.de>
Date:   Mon May 26 18:01:31 2014 +0200

    Fix invalid file descriptor reuse while sending DNS query (BZ #15946)
    
    (cherry picked from commit f9d2d03254a58d92635a311a42253eeed5a40a47)
    
    Conflicts:
    	NEWS

diff --git a/ChangeLog b/ChangeLog
index 150016c..d833701 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2014-06-03  Andreas Schwab  <schwab@suse.de>
+
+	[BZ #15946]
+	* resolv/res_send.c (send_dg): Reload file descriptor after
+	calling reopen.
+
 2014-02-18  Andreas Schwab  <schwab@suse.de>
 
 	[BZ #16574]
diff --git a/NEWS b/NEWS
index d2b3419..4eebd67 100644
--- a/NEWS
+++ b/NEWS
@@ -9,7 +9,8 @@ Version 2.19.1
 
 * The following bugs are resolved with this release:
 
-  16545, 16574, 16623, 16882, 16885, 16916, 16932, 16943, 16958, 17048.
+  15946, 16545, 16574, 16623, 16882, 16885, 16916, 16932, 16943, 16958,
+  17048.
 
 * CVE-2014-4043 The posix_spawn_file_actions_addopen implementation did not
   copy the path argument.  This allowed programs to cause posix_spawn to
diff --git a/resolv/res_send.c b/resolv/res_send.c
index 704542c..416da87 100644
--- a/resolv/res_send.c
+++ b/resolv/res_send.c
@@ -1410,6 +1410,7 @@ send_dg(res_state statp,
 					retval = reopen (statp, terrno, ns);
 					if (retval <= 0)
 						return retval;
+					pfd[0].fd = EXT(statp).nssocks[ns];
 				}
 			}
 			goto wait;

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=76aebfbb87ecc33e59d29a8adda76dfcdbc9213d

commit 76aebfbb87ecc33e59d29a8adda76dfcdbc9213d
Author: Andreas Schwab <schwab@suse.de>
Date:   Tue Feb 18 10:57:25 2014 +0100

    Properly fix memory leak in _nss_dns_gethostbyname4_r with big DNS answer
    
    Instead of trying to guess whether the second buffer needs to be freed
    set a flag at the place it is allocated
    
    (cherry picked from commit ab09bf616ad527b249aca5f2a4956fd526f0712f)

diff --git a/ChangeLog b/ChangeLog
index 2efb7a2..150016c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,40 @@
+2014-02-18  Andreas Schwab  <schwab@suse.de>
+
+	[BZ #16574]
+	* resolv/res_send.c (send_vc): Add parameter ansp2_malloced.
+	Store non-zero if the second buffer was newly allocated.
+	(send_dg): Likewise.
+	(__libc_res_nsend): Add parameter ansp2_malloced and pass it down
+	to send_vc and send_dg.
+	(res_nsend): Pass NULL for ansp2_malloced.
+	* resolv/res_query.c (__libc_res_nquery): Add parameter
+	answerp2_malloced and pass it down to __libc_res_nsend.
+	(res_nquery): Pass additional NULL to __libc_res_nquery.
+	(__libc_res_nsearch): Add parameter answerp2_malloced and pass it
+	down to __libc_res_nquery and __libc_res_nquerydomain.  Deallocate
+	second answer buffer if answerp2_malloced was set.
+	(res_nsearch): Pass additional NULL to __libc_res_nsearch.
+	(__libc_res_nquerydomain): Add parameter
+	answerp2_malloced and pass it down to __libc_res_nquery.
+	(res_nquerydomain): Pass additional NULL to
+	__libc_res_nquerydomain.
+	* resolv/nss_dns/dns-network.c (_nss_dns_getnetbyname_r): Pass
+	additional NULL to __libc_res_nsend and __libc_res_nquery.
+	* resolv/nss_dns/dns-host.c (_nss_dns_gethostbyname3_r): Pass
+	additional NULL to __libc_res_nsearch.
+	(_nss_dns_gethostbyname4_r): Revert last change.  Use new
+	parameter of __libc_res_nsearch to check for separately allocated
+	second buffer.
+	(_nss_dns_gethostbyaddr2_r): Pass additional NULL to
+	__libc_res_nquery.
+	* resolv/nss_dns/dns-canon.c (_nss_dns_getcanonname_r): Pass
+	additional NULL to __libc_res_nquery.
+	* resolv/gethnamaddr.c (gethostbyname2): Pass additional NULL to
+	__libc_res_nsearch.
+	(gethostbyaddr): Pass additional NULL to __libc_res_nquery.
+	* include/resolv.h: Update prototypes of __libc_res_nquery,
+	__libc_res_nsearch, __libc_res_nsend.
+
 2014-02-13  Andreas Schwab  <schwab@suse.de>
 
 	[BZ #16574]
diff --git a/include/resolv.h b/include/resolv.h
index 87b3598..3904cb7 100644
--- a/include/resolv.h
+++ b/include/resolv.h
@@ -48,11 +48,11 @@ libc_hidden_proto (__res_randomid)
 libc_hidden_proto (__res_state)
 
 int __libc_res_nquery (res_state, const char *, int, int, u_char *, int,
-		       u_char **, u_char **, int *, int *);
+		       u_char **, u_char **, int *, int *, int *);
 int __libc_res_nsearch (res_state, const char *, int, int, u_char *, int,
-			u_char **, u_char **, int *, int *);
+			u_char **, u_char **, int *, int *, int *);
 int __libc_res_nsend (res_state, const u_char *, int, const u_char *, int,
-		      u_char *, int, u_char **, u_char **, int *, int *)
+		      u_char *, int, u_char **, u_char **, int *, int *, int *)
   attribute_hidden;
 
 libresolv_hidden_proto (_sethtent)
diff --git a/resolv/gethnamaddr.c b/resolv/gethnamaddr.c
index 1fd8f92..c73a0dc 100644
--- a/resolv/gethnamaddr.c
+++ b/resolv/gethnamaddr.c
@@ -621,7 +621,7 @@ gethostbyname2(name, af)
 	buf.buf = origbuf = (querybuf *) alloca (1024);
 
 	if ((n = __libc_res_nsearch(&_res, name, C_IN, type, buf.buf->buf, 1024,
-				    &buf.ptr, NULL, NULL, NULL)) < 0) {
+				    &buf.ptr, NULL, NULL, NULL, NULL)) < 0) {
 		if (buf.buf != origbuf)
 			free (buf.buf);
 		Dprintf("res_nsearch failed (%d)\n", n);
@@ -716,12 +716,12 @@ gethostbyaddr(addr, len, af)
 	buf.buf = orig_buf = (querybuf *) alloca (1024);
 
 	n = __libc_res_nquery(&_res, qbuf, C_IN, T_PTR, buf.buf->buf, 1024,
-			      &buf.ptr, NULL, NULL, NULL);
+			      &buf.ptr, NULL, NULL, NULL, NULL);
 	if (n < 0 && af == AF_INET6 && (_res.options & RES_NOIP6DOTINT) == 0) {
 		strcpy(qp, "ip6.int");
 		n = __libc_res_nquery(&_res, qbuf, C_IN, T_PTR, buf.buf->buf,
 				      buf.buf != orig_buf ? MAXPACKET : 1024,
-				      &buf.ptr, NULL, NULL, NULL);
+				      &buf.ptr, NULL, NULL, NULL, NULL);
 	}
 	if (n < 0) {
 		if (buf.buf != orig_buf)
diff --git a/resolv/nss_dns/dns-canon.c b/resolv/nss_dns/dns-canon.c
index a9db232..e8c112c 100644
--- a/resolv/nss_dns/dns-canon.c
+++ b/resolv/nss_dns/dns-canon.c
@@ -62,7 +62,7 @@ _nss_dns_getcanonname_r (const char *name, char *buffer, size_t buflen,
     {
       int r = __libc_res_nquery (&_res, name, ns_c_in, qtypes[i],
 				 buf, sizeof (buf), &ansp.ptr, NULL, NULL,
-				 NULL);
+				 NULL, NULL);
       if (r > 0)
 	{
 	  /* We need to decode the response.  Just one question record.
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
index 71b3b96..f0b4b17 100644
--- a/resolv/nss_dns/dns-host.c
+++ b/resolv/nss_dns/dns-host.c
@@ -190,7 +190,7 @@ _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result,
   host_buffer.buf = orig_host_buffer = (querybuf *) alloca (1024);
 
   n = __libc_res_nsearch (&_res, name, C_IN, type, host_buffer.buf->buf,
-			  1024, &host_buffer.ptr, NULL, NULL, NULL);
+			  1024, &host_buffer.ptr, NULL, NULL, NULL, NULL);
   if (n < 0)
     {
       switch (errno)
@@ -225,7 +225,7 @@ _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result,
 	n = __libc_res_nsearch (&_res, name, C_IN, T_A, host_buffer.buf->buf,
 				host_buffer.buf != orig_host_buffer
 				? MAXPACKET : 1024, &host_buffer.ptr,
-				NULL, NULL, NULL);
+				NULL, NULL, NULL, NULL);
 
       if (n < 0)
 	{
@@ -298,23 +298,23 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
 	name = cp;
     }
 
-  int anslen = 2048;
   union
   {
     querybuf *buf;
     u_char *ptr;
   } host_buffer;
   querybuf *orig_host_buffer;
-  host_buffer.buf = orig_host_buffer = (querybuf *) alloca (anslen);
+  host_buffer.buf = orig_host_buffer = (querybuf *) alloca (2048);
   u_char *ans2p = NULL;
   int nans2p = 0;
   int resplen2 = 0;
+  int ans2p_malloced = 0;
 
   int olderr = errno;
   enum nss_status status;
   int n = __libc_res_nsearch (&_res, name, C_IN, T_UNSPEC,
-			      host_buffer.buf->buf, anslen, &host_buffer.ptr,
-			      &ans2p, &nans2p, &resplen2);
+			      host_buffer.buf->buf, 2048, &host_buffer.ptr,
+			      &ans2p, &nans2p, &resplen2, &ans2p_malloced);
   if (n >= 0)
     {
       status = gaih_getanswer (host_buffer.buf, n, (const querybuf *) ans2p,
@@ -351,10 +351,7 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
     }
 
   /* Check whether ans2p was separately allocated.  */
-  if (host_buffer.buf != orig_host_buffer)
-    anslen = MAXPACKET;
-  if (ans2p != NULL
-      && (ans2p < host_buffer.ptr || ans2p >= host_buffer.ptr + anslen))
+  if (ans2p_malloced)
     free (ans2p);
 
   if (host_buffer.buf != orig_host_buffer)
@@ -465,7 +462,7 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af,
 	  strcpy (qp, "].ip6.arpa");
 	  n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR,
 				 host_buffer.buf->buf, 1024, &host_buffer.ptr,
-				 NULL, NULL, NULL);
+				 NULL, NULL, NULL, NULL);
 	  if (n >= 0)
 	    goto got_it_already;
 	}
@@ -486,14 +483,14 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af,
     }
 
   n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, host_buffer.buf->buf,
-			 1024, &host_buffer.ptr, NULL, NULL, NULL);
+			 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL);
   if (n < 0 && af == AF_INET6 && (_res.options & RES_NOIP6DOTINT) == 0)
     {
       strcpy (qp, "ip6.int");
       n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, host_buffer.buf->buf,
 			     host_buffer.buf != orig_host_buffer
 			     ? MAXPACKET : 1024, &host_buffer.ptr,
-			     NULL, NULL, NULL);
+			     NULL, NULL, NULL, NULL);
     }
   if (n < 0)
     {
diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c
index 8e80a60..13ad38c 100644
--- a/resolv/nss_dns/dns-network.c
+++ b/resolv/nss_dns/dns-network.c
@@ -129,7 +129,7 @@ _nss_dns_getnetbyname_r (const char *name, struct netent *result,
   net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024);
 
   anslen = __libc_res_nsearch (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf,
-			       1024, &net_buffer.ptr, NULL, NULL, NULL);
+			       1024, &net_buffer.ptr, NULL, NULL, NULL, NULL);
   if (anslen < 0)
     {
       /* Nothing found.  */
@@ -205,7 +205,7 @@ _nss_dns_getnetbyaddr_r (uint32_t net, int type, struct netent *result,
   net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024);
 
   anslen = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf,
-			      1024, &net_buffer.ptr, NULL, NULL, NULL);
+			      1024, &net_buffer.ptr, NULL, NULL, NULL, NULL);
   if (anslen < 0)
     {
       /* Nothing found.  */
diff --git a/resolv/res_query.c b/resolv/res_query.c
index 1325f97..c5c3402 100644
--- a/resolv/res_query.c
+++ b/resolv/res_query.c
@@ -98,7 +98,7 @@ static int
 __libc_res_nquerydomain(res_state statp, const char *name, const char *domain,
 			int class, int type, u_char *answer, int anslen,
 			u_char **answerp, u_char **answerp2, int *nanswerp2,
-			int *resplen2);
+			int *resplen2, int *answerp2_malloced);
 
 /*
  * Formulate a normal query, send, and await answer.
@@ -119,7 +119,8 @@ __libc_res_nquery(res_state statp,
 		  u_char **answerp,	/* if buffer needs to be enlarged */
 		  u_char **answerp2,
 		  int *nanswerp2,
-		  int *resplen2)
+		  int *resplen2,
+		  int *answerp2_malloced)
 {
 	HEADER *hp = (HEADER *) answer;
 	HEADER *hp2;
@@ -224,7 +225,8 @@ __libc_res_nquery(res_state statp,
 	}
 	assert (answerp == NULL || (void *) *answerp == (void *) answer);
 	n = __libc_res_nsend(statp, query1, nquery1, query2, nquery2, answer,
-			     anslen, answerp, answerp2, nanswerp2, resplen2);
+			     anslen, answerp, answerp2, nanswerp2, resplen2,
+			     answerp2_malloced);
 	if (use_malloc)
 		free (buf);
 	if (n < 0) {
@@ -316,7 +318,7 @@ res_nquery(res_state statp,
 	   int anslen)		/* size of answer buffer */
 {
 	return __libc_res_nquery(statp, name, class, type, answer, anslen,
-				 NULL, NULL, NULL, NULL);
+				 NULL, NULL, NULL, NULL, NULL);
 }
 libresolv_hidden_def (res_nquery)
 
@@ -335,7 +337,8 @@ __libc_res_nsearch(res_state statp,
 		   u_char **answerp,
 		   u_char **answerp2,
 		   int *nanswerp2,
-		   int *resplen2)
+		   int *resplen2,
+		   int *answerp2_malloced)
 {
 	const char *cp, * const *domain;
 	HEADER *hp = (HEADER *) answer;
@@ -360,7 +363,7 @@ __libc_res_nsearch(res_state statp,
 	if (!dots && (cp = res_hostalias(statp, name, tmp, sizeof tmp))!= NULL)
 		return (__libc_res_nquery(statp, cp, class, type, answer,
 					  anslen, answerp, answerp2,
-					  nanswerp2, resplen2));
+					  nanswerp2, resplen2, answerp2_malloced));
 
 #ifdef DEBUG
 	if (statp->options & RES_DEBUG)
@@ -377,7 +380,8 @@ __libc_res_nsearch(res_state statp,
 	if (dots >= statp->ndots || trailing_dot) {
 		ret = __libc_res_nquerydomain(statp, name, NULL, class, type,
 					      answer, anslen, answerp,
-					      answerp2, nanswerp2, resplen2);
+					      answerp2, nanswerp2, resplen2,
+					      answerp2_malloced);
 		if (ret > 0 || trailing_dot)
 			return (ret);
 		saved_herrno = h_errno;
@@ -386,11 +390,11 @@ __libc_res_nsearch(res_state statp,
 			answer = *answerp;
 			anslen = MAXPACKET;
 		}
-		if (answerp2
-		    && (*answerp2 < answer || *answerp2 >= answer + anslen))
+		if (answerp2 && *answerp2_malloced)
 		  {
 		    free (*answerp2);
 		    *answerp2 = NULL;
+		    *answerp2_malloced = 0;
 		  }
 	}
 
@@ -417,7 +421,7 @@ __libc_res_nsearch(res_state statp,
 						      class, type,
 						      answer, anslen, answerp,
 						      answerp2, nanswerp2,
-						      resplen2);
+						      resplen2, answerp2_malloced);
 			if (ret > 0)
 				return (ret);
 
@@ -425,12 +429,11 @@ __libc_res_nsearch(res_state statp,
 				answer = *answerp;
 				anslen = MAXPACKET;
 			}
-			if (answerp2
-			    && (*answerp2 < answer
-				|| *answerp2 >= answer + anslen))
+			if (answerp2 && *answerp2_malloced)
 			  {
 			    free (*answerp2);
 			    *answerp2 = NULL;
+			    *answerp2_malloced = 0;
 			  }
 
 			/*
@@ -486,7 +489,8 @@ __libc_res_nsearch(res_state statp,
 	    && !(tried_as_is || root_on_list)) {
 		ret = __libc_res_nquerydomain(statp, name, NULL, class, type,
 					      answer, anslen, answerp,
-					      answerp2, nanswerp2, resplen2);
+					      answerp2, nanswerp2, resplen2,
+					      answerp2_malloced);
 		if (ret > 0)
 			return (ret);
 	}
@@ -498,10 +502,11 @@ __libc_res_nsearch(res_state statp,
 	 * else send back meaningless H_ERRNO, that being the one from
 	 * the last DNSRCH we did.
 	 */
-	if (answerp2 && (*answerp2 < answer || *answerp2 >= answer + anslen))
+	if (answerp2 && *answerp2_malloced)
 	  {
 	    free (*answerp2);
 	    *answerp2 = NULL;
+	    *answerp2_malloced = 0;
 	  }
 	if (saved_herrno != -1)
 		RES_SET_H_ERRNO(statp, saved_herrno);
@@ -521,7 +526,7 @@ res_nsearch(res_state statp,
 	    int anslen)		/* size of answer */
 {
 	return __libc_res_nsearch(statp, name, class, type, answer,
-				  anslen, NULL, NULL, NULL, NULL);
+				  anslen, NULL, NULL, NULL, NULL, NULL);
 }
 libresolv_hidden_def (res_nsearch)
 
@@ -539,7 +544,8 @@ __libc_res_nquerydomain(res_state statp,
 			u_char **answerp,
 			u_char **answerp2,
 			int *nanswerp2,
-			int *resplen2)
+			int *resplen2,
+			int *answerp2_malloced)
 {
 	char nbuf[MAXDNAME];
 	const char *longname = nbuf;
@@ -581,7 +587,7 @@ __libc_res_nquerydomain(res_state statp,
 	}
 	return (__libc_res_nquery(statp, longname, class, type, answer,
 				  anslen, answerp, answerp2, nanswerp2,
-				  resplen2));
+				  resplen2, answerp2_malloced));
 }
 
 int
@@ -593,7 +599,8 @@ res_nquerydomain(res_state statp,
 	    int anslen)		/* size of answer */
 {
 	return __libc_res_nquerydomain(statp, name, domain, class, type,
-				       answer, anslen, NULL, NULL, NULL, NULL);
+				       answer, anslen, NULL, NULL, NULL, NULL,
+				       NULL);
 }
 libresolv_hidden_def (res_nquerydomain)
 
diff --git a/resolv/res_send.c b/resolv/res_send.c
index 7f2e85f..704542c 100644
--- a/resolv/res_send.c
+++ b/resolv/res_send.c
@@ -186,12 +186,12 @@ evNowTime(struct timespec *res) {
 static int		send_vc(res_state, const u_char *, int,
 				const u_char *, int,
 				u_char **, int *, int *, int, u_char **,
-				u_char **, int *, int *);
+				u_char **, int *, int *, int *);
 static int		send_dg(res_state, const u_char *, int,
 				const u_char *, int,
 				u_char **, int *, int *, int,
 				int *, int *, u_char **,
-				u_char **, int *, int *);
+				u_char **, int *, int *, int *);
 #ifdef DEBUG
 static void		Aerror(const res_state, FILE *, const char *, int,
 			       const struct sockaddr *);
@@ -343,7 +343,7 @@ int
 __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
 		 const u_char *buf2, int buflen2,
 		 u_char *ans, int anssiz, u_char **ansp, u_char **ansp2,
-		 int *nansp2, int *resplen2)
+		 int *nansp2, int *resplen2, int *ansp2_malloced)
 {
   int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
 
@@ -546,7 +546,8 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
 			try = statp->retry;
 			n = send_vc(statp, buf, buflen, buf2, buflen2,
 				    &ans, &anssiz, &terrno,
-				    ns, ansp, ansp2, nansp2, resplen2);
+				    ns, ansp, ansp2, nansp2, resplen2,
+				    ansp2_malloced);
 			if (n < 0)
 				return (-1);
 			if (n == 0 && (buf2 == NULL || *resplen2 == 0))
@@ -556,7 +557,7 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
 			n = send_dg(statp, buf, buflen, buf2, buflen2,
 				    &ans, &anssiz, &terrno,
 				    ns, &v_circuit, &gotsomewhere, ansp,
-				    ansp2, nansp2, resplen2);
+				    ansp2, nansp2, resplen2, ansp2_malloced);
 			if (n < 0)
 				return (-1);
 			if (n == 0 && (buf2 == NULL || *resplen2 == 0))
@@ -646,7 +647,7 @@ res_nsend(res_state statp,
 	  const u_char *buf, int buflen, u_char *ans, int anssiz)
 {
   return __libc_res_nsend(statp, buf, buflen, NULL, 0, ans, anssiz,
-			  NULL, NULL, NULL, NULL);
+			  NULL, NULL, NULL, NULL, NULL);
 }
 libresolv_hidden_def (res_nsend)
 
@@ -657,7 +658,7 @@ send_vc(res_state statp,
 	const u_char *buf, int buflen, const u_char *buf2, int buflen2,
 	u_char **ansp, int *anssizp,
 	int *terrno, int ns, u_char **anscp, u_char **ansp2, int *anssizp2,
-	int *resplen2)
+	int *resplen2, int *ansp2_malloced)
 {
 	const HEADER *hp = (HEADER *) buf;
 	const HEADER *hp2 = (HEADER *) buf2;
@@ -823,6 +824,8 @@ send_vc(res_state statp,
 			}
 			*thisanssizp = MAXPACKET;
 			*thisansp = newp;
+			if (thisansp == ansp2)
+			  *ansp2_malloced = 1;
 			anhp = (HEADER *) newp;
 			len = rlen;
 		} else {
@@ -992,7 +995,7 @@ send_dg(res_state statp,
 	const u_char *buf, int buflen, const u_char *buf2, int buflen2,
 	u_char **ansp, int *anssizp,
 	int *terrno, int ns, int *v_circuit, int *gotsomewhere, u_char **anscp,
-	u_char **ansp2, int *anssizp2, int *resplen2)
+	u_char **ansp2, int *anssizp2, int *resplen2, int *ansp2_malloced)
 {
 	const HEADER *hp = (HEADER *) buf;
 	const HEADER *hp2 = (HEADER *) buf2;
@@ -1238,6 +1241,8 @@ send_dg(res_state statp,
 			if (newp != NULL) {
 				*anssizp = MAXPACKET;
 				*thisansp = ans = newp;
+				if (thisansp == ansp2)
+				  *ansp2_malloced = 1;
 			}
 		}
 		HEADER *anhp = (HEADER *) *thisansp;

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=c6ce0dadcfd14973ba880f4e043058a9367f00ce

commit c6ce0dadcfd14973ba880f4e043058a9367f00ce
Author: OndÅ?ej Bílka <neleai@seznam.cz>
Date:   Sun Feb 16 12:59:23 2014 +0100

    Deduplicate resolv/nss_dns/dns-host.c
    
    In resolv/nss_dns/dns-host.c one of code path duplicated code after
    that. We merge these paths.
    
    (cherry picked from commit ab7ac0f2cf8731fe4c3f3aea6088a7c0127b5725)

diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
index f56dd35..71b3b96 100644
--- a/resolv/nss_dns/dns-host.c
+++ b/resolv/nss_dns/dns-host.c
@@ -315,7 +315,13 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
   int n = __libc_res_nsearch (&_res, name, C_IN, T_UNSPEC,
 			      host_buffer.buf->buf, anslen, &host_buffer.ptr,
 			      &ans2p, &nans2p, &resplen2);
-  if (n < 0)
+  if (n >= 0)
+    {
+      status = gaih_getanswer (host_buffer.buf, n, (const querybuf *) ans2p,
+			       resplen2, name, pat, buffer, buflen,
+			       errnop, herrnop, ttlp);
+    }
+  else
     {
       switch (errno)
 	{
@@ -342,17 +348,8 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
 	*errnop = EAGAIN;
       else
 	__set_errno (olderr);
-
-      if (host_buffer.buf != orig_host_buffer)
-	free (host_buffer.buf);
-
-      return status;
     }
 
-  status = gaih_getanswer(host_buffer.buf, n, (const querybuf *) ans2p,
-			  resplen2, name, pat, buffer, buflen,
-			  errnop, herrnop, ttlp);
-
   /* Check whether ans2p was separately allocated.  */
   if (host_buffer.buf != orig_host_buffer)
     anslen = MAXPACKET;

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=4ad0ab7bdb6c4afb3fc561c6497759eb939d2a73

commit 4ad0ab7bdb6c4afb3fc561c6497759eb939d2a73
Author: Andreas Schwab <schwab@suse.de>
Date:   Thu Feb 13 11:01:57 2014 +0100

    Fix memory leak in _nss_dns_gethostbyname4_r with big DNS answer
    
    (cherry picked from commit d668061994a7486a3ba9c7d5e7882d85a2883707)
    
    Conflicts:
    	NEWS

diff --git a/ChangeLog b/ChangeLog
index 60db892..2efb7a2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2014-02-13  Andreas Schwab  <schwab@suse.de>
+
+	[BZ #16574]
+	* resolv/nss_dns/dns-host.c (_nss_dns_gethostbyname4_r): Free the
+	second answer buffer if it was separately allocated.
+
 2014-05-12  Andreas Schwab  <schwab@suse.de>
 
 	[BZ #16932]
diff --git a/NEWS b/NEWS
index d10a3aa..d2b3419 100644
--- a/NEWS
+++ b/NEWS
@@ -9,7 +9,7 @@ Version 2.19.1
 
 * The following bugs are resolved with this release:
 
-  16545, 16623, 16882, 16885, 16916, 16932, 16943, 16958, 17048.
+  16545, 16574, 16623, 16882, 16885, 16916, 16932, 16943, 16958, 17048.
 
 * CVE-2014-4043 The posix_spawn_file_actions_addopen implementation did not
   copy the path argument.  This allowed programs to cause posix_spawn to
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
index f8f192e..f56dd35 100644
--- a/resolv/nss_dns/dns-host.c
+++ b/resolv/nss_dns/dns-host.c
@@ -298,13 +298,14 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
 	name = cp;
     }
 
+  int anslen = 2048;
   union
   {
     querybuf *buf;
     u_char *ptr;
   } host_buffer;
   querybuf *orig_host_buffer;
-  host_buffer.buf = orig_host_buffer = (querybuf *) alloca (2048);
+  host_buffer.buf = orig_host_buffer = (querybuf *) alloca (anslen);
   u_char *ans2p = NULL;
   int nans2p = 0;
   int resplen2 = 0;
@@ -312,7 +313,7 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
   int olderr = errno;
   enum nss_status status;
   int n = __libc_res_nsearch (&_res, name, C_IN, T_UNSPEC,
-			      host_buffer.buf->buf, 2048, &host_buffer.ptr,
+			      host_buffer.buf->buf, anslen, &host_buffer.ptr,
 			      &ans2p, &nans2p, &resplen2);
   if (n < 0)
     {
@@ -352,6 +353,13 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
 			  resplen2, name, pat, buffer, buflen,
 			  errnop, herrnop, ttlp);
 
+  /* Check whether ans2p was separately allocated.  */
+  if (host_buffer.buf != orig_host_buffer)
+    anslen = MAXPACKET;
+  if (ans2p != NULL
+      && (ans2p < host_buffer.ptr || ans2p >= host_buffer.ptr + anslen))
+    free (ans2p);
+
   if (host_buffer.buf != orig_host_buffer)
     free (host_buffer.buf);
 

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=00a84253c5bc7dffb7a0a666cea21ea5e0288771

commit 00a84253c5bc7dffb7a0a666cea21ea5e0288771
Author: Andreas Schwab <schwab@suse.de>
Date:   Thu May 8 16:53:01 2014 +0200

    Fix unbound stack use in NIS NSS module
    
    (cherry picked from commit 315eb1d86aea489cd6325fd1c2521dcfb4fc0e1c)
    
    Conflicts:
    	NEWS

diff --git a/ChangeLog b/ChangeLog
index ef754cf..60db892 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2014-05-12  Andreas Schwab  <schwab@suse.de>
+
+	[BZ #16932]
+	* nis/nss_nis/nis-hosts.c (internal_gethostbyname2_r)
+	(_nss_nis_gethostbyname4_r): Return error if item length is larger
+	than maximum RPC packet size.
+	* nis/nss_nis/nis-initgroups.c (initgroups_netid): Likewise.
+	* nis/nss_nis/nis-network.c (_nss_nis_getnetbyname_r): Likewise.
+	* nis/nss_nis/nis-service.c (_nss_nis_getservbyname_r)
+	(_nss_nis_getservbyport_r): Likewise.
+
 2014-06-21  Allan McRae  <allan@archlinux.org>
 
 	* NEWS: Mention CVE-2014-4043.
diff --git a/NEWS b/NEWS
index 4a51ac6..d10a3aa 100644
--- a/NEWS
+++ b/NEWS
@@ -9,7 +9,7 @@ Version 2.19.1
 
 * The following bugs are resolved with this release:
 
-  16545, 16623, 16882, 16885, 16916, 16943, 16958, 17048.
+  16545, 16623, 16882, 16885, 16916, 16932, 16943, 16958, 17048.
 
 * CVE-2014-4043 The posix_spawn_file_actions_addopen implementation did not
   copy the path argument.  This allowed programs to cause posix_spawn to
diff --git a/nis/nss_nis/nis-hosts.c b/nis/nss_nis/nis-hosts.c
index f73a0ec..3006a99 100644
--- a/nis/nss_nis/nis-hosts.c
+++ b/nis/nss_nis/nis-hosts.c
@@ -270,6 +270,13 @@ internal_gethostbyname2_r (const char *name, int af, struct hostent *host,
 
   /* Convert name to lowercase.  */
   size_t namlen = strlen (name);
+  /* Limit name length to the maximum size of an RPC packet.  */
+  if (namlen > UDPMSGSIZE)
+    {
+      *errnop = ERANGE;
+      return NSS_STATUS_UNAVAIL;
+    }
+
   char name2[namlen + 1];
   size_t i;
 
@@ -461,6 +468,13 @@ _nss_nis_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
 
   /* Convert name to lowercase.  */
   size_t namlen = strlen (name);
+  /* Limit name length to the maximum size of an RPC packet.  */
+  if (namlen > UDPMSGSIZE)
+    {
+      *errnop = ERANGE;
+      return NSS_STATUS_UNAVAIL;
+    }
+
   char name2[namlen + 1];
   size_t i;
 
diff --git a/nis/nss_nis/nis-initgroups.c b/nis/nss_nis/nis-initgroups.c
index 30bc90f..dd8c765 100644
--- a/nis/nss_nis/nis-initgroups.c
+++ b/nis/nss_nis/nis-initgroups.c
@@ -150,6 +150,13 @@ initgroups_netid (uid_t uid, gid_t group, long int *start, long int *size,
 		  gid_t **groupsp, long int limit, int *errnop,
 		  const char *domainname)
 {
+  /* Limit domainname length to the maximum size of an RPC packet.  */
+  if (strlen (domainname) > UDPMSGSIZE)
+    {
+      *errnop = ERANGE;
+      return NSS_STATUS_UNAVAIL;
+    }
+
   /* Prepare the key.  The form is "unix.UID@DOMAIN" with the UID and
      DOMAIN field filled in appropriately.  */
   char key[sizeof ("unix.@") + sizeof (uid_t) * 3 + strlen (domainname)];
diff --git a/nis/nss_nis/nis-network.c b/nis/nss_nis/nis-network.c
index da28860..6a82302 100644
--- a/nis/nss_nis/nis-network.c
+++ b/nis/nss_nis/nis-network.c
@@ -179,6 +179,13 @@ _nss_nis_getnetbyname_r (const char *name, struct netent *net, char *buffer,
 
   /* Convert name to lowercase.  */
   size_t namlen = strlen (name);
+  /* Limit name length to the maximum size of an RPC packet.  */
+  if (namlen > UDPMSGSIZE)
+    {
+      *errnop = ERANGE;
+      return NSS_STATUS_UNAVAIL;
+    }
+
   char name2[namlen + 1];
   size_t i;
 
diff --git a/nis/nss_nis/nis-service.c b/nis/nss_nis/nis-service.c
index fd79d3f..4991ed3 100644
--- a/nis/nss_nis/nis-service.c
+++ b/nis/nss_nis/nis-service.c
@@ -271,6 +271,13 @@ _nss_nis_getservbyname_r (const char *name, const char *protocol,
   /* If the protocol is given, we could try if our NIS server knows
      about services.byservicename map. If yes, we only need one query.  */
   size_t keylen = strlen (name) + (protocol ? 1 + strlen (protocol) : 0);
+  /* Limit key length to the maximum size of an RPC packet.  */
+  if (keylen > UDPMSGSIZE)
+    {
+      *errnop = ERANGE;
+      return NSS_STATUS_UNAVAIL;
+    }
+
   char key[keylen + 1];
 
   /* key is: "name/proto" */
@@ -355,6 +362,13 @@ _nss_nis_getservbyport_r (int port, const char *protocol,
      Otherwise try first port/tcp, then port/udp and then fallback
      to sequential scanning of services.byname.  */
   const char *proto = protocol != NULL ? protocol : "tcp";
+  /* Limit protocol name length to the maximum size of an RPC packet.  */
+  if (strlen (proto) > UDPMSGSIZE)
+    {
+      *errnop = ERANGE;
+      return NSS_STATUS_UNAVAIL;
+    }
+
   do
     {
       /* key is: "port/proto" */

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=30026b69015db3f82407df83dc1118518ee1fa5c

commit 30026b69015db3f82407df83dc1118518ee1fa5c
Author: Allan McRae <allan@archlinux.org>
Date:   Sat Jun 21 17:23:55 2014 +1000

    Mention CVE-2014-4043 in NEWS
    
    (cherry picked from commit d03efb2f979defd473955a455d66b949961d26b2)
    
    Conflicts:
    	NEWS

diff --git a/ChangeLog b/ChangeLog
index 1c9518c..ef754cf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2014-06-21  Allan McRae  <allan@archlinux.org>
+
+	* NEWS: Mention CVE-2014-4043.
+
 2014-06-11  Florian Weimer  <fweimer@redhat.com>
 
 	[BZ #17048]
diff --git a/NEWS b/NEWS
index 9539294..4a51ac6 100644
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,12 @@ Version 2.19.1
 * The following bugs are resolved with this release:
 
   16545, 16623, 16882, 16885, 16916, 16943, 16958, 17048.
+
+* CVE-2014-4043 The posix_spawn_file_actions_addopen implementation did not
+  copy the path argument.  This allowed programs to cause posix_spawn to
+  deference a dangling pointer, or use an unexpected pathname argument if
+  the string was modified after the posix_spawn_file_actions_addopen
+  invocation.
 
 Version 2.19
 

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=e698ea2c03ddfdfa87459c1a0e53e2a4289de0fa

commit e698ea2c03ddfdfa87459c1a0e53e2a4289de0fa
Author: Florian Weimer <fweimer@redhat.com>
Date:   Wed Jun 11 23:12:52 2014 +0200

    posix_spawn_file_actions_addopen needs to copy the path argument (BZ 17048)
    
    POSIX requires that we make a copy, so we allocate a new string
    and free it in posix_spawn_file_actions_destroy.
    
    Reported by David Reid, Alex Gaynor, and Glyph Lefkowitz.  This bug
    may have security implications.
    
    (cherry picked from commit 89e435f3559c53084498e9baad22172b64429362)
    
    Conflicts:
    	NEWS

diff --git a/ChangeLog b/ChangeLog
index 7fa7e06..1c9518c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2014-06-11  Florian Weimer  <fweimer@redhat.com>
+
+	[BZ #17048]
+	* posix/spawn_int.h (struct __spawn_action): Make the path string
+	non-const to support deallocation.
+	* posix/spawn_faction_addopen.c
+	(posix_spawn_file_actions_addopen): Make a copy of the pathname.
+	* posix/spawn_faction_destroy.c
+	(posix_spawn_file_actions_destroy): Adjust comment.  Deallocate
+	path in all spawn_do_open actions.
+	* posix/tst-spawn.c (do_test): Exercise the copy operation in
+	posix_spawn_file_actions_addopen.
+
 2014-06-03  Guo Yixuan  <culu.gyx@gmail.com>
 
 	[BZ #16882]
diff --git a/NEWS b/NEWS
index 64b2b11..9539294 100644
--- a/NEWS
+++ b/NEWS
@@ -9,8 +9,7 @@ Version 2.19.1
 
 * The following bugs are resolved with this release:
 
-  16545, 16623, 16882, 16885, 16916, 16943, 16958.
-
+  16545, 16623, 16882, 16885, 16916, 16943, 16958, 17048.
 
 Version 2.19
 
diff --git a/posix/spawn_faction_addopen.c b/posix/spawn_faction_addopen.c
index 47f6242..40800b8 100644
--- a/posix/spawn_faction_addopen.c
+++ b/posix/spawn_faction_addopen.c
@@ -35,17 +35,24 @@ posix_spawn_file_actions_addopen (posix_spawn_file_actions_t *file_actions,
   if (fd < 0 || fd >= maxfd)
     return EBADF;
 
+  char *path_copy = strdup (path);
+  if (path_copy == NULL)
+    return ENOMEM;
+
   /* Allocate more memory if needed.  */
   if (file_actions->__used == file_actions->__allocated
       && __posix_spawn_file_actions_realloc (file_actions) != 0)
-    /* This can only mean we ran out of memory.  */
-    return ENOMEM;
+    {
+      /* This can only mean we ran out of memory.  */
+      free (path_copy);
+      return ENOMEM;
+    }
 
   /* Add the new value.  */
   rec = &file_actions->__actions[file_actions->__used];
   rec->tag = spawn_do_open;
   rec->action.open_action.fd = fd;
-  rec->action.open_action.path = path;
+  rec->action.open_action.path = path_copy;
   rec->action.open_action.oflag = oflag;
   rec->action.open_action.mode = mode;
 
diff --git a/posix/spawn_faction_destroy.c b/posix/spawn_faction_destroy.c
index 4d165aa..1b87010 100644
--- a/posix/spawn_faction_destroy.c
+++ b/posix/spawn_faction_destroy.c
@@ -18,11 +18,29 @@
 #include <spawn.h>
 #include <stdlib.h>
 
-/* Initialize data structure for file attribute for `spawn' call.  */
+#include "spawn_int.h"
+
+/* Deallocate the file actions.  */
 int
 posix_spawn_file_actions_destroy (posix_spawn_file_actions_t *file_actions)
 {
-  /* Free the memory allocated.  */
+  /* Free the paths in the open actions.  */
+  for (int i = 0; i < file_actions->__used; ++i)
+    {
+      struct __spawn_action *sa = &file_actions->__actions[i];
+      switch (sa->tag)
+	{
+	case spawn_do_open:
+	  free (sa->action.open_action.path);
+	  break;
+	case spawn_do_close:
+	case spawn_do_dup2:
+	  /* No cleanup required.  */
+	  break;
+	}
+    }
+
+  /* Free the array of actions.  */
   free (file_actions->__actions);
   return 0;
 }
diff --git a/posix/spawn_int.h b/posix/spawn_int.h
index 5609e58..861e3b4 100644
--- a/posix/spawn_int.h
+++ b/posix/spawn_int.h
@@ -22,7 +22,7 @@ struct __spawn_action
     struct
     {
       int fd;
-      const char *path;
+      char *path;
       int oflag;
       mode_t mode;
     } open_action;
diff --git a/posix/tst-spawn.c b/posix/tst-spawn.c
index 84cecf2..6cd874a 100644
--- a/posix/tst-spawn.c
+++ b/posix/tst-spawn.c
@@ -168,6 +168,7 @@ do_test (int argc, char *argv[])
   char fd2name[18];
   char fd3name[18];
   char fd4name[18];
+  char *name3_copy;
   char *spargv[12];
   int i;
 
@@ -222,9 +223,15 @@ do_test (int argc, char *argv[])
    if (posix_spawn_file_actions_addclose (&actions, fd1) != 0)
      error (EXIT_FAILURE, errno, "posix_spawn_file_actions_addclose");
    /* We want to open the third file.  */
-   if (posix_spawn_file_actions_addopen (&actions, fd3, name3,
+   name3_copy = strdup (name3);
+   if (name3_copy == NULL)
+     error (EXIT_FAILURE, errno, "strdup");
+   if (posix_spawn_file_actions_addopen (&actions, fd3, name3_copy,
 					 O_RDONLY, 0666) != 0)
      error (EXIT_FAILURE, errno, "posix_spawn_file_actions_addopen");
+   /* Overwrite the name to check that a copy has been made.  */
+   memset (name3_copy, 'X', strlen (name3_copy));
+
    /* We dup the second descriptor.  */
    fd4 = MAX (2, MAX (fd1, MAX (fd2, fd3))) + 1;
    if (posix_spawn_file_actions_adddup2 (&actions, fd2, fd4) != 0)
@@ -253,6 +260,7 @@ do_test (int argc, char *argv[])
    /* Cleanup.  */
    if (posix_spawn_file_actions_destroy (&actions) != 0)
      error (EXIT_FAILURE, errno, "posix_spawn_file_actions_destroy");
+   free (name3_copy);
 
   /* Wait for the child.  */
   if (waitpid (pid, &status, 0) != pid)

-----------------------------------------------------------------------


hooks/post-receive
-- 
GNU C Library master sources


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]