mirror of
https://github.com/vincentmli/bpfire.git
synced 2026-04-20 07:53:01 +02:00
glibc: Backport hotfixes from RHEL
This commit is contained in:
13
lfs/glibc
13
lfs/glibc
@@ -268,12 +268,21 @@ endif
|
||||
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh966775.patch
|
||||
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh966778.patch
|
||||
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh970090.patch
|
||||
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh995972.patch
|
||||
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1008310.patch
|
||||
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1019916.patch
|
||||
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1022022.patch
|
||||
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1091162.patch
|
||||
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1098050.patch
|
||||
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1027101.patch
|
||||
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1027261.patch
|
||||
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1032628.patch
|
||||
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1044628.patch
|
||||
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1111460.patch
|
||||
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1133809-1.patch
|
||||
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1133809-2.patch
|
||||
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1139571.patch
|
||||
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1154563.patch
|
||||
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1170121.patch
|
||||
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1183533.patch
|
||||
|
||||
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc-resolv-stack_chk_fail.patch
|
||||
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc-remove-ctors-dtors-output-sections.patch
|
||||
|
||||
39
src/patches/glibc/glibc-rh1019916.patch
Normal file
39
src/patches/glibc/glibc-rh1019916.patch
Normal file
@@ -0,0 +1,39 @@
|
||||
commit 48b67d71ec677d1b3168e52a68b644784cead604
|
||||
Author: Andreas Schwab <schwab@redhat.com>
|
||||
Date: Wed Sep 14 12:12:25 2011 +0200
|
||||
|
||||
Also relocate in dependency order when doing symbol dependency testing
|
||||
|
||||
diff --git a/elf/rtld.c b/elf/rtld.c
|
||||
index 764140d..324d979 100644
|
||||
--- a/elf/rtld.c
|
||||
+++ b/elf/rtld.c
|
||||
@@ -2027,24 +2027,21 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||||
{
|
||||
/* We have to do symbol dependency testing. */
|
||||
struct relocate_args args;
|
||||
- struct link_map *l;
|
||||
+ unsigned int i;
|
||||
|
||||
args.reloc_mode = GLRO(dl_lazy) ? RTLD_LAZY : 0;
|
||||
|
||||
- l = main_map;
|
||||
- while (l->l_next != NULL)
|
||||
- l = l->l_next;
|
||||
- do
|
||||
+ i = main_map->l_searchlist.r_nlist;
|
||||
+ while (i-- > 0)
|
||||
{
|
||||
+ struct link_map *l = main_map->l_initfini[i];
|
||||
if (l != &GL(dl_rtld_map) && ! l->l_faked)
|
||||
{
|
||||
args.l = l;
|
||||
_dl_receive_error (print_unresolved, relocate_doit,
|
||||
&args);
|
||||
}
|
||||
- l = l->l_prev;
|
||||
}
|
||||
- while (l != NULL);
|
||||
|
||||
if ((GLRO(dl_debug_mask) & DL_DEBUG_PRELINK)
|
||||
&& rtld_multiple_ref)
|
||||
28
src/patches/glibc/glibc-rh1027261.patch
Normal file
28
src/patches/glibc/glibc-rh1027261.patch
Normal file
@@ -0,0 +1,28 @@
|
||||
commit 4d653a59ffeae0f46f76a40230e2cfa9587b7e7e
|
||||
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
|
||||
Date: Fri May 30 22:43:52 2014 +0530
|
||||
|
||||
Add mmap usage in malloc_info output
|
||||
|
||||
The current malloc_info xml output only has information about
|
||||
allocations on the heap. Display information about number of mappings
|
||||
and total mmapped size to this to complete the picture.
|
||||
|
||||
diff -pruN a/malloc/malloc.c b/malloc/malloc.c
|
||||
--- a/malloc/malloc.c 2014-06-02 07:35:22.573256155 +0530
|
||||
+++ b/malloc/malloc.c 2014-06-02 07:34:58.856257177 +0530
|
||||
@@ -6553,12 +6553,14 @@ malloc_info (int options, FILE *fp)
|
||||
fprintf (fp,
|
||||
"<total type=\"fast\" count=\"%zu\" size=\"%zu\"/>\n"
|
||||
"<total type=\"rest\" count=\"%zu\" size=\"%zu\"/>\n"
|
||||
+ "<total type=\"mmap\" count=\"%d\" size=\"%zu\"/>\n"
|
||||
"<system type=\"current\" size=\"%zu\"/>\n"
|
||||
"<system type=\"max\" size=\"%zu\"/>\n"
|
||||
"<aspace type=\"total\" size=\"%zu\"/>\n"
|
||||
"<aspace type=\"mprotect\" size=\"%zu\"/>\n"
|
||||
"</malloc>\n",
|
||||
total_nfastblocks, total_fastavail, total_nblocks, total_avail,
|
||||
+ mp_.n_mmaps, mp_.mmapped_mem,
|
||||
total_system, total_max_system,
|
||||
total_aspace, total_aspace_mprotect);
|
||||
|
||||
166
src/patches/glibc/glibc-rh1032628.patch
Normal file
166
src/patches/glibc/glibc-rh1032628.patch
Normal file
@@ -0,0 +1,166 @@
|
||||
commit 028478fa40d85a73b19638dbe3f83b1acebf370c
|
||||
Author: Ulrich Drepper <drepper@gmail.com>
|
||||
Date: Thu Mar 10 12:51:33 2011 -0500
|
||||
|
||||
Fix copy relocations handling of unique objects.
|
||||
|
||||
2011-03-06 Ulrich Drepper <drepper@gmail.com>
|
||||
|
||||
and a part of:
|
||||
|
||||
commit 33f85a3fb9fe432e0ebf6a3481bc2d5e29cb605f
|
||||
Author: Ulrich Drepper <drepper@gmail.com>
|
||||
Date: Thu Mar 10 03:18:21 2011 -0500
|
||||
|
||||
Don't run tests checking xecutable stack when SELinux is enforcing.
|
||||
|
||||
since the latter incorrectly had a bit of the former changes.
|
||||
|
||||
Additionally, the test case needs -lstdc++ to build.
|
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile
|
||||
index c427679..56cb1b1 100644
|
||||
--- a/elf/Makefile
|
||||
+++ b/elf/Makefile
|
||||
@@ -201,7 +201,7 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
|
||||
unload3 unload4 unload5 unload6 unload7 unload8 tst-global1 order2 \
|
||||
tst-audit1 tst-audit2 tst-audit9 \
|
||||
tst-stackguard1 tst-addr1 tst-thrlock \
|
||||
- tst-unique1 tst-unique2
|
||||
+ tst-unique1 tst-unique2 tst-unique3
|
||||
# reldep9
|
||||
test-srcs = tst-pathopt
|
||||
tests-execstack-yes = tst-execstack tst-execstack-needed tst-execstack-prog
|
||||
@@ -255,6 +255,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
||||
order2mod1 order2mod2 order2mod3 order2mod4 \
|
||||
tst-unique1mod1 tst-unique1mod2 \
|
||||
tst-unique2mod1 tst-unique2mod2 \
|
||||
+ tst-unique3lib tst-unique3lib2 \
|
||||
tst-auditmod9a tst-auditmod9b
|
||||
ifeq (yes,$(have-initfini-array))
|
||||
modules-names += tst-array2dep tst-array5dep
|
||||
@@ -1178,6 +1179,11 @@ $(objpfx)tst-unique1.out: $(objpfx)tst-unique1mod1.so \
|
||||
$(objpfx)tst-unique2: $(libdl) $(objpfx)tst-unique2mod1.so
|
||||
$(objpfx)tst-unique2.out: $(objpfx)tst-unique2mod2.so
|
||||
|
||||
+LDLIBS-tst-unique3lib.so = -lstdc++
|
||||
+LDLIBS-tst-unique3lib2.so = -lstdc++
|
||||
+$(objpfx)tst-unique3: $(libdl) $(objpfx)tst-unique3lib.so
|
||||
+$(objpfx)tst-unique3.out: $(objpfx)tst-unique3lib2.so
|
||||
+
|
||||
ifeq (yes,$(config-cflags-avx))
|
||||
CFLAGS-tst-audit4.c += -mavx
|
||||
CFLAGS-tst-auditmod4a.c += -mavx
|
||||
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
|
||||
index 78c8669..874a4bb 100644
|
||||
--- a/elf/dl-lookup.c
|
||||
+++ b/elf/dl-lookup.c
|
||||
@@ -364,8 +363,19 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
|
||||
if (entries[idx].hashval == new_hash
|
||||
&& strcmp (entries[idx].name, undef_name) == 0)
|
||||
{
|
||||
- result->s = entries[idx].sym;
|
||||
- result->m = (struct link_map *) entries[idx].map;
|
||||
+ if ((type_class & ELF_RTYPE_CLASS_COPY) != 0)
|
||||
+ {
|
||||
+ /* We possibly have to initialize the central
|
||||
+ copy from the copy addressed through the
|
||||
+ relocation. */
|
||||
+ result->s = sym;
|
||||
+ result->m = (struct link_map *) map;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ result->s = entries[idx].sym;
|
||||
+ result->m = (struct link_map *) entries[idx].map;
|
||||
+ }
|
||||
__rtld_lock_unlock_recursive (tab->lock);
|
||||
return 1;
|
||||
}
|
||||
diff --git a/elf/tst-unique3.cc b/elf/tst-unique3.cc
|
||||
new file mode 100644
|
||||
index 0000000..b2c9593
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-unique3.cc
|
||||
@@ -0,0 +1,23 @@
|
||||
+#include "tst-unique3.h"
|
||||
+#include <cstdio>
|
||||
+#include "../dlfcn/dlfcn.h"
|
||||
+
|
||||
+int t = S<char>::i;
|
||||
+
|
||||
+int
|
||||
+main (void)
|
||||
+{
|
||||
+ std::printf ("%d %d\n", S<char>::i, t);
|
||||
+ int result = S<char>::i++ != 1 || t != 1;
|
||||
+ result |= in_lib ();
|
||||
+ void *d = dlopen ("$ORIGIN/tst-unique3lib2.so", RTLD_LAZY);
|
||||
+ int (*fp) ();
|
||||
+ if (d == NULL || (fp = (int(*)()) dlsym (d, "in_lib2")) == NULL)
|
||||
+ {
|
||||
+ std::printf ("failed to get symbol in_lib2\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+ result |= fp ();
|
||||
+ dlclose (d);
|
||||
+ return result;
|
||||
+}
|
||||
diff --git a/elf/tst-unique3.h b/elf/tst-unique3.h
|
||||
new file mode 100644
|
||||
index 0000000..716d236
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-unique3.h
|
||||
@@ -0,0 +1,8 @@
|
||||
+// BZ 12510
|
||||
+template<typename T>
|
||||
+struct S
|
||||
+{
|
||||
+ static int i;
|
||||
+};
|
||||
+
|
||||
+extern int in_lib (void);
|
||||
diff --git a/elf/tst-unique3lib.cc b/elf/tst-unique3lib.cc
|
||||
new file mode 100644
|
||||
index 0000000..fa8e85a
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-unique3lib.cc
|
||||
@@ -0,0 +1,11 @@
|
||||
+#include <cstdio>
|
||||
+#include "tst-unique3.h"
|
||||
+template<typename T> int S<T>::i = 1;
|
||||
+static int i = S<char>::i;
|
||||
+
|
||||
+int
|
||||
+in_lib (void)
|
||||
+{
|
||||
+ std::printf ("in_lib: %d %d\n", S<char>::i, i);
|
||||
+ return S<char>::i++ != 2 || i != 1;
|
||||
+}
|
||||
diff --git a/elf/tst-unique3lib2.cc b/elf/tst-unique3lib2.cc
|
||||
new file mode 100644
|
||||
index 0000000..17d817e
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-unique3lib2.cc
|
||||
@@ -0,0 +1,12 @@
|
||||
+#include <cstdio>
|
||||
+#include "tst-unique3.h"
|
||||
+
|
||||
+template<typename T> int S<T>::i;
|
||||
+
|
||||
+extern "C"
|
||||
+int
|
||||
+in_lib2 ()
|
||||
+{
|
||||
+ std::printf ("in_lib2: %d\n", S<char>::i);
|
||||
+ return S<char>::i != 3;
|
||||
+}
|
||||
diff --git a/include/bits/dlfcn.h b/include/bits/dlfcn.h
|
||||
index cb4a5c2..c31a645 100644
|
||||
--- a/include/bits/dlfcn.h
|
||||
+++ b/include/bits/dlfcn.h
|
||||
@@ -1,4 +1,3 @@
|
||||
#include_next <bits/dlfcn.h>
|
||||
|
||||
-extern void _dl_mcount_wrapper_check (void *__selfpc);
|
||||
libc_hidden_proto (_dl_mcount_wrapper_check)
|
||||
341
src/patches/glibc/glibc-rh1111460.patch
Normal file
341
src/patches/glibc/glibc-rh1111460.patch
Normal file
@@ -0,0 +1,341 @@
|
||||
commit 7cbcdb3699584db8913ca90f705d6337633ee10f
|
||||
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
|
||||
Date: Fri Oct 25 10:22:12 2013 +0530
|
||||
|
||||
Fix stack overflow due to large AF_INET6 requests
|
||||
|
||||
Resolves #16072 (CVE-2013-4458).
|
||||
|
||||
This patch fixes another stack overflow in getaddrinfo when it is
|
||||
called with AF_INET6. The AF_UNSPEC case was fixed as CVE-2013-1914,
|
||||
but the AF_INET6 case went undetected back then.
|
||||
|
||||
commit 91ce40854d0b7f865cf5024ef95a8026b76096f3
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Aug 16 09:38:52 2013 +0200
|
||||
|
||||
CVE-2013-4237, BZ #14699: Buffer overflow in readdir_r
|
||||
|
||||
* sysdeps/posix/dirstream.h (struct __dirstream): Add errcode
|
||||
member.
|
||||
* sysdeps/posix/opendir.c (__alloc_dir): Initialize errcode
|
||||
member.
|
||||
* sysdeps/posix/rewinddir.c (rewinddir): Reset errcode member.
|
||||
* sysdeps/posix/readdir_r.c (__READDIR_R): Enforce NAME_MAX limit.
|
||||
Return delayed error code. Remove GETDENTS_64BIT_ALIGNED
|
||||
conditional.
|
||||
* sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c: Do not define
|
||||
GETDENTS_64BIT_ALIGNED.
|
||||
* sysdeps/unix/sysv/linux/i386/readdir64_r.c: Likewise.
|
||||
* manual/filesys.texi (Reading/Closing Directory): Document
|
||||
ENAMETOOLONG return value of readdir_r. Recommend readdir more
|
||||
strongly.
|
||||
* manual/conf.texi (Limits for Files): Add portability note to
|
||||
NAME_MAX, PATH_MAX.
|
||||
(Pathconf): Add portability note for _PC_NAME_MAX, _PC_PATH_MAX.
|
||||
|
||||
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
|
||||
index e6ce4cf..8ff74b4 100644
|
||||
--- a/sysdeps/posix/getaddrinfo.c
|
||||
+++ b/sysdeps/posix/getaddrinfo.c
|
||||
@@ -197,7 +197,22 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
|
||||
&rc, &herrno, NULL, &localcanon)); \
|
||||
if (rc != ERANGE || herrno != NETDB_INTERNAL) \
|
||||
break; \
|
||||
- tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen); \
|
||||
+ if (!malloc_tmpbuf && __libc_use_alloca (alloca_used + 2 * tmpbuflen)) \
|
||||
+ tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen, 2 * tmpbuflen, \
|
||||
+ alloca_used); \
|
||||
+ else \
|
||||
+ { \
|
||||
+ char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL, \
|
||||
+ 2 * tmpbuflen); \
|
||||
+ if (newp == NULL) \
|
||||
+ { \
|
||||
+ result = -EAI_MEMORY; \
|
||||
+ goto free_and_return; \
|
||||
+ } \
|
||||
+ tmpbuf = newp; \
|
||||
+ malloc_tmpbuf = true; \
|
||||
+ tmpbuflen = 2 * tmpbuflen; \
|
||||
+ } \
|
||||
} \
|
||||
if (status == NSS_STATUS_SUCCESS && rc == 0) \
|
||||
h = &th; \
|
||||
@@ -209,7 +224,8 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
|
||||
{ \
|
||||
__set_h_errno (herrno); \
|
||||
_res.options = old_res_options; \
|
||||
- return -EAI_SYSTEM; \
|
||||
+ result = -EAI_SYSTEM; \
|
||||
+ goto free_and_return; \
|
||||
} \
|
||||
if (herrno == TRY_AGAIN) \
|
||||
no_data = EAI_AGAIN; \
|
||||
|
||||
diff --git a/manual/conf.texi b/manual/conf.texi
|
||||
index 7eb8b36..c720063 100644
|
||||
--- a/manual/conf.texi
|
||||
+++ b/manual/conf.texi
|
||||
@@ -1149,6 +1149,9 @@ typed ahead as input. @xref{I/O Queues}.
|
||||
@comment POSIX.1
|
||||
@deftypevr Macro int NAME_MAX
|
||||
The uniform system limit (if any) for the length of a file name component.
|
||||
+
|
||||
+@strong{Portability Note:} On some systems, the GNU C Library defines
|
||||
+@code{NAME_MAX}, but does not actually enforce this limit.
|
||||
@end deftypevr
|
||||
|
||||
@comment limits.h
|
||||
@@ -1157,6 +1160,9 @@ including the terminating null character.
|
||||
@deftypevr Macro int PATH_MAX
|
||||
The uniform system limit (if any) for the length of an entire file name (that
|
||||
is, the argument given to system calls such as @code{open}).
|
||||
+
|
||||
+@strong{Portability Note:} The GNU C Library does not enforce this limit
|
||||
+even if @code{PATH_MAX} is defined.
|
||||
@end deftypevr
|
||||
|
||||
@cindex limits, pipe buffer size
|
||||
@@ -1476,6 +1482,9 @@ Inquire about the value of @code{POSIX_REC_MIN_XFER_SIZE}.
|
||||
Inquire about the value of @code{POSIX_REC_XFER_ALIGN}.
|
||||
@end table
|
||||
|
||||
+@strong{Portability Note:} On some systems, the GNU C Library does not
|
||||
+enforce @code{_PC_NAME_MAX} or @code{_PC_PATH_MAX} limits.
|
||||
+
|
||||
@node Utility Limits
|
||||
@section Utility Program Capacity Limits
|
||||
|
||||
diff --git a/manual/filesys.texi b/manual/filesys.texi
|
||||
index 1df9cf2..814c210 100644
|
||||
--- a/manual/filesys.texi
|
||||
+++ b/manual/filesys.texi
|
||||
@@ -444,9 +444,9 @@ symbols are declared in the header file @file{dirent.h}.
|
||||
@comment POSIX.1
|
||||
@deftypefun {struct dirent *} readdir (DIR *@var{dirstream})
|
||||
This function reads the next entry from the directory. It normally
|
||||
-returns a pointer to a structure containing information about the file.
|
||||
-This structure is statically allocated and can be rewritten by a
|
||||
-subsequent call.
|
||||
+returns a pointer to a structure containing information about the
|
||||
+file. This structure is associated with the @var{dirstream} handle
|
||||
+and can be rewritten by a subsequent call.
|
||||
|
||||
@strong{Portability Note:} On some systems @code{readdir} may not
|
||||
return entries for @file{.} and @file{..}, even though these are always
|
||||
@@ -461,19 +461,61 @@ conditions are defined for this function:
|
||||
The @var{dirstream} argument is not valid.
|
||||
@end table
|
||||
|
||||
-@code{readdir} is not thread safe. Multiple threads using
|
||||
-@code{readdir} on the same @var{dirstream} may overwrite the return
|
||||
-value. Use @code{readdir_r} when this is critical.
|
||||
+To distinguish between an end-of-directory condition or an error, you
|
||||
+must set @code{errno} to zero before calling @code{readdir}. To avoid
|
||||
+entering an infinite loop, you should stop reading from the directory
|
||||
+after the first error.
|
||||
+
|
||||
+In POSIX.1-2008, @code{readdir} is not thread-safe. In the GNU C Library
|
||||
+implementation, it is safe to call @code{readdir} concurrently on
|
||||
+different @var{dirstream}s, but multiple threads accessing the same
|
||||
+@var{dirstream} result in undefined behavior. @code{readdir_r} is a
|
||||
+fully thread-safe alternative, but suffers from poor portability (see
|
||||
+below). It is recommended that you use @code{readdir}, with external
|
||||
+locking if multiple threads access the same @var{dirstream}.
|
||||
@end deftypefun
|
||||
|
||||
@comment dirent.h
|
||||
@comment GNU
|
||||
@deftypefun int readdir_r (DIR *@var{dirstream}, struct dirent *@var{entry}, struct dirent **@var{result})
|
||||
-This function is the reentrant version of @code{readdir}. Like
|
||||
-@code{readdir} it returns the next entry from the directory. But to
|
||||
-prevent conflicts between simultaneously running threads the result is
|
||||
-not stored in statically allocated memory. Instead the argument
|
||||
-@var{entry} points to a place to store the result.
|
||||
+This function is a version of @code{readdir} which performs internal
|
||||
+locking. Like @code{readdir} it returns the next entry from the
|
||||
+directory. To prevent conflicts between simultaneously running
|
||||
+threads the result is stored inside the @var{entry} object.
|
||||
+
|
||||
+@strong{Portability Note:} It is recommended to use @code{readdir}
|
||||
+instead of @code{readdir_r} for the following reasons:
|
||||
+
|
||||
+@itemize @bullet
|
||||
+@item
|
||||
+On systems which do not define @code{NAME_MAX}, it may not be possible
|
||||
+to use @code{readdir_r} safely because the caller does not specify the
|
||||
+length of the buffer for the directory entry.
|
||||
+
|
||||
+@item
|
||||
+On some systems, @code{readdir_r} cannot read directory entries with
|
||||
+very long names. If such a name is encountered, the GNU C Library
|
||||
+implementation of @code{readdir_r} returns with an error code of
|
||||
+@code{ENAMETOOLONG} after the final directory entry has been read. On
|
||||
+other systems, @code{readdir_r} may return successfully, but the
|
||||
+@code{d_name} member may not be NUL-terminated or may be truncated.
|
||||
+
|
||||
+@item
|
||||
+POSIX-1.2008 does not guarantee that @code{readdir} is thread-safe,
|
||||
+even when access to the same @var{dirstream} is serialized. But in
|
||||
+current implementations (including the GNU C Library), it is safe to call
|
||||
+@code{readdir} concurrently on different @var{dirstream}s, so there is
|
||||
+no need to use @code{readdir_r} in most multi-threaded programs. In
|
||||
+the rare case that multiple threads need to read from the same
|
||||
+@var{dirstream}, it is still better to use @code{readdir} and external
|
||||
+synchronization.
|
||||
+
|
||||
+@item
|
||||
+It is expected that future versions of POSIX will obsolete
|
||||
+@code{readdir_r} and mandate the level of thread safety for
|
||||
+@code{readdir} which is provided by the GNU C Library and other
|
||||
+implementations today.
|
||||
+@end itemize
|
||||
|
||||
Normally @code{readdir_r} returns zero and sets @code{*@var{result}}
|
||||
to @var{entry}. If there are no more entries in the directory or an
|
||||
@@ -481,15 +523,6 @@ error is detected, @code{readdir_r} sets @code{*@var{result}} to a
|
||||
null pointer and returns a nonzero error code, also stored in
|
||||
@code{errno}, as described for @code{readdir}.
|
||||
|
||||
-@strong{Portability Note:} On some systems @code{readdir_r} may not
|
||||
-return a NUL terminated string for the file name, even when there is no
|
||||
-@code{d_reclen} field in @code{struct dirent} and the file
|
||||
-name is the maximum allowed size. Modern systems all have the
|
||||
-@code{d_reclen} field, and on old systems multi-threading is not
|
||||
-critical. In any case there is no such problem with the @code{readdir}
|
||||
-function, so that even on systems without the @code{d_reclen} member one
|
||||
-could use multiple threads by using external locking.
|
||||
-
|
||||
It is also important to look at the definition of the @code{struct
|
||||
dirent} type. Simply passing a pointer to an object of this type for
|
||||
the second parameter of @code{readdir_r} might not be enough. Some
|
||||
diff --git a/sysdeps/unix/dirstream.h b/sysdeps/unix/dirstream.h
|
||||
index a7a074d..8e8570d 100644
|
||||
--- a/sysdeps/unix/dirstream.h
|
||||
+++ b/sysdeps/unix/dirstream.h
|
||||
@@ -39,6 +39,8 @@ struct __dirstream
|
||||
|
||||
off_t filepos; /* Position of next entry to read. */
|
||||
|
||||
+ int errcode; /* Delayed error code. */
|
||||
+
|
||||
/* Directory block. */
|
||||
char data[0] __attribute__ ((aligned (__alignof__ (void*))));
|
||||
};
|
||||
diff --git a/sysdeps/unix/opendir.c b/sysdeps/unix/opendir.c
|
||||
index ddfc3a7..fc05b0f 100644
|
||||
--- a/sysdeps/unix/opendir.c
|
||||
+++ b/sysdeps/unix/opendir.c
|
||||
@@ -231,6 +231,7 @@ __alloc_dir (int fd, bool close_fd, int flags, const struct stat64 *statp)
|
||||
dirp->size = 0;
|
||||
dirp->offset = 0;
|
||||
dirp->filepos = 0;
|
||||
+ dirp->errcode = 0;
|
||||
|
||||
return dirp;
|
||||
}
|
||||
diff --git a/sysdeps/unix/readdir_r.c b/sysdeps/unix/readdir_r.c
|
||||
index b5a8e2e..8ed5c3f 100644
|
||||
--- a/sysdeps/unix/readdir_r.c
|
||||
+++ b/sysdeps/unix/readdir_r.c
|
||||
@@ -40,6 +40,7 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result)
|
||||
DIRENT_TYPE *dp;
|
||||
size_t reclen;
|
||||
const int saved_errno = errno;
|
||||
+ int ret;
|
||||
|
||||
__libc_lock_lock (dirp->lock);
|
||||
|
||||
@@ -70,10 +71,10 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result)
|
||||
bytes = 0;
|
||||
__set_errno (saved_errno);
|
||||
}
|
||||
+ if (bytes < 0)
|
||||
+ dirp->errcode = errno;
|
||||
|
||||
dp = NULL;
|
||||
- /* Reclen != 0 signals that an error occurred. */
|
||||
- reclen = bytes != 0;
|
||||
break;
|
||||
}
|
||||
dirp->size = (size_t) bytes;
|
||||
@@ -106,28 +107,46 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result)
|
||||
dirp->filepos += reclen;
|
||||
#endif
|
||||
|
||||
- /* Skip deleted files. */
|
||||
+#ifdef NAME_MAX
|
||||
+ if (reclen > offsetof (DIRENT_TYPE, d_name) + NAME_MAX + 1)
|
||||
+ {
|
||||
+ /* The record is very long. It could still fit into the
|
||||
+ caller-supplied buffer if we can skip padding at the
|
||||
+ end. */
|
||||
+ size_t namelen = _D_EXACT_NAMLEN (dp);
|
||||
+ if (namelen <= NAME_MAX)
|
||||
+ reclen = offsetof (DIRENT_TYPE, d_name) + namelen + 1;
|
||||
+ else
|
||||
+ {
|
||||
+ /* The name is too long. Ignore this file. */
|
||||
+ dirp->errcode = ENAMETOOLONG;
|
||||
+ dp->d_ino = 0;
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
+ /* Skip deleted and ignored files. */
|
||||
}
|
||||
while (dp->d_ino == 0);
|
||||
|
||||
if (dp != NULL)
|
||||
{
|
||||
-#ifdef GETDENTS_64BIT_ALIGNED
|
||||
- /* The d_reclen value might include padding which is not part of
|
||||
- the DIRENT_TYPE data structure. */
|
||||
- reclen = MIN (reclen, sizeof (DIRENT_TYPE));
|
||||
-#endif
|
||||
*result = memcpy (entry, dp, reclen);
|
||||
-#ifdef GETDENTS_64BIT_ALIGNED
|
||||
+#ifdef _DIRENT_HAVE_D_RECLEN
|
||||
entry->d_reclen = reclen;
|
||||
#endif
|
||||
+ ret = 0;
|
||||
}
|
||||
else
|
||||
- *result = NULL;
|
||||
+ {
|
||||
+ *result = NULL;
|
||||
+ ret = dirp->errcode;
|
||||
+ }
|
||||
|
||||
__libc_lock_unlock (dirp->lock);
|
||||
|
||||
- return dp != NULL ? 0 : reclen ? errno : 0;
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
#ifdef __READDIR_R_ALIAS
|
||||
diff --git a/sysdeps/unix/rewinddir.c b/sysdeps/unix/rewinddir.c
|
||||
index 2935a8e..d4991ad 100644
|
||||
--- a/sysdeps/unix/rewinddir.c
|
||||
+++ b/sysdeps/unix/rewinddir.c
|
||||
@@ -33,5 +33,6 @@ rewinddir (dirp)
|
||||
dirp->filepos = 0;
|
||||
dirp->offset = 0;
|
||||
dirp->size = 0;
|
||||
+ dirp->errcode = 0;
|
||||
__libc_lock_unlock (dirp->lock);
|
||||
}
|
||||
diff --git a/sysdeps/unix/sysv/linux/i386/readdir64_r.c b/sysdeps/unix/sysv/linux/i386/readdir64_r.c
|
||||
index 8ebbcfd..a7d114e 100644
|
||||
--- a/sysdeps/unix/sysv/linux/i386/readdir64_r.c
|
||||
+++ b/sysdeps/unix/sysv/linux/i386/readdir64_r.c
|
||||
@@ -18,7 +18,6 @@
|
||||
#define __READDIR_R __readdir64_r
|
||||
#define __GETDENTS __getdents64
|
||||
#define DIRENT_TYPE struct dirent64
|
||||
-#define GETDENTS_64BIT_ALIGNED 1
|
||||
|
||||
#include <sysdeps/unix/readdir_r.c>
|
||||
|
||||
154
src/patches/glibc/glibc-rh1139571.patch
Normal file
154
src/patches/glibc/glibc-rh1139571.patch
Normal file
@@ -0,0 +1,154 @@
|
||||
commit 41488498b6d9440ee66ab033808cce8323bba7ac
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Wed Sep 3 19:45:43 2014 +0200
|
||||
|
||||
CVE-2014-6040: Crashes on invalid input in IBM gconv modules [BZ #17325]
|
||||
|
||||
These changes are based on the fix for BZ #14134 in commit
|
||||
6e230d11837f3ae7b375ea69d7905f0d18eb79e5.
|
||||
|
||||
diff --git a/iconvdata/Makefile b/iconvdata/Makefile
|
||||
index 0a410a1..b6327d6 100644
|
||||
--- a/iconvdata/Makefile
|
||||
+++ b/iconvdata/Makefile
|
||||
@@ -297,6 +297,7 @@ $(objpfx)tst-iconv7.out: $(objpfx)gconv-modules \
|
||||
$(objpfx)iconv-test.out: run-iconv-test.sh $(objpfx)gconv-modules \
|
||||
$(addprefix $(objpfx),$(modules.so)) \
|
||||
$(common-objdir)/iconv/iconv_prog TESTS
|
||||
+ iconv_modules="$(modules)" \
|
||||
$(SHELL) -e $< $(common-objdir) > $@
|
||||
|
||||
$(objpfx)tst-tables.out: tst-tables.sh $(objpfx)gconv-modules \
|
||||
diff --git a/iconvdata/ibm1364.c b/iconvdata/ibm1364.c
|
||||
index 0b5484f..cf80993 100644
|
||||
--- a/iconvdata/ibm1364.c
|
||||
+++ b/iconvdata/ibm1364.c
|
||||
@@ -221,7 +221,8 @@ enum
|
||||
++rp2; \
|
||||
\
|
||||
uint32_t res; \
|
||||
- if (__builtin_expect (ch < rp2->start, 0) \
|
||||
+ if (__builtin_expect (rp2->start == 0xffff, 0) \
|
||||
+ || __builtin_expect (ch < rp2->start, 0) \
|
||||
|| (res = DB_TO_UCS4[ch + rp2->idx], \
|
||||
__builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \
|
||||
{ \
|
||||
diff --git a/iconvdata/ibm932.c b/iconvdata/ibm932.c
|
||||
index f5dca59..aa69d65 100644
|
||||
--- a/iconvdata/ibm932.c
|
||||
+++ b/iconvdata/ibm932.c
|
||||
@@ -74,11 +74,12 @@
|
||||
} \
|
||||
\
|
||||
ch = (ch * 0x100) + inptr[1]; \
|
||||
+ /* ch was less than 0xfd. */ \
|
||||
+ assert (ch < 0xfd00); \
|
||||
while (ch > rp2->end) \
|
||||
++rp2; \
|
||||
\
|
||||
- if (__builtin_expect (rp2 == NULL, 0) \
|
||||
- || __builtin_expect (ch < rp2->start, 0) \
|
||||
+ if (__builtin_expect (ch < rp2->start, 0) \
|
||||
|| (res = __ibm932db_to_ucs4[ch + rp2->idx], \
|
||||
__builtin_expect (res, '\1') == 0 && ch !=0)) \
|
||||
{ \
|
||||
diff --git a/iconvdata/ibm933.c b/iconvdata/ibm933.c
|
||||
index f46dfb5..461fb5e 100644
|
||||
--- a/iconvdata/ibm933.c
|
||||
+++ b/iconvdata/ibm933.c
|
||||
@@ -162,7 +162,7 @@ enum
|
||||
while (ch > rp2->end) \
|
||||
++rp2; \
|
||||
\
|
||||
- if (__builtin_expect (rp2 == NULL, 0) \
|
||||
+ if (__builtin_expect (rp2->start == 0xffff, 0) \
|
||||
|| __builtin_expect (ch < rp2->start, 0) \
|
||||
|| (res = __ibm933db_to_ucs4[ch + rp2->idx], \
|
||||
__builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \
|
||||
diff --git a/iconvdata/ibm935.c b/iconvdata/ibm935.c
|
||||
index a8e4e6c..132d816 100644
|
||||
--- a/iconvdata/ibm935.c
|
||||
+++ b/iconvdata/ibm935.c
|
||||
@@ -162,7 +162,7 @@ enum
|
||||
while (ch > rp2->end) \
|
||||
++rp2; \
|
||||
\
|
||||
- if (__builtin_expect (rp2 == NULL, 0) \
|
||||
+ if (__builtin_expect (rp2->start == 0xffff, 0) \
|
||||
|| __builtin_expect (ch < rp2->start, 0) \
|
||||
|| (res = __ibm935db_to_ucs4[ch + rp2->idx], \
|
||||
__builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \
|
||||
diff --git a/iconvdata/ibm937.c b/iconvdata/ibm937.c
|
||||
index 239be61..69b154d 100644
|
||||
--- a/iconvdata/ibm937.c
|
||||
+++ b/iconvdata/ibm937.c
|
||||
@@ -162,7 +162,7 @@ enum
|
||||
while (ch > rp2->end) \
|
||||
++rp2; \
|
||||
\
|
||||
- if (__builtin_expect (rp2 == NULL, 0) \
|
||||
+ if (__builtin_expect (rp2->start == 0xffff, 0) \
|
||||
|| __builtin_expect (ch < rp2->start, 0) \
|
||||
|| (res = __ibm937db_to_ucs4[ch + rp2->idx], \
|
||||
__builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \
|
||||
diff --git a/iconvdata/ibm939.c b/iconvdata/ibm939.c
|
||||
index 5d0db36..9936e2c 100644
|
||||
--- a/iconvdata/ibm939.c
|
||||
+++ b/iconvdata/ibm939.c
|
||||
@@ -162,7 +162,7 @@ enum
|
||||
while (ch > rp2->end) \
|
||||
++rp2; \
|
||||
\
|
||||
- if (__builtin_expect (rp2 == NULL, 0) \
|
||||
+ if (__builtin_expect (rp2->start == 0xffff, 0) \
|
||||
|| __builtin_expect (ch < rp2->start, 0) \
|
||||
|| (res = __ibm939db_to_ucs4[ch + rp2->idx], \
|
||||
__builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \
|
||||
diff --git a/iconvdata/ibm943.c b/iconvdata/ibm943.c
|
||||
index be0c14f..c5d5742 100644
|
||||
--- a/iconvdata/ibm943.c
|
||||
+++ b/iconvdata/ibm943.c
|
||||
@@ -75,11 +75,12 @@
|
||||
} \
|
||||
\
|
||||
ch = (ch * 0x100) + inptr[1]; \
|
||||
+ /* ch was less than 0xfd. */ \
|
||||
+ assert (ch < 0xfd00); \
|
||||
while (ch > rp2->end) \
|
||||
++rp2; \
|
||||
\
|
||||
- if (__builtin_expect (rp2 == NULL, 0) \
|
||||
- || __builtin_expect (ch < rp2->start, 0) \
|
||||
+ if (__builtin_expect (ch < rp2->start, 0) \
|
||||
|| (res = __ibm943db_to_ucs4[ch + rp2->idx], \
|
||||
__builtin_expect (res, '\1') == 0 && ch !=0)) \
|
||||
{ \
|
||||
diff --git a/iconvdata/run-iconv-test.sh b/iconvdata/run-iconv-test.sh
|
||||
index c98c929..5dfb69f 100755
|
||||
--- a/iconvdata/run-iconv-test.sh
|
||||
+++ b/iconvdata/run-iconv-test.sh
|
||||
@@ -184,6 +184,24 @@ while read utf8 from filename; do
|
||||
|
||||
done < TESTS2
|
||||
|
||||
+# Check for crashes in decoders.
|
||||
+printf '\016\377\377\377\377\377\377\377' > $temp1
|
||||
+for from in $iconv_modules ; do
|
||||
+ echo $ac_n "test decoder $from $ac_c"
|
||||
+ PROG=`eval echo $ICONV`
|
||||
+ if $PROG < $temp1 >/dev/null 2>&1 ; then
|
||||
+ : # fall through
|
||||
+ else
|
||||
+ status=$?
|
||||
+ if test $status -gt 1 ; then
|
||||
+ echo "/FAILED"
|
||||
+ failed=1
|
||||
+ continue
|
||||
+ fi
|
||||
+ fi
|
||||
+ echo "OK"
|
||||
+done
|
||||
+
|
||||
exit $failed
|
||||
# Local Variables:
|
||||
# mode:shell-script
|
||||
333
src/patches/glibc/glibc-rh1154563.patch
Normal file
333
src/patches/glibc/glibc-rh1154563.patch
Normal file
@@ -0,0 +1,333 @@
|
||||
#
|
||||
# This is a special patch for rhel-6 to fix recursive dlopen.
|
||||
# It is likely the upstream patch will always be too risky for
|
||||
# rhel-6 and will involve reorganizing the way in which recursive
|
||||
# dlopen is allowed to operate and how the _r_debug and stap
|
||||
# points are used by gdb for the recursive case.
|
||||
#
|
||||
# This fix changes the internal API to duplicate the ldconfig
|
||||
# cache data. This means that at any point the cache can be
|
||||
# unmapped without any consequences. The caller is responsible
|
||||
# fore freeing the returned string.
|
||||
#
|
||||
# A regression test is added to verify the assertion for _r_debug
|
||||
# is no longer triggered due to the recursive dlopen. The test to
|
||||
# verify the fix in _dl_load_cache_lookup is not automated and
|
||||
# has to be run by hand.
|
||||
#
|
||||
diff -urN glibc-2.12-2-gc4ccff1/elf/dl-cache.c glibc-2.12-2-gc4ccff1.mod/elf/dl-cache.c
|
||||
--- glibc-2.12-2-gc4ccff1/elf/dl-cache.c 2010-05-04 07:27:23.000000000 -0400
|
||||
+++ glibc-2.12-2-gc4ccff1.mod/elf/dl-cache.c 2014-12-10 21:54:08.801985045 -0500
|
||||
@@ -175,9 +175,12 @@
|
||||
|
||||
|
||||
/* Look up NAME in ld.so.cache and return the file name stored there,
|
||||
- or null if none is found. */
|
||||
-
|
||||
-const char *
|
||||
+ or null if none is found.
|
||||
+ The caller is responsible for freeing the returned string. The ld.so.cache
|
||||
+ may be unmapped at any time by a completing recursive dlopen and
|
||||
+ this function must take care that it does not return references to
|
||||
+ any data in the mapping. */
|
||||
+char *
|
||||
internal_function
|
||||
_dl_load_cache_lookup (const char *name)
|
||||
{
|
||||
@@ -290,7 +293,17 @@
|
||||
&& best != NULL)
|
||||
_dl_debug_printf (" trying file=%s\n", best);
|
||||
|
||||
- return best;
|
||||
+ if (best == NULL)
|
||||
+ return NULL;
|
||||
+
|
||||
+ /* The double copy is *required* since malloc may be interposed
|
||||
+ and call dlopen itself whose completion would unmap the data
|
||||
+ we are accessing. Therefore we must make the copy of the
|
||||
+ mapping data without using malloc. */
|
||||
+ char *temp;
|
||||
+ temp = alloca (strlen (best) + 1);
|
||||
+ strcpy (temp, best);
|
||||
+ return strdup (temp);
|
||||
}
|
||||
|
||||
#ifndef MAP_COPY
|
||||
diff -urN glibc-2.12-2-gc4ccff1/elf/dl-load.c glibc-2.12-2-gc4ccff1.mod/elf/dl-load.c
|
||||
--- glibc-2.12-2-gc4ccff1/elf/dl-load.c 2014-12-10 11:03:17.966048404 -0500
|
||||
+++ glibc-2.12-2-gc4ccff1.mod/elf/dl-load.c 2014-12-10 21:47:29.319387538 -0500
|
||||
@@ -2126,7 +2126,7 @@
|
||||
{
|
||||
/* Check the list of libraries in the file /etc/ld.so.cache,
|
||||
for compatibility with Linux's ldconfig program. */
|
||||
- const char *cached = _dl_load_cache_lookup (name);
|
||||
+ char *cached = _dl_load_cache_lookup (name);
|
||||
|
||||
if (cached != NULL)
|
||||
{
|
||||
@@ -2156,6 +2156,7 @@
|
||||
if (memcmp (cached, dirp, system_dirs_len[cnt]) == 0)
|
||||
{
|
||||
/* The prefix matches. Don't use the entry. */
|
||||
+ free (cached);
|
||||
cached = NULL;
|
||||
break;
|
||||
}
|
||||
@@ -2172,14 +2173,9 @@
|
||||
&fb, loader ?: GL(dl_ns)[nsid]._ns_loaded,
|
||||
LA_SER_CONFIG, &found_other_class, false);
|
||||
if (__builtin_expect (fd != -1, 1))
|
||||
- {
|
||||
- realname = local_strdup (cached);
|
||||
- if (realname == NULL)
|
||||
- {
|
||||
- __close (fd);
|
||||
- fd = -1;
|
||||
- }
|
||||
- }
|
||||
+ realname = cached;
|
||||
+ else
|
||||
+ free (cached);
|
||||
}
|
||||
}
|
||||
}
|
||||
diff -urN glibc-2.12-2-gc4ccff1/elf/dl-open.c glibc-2.12-2-gc4ccff1.mod/elf/dl-open.c
|
||||
--- glibc-2.12-2-gc4ccff1/elf/dl-open.c 2014-12-10 11:03:18.083048497 -0500
|
||||
+++ glibc-2.12-2-gc4ccff1.mod/elf/dl-open.c 2014-12-10 20:34:16.017503638 -0500
|
||||
@@ -220,7 +220,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
- assert (_dl_debug_initialize (0, args->nsid)->r_state == RT_CONSISTENT);
|
||||
+ /* One might be tempted to assert that we are RT_CONSISTENT at this point, but that
|
||||
+ may not be true if this is a recursive call to dlopen.
|
||||
+ TODO: Fix all of the debug state so we end up at RT_CONSISTENT only when the last
|
||||
+ recursive dlopen completes. */
|
||||
+ _dl_debug_initialize (0, args->nsid);
|
||||
|
||||
/* Load the named object. */
|
||||
struct link_map *new;
|
||||
diff -urN glibc-2.12-2-gc4ccff1/sysdeps/generic/ldsodefs.h glibc-2.12-2-gc4ccff1.mod/sysdeps/generic/ldsodefs.h
|
||||
--- glibc-2.12-2-gc4ccff1/sysdeps/generic/ldsodefs.h 2014-12-10 11:03:17.944048387 -0500
|
||||
+++ glibc-2.12-2-gc4ccff1.mod/sysdeps/generic/ldsodefs.h 2014-12-10 21:46:14.071344018 -0500
|
||||
@@ -996,8 +996,8 @@
|
||||
internal_function;
|
||||
|
||||
/* Look up NAME in ld.so.cache and return the file name stored there,
|
||||
- or null if none is found. */
|
||||
-extern const char *_dl_load_cache_lookup (const char *name)
|
||||
+ or null if none is found. Caller must free returned string. */
|
||||
+extern char *_dl_load_cache_lookup (const char *name)
|
||||
internal_function;
|
||||
|
||||
/* If the system does not support MAP_COPY we cannot leave the file open
|
||||
diff -urN glibc-2.12-2-gc4ccff1/dlfcn/Makefile glibc-2.12-2-gc4ccff1.mod/dlfcn/Makefile
|
||||
--- glibc-2.12-2-gc4ccff1/dlfcn/Makefile 2010-05-04 07:27:23.000000000 -0400
|
||||
+++ glibc-2.12-2-gc4ccff1.mod/dlfcn/Makefile 2014-12-11 16:58:55.719803063 -0500
|
||||
@@ -42,12 +42,12 @@
|
||||
ifeq (yes,$(build-shared))
|
||||
tests = glrefmain failtest tst-dladdr default errmsg1 tstcxaatexit \
|
||||
bug-dlopen1 bug-dlsym1 tst-dlinfo bug-atexit1 bug-atexit2 \
|
||||
- bug-atexit3 tstatexit
|
||||
+ bug-atexit3 tstatexit tst-rec-dlopen
|
||||
endif
|
||||
modules-names = glreflib1 glreflib2 glreflib3 failtestmod defaultmod1 \
|
||||
defaultmod2 errmsg1mod modatexit modcxaatexit \
|
||||
bug-dlsym1-lib1 bug-dlsym1-lib2 bug-atexit1-lib \
|
||||
- bug-atexit2-lib bug-atexit3-lib
|
||||
+ bug-atexit2-lib bug-atexit3-lib moddummy1 moddummy2
|
||||
|
||||
failtestmod.so-no-z-defs = yes
|
||||
glreflib2.so-no-z-defs = yes
|
||||
@@ -142,6 +142,8 @@
|
||||
$(objpfx)bug-atexit3-lib.so: $(common-objpfx)libc.so \
|
||||
$(common-objpfx)libc_nonshared.a
|
||||
|
||||
+LDLIBS-tst-rec-dlopen = -ldl
|
||||
+$(objpfx)tst-rec-dlopen: $(libdl)
|
||||
|
||||
# Depend on libc.so so a DT_NEEDED is generated in the shared objects.
|
||||
# This ensures they will load libc.so for needed symbols if loaded by
|
||||
diff -urN glibc-2.12-2-gc4ccff1/dlfcn/moddummy1.c glibc-2.12-2-gc4ccff1.mod/dlfcn/moddummy1.c
|
||||
--- glibc-2.12-2-gc4ccff1/dlfcn/moddummy1.c 1969-12-31 19:00:00.000000000 -0500
|
||||
+++ glibc-2.12-2-gc4ccff1.mod/dlfcn/moddummy1.c 2014-12-11 16:57:54.108797285 -0500
|
||||
@@ -0,0 +1,13 @@
|
||||
+/* Provide a dummy DSO for tst-recursive-dlopen to use. */
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+
|
||||
+int called_dummy1;
|
||||
+
|
||||
+void
|
||||
+dummy1 (void)
|
||||
+{
|
||||
+ printf ("Called dummy1()\n");
|
||||
+ called_dummy1++;
|
||||
+}
|
||||
+
|
||||
diff -urN glibc-2.12-2-gc4ccff1/dlfcn/moddummy2.c glibc-2.12-2-gc4ccff1.mod/dlfcn/moddummy2.c
|
||||
--- glibc-2.12-2-gc4ccff1/dlfcn/moddummy2.c 1969-12-31 19:00:00.000000000 -0500
|
||||
+++ glibc-2.12-2-gc4ccff1.mod/dlfcn/moddummy2.c 2014-12-11 16:57:54.108797285 -0500
|
||||
@@ -0,0 +1,13 @@
|
||||
+/* Provide a dummy DSO for tst-recursive-dlopen to use. */
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+
|
||||
+int called_dummy2;
|
||||
+
|
||||
+void
|
||||
+dummy2 (void)
|
||||
+{
|
||||
+ printf ("Called dummy2()\n");
|
||||
+ called_dummy2++;
|
||||
+}
|
||||
+
|
||||
diff -urN glibc-2.12-2-gc4ccff1/dlfcn/tst-rec-dlopen.c glibc-2.12-2-gc4ccff1.mod/dlfcn/tst-rec-dlopen.c
|
||||
--- glibc-2.12-2-gc4ccff1/dlfcn/tst-rec-dlopen.c 1969-12-31 19:00:00.000000000 -0500
|
||||
+++ glibc-2.12-2-gc4ccff1.mod/dlfcn/tst-rec-dlopen.c 2014-12-11 20:53:28.617848774 -0500
|
||||
@@ -0,0 +1,145 @@
|
||||
+/* Test recursive dlopen using malloc hooks.
|
||||
+ Copyright (C) 1998-2014 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
|
||||
+
|
||||
+ 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 <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <malloc.h>
|
||||
+#include <dlfcn.h>
|
||||
+
|
||||
+#define DSO "moddummy1.so"
|
||||
+#define FUNC "dummy1"
|
||||
+
|
||||
+#define DSO1 "moddummy2.so"
|
||||
+#define FUNC1 "dummy2"
|
||||
+
|
||||
+/* Prevent the compiler from moving the assignment to called_func
|
||||
+ before (*func)() since the compiler doesn't know we might abort
|
||||
+ or catch a SIGSEGV signal and it may move the store. */
|
||||
+volatile int called_func;
|
||||
+
|
||||
+/* Prototype for my hook. */
|
||||
+void *custom_malloc_hook (size_t, const void *);
|
||||
+
|
||||
+/* Pointer to old malloc hooks. */
|
||||
+void *(*old_malloc_hook) (size_t, const void *);
|
||||
+
|
||||
+/* Call function func_name in DSO dso_name via dlopen. */
|
||||
+void
|
||||
+call_func (const char *dso_name, const char *func_name)
|
||||
+{
|
||||
+ int ret;
|
||||
+ void *dso;
|
||||
+ void (*func) (void);
|
||||
+ char *err;
|
||||
+
|
||||
+ /* Open the DSO. */
|
||||
+ dso = dlopen (dso_name, RTLD_NOW|RTLD_GLOBAL);
|
||||
+ if (dso == NULL)
|
||||
+ {
|
||||
+ err = dlerror ();
|
||||
+ fprintf (stderr, "%s\n", err);
|
||||
+ exit (1);
|
||||
+ }
|
||||
+ /* Clear any errors. */
|
||||
+ dlerror ();
|
||||
+
|
||||
+ /* Lookup func. */
|
||||
+ *(void **) (&func) = dlsym (dso, func_name);
|
||||
+ if (func == NULL)
|
||||
+ {
|
||||
+ err = dlerror ();
|
||||
+ if (err != NULL)
|
||||
+ {
|
||||
+ fprintf (stderr, "%s\n", err);
|
||||
+ exit (1);
|
||||
+ }
|
||||
+ }
|
||||
+ /* Call func. */
|
||||
+ (*func) ();
|
||||
+ called_func = 1;
|
||||
+
|
||||
+ /* Close the library and look for errors too. */
|
||||
+ ret = dlclose (dso);
|
||||
+ if (ret != 0)
|
||||
+ {
|
||||
+ err = dlerror ();
|
||||
+ fprintf (stderr, "%s\n", err);
|
||||
+ exit (1);
|
||||
+ }
|
||||
+
|
||||
+}
|
||||
+
|
||||
+/* Empty hook that does nothing. */
|
||||
+void *
|
||||
+custom_malloc_hook (size_t size, const void *caller)
|
||||
+{
|
||||
+ void *result;
|
||||
+ /* Restore old hooks. */
|
||||
+ __malloc_hook = old_malloc_hook;
|
||||
+ /* First call a function in another library via dlopen. */
|
||||
+ call_func (DSO1, FUNC1);
|
||||
+ /* Called recursively. */
|
||||
+ result = malloc (size);
|
||||
+ /* Restore new hooks. */
|
||||
+ __malloc_hook = custom_malloc_hook;
|
||||
+ return result;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ /* Save old hook. */
|
||||
+ old_malloc_hook = __malloc_hook;
|
||||
+ /* Install new hook. */
|
||||
+ __malloc_hook = custom_malloc_hook;
|
||||
+
|
||||
+ /* Bug 17702 fixes two things:
|
||||
+ * A recursive dlopen unmapping the ld.so.cache.
|
||||
+ * An assertion that _r_debug is RT_CONSISTENT at entry to dlopen.
|
||||
+ We can only test the latter. Testing the former requires modifying
|
||||
+ ld.so.conf to cache the dummy libraries, then running ldconfig,
|
||||
+ then run the test. If you do all of that (and glibc's test
|
||||
+ infrastructure doesn't support that yet) then the test will
|
||||
+ SEGFAULT without the fix. If you don't do that, then the test
|
||||
+ will abort because of the assert described in detail below. */
|
||||
+ call_func (DSO, FUNC);
|
||||
+
|
||||
+ /* Restore old hook. */
|
||||
+ __malloc_hook = old_malloc_hook;
|
||||
+
|
||||
+ /* The function dummy2() is called by the malloc hook. Check to
|
||||
+ see that it was called. This ensures the second recursive
|
||||
+ dlopen happened and we called the function in that library.
|
||||
+
|
||||
+ Before the fix you either get a SIGSEGV when accessing mmap'd
|
||||
+ ld.so.cache data or an assertion failure about _r_debug not
|
||||
+ beint RT_CONSISTENT. We don't test for the SIGSEGV since it
|
||||
+ would require finding moddummy1 or moddummy2 in the cache and
|
||||
+ we don't have any infrastructure to test that, but the _r_debug
|
||||
+ assertion triggers. */
|
||||
+ if (called_func > 0)
|
||||
+ printf ("PASS: Function call_func() called more than once.\n");
|
||||
+ else
|
||||
+ printf ("FAIL: Function call_func() not called.\n");
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#define TEST_FUNCTION do_test ()
|
||||
+#include "../test-skeleton.c"
|
||||
163
src/patches/glibc/glibc-rh1170121.patch
Normal file
163
src/patches/glibc/glibc-rh1170121.patch
Normal file
@@ -0,0 +1,163 @@
|
||||
#
|
||||
# commit a39208bd7fb76c1b01c127b4c61f9bfd915bfe7c
|
||||
# Author: Carlos O'Donell <carlos@redhat.com>
|
||||
# Date: Wed Nov 19 11:44:12 2014 -0500
|
||||
#
|
||||
# CVE-2014-7817: wordexp fails to honour WRDE_NOCMD.
|
||||
#
|
||||
# The function wordexp() fails to properly handle the WRDE_NOCMD
|
||||
# flag when processing arithmetic inputs in the form of "$((... ``))"
|
||||
# where "..." can be anything valid. The backticks in the arithmetic
|
||||
# epxression are evaluated by in a shell even if WRDE_NOCMD forbade
|
||||
# command substitution. This allows an attacker to attempt to pass
|
||||
# dangerous commands via constructs of the above form, and bypass
|
||||
# the WRDE_NOCMD flag. This patch fixes this by checking for WRDE_NOCMD
|
||||
# in exec_comm(), the only place that can execute a shell. All other
|
||||
# checks for WRDE_NOCMD are superfluous and removed.
|
||||
#
|
||||
# We expand the testsuite and add 3 new regression tests of roughly
|
||||
# the same form but with a couple of nested levels.
|
||||
#
|
||||
# On top of the 3 new tests we add fork validation to the WRDE_NOCMD
|
||||
# testing. If any forks are detected during the execution of a wordexp()
|
||||
# call with WRDE_NOCMD, the test is marked as failed. This is slightly
|
||||
# heuristic since vfork might be used in the future, but it provides a
|
||||
# higher level of assurance that no shells were executed as part of
|
||||
# command substitution with WRDE_NOCMD in effect. In addition it doesn't
|
||||
# require libpthread or libdl, instead we use the public implementation
|
||||
# namespace function __register_atfork (already part of the public ABI
|
||||
# for libpthread).
|
||||
#
|
||||
# Tested on x86_64 with no regressions.
|
||||
#
|
||||
diff --git a/posix/wordexp-test.c b/posix/wordexp-test.c
|
||||
index 4957006..bdd65e4 100644
|
||||
--- a/posix/wordexp-test.c
|
||||
+++ b/posix/wordexp-test.c
|
||||
@@ -27,6 +27,25 @@
|
||||
|
||||
#define IFS " \n\t"
|
||||
|
||||
+extern void *__dso_handle __attribute__ ((__weak__, __visibility__ ("hidden")));
|
||||
+extern int __register_atfork (void (*) (void), void (*) (void), void (*) (void), void *);
|
||||
+
|
||||
+static int __app_register_atfork (void (*prepare) (void), void (*parent) (void), void (*child) (void))
|
||||
+{
|
||||
+ return __register_atfork (prepare, parent, child,
|
||||
+ &__dso_handle == NULL ? NULL : __dso_handle);
|
||||
+}
|
||||
+
|
||||
+/* Number of forks seen. */
|
||||
+static int registered_forks;
|
||||
+
|
||||
+/* For each fork increment the fork count. */
|
||||
+static void
|
||||
+register_fork (void)
|
||||
+{
|
||||
+ registered_forks++;
|
||||
+}
|
||||
+
|
||||
struct test_case_struct
|
||||
{
|
||||
int retval;
|
||||
@@ -206,6 +225,12 @@ struct test_case_struct
|
||||
{ WRDE_SYNTAX, NULL, "$((2+))", 0, 0, { NULL, }, IFS },
|
||||
{ WRDE_SYNTAX, NULL, "`", 0, 0, { NULL, }, IFS },
|
||||
{ WRDE_SYNTAX, NULL, "$((010+4+))", 0, 0, { NULL }, IFS },
|
||||
+ /* Test for CVE-2014-7817. We test 3 combinations of command
|
||||
+ substitution inside an arithmetic expression to make sure that
|
||||
+ no commands are executed and error is returned. */
|
||||
+ { WRDE_CMDSUB, NULL, "$((`echo 1`))", WRDE_NOCMD, 0, { NULL, }, IFS },
|
||||
+ { WRDE_CMDSUB, NULL, "$((1+`echo 1`))", WRDE_NOCMD, 0, { NULL, }, IFS },
|
||||
+ { WRDE_CMDSUB, NULL, "$((1+$((`echo 1`))))", WRDE_NOCMD, 0, { NULL, }, IFS },
|
||||
|
||||
{ -1, NULL, NULL, 0, 0, { NULL, }, IFS },
|
||||
};
|
||||
@@ -258,6 +283,15 @@ main (int argc, char *argv[])
|
||||
return -1;
|
||||
}
|
||||
|
||||
+ /* If we are not allowed to do command substitution, we install
|
||||
+ fork handlers to verify that no forks happened. No forks should
|
||||
+ happen at all if command substitution is disabled. */
|
||||
+ if (__app_register_atfork (register_fork, NULL, NULL) != 0)
|
||||
+ {
|
||||
+ printf ("Failed to register fork handler.\n");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
for (test = 0; test_case[test].retval != -1; test++)
|
||||
if (testit (&test_case[test]))
|
||||
++fail;
|
||||
@@ -367,6 +401,9 @@ testit (struct test_case_struct *tc)
|
||||
|
||||
printf ("Test %d (%s): ", ++tests, tc->words);
|
||||
|
||||
+ if (tc->flags & WRDE_NOCMD)
|
||||
+ registered_forks = 0;
|
||||
+
|
||||
if (tc->flags & WRDE_APPEND)
|
||||
{
|
||||
/* initial wordexp() call, to be appended to */
|
||||
@@ -378,6 +415,13 @@ testit (struct test_case_struct *tc)
|
||||
}
|
||||
retval = wordexp (tc->words, &we, tc->flags);
|
||||
|
||||
+ if ((tc->flags & WRDE_NOCMD)
|
||||
+ && (registered_forks > 0))
|
||||
+ {
|
||||
+ printf ("FAILED fork called for WRDE_NOCMD\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
if (tc->flags & WRDE_DOOFFS)
|
||||
start_offs = sav_we.we_offs;
|
||||
|
||||
diff --git a/posix/wordexp.c b/posix/wordexp.c
|
||||
index b6b65dd..26f3a26 100644
|
||||
--- a/posix/wordexp.c
|
||||
+++ b/posix/wordexp.c
|
||||
@@ -893,6 +893,10 @@ exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length,
|
||||
pid_t pid;
|
||||
int noexec = 0;
|
||||
|
||||
+ /* Do nothing if command substitution should not succeed. */
|
||||
+ if (flags & WRDE_NOCMD)
|
||||
+ return WRDE_CMDSUB;
|
||||
+
|
||||
/* Don't fork() unless necessary */
|
||||
if (!comm || !*comm)
|
||||
return 0;
|
||||
@@ -2082,9 +2086,6 @@ parse_dollars (char **word, size_t *word_length, size_t *max_length,
|
||||
}
|
||||
}
|
||||
|
||||
- if (flags & WRDE_NOCMD)
|
||||
- return WRDE_CMDSUB;
|
||||
-
|
||||
(*offset) += 2;
|
||||
return parse_comm (word, word_length, max_length, words, offset, flags,
|
||||
quoted? NULL : pwordexp, ifs, ifs_white);
|
||||
@@ -2196,9 +2197,6 @@ parse_dquote (char **word, size_t *word_length, size_t *max_length,
|
||||
break;
|
||||
|
||||
case '`':
|
||||
- if (flags & WRDE_NOCMD)
|
||||
- return WRDE_CMDSUB;
|
||||
-
|
||||
++(*offset);
|
||||
error = parse_backtick (word, word_length, max_length, words,
|
||||
offset, flags, NULL, NULL, NULL);
|
||||
@@ -2357,12 +2355,6 @@ wordexp (const char *words, wordexp_t *pwordexp, int flags)
|
||||
break;
|
||||
|
||||
case '`':
|
||||
- if (flags & WRDE_NOCMD)
|
||||
- {
|
||||
- error = WRDE_CMDSUB;
|
||||
- goto do_error;
|
||||
- }
|
||||
-
|
||||
++words_offset;
|
||||
error = parse_backtick (&word, &word_length, &max_length, words,
|
||||
&words_offset, flags, pwordexp, ifs,
|
||||
210
src/patches/glibc/glibc-rh1183533.patch
Normal file
210
src/patches/glibc/glibc-rh1183533.patch
Normal file
@@ -0,0 +1,210 @@
|
||||
commit d5dd6189d506068ed11c8bfa1e1e9bffde04decd
|
||||
Author: Andreas Schwab <schwab@suse.de>
|
||||
Date: Mon Jan 21 17:41:28 2013 +0100
|
||||
|
||||
Fix parsing of numeric hosts in gethostbyname_r
|
||||
|
||||
diff --git a/nss/digits_dots.c b/nss/digits_dots.c
|
||||
index 2b86295..e007ef4 100644
|
||||
--- a/nss/digits_dots.c
|
||||
+++ b/nss/digits_dots.c
|
||||
@@ -46,7 +46,10 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf,
|
||||
{
|
||||
if (h_errnop)
|
||||
*h_errnop = NETDB_INTERNAL;
|
||||
- *result = NULL;
|
||||
+ if (buffer_size == NULL)
|
||||
+ *status = NSS_STATUS_TRYAGAIN;
|
||||
+ else
|
||||
+ *result = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -83,14 +86,16 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf,
|
||||
}
|
||||
|
||||
size_needed = (sizeof (*host_addr)
|
||||
- + sizeof (*h_addr_ptrs) + strlen (name) + 1);
|
||||
+ + sizeof (*h_addr_ptrs)
|
||||
+ + sizeof (*h_alias_ptr) + strlen (name) + 1);
|
||||
|
||||
if (buffer_size == NULL)
|
||||
{
|
||||
if (buflen < size_needed)
|
||||
{
|
||||
+ *status = NSS_STATUS_TRYAGAIN;
|
||||
if (h_errnop != NULL)
|
||||
- *h_errnop = TRY_AGAIN;
|
||||
+ *h_errnop = NETDB_INTERNAL;
|
||||
__set_errno (ERANGE);
|
||||
goto done;
|
||||
}
|
||||
@@ -109,7 +114,7 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf,
|
||||
*buffer_size = 0;
|
||||
__set_errno (save);
|
||||
if (h_errnop != NULL)
|
||||
- *h_errnop = TRY_AGAIN;
|
||||
+ *h_errnop = NETDB_INTERNAL;
|
||||
*result = NULL;
|
||||
goto done;
|
||||
}
|
||||
@@ -149,7 +154,9 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf,
|
||||
if (! ok)
|
||||
{
|
||||
*h_errnop = HOST_NOT_FOUND;
|
||||
- if (buffer_size)
|
||||
+ if (buffer_size == NULL)
|
||||
+ *status = NSS_STATUS_NOTFOUND;
|
||||
+ else
|
||||
*result = NULL;
|
||||
goto done;
|
||||
}
|
||||
@@ -190,7 +197,7 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf,
|
||||
if (buffer_size == NULL)
|
||||
*status = NSS_STATUS_SUCCESS;
|
||||
else
|
||||
- *result = resbuf;
|
||||
+ *result = resbuf;
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -201,15 +208,6 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf,
|
||||
|
||||
if ((isxdigit (name[0]) && strchr (name, ':') != NULL) || name[0] == ':')
|
||||
{
|
||||
- const char *cp;
|
||||
- char *hostname;
|
||||
- typedef unsigned char host_addr_t[16];
|
||||
- host_addr_t *host_addr;
|
||||
- typedef char *host_addr_list_t[2];
|
||||
- host_addr_list_t *h_addr_ptrs;
|
||||
- size_t size_needed;
|
||||
- int addr_size;
|
||||
-
|
||||
switch (af)
|
||||
{
|
||||
default:
|
||||
@@ -225,7 +223,10 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf,
|
||||
/* This is not possible. We cannot represent an IPv6 address
|
||||
in an `struct in_addr' variable. */
|
||||
*h_errnop = HOST_NOT_FOUND;
|
||||
- *result = NULL;
|
||||
+ if (buffer_size == NULL)
|
||||
+ *status = NSS_STATUS_NOTFOUND;
|
||||
+ else
|
||||
+ *result = NULL;
|
||||
goto done;
|
||||
|
||||
case AF_INET6:
|
||||
@@ -233,42 +234,6 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf,
|
||||
break;
|
||||
}
|
||||
|
||||
- size_needed = (sizeof (*host_addr)
|
||||
- + sizeof (*h_addr_ptrs) + strlen (name) + 1);
|
||||
-
|
||||
- if (buffer_size == NULL && buflen < size_needed)
|
||||
- {
|
||||
- if (h_errnop != NULL)
|
||||
- *h_errnop = TRY_AGAIN;
|
||||
- __set_errno (ERANGE);
|
||||
- goto done;
|
||||
- }
|
||||
- else if (buffer_size != NULL && *buffer_size < size_needed)
|
||||
- {
|
||||
- char *new_buf;
|
||||
- *buffer_size = size_needed;
|
||||
- new_buf = realloc (*buffer, *buffer_size);
|
||||
-
|
||||
- if (new_buf == NULL)
|
||||
- {
|
||||
- save = errno;
|
||||
- free (*buffer);
|
||||
- __set_errno (save);
|
||||
- *buffer = NULL;
|
||||
- *buffer_size = 0;
|
||||
- *result = NULL;
|
||||
- goto done;
|
||||
- }
|
||||
- *buffer = new_buf;
|
||||
- }
|
||||
-
|
||||
- memset (*buffer, '\0', size_needed);
|
||||
-
|
||||
- host_addr = (host_addr_t *) *buffer;
|
||||
- h_addr_ptrs = (host_addr_list_t *)
|
||||
- ((char *) host_addr + sizeof (*host_addr));
|
||||
- hostname = (char *) h_addr_ptrs + sizeof (*h_addr_ptrs);
|
||||
-
|
||||
for (cp = name;; ++cp)
|
||||
{
|
||||
if (!*cp)
|
||||
@@ -281,7 +246,9 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf,
|
||||
if (inet_pton (AF_INET6, name, host_addr) <= 0)
|
||||
{
|
||||
*h_errnop = HOST_NOT_FOUND;
|
||||
- if (buffer_size)
|
||||
+ if (buffer_size == NULL)
|
||||
+ *status = NSS_STATUS_NOTFOUND;
|
||||
+ else
|
||||
*result = NULL;
|
||||
goto done;
|
||||
}
|
||||
diff --git a/nss/getXXbyYY_r.c b/nss/getXXbyYY_r.c
|
||||
index 1067744..44d00f4 100644
|
||||
--- a/nss/getXXbyYY_r.c
|
||||
+++ b/nss/getXXbyYY_r.c
|
||||
@@ -179,6 +179,9 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
|
||||
case -1:
|
||||
return errno;
|
||||
case 1:
|
||||
+#ifdef NEED_H_ERRNO
|
||||
+ any_service = true;
|
||||
+#endif
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
diff --git a/nss/test-digits-dots.c b/nss/test-digits-dots.c
|
||||
new file mode 100644
|
||||
index 0000000..1efa344
|
||||
--- /dev/null
|
||||
+++ b/nss/test-digits-dots.c
|
||||
@@ -0,0 +1,38 @@
|
||||
+/* 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/>. */
|
||||
+
|
||||
+/* Testcase for BZ #15014 */
|
||||
+
|
||||
+#include <stdlib.h>
|
||||
+#include <netdb.h>
|
||||
+#include <errno.h>
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ char buf[32];
|
||||
+ struct hostent *result = NULL;
|
||||
+ struct hostent ret;
|
||||
+ int h_err = 0;
|
||||
+ int err;
|
||||
+
|
||||
+ err = gethostbyname_r ("1.2.3.4", &ret, buf, sizeof (buf), &result, &h_err);
|
||||
+ return err == ERANGE && h_err == NETDB_INTERNAL ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
+}
|
||||
+
|
||||
+#define TEST_FUNCTION do_test ()
|
||||
+#include "../test-skeleton.c"
|
||||
246
src/patches/glibc/glibc-rh995972.patch
Normal file
246
src/patches/glibc/glibc-rh995972.patch
Normal file
@@ -0,0 +1,246 @@
|
||||
commit d26dfc60edc8c6dd160eefff16a734152a835ca0
|
||||
Author: Martin von Gagern <Martin.vGagern@gmx.net>
|
||||
Date: Sat May 14 21:25:43 2011 -0400
|
||||
|
||||
Fix handling of static TLS in dlopen'ed objects
|
||||
|
||||
When dynamically loading a library along with several dependencies, calls to
|
||||
_dl_add_to_slotinfo and _dl_update_slotinfo can become intermixed. As a
|
||||
consequence, _dl_update_slotinfo will update the generation counter of the dtv
|
||||
although not all of the slots belonging to that generation have been added.
|
||||
Subsequent calls to _dl_add_to_slotinfo will add more slots to the same
|
||||
generation, for which no storage will be allocated, as the dtv generation
|
||||
checks will claim no work is necessary. This will lead to uninitialized dtv
|
||||
entries and will likely cause a SIGSEGV when thread local variables are
|
||||
accessed.
|
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile
|
||||
index 8d9657d..6efb86c 100644
|
||||
--- a/elf/Makefile
|
||||
+++ b/elf/Makefile
|
||||
@@ -76,6 +76,7 @@ distribute := rtld-Rules \
|
||||
tst-tlsmod12.c tst-tls10.h tst-alignmod.c tst-alignmod2.c \
|
||||
circlemod1.c circlemod1a.c circlemod2.c circlemod2a.c \
|
||||
circlemod3.c circlemod3a.c nodlopenmod2.c \
|
||||
+ tst-tls19mod1.c tst-tls19mod2.c tst-tls19mod3.c \
|
||||
tls-macros.h \
|
||||
reldep8mod1.c reldep8mod2.c reldep8mod3.c \
|
||||
nodel2mod1.c nodel2mod2.c nodel2mod3.c \
|
||||
@@ -194,7 +195,7 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
|
||||
restest2 next dblload dblunload reldep5 reldep6 reldep7 reldep8 \
|
||||
circleload1 tst-tls3 tst-tls4 tst-tls5 tst-tls6 tst-tls7 tst-tls8 \
|
||||
tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-tls15 \
|
||||
- tst-tls16 tst-tls17 tst-tls18 tst-tls-dlinfo \
|
||||
+ tst-tls16 tst-tls17 tst-tls18 tst-tls19 tst-tls-dlinfo \
|
||||
tst-align tst-align2 $(tests-execstack-$(have-z-execstack)) \
|
||||
tst-dlmodcount tst-dlopenrpath tst-deep1 \
|
||||
tst-dlmopen1 tst-dlmopen2 tst-dlmopen3 \
|
||||
@@ -240,6 +241,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
||||
$(patsubst %,tst-tlsmod17a%,$(tlsmod17a-suffixes)) \
|
||||
tst-tlsmod17b \
|
||||
$(patsubst %,tst-tlsmod18a%,$(tlsmod18a-suffixes)) \
|
||||
+ tst-tls19mod1 tst-tls19mod2 tst-tls19mod3 \
|
||||
circlemod1 circlemod1a circlemod2 circlemod2a \
|
||||
circlemod3 circlemod3a \
|
||||
reldep8mod1 reldep8mod2 reldep8mod3 \
|
||||
@@ -525,6 +527,8 @@ $(objpfx)tst-tlsmod13a.so: $(objpfx)tst-tlsmod13.so
|
||||
# For tst-tls9-static, make sure the modules it dlopens have libc.so in DT_NEEDED
|
||||
$(objpfx)tst-tlsmod5.so: $(common-objpfx)libc.so
|
||||
$(objpfx)tst-tlsmod6.so: $(common-objpfx)libc.so
|
||||
+$(objpfx)tst-tls19mod1.so: $(objpfx)tst-tls19mod2.so $(objpfx)tst-tls19mod3.so
|
||||
+$(objpfx)tst-tls19mod3.so: $(objpfx)ld.so
|
||||
$(objpfx)reldep8mod3.so: $(objpfx)reldep8mod1.so $(objpfx)reldep8mod2.so
|
||||
$(objpfx)nodel2mod3.so: $(objpfx)nodel2mod1.so $(objpfx)nodel2mod2.so
|
||||
$(objpfx)reldep9mod2.so: $(objpfx)reldep9mod1.so
|
||||
@@ -822,6 +826,9 @@ $(patsubst %,$(objpfx)%.os,$(tlsmod18a-modules)): $(objpfx)tst-tlsmod18a%.os : t
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ -DN=$* -DNOT_IN_libc=1 $<
|
||||
$(patsubst %,$(objpfx)tst-tlsmod18a%.so,$(tlsmod18a-suffixes)): $(objpfx)tst-tlsmod18a%.so: $(objpfx)ld.so
|
||||
|
||||
+$(objpfx)tst-tls19: $(libdl)
|
||||
+$(objpfx)tst-tls19.out: $(objpfx)tst-tls19mod1.so
|
||||
+
|
||||
CFLAGS-tst-align.c = $(stack-align-test-flags)
|
||||
CFLAGS-tst-align2.c = $(stack-align-test-flags)
|
||||
CFLAGS-tst-alignmod.c = $(stack-align-test-flags)
|
||||
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
||||
index cf8e8cc..8d90b56 100644
|
||||
--- a/elf/dl-open.c
|
||||
+++ b/elf/dl-open.c
|
||||
@@ -347,6 +347,7 @@ dl_open_worker (void *a)
|
||||
/* If the file is not loaded now as a dependency, add the search
|
||||
list of the newly loaded object to the scope. */
|
||||
bool any_tls = false;
|
||||
+ unsigned int first_static_tls = new->l_searchlist.r_nlist;
|
||||
for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
|
||||
{
|
||||
struct link_map *imap = new->l_searchlist.r_list[i];
|
||||
@@ -425,30 +426,9 @@ dl_open_worker (void *a)
|
||||
might have to increase its size. */
|
||||
_dl_add_to_slotinfo (imap);
|
||||
|
||||
- if (imap->l_need_tls_init)
|
||||
- {
|
||||
- /* For static TLS we have to allocate the memory here
|
||||
- and now. This includes allocating memory in the DTV.
|
||||
- But we cannot change any DTV other than our own. So,
|
||||
- if we cannot guarantee that there is room in the DTV
|
||||
- we don't even try it and fail the load.
|
||||
-
|
||||
- XXX We could track the minimum DTV slots allocated in
|
||||
- all threads. */
|
||||
- if (! RTLD_SINGLE_THREAD_P && imap->l_tls_modid > DTV_SURPLUS)
|
||||
- _dl_signal_error (0, "dlopen", NULL, N_("\
|
||||
-cannot load any more object with static TLS"));
|
||||
-
|
||||
- imap->l_need_tls_init = 0;
|
||||
-#ifdef SHARED
|
||||
- /* Update the slot information data for at least the
|
||||
- generation of the DSO we are allocating data for. */
|
||||
- _dl_update_slotinfo (imap->l_tls_modid);
|
||||
-#endif
|
||||
-
|
||||
- GL(dl_init_static_tls) (imap);
|
||||
- assert (imap->l_need_tls_init == 0);
|
||||
- }
|
||||
+ if (imap->l_need_tls_init
|
||||
+ && first_static_tls == new->l_searchlist.r_nlist)
|
||||
+ first_static_tls = i;
|
||||
|
||||
/* We have to bump the generation counter. */
|
||||
any_tls = true;
|
||||
@@ -460,6 +440,40 @@ cannot load any more object with static TLS"));
|
||||
_dl_fatal_printf (N_("\
|
||||
TLS generation counter wrapped! Please report this."));
|
||||
|
||||
+ /* We need a second pass for static tls data, because _dl_update_slotinfo
|
||||
+ must not be run while calls to _dl_add_to_slotinfo are still pending. */
|
||||
+ for (unsigned int i = first_static_tls; i < new->l_searchlist.r_nlist; ++i)
|
||||
+ {
|
||||
+ struct link_map *imap = new->l_searchlist.r_list[i];
|
||||
+
|
||||
+ if (imap->l_need_tls_init
|
||||
+ && ! imap->l_init_called
|
||||
+ && imap->l_tls_blocksize > 0)
|
||||
+ {
|
||||
+ /* For static TLS we have to allocate the memory here and
|
||||
+ now. This includes allocating memory in the DTV. But we
|
||||
+ cannot change any DTV other than our own. So, if we
|
||||
+ cannot guarantee that there is room in the DTV we don't
|
||||
+ even try it and fail the load.
|
||||
+
|
||||
+ XXX We could track the minimum DTV slots allocated in
|
||||
+ all threads. */
|
||||
+ if (! RTLD_SINGLE_THREAD_P && imap->l_tls_modid > DTV_SURPLUS)
|
||||
+ _dl_signal_error (0, "dlopen", NULL, N_("\
|
||||
+cannot load any more object with static TLS"));
|
||||
+
|
||||
+ imap->l_need_tls_init = 0;
|
||||
+#ifdef SHARED
|
||||
+ /* Update the slot information data for at least the
|
||||
+ generation of the DSO we are allocating data for. */
|
||||
+ _dl_update_slotinfo (imap->l_tls_modid);
|
||||
+#endif
|
||||
+
|
||||
+ GL(dl_init_static_tls) (imap);
|
||||
+ assert (imap->l_need_tls_init == 0);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/* Notify the debugger all new objects have been relocated. */
|
||||
if (relocation_in_progress)
|
||||
LIBC_PROBE (rtld_reloc_complete, 3, args->nsid, r, new);
|
||||
diff --git a/elf/tst-tls19.c b/elf/tst-tls19.c
|
||||
new file mode 100644
|
||||
index 0000000..acbc1d6
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-tls19.c
|
||||
@@ -0,0 +1,27 @@
|
||||
+// BZ 12453
|
||||
+#include <stdio.h>
|
||||
+#include <dlfcn.h>
|
||||
+
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ void* dl = dlopen ("tst-tls19mod1.so", RTLD_LAZY | RTLD_GLOBAL);
|
||||
+ if (dl == NULL)
|
||||
+ {
|
||||
+ printf ("Error loading tst-tls19mod1.so: %s\n", dlerror ());
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ int (*fn) (void) = dlsym (dl, "foo");
|
||||
+ if (fn == NULL)
|
||||
+ {
|
||||
+ printf("Error obtaining symbol foo\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return fn ();
|
||||
+}
|
||||
+
|
||||
+#define TEST_FUNCTION do_test ()
|
||||
+#include "../test-skeleton.c"
|
||||
diff --git a/elf/tst-tls19mod1.c b/elf/tst-tls19mod1.c
|
||||
new file mode 100644
|
||||
index 0000000..2790097
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-tls19mod1.c
|
||||
@@ -0,0 +1,15 @@
|
||||
+#include <stdio.h>
|
||||
+
|
||||
+extern int bar (void);
|
||||
+extern int baz (void);
|
||||
+
|
||||
+int
|
||||
+foo (void)
|
||||
+{
|
||||
+ int v1 = bar ();
|
||||
+ int v2 = baz ();
|
||||
+
|
||||
+ printf ("bar=%d, baz=%d\n", v1, v2);
|
||||
+
|
||||
+ return v1 != 666 || v2 != 42;
|
||||
+}
|
||||
diff --git a/elf/tst-tls19mod2.c b/elf/tst-tls19mod2.c
|
||||
new file mode 100644
|
||||
index 0000000..cae702f
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-tls19mod2.c
|
||||
@@ -0,0 +1,13 @@
|
||||
+static int __thread tbar __attribute__ ((tls_model ("initial-exec"))) = 666;
|
||||
+
|
||||
+void
|
||||
+setter (int a)
|
||||
+{
|
||||
+ tbar = a;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+bar (void)
|
||||
+{
|
||||
+ return tbar;
|
||||
+}
|
||||
diff --git a/elf/tst-tls19mod3.c b/elf/tst-tls19mod3.c
|
||||
new file mode 100644
|
||||
index 0000000..e7b2801
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-tls19mod3.c
|
||||
@@ -0,0 +1,16 @@
|
||||
+#include <stdio.h>
|
||||
+
|
||||
+static int __thread tbaz __attribute__ ((tls_model ("local-dynamic"))) = 42;
|
||||
+
|
||||
+void
|
||||
+setter2 (int a)
|
||||
+{
|
||||
+ tbaz = a;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+baz (void)
|
||||
+{
|
||||
+ printf ("&tbaz=%p\n", &tbaz);
|
||||
+ return tbaz;
|
||||
+}
|
||||
Reference in New Issue
Block a user