Skip to content

Instantly share code, notes, and snippets.

@brandt
Last active February 23, 2016 19:26
Show Gist options
  • Save brandt/aff503bad08ade6d6930 to your computer and use it in GitHub Desktop.
Save brandt/aff503bad08ade6d6930 to your computer and use it in GitHub Desktop.
Changes in RHEL/CentOS from glibc-2.12-1.149 glibc-2.12-1.166
glibc-2.12-1.166.el6_7.7.i686 updates
* Thu Jan 28 12:00:00 2016 Carlos O'Donell <carlos@redhat.com> - 2.12-1.166.7
- Update fix for CVE-2015-7547 (#1296028).
* Mon Jan 25 12:00:00 2016 Carlos O'Donell <carlos@redhat.com> - 2.12-1.166.6
- Create helper threads with enough stack for POSIX AIO and timers (#1301625).
* Thu Jan 14 12:00:00 2016 Carlos O'Donell <carlos@redhat.com> - 2.12-1.166.5
- Fix CVE-2015-7547: getaddrinfo() stack-based buffer overflow (#1296028).
* Mon Jan 4 12:00:00 2016 Carlos O'Donell <carlos@redhat.com> - 2.12-1.166.4
- Support loading more libraries with static TLS (#1291270).
* Wed Aug 26 12:00:00 2015 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.166.3
- Check for NULL arena pointer in _int_pvalloc (#1256890).
- Don't change no_dyn_threshold on mallopt failure (#1256891).
* Tue Aug 25 12:00:00 2015 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.166.2
- Unlock main arena after allocation in calloc (#1256812).
- Enable robust malloc change again (#1256812).
- Fix perturbing in malloc on free and simply perturb_byte (#1256812).
- Don't fall back to mmap prematurely (#1256812).
* Thu Jul 16 12:00:00 2015 Carlos O'Donell <carlos@redhat.com> -2.12-1.166.1
- The malloc deadlock avoidance support has been temporarily removed since it
triggers deadlocks in certain applications (#1244002).
* Wed May 20 12:00:00 2015 Carlos O'Donell <carlos@redhat.com> - 2.12-1.166
- Fix ruserok() check to reject, not skip, negative user checks (#1217186).
* Thu May 7 12:00:00 2015 Carlos O'Donell <carlos@redhat.com> - 2.12-1.165
- Optimize ruserok() function for large ~/.rhosts (#1217186).
* Mon Apr 20 12:00:00 2015 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.164
- Fix crash in valloc due to the backtrace deadlock fix (#1207236).
* Tue Apr 7 12:00:00 2015 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.163
- Fix buffer overflow in gethostbyname_r with misaligned buffer
(#1209376, CVE-2015-1781).
* Wed Mar 4 12:00:00 2015 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.162
- Avoid deadlock in malloc on backtrace (#1066724).
* Wed Mar 4 12:00:00 2015 Carlos O'Donell <carlos@redhat.com> - 2.12-1.161
- Support running applications that use Intel AVX-512 (#1195453).
* Thu Feb 19 12:00:00 2015 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.160
- Silence logging of record type mismatch for DNSSEC records (#1088301).
* Thu Feb 19 12:00:00 2015 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.159
- Shrink heap on free when vm.overcommit_memory == 2 (#867679).
* Wed Feb 18 12:00:00 2015 Carlos O'Donell <carlos@redhat.com> - 2.12-1.158
- Enhance nscd to detect any configuration file changes (#859965).
- Fix __times() handling of EFAULT when buf is NULL (#1124204).
- Fix memory leak with dlopen() and thread-local storage variables (#978098).
- Prevent getaddrinfo from writing DNS queries to random fd (CVE-2013-7423,
- Implement userspace half of in6.h header coordination (#1053178).
- Correctely size relocation cache used by profiler (#1144132).
- Fix reuse of cached stack leading to bounds overrun of DTV (#1116050).
* Fri Jan 30 12:00:00 2015 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.157
- Return failure in getnetgrent only when all netgroups have been searched
(#1085312).
- Fix valgrind warning in nscd_stats (#1091915).
* Tue Jan 27 12:00:00 2015 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.156
- Initialize xports array (#1159167).
- Fix tst-default-attr test to not fail on powerpc (#1023306).
* Mon Jan 19 12:00:00 2015 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.155
- Fix parsing of numeric hosts in gethostbyname_r (CVE-2015-0235, #1183534).
* Tue Jan 13 12:00:00 2015 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.154
- Fix typo in nscd/selinux.c (#1125307).
- Actually run test-iconv modules (#1176907).
* Thu Dec 11 12:00:00 2014 Carlos O'Donell <carlos@redhat.com> - 2.12-1.153
- Fix recursive dlopen() (#1154563).
* Tue Dec 9 12:00:00 2014 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.152
- Fix crashes on invalid input in IBM gconv modules (CVE-2014-6040, #1172044).
* Tue Dec 9 12:00:00 2014 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.151
- Fix wordexp() to honour WRDE_NOCMD (CVE-2014-7817, #1171296).
* Tue Dec 9 12:00:00 2014 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.150
- Fix typo in res_send and res_query (#rh1138769).
* Tue Aug 26 12:00:00 2014 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.149
- Remove gconv transliteration loadable modules support (CVE-2014-5119,
- _nl_find_locale: Improve handling of crafted locale names (CVE-2014-0475,
glibc-common-2.12-1.166.el6_7.7.x86_64 updates
* Thu Jan 28 12:00:00 2016 Carlos O'Donell <carlos@redhat.com> - 2.12-1.166.7
- Update fix for CVE-2015-7547 (#1296028).
* Mon Jan 25 12:00:00 2016 Carlos O'Donell <carlos@redhat.com> - 2.12-1.166.6
- Create helper threads with enough stack for POSIX AIO and timers (#1301625).
* Thu Jan 14 12:00:00 2016 Carlos O'Donell <carlos@redhat.com> - 2.12-1.166.5
- Fix CVE-2015-7547: getaddrinfo() stack-based buffer overflow (#1296028).
* Mon Jan 4 12:00:00 2016 Carlos O'Donell <carlos@redhat.com> - 2.12-1.166.4
- Support loading more libraries with static TLS (#1291270).
* Wed Aug 26 12:00:00 2015 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.166.3
- Check for NULL arena pointer in _int_pvalloc (#1256890).
- Don't change no_dyn_threshold on mallopt failure (#1256891).
* Tue Aug 25 12:00:00 2015 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.166.2
- Unlock main arena after allocation in calloc (#1256812).
- Enable robust malloc change again (#1256812).
- Fix perturbing in malloc on free and simply perturb_byte (#1256812).
- Don't fall back to mmap prematurely (#1256812).
* Thu Jul 16 12:00:00 2015 Carlos O'Donell <carlos@redhat.com> -2.12-1.166.1
- The malloc deadlock avoidance support has been temporarily removed since it
triggers deadlocks in certain applications (#1244002).
* Wed May 20 12:00:00 2015 Carlos O'Donell <carlos@redhat.com> - 2.12-1.166
- Fix ruserok() check to reject, not skip, negative user checks (#1217186).
* Thu May 7 12:00:00 2015 Carlos O'Donell <carlos@redhat.com> - 2.12-1.165
- Optimize ruserok() function for large ~/.rhosts (#1217186).
* Mon Apr 20 12:00:00 2015 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.164
- Fix crash in valloc due to the backtrace deadlock fix (#1207236).
* Tue Apr 7 12:00:00 2015 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.163
- Fix buffer overflow in gethostbyname_r with misaligned buffer
(#1209376, CVE-2015-1781).
* Wed Mar 4 12:00:00 2015 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.162
- Avoid deadlock in malloc on backtrace (#1066724).
* Wed Mar 4 12:00:00 2015 Carlos O'Donell <carlos@redhat.com> - 2.12-1.161
- Support running applications that use Intel AVX-512 (#1195453).
* Thu Feb 19 12:00:00 2015 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.160
- Silence logging of record type mismatch for DNSSEC records (#1088301).
* Thu Feb 19 12:00:00 2015 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.159
- Shrink heap on free when vm.overcommit_memory == 2 (#867679).
* Wed Feb 18 12:00:00 2015 Carlos O'Donell <carlos@redhat.com> - 2.12-1.158
- Enhance nscd to detect any configuration file changes (#859965).
- Fix __times() handling of EFAULT when buf is NULL (#1124204).
- Fix memory leak with dlopen() and thread-local storage variables (#978098).
- Prevent getaddrinfo from writing DNS queries to random fd (CVE-2013-7423,
- Implement userspace half of in6.h header coordination (#1053178).
- Correctely size relocation cache used by profiler (#1144132).
- Fix reuse of cached stack leading to bounds overrun of DTV (#1116050).
* Fri Jan 30 12:00:00 2015 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.157
- Return failure in getnetgrent only when all netgroups have been searched
(#1085312).
- Fix valgrind warning in nscd_stats (#1091915).
* Tue Jan 27 12:00:00 2015 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.156
- Initialize xports array (#1159167).
- Fix tst-default-attr test to not fail on powerpc (#1023306).
* Mon Jan 19 12:00:00 2015 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.155
- Fix parsing of numeric hosts in gethostbyname_r (CVE-2015-0235, #1183534).
* Tue Jan 13 12:00:00 2015 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.154
- Fix typo in nscd/selinux.c (#1125307).
- Actually run test-iconv modules (#1176907).
* Thu Dec 11 12:00:00 2014 Carlos O'Donell <carlos@redhat.com> - 2.12-1.153
- Fix recursive dlopen() (#1154563).
* Tue Dec 9 12:00:00 2014 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.152
- Fix crashes on invalid input in IBM gconv modules (CVE-2014-6040, #1172044).
* Tue Dec 9 12:00:00 2014 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.151
- Fix wordexp() to honour WRDE_NOCMD (CVE-2014-7817, #1171296).
* Tue Dec 9 12:00:00 2014 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.150
- Fix typo in res_send and res_query (#rh1138769).
* Tue Aug 26 12:00:00 2014 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.149
- Remove gconv transliteration loadable modules support (CVE-2014-5119,
- _nl_find_locale: Improve handling of crafted locale names (CVE-2014-0475,
diff -pruN glibc-2.17-c758a686/nptl/Makefile glibc-2.17-c758a686.new/nptl/Makefile
--- glibc-2.17-c758a686/nptl/Makefile 2013-07-31 11:51:24.882747234 +0530
+++ glibc-2.17-c758a686.new/nptl/Makefile 2013-07-31 11:58:55.964731526 +0530
@@ -276,10 +276,7 @@ gen-as-const-headers = pthread-errnos.sy
LDFLAGS-tst-cond24 = -lrt
LDFLAGS-tst-cond25 = -lrt
-# The size is 1MB + 4KB. The extra 4KB has been added to prevent allocatestack
-# from resizing the input size to avoid the 64K aliasing conflict on Intel
-# processors.
-DEFAULT_STACKSIZE=1052672
+DEFAULT_STACKSIZE=1048576
CFLAGS-tst-default-attr.c = -DDEFAULT_STACKSIZE=$(DEFAULT_STACKSIZE)
tst-default-attr-ENV = GLIBC_PTHREAD_STACKSIZE=$(DEFAULT_STACKSIZE)
diff -pruN glibc-2.17-c758a686/nptl/tst-default-attr.c glibc-2.17-c758a686.new/nptl/tst-default-attr.c
--- glibc-2.17-c758a686/nptl/tst-default-attr.c 2013-07-31 11:51:24.885747234 +0530
+++ glibc-2.17-c758a686.new/nptl/tst-default-attr.c 2013-07-31 12:18:10.016691337 +0530
@@ -38,6 +38,7 @@
/* DEFAULT_STACKSIZE macro is defined in the Makefile. */
static size_t stacksize = DEFAULT_STACKSIZE;
+long int pagesize;
static int
verify_stacksize_result (pthread_attr_t *attr)
@@ -46,12 +47,20 @@ verify_stacksize_result (pthread_attr_t
RETURN_IF_FAIL (pthread_attr_getstacksize, attr, &stack);
- if (stacksize != stack)
+ /* pthread_create perturbs the stack size by a page if it aligns to 64K to
+ avoid the 64K aliasing conflict. We cannot simply add 4K to the size in
+ the Makefile because it breaks the test on powerpc since the page size
+ there is 64K, resulting in a resize in __pthread_initialize_minimal.
+ Hence, our check is to ensure that the stack size is not more than a page
+ more than the requested size. */
+ if (stack < stacksize || stack > stacksize + pagesize)
{
printf ("failed to set default stacksize (%zu, %zu)\n", stacksize, stack);
return 1;
}
+ printf ("Requested %zu and got %zu\n", stacksize, stack);
+
return 0;
}
@@ -101,6 +110,15 @@ run_threads (void)
static int
do_test (void)
{
+ pthread_attr_t attr;
+
+ pagesize = sysconf (_SC_PAGESIZE);
+ if (pagesize < 0)
+ {
+ printf ("sysconf failed: %s\n", strerror (errno));
+ return 1;
+ }
+
RETURN_IF_FAIL (run_threads);
return 0;
}
#
# Based on the commit:
#
# commit 6c82a2f8d7c8e21e39237225c819f182ae438db3
# Author: Carlos O'Donell <carlos@redhat.com>
# Date: Fri Sep 6 01:02:30 2013 -0400
#
# Coordinate IPv6 definitions for Linux and glibc
#
# This change synchronizes the glibc headers with the Linux kernel
# headers and arranges to coordinate the definition of structures
# already defined the Linux kernel UAPI headers.
#
# It is now safe to include glibc's netinet/in.h or Linux's linux/in6.h
# in any order in a userspace application and you will get the same
# ABI. The ABI is guaranteed by UAPI and glibc.
#
# 2013-09-05 Carlos O'Donell <carlos@redhat.com>
# Cong Wang <amwang@redhat.com>
#
# * sysdeps/unix/sysv/linux/bits/in.h
# [_UAPI_LINUX_IN6_H]: Define __USE_KERNEL_IPV6_DEFS.
# * inet/netinet/in.h: Move in_addr definition and bits/in.h inclusion
# before __USE_KERNEL_IPV6_DEFS uses.
# * inet/netinet/in.h [!__USE_KERNEL_IPV6_DEFS]: Define IPPROTO_MH, and
# IPPROTO_BEETPH.
# [__USE_KERNEL_IPV6_DEFS]: Don't define any of IPPROTO_*, in6_addr,
# sockaddr_in6, or ipv6_mreq.
#
diff -urN glibc-2.12-2-gc4ccff1/inet/netinet/in.h glibc-2.12-2-gc4ccff1.mod/inet/netinet/in.h
--- glibc-2.12-2-gc4ccff1/inet/netinet/in.h 2010-05-04 07:27:23.000000000 -0400
+++ glibc-2.12-2-gc4ccff1.mod/inet/netinet/in.h 2015-02-18 13:06:56.436802873 -0500
@@ -28,13 +28,21 @@
__BEGIN_DECLS
+/* Internet address. */
+typedef uint32_t in_addr_t;
+struct in_addr
+ {
+ in_addr_t s_addr;
+ };
+
+/* Get system-specific definitions. */
+#include <bits/in.h>
+
/* Standard well-defined IP protocols. */
enum
{
IPPROTO_IP = 0, /* Dummy protocol for TCP. */
#define IPPROTO_IP IPPROTO_IP
- IPPROTO_HOPOPTS = 0, /* IPv6 Hop-by-Hop options. */
-#define IPPROTO_HOPOPTS IPPROTO_HOPOPTS
IPPROTO_ICMP = 1, /* Internet Control Message Protocol. */
#define IPPROTO_ICMP IPPROTO_ICMP
IPPROTO_IGMP = 2, /* Internet Group Management Protocol. */
@@ -57,10 +65,6 @@
#define IPPROTO_DCCP IPPROTO_DCCP
IPPROTO_IPV6 = 41, /* IPv6 header. */
#define IPPROTO_IPV6 IPPROTO_IPV6
- IPPROTO_ROUTING = 43, /* IPv6 routing header. */
-#define IPPROTO_ROUTING IPPROTO_ROUTING
- IPPROTO_FRAGMENT = 44, /* IPv6 fragmentation header. */
-#define IPPROTO_FRAGMENT IPPROTO_FRAGMENT
IPPROTO_RSVP = 46, /* Reservation Protocol. */
#define IPPROTO_RSVP IPPROTO_RSVP
IPPROTO_GRE = 47, /* General Routing Encapsulation. */
@@ -69,14 +73,10 @@
#define IPPROTO_ESP IPPROTO_ESP
IPPROTO_AH = 51, /* authentication header. */
#define IPPROTO_AH IPPROTO_AH
- IPPROTO_ICMPV6 = 58, /* ICMPv6. */
-#define IPPROTO_ICMPV6 IPPROTO_ICMPV6
- IPPROTO_NONE = 59, /* IPv6 no next header. */
-#define IPPROTO_NONE IPPROTO_NONE
- IPPROTO_DSTOPTS = 60, /* IPv6 destination options. */
-#define IPPROTO_DSTOPTS IPPROTO_DSTOPTS
IPPROTO_MTP = 92, /* Multicast Transport Protocol. */
#define IPPROTO_MTP IPPROTO_MTP
+ IPPROTO_BEETPH = 94, /* IP option pseudo header for BEET. */
+#define IPPROTO_BEETPH IPPROTO_BEETPH
IPPROTO_ENCAP = 98, /* Encapsulation Header. */
#define IPPROTO_ENCAP IPPROTO_ENCAP
IPPROTO_PIM = 103, /* Protocol Independent Multicast. */
@@ -92,6 +92,28 @@
IPPROTO_MAX
};
+/* If __USER_KERNEL_IPV6_DEFS is defined then the user has included the kernel
+ network headers first and we should use those ABI-identical definitions
+ instead of our own. */
+#ifndef __USE_KERNEL_IPV6_DEFS
+enum
+ {
+ IPPROTO_HOPOPTS = 0, /* IPv6 Hop-by-Hop options. */
+#define IPPROTO_HOPOPTS IPPROTO_HOPOPTS
+ IPPROTO_ROUTING = 43, /* IPv6 routing header. */
+#define IPPROTO_ROUTING IPPROTO_ROUTING
+ IPPROTO_FRAGMENT = 44, /* IPv6 fragmentation header. */
+#define IPPROTO_FRAGMENT IPPROTO_FRAGMENT
+ IPPROTO_ICMPV6 = 58, /* ICMPv6. */
+#define IPPROTO_ICMPV6 IPPROTO_ICMPV6
+ IPPROTO_NONE = 59, /* IPv6 no next header. */
+#define IPPROTO_NONE IPPROTO_NONE
+ IPPROTO_DSTOPTS = 60, /* IPv6 destination options. */
+#define IPPROTO_DSTOPTS IPPROTO_DSTOPTS
+ IPPROTO_MH = 135, /* IPv6 mobility header. */
+#define IPPROTO_MH IPPROTO_MH
+ };
+#endif /* !__USE_KERNEL_IPV6_DEFS */
/* Type to represent a port. */
typedef uint16_t in_port_t;
@@ -136,15 +158,6 @@
IPPORT_USERRESERVED = 5000
};
-
-/* Internet address. */
-typedef uint32_t in_addr_t;
-struct in_addr
- {
- in_addr_t s_addr;
- };
-
-
/* Definitions of the bits in an Internet address integer.
On subnets, host and network parts are found according to
@@ -193,7 +206,7 @@
#define INADDR_ALLRTRS_GROUP ((in_addr_t) 0xe0000002) /* 224.0.0.2 */
#define INADDR_MAX_LOCAL_GROUP ((in_addr_t) 0xe00000ff) /* 224.0.0.255 */
-
+#ifndef __USE_KERNEL_IPV6_DEFS
/* IPv6 address */
struct in6_addr
{
@@ -211,6 +224,7 @@
# define s6_addr32 __in6_u.__u6_addr32
#endif
};
+#endif /* !__USE_KERNEL_IPV6_DEFS */
extern const struct in6_addr in6addr_any; /* :: */
extern const struct in6_addr in6addr_loopback; /* ::1 */
@@ -235,6 +249,7 @@
sizeof (struct in_addr)];
};
+#ifndef __USE_KERNEL_IPV6_DEFS
/* Ditto, for IPv6. */
struct sockaddr_in6
{
@@ -244,7 +259,7 @@
struct in6_addr sin6_addr; /* IPv6 address */
uint32_t sin6_scope_id; /* IPv6 scope-id */
};
-
+#endif /* !__USE_KERNEL_IPV6_DEFS */
#if defined __USE_MISC || defined __USE_GNU
/* IPv4 multicast request. */
@@ -270,7 +285,7 @@
};
#endif
-
+#ifndef __USE_KERNEL_IPV6_DEFS
/* Likewise, for IPv6. */
struct ipv6_mreq
{
@@ -280,7 +295,7 @@
/* local interface */
unsigned int ipv6mr_interface;
};
-
+#endif /* !__USE_KERNEL_IPV6_DEFS */
#if defined __USE_MISC || defined __USE_GNU
/* Multicast group request. */
@@ -351,10 +366,6 @@
* sizeof (struct sockaddr_storage)))
#endif
-
-/* Get system-specific definitions. */
-#include <bits/in.h>
-
/* Functions to convert between host and network byte order.
Please note that these functions normally take `unsigned long int' or
diff -urN glibc-2.12-2-gc4ccff1/sysdeps/unix/sysv/linux/bits/in.h glibc-2.12-2-gc4ccff1.mod/sysdeps/unix/sysv/linux/bits/in.h
--- glibc-2.12-2-gc4ccff1/sysdeps/unix/sysv/linux/bits/in.h 2015-02-18 13:04:15.547734092 -0500
+++ glibc-2.12-2-gc4ccff1.mod/sysdeps/unix/sysv/linux/bits/in.h 2015-02-18 13:06:56.436802873 -0500
@@ -22,6 +22,18 @@
# error "Never use <bits/in.h> directly; include <netinet/in.h> instead."
#endif
+/* If the application has already included linux/in6.h from a linux-based
+ kernel then we will not define the IPv6 IPPROTO_* defines, in6_addr (nor the
+ defines), sockaddr_in6, or ipv6_mreq. The ABI used by the linux-kernel and
+ glibc match exactly. Neither the linux kernel nor glibc should break this
+ ABI without coordination. */
+#ifdef _UAPI_LINUX_IN6_H
+/* This is not quite the same API since the kernel always defines s6_addr16 and
+ s6_addr32. This is not a violation of POSIX since POSIX says "at least the
+ following member" and that holds true. */
+# define __USE_KERNEL_IPV6_DEFS
+#endif
+
/* Options for use with `getsockopt' and `setsockopt' at the IP level.
The first word in the comment at the right is the data type used;
"bool" means a boolean value stored in an `int'. */
diff --git a/malloc/Makefile b/malloc/Makefile
index e7ec1ab..5330a3b 100644
--- a/malloc/Makefile
+++ b/malloc/Makefile
@@ -27,7 +27,8 @@ all:
dist-headers := malloc.h
headers := $(dist-headers) obstack.h mcheck.h
tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
- tst-mallocstate tst-mcheck tst-mallocfork tst-trim1
+ tst-mallocstate tst-mcheck tst-mallocfork tst-trim1 \
+ tst-malloc-backtrace
test-srcs = tst-mtrace
distribute = thread-m.h mtrace.pl mcheck-init.c stackinfo.h memusage.h \
@@ -49,6 +50,9 @@ extra-libs-others = $(extra-libs)
libmemusage-routines = memusage
libmemusage-inhibit-o = $(filter-out .os,$(object-suffixes))
+$(objpfx)tst-malloc-backtrace: $(common-objpfx)nptl/libpthread.so \
+ $(common-objpfx)nptl/libpthread_nonshared.a
+
# These should be removed by `make clean'.
extra-objs = mcheck-init.o libmcheck.a
diff --git a/malloc/arena.c b/malloc/arena.c
index 18bea2b..5180516 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -123,7 +123,7 @@ int __malloc_initialized = -1;
#ifdef PER_THREAD
#define arena_lock(ptr, size) do { \
- if(ptr) \
+ if(ptr && !arena_is_corrupt (ptr)) \
(void)mutex_lock(&ptr->mutex); \
else \
ptr = arena_get2(ptr, (size), false); \
@@ -1011,7 +1011,21 @@ reused_arena (bool retrying)
if (retrying && result == &main_arena)
result = result->next;
- /* No arena available. Wait for the next in line. */
+ /* Make sure that the arena we get is not corrupted. */
+ mstate begin = result;
+ while (arena_is_corrupt (result))
+ {
+ result = result->next;
+ if (result == begin)
+ break;
+ }
+
+ /* We could not find any arena that was either not corrupted or not the one
+ we wanted to avoid. */
+ if (result == begin)
+ return NULL;
+
+ /* No arena available without contention. Wait for the next in line. */
(void)mutex_lock(&result->mutex);
out:
diff --git a/malloc/hooks.c b/malloc/hooks.c
index cc83d21..38d2542 100644
--- a/malloc/hooks.c
+++ b/malloc/hooks.c
@@ -220,7 +220,8 @@ top_check()
return 0;
mutex_unlock(&main_arena);
- malloc_printerr (check_action, "malloc: top chunk is corrupt", t);
+ malloc_printerr (check_action, "malloc: top chunk is corrupt", t,
+ &main_arena);
mutex_lock(&main_arena);
/* Try to set up a new top chunk. */
@@ -283,7 +284,7 @@ free_check(mem, caller) Void_t* mem; const Void_t *caller;
if(!p) {
(void)mutex_unlock(&main_arena.mutex);
- malloc_printerr(check_action, "free(): invalid pointer", mem);
+ malloc_printerr(check_action, "free(): invalid pointer", mem, &main_arena);
return;
}
#if HAVE_MMAP
@@ -329,7 +330,8 @@ realloc_check(oldmem, bytes, caller)
const mchunkptr oldp = mem2chunk_check(oldmem, &magic_p);
(void)mutex_unlock(&main_arena.mutex);
if(!oldp) {
- malloc_printerr(check_action, "realloc(): invalid pointer", oldmem);
+ malloc_printerr(check_action, "realloc(): invalid pointer", oldmem,
+ &main_arena);
return malloc_check(bytes, NULL);
}
const INTERNAL_SIZE_T oldsize = chunksize(oldp);
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 597c7b0..20ac534 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -1633,7 +1633,7 @@ static size_t mUSABLe(Void_t*);
static void mSTATs(void);
static int mALLOPt(int, int);
static struct mallinfo mALLINFo(mstate);
-static void malloc_printerr(int action, const char *str, void *ptr);
+static void malloc_printerr(int action, const char *str, void *ptr, mstate av);
static Void_t* internal_function mem2mem_check(Void_t *p, size_t sz);
static int internal_function top_check(void);
@@ -2114,7 +2114,8 @@ typedef struct malloc_chunk* mbinptr;
BK = P->bk; \
if (__builtin_expect (FD->bk != P || BK->fd != P, 0)) { \
mutex_unlock(&(AV)->mutex); \
- malloc_printerr (check_action, "corrupted double-linked list", P); \
+ malloc_printerr (check_action, "corrupted double-linked list", P, \
+ AV); \
mutex_lock(&(AV)->mutex); \
} else { \
FD->bk = BK; \
@@ -2344,6 +2345,15 @@ typedef struct malloc_chunk* mfastbinptr;
#define set_noncontiguous(M) ((M)->flags |= NONCONTIGUOUS_BIT)
#define set_contiguous(M) ((M)->flags &= ~NONCONTIGUOUS_BIT)
+/* ARENA_CORRUPTION_BIT is set if a memory corruption was detected on the
+ arena. Such an arena is no longer used to allocate chunks. Chunks
+ allocated in that arena before detecting corruption are not freed. */
+
+#define ARENA_CORRUPTION_BIT (4U)
+
+#define arena_is_corrupt(A) (((A)->flags & ARENA_CORRUPTION_BIT))
+#define set_arena_corrupt(A) ((A)->flags |= ARENA_CORRUPTION_BIT)
+
/*
Set value of max_fast.
Use impossibly small value if 0.
@@ -3002,8 +3012,9 @@ static Void_t* sYSMALLOc(nb, av) INTERNAL_SIZE_T nb; mstate av;
rather than expanding top.
*/
- if ((unsigned long)(nb) >= (unsigned long)(mp_.mmap_threshold) &&
- (mp_.n_mmaps < mp_.n_mmaps_max)) {
+ if (av == NULL
+ || ((unsigned long)(nb) >= (unsigned long)(mp_.mmap_threshold) &&
+ (mp_.n_mmaps < mp_.n_mmaps_max))) {
char* mm; /* return value from mmap call*/
@@ -3079,6 +3090,10 @@ static Void_t* sYSMALLOc(nb, av) INTERNAL_SIZE_T nb; mstate av;
}
#endif
+ /* There are no usable arenas and mmap also failed. */
+ if (av == NULL)
+ return 0;
+
/* Record incoming configuration of top */
old_top = av->top;
@@ -3260,7 +3275,7 @@ static Void_t* sYSMALLOc(nb, av) INTERNAL_SIZE_T nb; mstate av;
else if (contiguous(av) && old_size && brk < old_end) {
/* Oops! Someone else killed our space.. Can't touch anything. */
mutex_unlock(&av->mutex);
- malloc_printerr (3, "break adjusted to free malloc space", brk);
+ malloc_printerr (3, "break adjusted to free malloc space", brk, av);
mutex_lock(&av->mutex);
}
@@ -3542,7 +3557,7 @@ munmap_chunk(p) mchunkptr p;
if (__builtin_expect (((block | total_size) & (mp_.pagesize - 1)) != 0, 0))
{
malloc_printerr (check_action, "munmap_chunk(): invalid pointer",
- chunk2mem (p));
+ chunk2mem (p), NULL);
return;
}
@@ -3625,65 +3640,31 @@ public_mALLOc(size_t bytes)
if (__builtin_expect (hook != NULL, 0))
return (*hook)(bytes, RETURN_ADDRESS (0));
- arena_lookup(ar_ptr);
-#if 0
- // XXX We need double-word CAS and fastbins must be extended to also
- // XXX hold a generation counter for each entry.
- if (ar_ptr) {
- INTERNAL_SIZE_T nb; /* normalized request size */
- checked_request2size(bytes, nb);
- if (nb <= get_max_fast ()) {
- long int idx = fastbin_index(nb);
- mfastbinptr* fb = &fastbin (ar_ptr, idx);
- mchunkptr pp = *fb;
- mchunkptr v;
- do
- {
- v = pp;
- if (v == NULL)
- break;
- }
- while ((pp = catomic_compare_and_exchange_val_acq (fb, v->fd, v)) != v);
- if (v != 0) {
- if (__builtin_expect (fastbin_index (chunksize (v)) != idx, 0))
- malloc_printerr (check_action, "malloc(): memory corruption (fast)",
- chunk2mem (v));
- check_remalloced_chunk(ar_ptr, v, nb);
- void *p = chunk2mem(v);
- if (__builtin_expect (perturb_byte, 0))
- alloc_perturb (p, bytes);
- return p;
- }
- }
- }
-#endif
+ arena_get(ar_ptr, bytes);
- arena_lock(ar_ptr, bytes);
- if(!ar_ptr)
- return 0;
victim = _int_malloc(ar_ptr, bytes);
- if(!victim) {
+ if(!victim && ar_ptr != NULL) {
/* Maybe the failure is due to running out of mmapped areas. */
if(ar_ptr != &main_arena) {
(void)mutex_unlock(&ar_ptr->mutex);
ar_ptr = &main_arena;
(void)mutex_lock(&ar_ptr->mutex);
victim = _int_malloc(ar_ptr, bytes);
- (void)mutex_unlock(&ar_ptr->mutex);
} else {
#if USE_ARENAS
/* ... or sbrk() has failed and there is still a chance to mmap() */
mstate prev = ar_ptr->next ? ar_ptr : 0;
(void)mutex_unlock(&ar_ptr->mutex);
ar_ptr = arena_get2(prev, bytes, true);
- if(ar_ptr) {
+ if(ar_ptr)
victim = _int_malloc(ar_ptr, bytes);
- (void)mutex_unlock(&ar_ptr->mutex);
- }
#endif
}
- } else
+ }
+
+ if (ar_ptr != NULL)
(void)mutex_unlock(&ar_ptr->mutex);
+
assert(!victim || chunk_is_mmapped(mem2chunk(victim)) ||
ar_ptr == arena_for_chunk(mem2chunk(victim)));
return victim;
@@ -3773,6 +3754,11 @@ public_rEALLOc(Void_t* oldmem, size_t bytes)
/* its size */
const INTERNAL_SIZE_T oldsize = chunksize(oldp);
+ if (chunk_is_mmapped (oldp))
+ ar_ptr = NULL;
+ else
+ ar_ptr = arena_for_chunk (oldp);
+
/* Little security check which won't hurt performance: the
allocator never wrapps around at the end of the address space.
Therefore we can exclude some size values which might appear
@@ -3780,7 +3766,8 @@ public_rEALLOc(Void_t* oldmem, size_t bytes)
if (__builtin_expect ((uintptr_t) oldp > (uintptr_t) -oldsize, 0)
|| __builtin_expect (misaligned_chunk (oldp), 0))
{
- malloc_printerr (check_action, "realloc(): invalid pointer", oldmem);
+ malloc_printerr (check_action, "realloc(): invalid pointer", oldmem,
+ ar_ptr);
return NULL;
}
@@ -3806,7 +3793,6 @@ public_rEALLOc(Void_t* oldmem, size_t bytes)
}
#endif
- ar_ptr = arena_for_chunk(oldp);
#if THREAD_STATS
if(!mutex_trylock(&ar_ptr->mutex))
++(ar_ptr->stat_lock_direct);
@@ -3887,31 +3873,29 @@ public_mEMALIGn(size_t alignment, size_t bytes)
}
arena_get(ar_ptr, bytes + alignment + MINSIZE);
- if(!ar_ptr)
- return 0;
p = _int_memalign(ar_ptr, alignment, bytes);
- if(!p) {
+ if(!p && ar_ptr != NULL) {
/* Maybe the failure is due to running out of mmapped areas. */
if(ar_ptr != &main_arena) {
(void)mutex_unlock(&ar_ptr->mutex);
ar_ptr = &main_arena;
(void)mutex_lock(&ar_ptr->mutex);
p = _int_memalign(ar_ptr, alignment, bytes);
- (void)mutex_unlock(&ar_ptr->mutex);
} else {
#if USE_ARENAS
/* ... or sbrk() has failed and there is still a chance to mmap() */
mstate prev = ar_ptr->next ? ar_ptr : 0;
(void)mutex_unlock(&ar_ptr->mutex);
ar_ptr = arena_get2(prev, bytes, true);
- if(ar_ptr) {
+ if(ar_ptr)
p = _int_memalign(ar_ptr, alignment, bytes);
- (void)mutex_unlock(&ar_ptr->mutex);
- }
#endif
}
- } else
+ }
+
+ if (ar_ptr != NULL)
(void)mutex_unlock(&ar_ptr->mutex);
+
assert(!p || chunk_is_mmapped(mem2chunk(p)) ||
ar_ptr == arena_for_chunk(mem2chunk(p)));
return p;
@@ -3945,31 +3929,29 @@ public_vALLOc(size_t bytes)
return (*hook)(pagesz, bytes, RETURN_ADDRESS (0));
arena_get(ar_ptr, bytes + pagesz + MINSIZE);
- if(!ar_ptr)
- return 0;
p = _int_valloc(ar_ptr, bytes);
- if(!p) {
+ if(!p && ar_ptr != NULL) {
/* Maybe the failure is due to running out of mmapped areas. */
if(ar_ptr != &main_arena) {
(void)mutex_unlock(&ar_ptr->mutex);
ar_ptr = &main_arena;
(void)mutex_lock(&ar_ptr->mutex);
p = _int_memalign(ar_ptr, pagesz, bytes);
- (void)mutex_unlock(&ar_ptr->mutex);
} else {
#if USE_ARENAS
/* ... or sbrk() has failed and there is still a chance to mmap() */
mstate prev = ar_ptr->next ? ar_ptr : 0;
(void)mutex_unlock(&ar_ptr->mutex);
ar_ptr = arena_get2(prev, bytes, true);
- if(ar_ptr) {
+ if(ar_ptr)
p = _int_memalign(ar_ptr, pagesz, bytes);
- (void)mutex_unlock(&ar_ptr->mutex);
- }
#endif
}
- } else
+ }
+
+ if (ar_ptr != NULL)
(void)mutex_unlock(&ar_ptr->mutex);
+
assert(!p || chunk_is_mmapped(mem2chunk(p)) ||
ar_ptr == arena_for_chunk(mem2chunk(p)));
@@ -4004,28 +3986,28 @@ public_pVALLOc(size_t bytes)
arena_get(ar_ptr, bytes + 2*pagesz + MINSIZE);
p = _int_pvalloc(ar_ptr, bytes);
- if(!p) {
+ if(!p && ar_ptr != NULL) {
/* Maybe the failure is due to running out of mmapped areas. */
if(ar_ptr != &main_arena) {
(void)mutex_unlock(&ar_ptr->mutex);
ar_ptr = &main_arena;
(void)mutex_lock(&ar_ptr->mutex);
p = _int_memalign(ar_ptr, pagesz, rounded_bytes);
- (void)mutex_unlock(&ar_ptr->mutex);
} else {
#if USE_ARENAS
/* ... or sbrk() has failed and there is still a chance to mmap() */
mstate prev = ar_ptr->next ? ar_ptr : 0;
(void)mutex_unlock(&ar_ptr->mutex);
ar_ptr = arena_get2(prev, bytes + 2*pagesz + MINSIZE, true);
- if(ar_ptr) {
+ if(ar_ptr)
p = _int_memalign(ar_ptr, pagesz, rounded_bytes);
- (void)mutex_unlock(&ar_ptr->mutex);
- }
#endif
}
- } else
+ }
+
+ if (ar_ptr != NULL)
(void)mutex_unlock(&ar_ptr->mutex);
+
assert(!p || chunk_is_mmapped(mem2chunk(p)) ||
ar_ptr == arena_for_chunk(mem2chunk(p)));
@@ -4072,55 +4054,65 @@ public_cALLOc(size_t n, size_t elem_size)
sz = bytes;
arena_get(av, sz);
- if(!av)
- return 0;
- /* Check if we hand out the top chunk, in which case there may be no
- need to clear. */
+ if (av)
+ {
+ /* Check if we hand out the top chunk, in which case there may be no
+ need to clear. */
#if MORECORE_CLEARS
- oldtop = top(av);
- oldtopsize = chunksize(top(av));
+ oldtop = top(av);
+ oldtopsize = chunksize(top(av));
#if MORECORE_CLEARS < 2
- /* Only newly allocated memory is guaranteed to be cleared. */
- if (av == &main_arena &&
- oldtopsize < mp_.sbrk_base + av->max_system_mem - (char *)oldtop)
- oldtopsize = (mp_.sbrk_base + av->max_system_mem - (char *)oldtop);
+ /* Only newly allocated memory is guaranteed to be cleared. */
+ if (av == &main_arena &&
+ oldtopsize < mp_.sbrk_base + av->max_system_mem - (char *)oldtop)
+ oldtopsize = (mp_.sbrk_base + av->max_system_mem - (char *)oldtop);
#endif
- if (av != &main_arena)
+ if (av != &main_arena)
+ {
+ heap_info *heap = heap_for_ptr (oldtop);
+ if (oldtopsize < (char *) heap + heap->mprotect_size - (char *) oldtop)
+ oldtopsize = (char *) heap + heap->mprotect_size - (char *) oldtop;
+ }
+#endif
+ }
+ else
{
- heap_info *heap = heap_for_ptr (oldtop);
- if (oldtopsize < (char *) heap + heap->mprotect_size - (char *) oldtop)
- oldtopsize = (char *) heap + heap->mprotect_size - (char *) oldtop;
+ /* No usable arenas. */
+ oldtop = 0;
+ oldtopsize = 0;
}
-#endif
mem = _int_malloc(av, sz);
-
assert(!mem || chunk_is_mmapped(mem2chunk(mem)) ||
av == arena_for_chunk(mem2chunk(mem)));
- if (mem == 0) {
+ if (mem == 0 && av != NULL) {
/* Maybe the failure is due to running out of mmapped areas. */
if(av != &main_arena) {
(void)mutex_unlock(&av->mutex);
(void)mutex_lock(&main_arena.mutex);
mem = _int_malloc(&main_arena, sz);
- (void)mutex_unlock(&main_arena.mutex);
} else {
#if USE_ARENAS
/* ... or sbrk() has failed and there is still a chance to mmap() */
mstate prev = av->next ? av : 0;
(void)mutex_unlock(&av->mutex);
av = arena_get2(prev, sz, true);
- if(av) {
+ if(av)
mem = _int_malloc(av, sz);
- (void)mutex_unlock(&av->mutex);
- }
#endif
}
if (mem == 0) return 0;
- } else
+ }
+
+ if (av != NULL)
(void)mutex_unlock(&av->mutex);
+
+ /* Allocation failed even after a retry. */
+ if (mem == 0)
+ return 0;
+
p = mem2chunk(mem);
/* Two optional cases in which clearing not necessary */
@@ -4175,6 +4167,8 @@ public_cALLOc(size_t n, size_t elem_size)
}
#ifndef _LIBC
+/* XXX These functions are not patched to detect arena corruption because they
+ are not built in glibc. */
Void_t**
public_iCALLOc(size_t n, size_t elem_size, Void_t** chunks)
@@ -4309,6 +4303,16 @@ _int_malloc(mstate av, size_t bytes)
checked_request2size(bytes, nb);
+ /* There are no usable arenas. Fall back to sysmalloc to get a chunk from
+ mmap. */
+ if (__glibc_unlikely (av == NULL))
+ {
+ void *p = sYSMALLOc (nb, av);
+ if (p != NULL)
+ alloc_perturb (p, bytes);
+ return p;
+ }
+
/*
If the size qualifies as a fastbin, first check corresponding bin.
This code is safe to execute even if av is not yet initialized, so we
@@ -4337,7 +4341,7 @@ _int_malloc(mstate av, size_t bytes)
errstr = "malloc(): memory corruption (fast)";
errout:
mutex_unlock(&av->mutex);
- malloc_printerr (check_action, errstr, chunk2mem (victim));
+ malloc_printerr (check_action, errstr, chunk2mem (victim), av);
mutex_lock(&av->mutex);
return NULL;
}
@@ -4429,7 +4433,7 @@ _int_malloc(mstate av, size_t bytes)
{
void *p = chunk2mem(victim);
mutex_unlock(&av->mutex);
- malloc_printerr (check_action, "malloc(): memory corruption", p);
+ malloc_printerr (check_action, "malloc(): memory corruption", p, av);
mutex_lock(&av->mutex);
}
size = chunksize(victim);
@@ -4829,7 +4833,7 @@ _int_free(mstate av, mchunkptr p)
if (have_lock || locked)
(void)mutex_unlock(&av->mutex);
#endif
- malloc_printerr (check_action, errstr, chunk2mem(p));
+ malloc_printerr (check_action, errstr, chunk2mem(p), av);
#ifdef ATOMIC_FASTBINS
if (have_lock)
mutex_lock(&av->mutex);
@@ -5281,7 +5285,7 @@ _int_realloc(mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize,
errstr = "realloc(): invalid old size";
errout:
mutex_unlock(&av->mutex);
- malloc_printerr (check_action, errstr, chunk2mem(oldp));
+ malloc_printerr (check_action, errstr, chunk2mem(oldp), av);
mutex_lock(&av->mutex);
return NULL;
}
@@ -5881,6 +5885,10 @@ static int mTRIm(mstate av, size_t pad)
static int mTRIm(av, pad) mstate av; size_t pad;
#endif
{
+ /* Don't touch corrupt arenas. */
+ if (arena_is_corrupt (av))
+ return 0;
+
/* Ensure initialization/consolidation */
malloc_consolidate (av);
@@ -6320,8 +6328,14 @@ int mALLOPt(param_number, value) int param_number; int value;
extern char **__libc_argv attribute_hidden;
static void
-malloc_printerr(int action, const char *str, void *ptr)
+malloc_printerr(int action, const char *str, void *ptr, mstate ar_ptr)
{
+ /* Avoid using this arena in future. We do not attempt to synchronize this
+ with anything else because we minimally want to ensure that __libc_message
+ gets its resources safely without stumbling on the current corruption. */
+ if (ar_ptr)
+ set_arena_corrupt (ar_ptr);
+
if ((action & 5) == 5)
__libc_message (action & 2, "%s\n", str);
else if (action & 1)
diff --git a/malloc/tst-malloc-backtrace.c b/malloc/tst-malloc-backtrace.c
new file mode 100644
index 0000000..796a42f
--- /dev/null
+++ b/malloc/tst-malloc-backtrace.c
@@ -0,0 +1,50 @@
+/* Verify that backtrace does not deadlock on itself on memory corruption.
+ Copyright (C) 2015 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 <stdlib.h>
+
+#define SIZE 4096
+
+/* Wrap free with a function to prevent gcc from optimizing it out. */
+static void
+__attribute__((noinline))
+call_free (void *ptr)
+{
+ free (ptr);
+ *(size_t *)(ptr - sizeof (size_t)) = 1;
+}
+
+int
+do_test (void)
+{
+ void *ptr1 = malloc (SIZE);
+ void *ptr2 = malloc (SIZE);
+
+ call_free ((void *) ptr1);
+ ptr1 = malloc (SIZE);
+
+ /* Not reached. The return statement is to put ptr2 into use so that gcc
+ doesn't optimize out that malloc call. */
+ return (ptr1 == ptr2);
+}
+
+#define TEST_FUNCTION do_test ()
+#define EXPECTED_SIGNAL SIGABRT
+
+#include "../test-skeleton.c"
commit 58b930ae216bfa98cd60212b954b07b9963d6d04
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date: Wed Sep 10 21:51:50 2014 +0530
Return failure in getnetgrent only when all netgroups have been searched (#17363)
The netgroups lookup code fails when one of the groups in the search
tree is empty. In such a case it only returns the leaves of the tree
after the blank netgroup. This is because the line parser returns a
NOTFOUND status when the netgroup exists but is empty. The
__getnetgrent_internal implementation needs to be fixed to try
remaining groups if the current group is entry. This patch implements
this fix. Tested on x86_64.
[BZ #17363]
* inet/getnetgrent_r.c (__internal_getnetgrent_r): Try next
group if the current group is empty.
diff --git a/inet/getnetgrent_r.c b/inet/getnetgrent_r.c
index f6d064d..e101537 100644
--- a/inet/getnetgrent_r.c
+++ b/inet/getnetgrent_r.c
@@ -297,7 +297,10 @@ __internal_getnetgrent_r (char **hostp, char **userp, char **domainp,
{
status = (*fct) (datap, buffer, buflen, &errno);
- if (status == NSS_STATUS_RETURN)
+ if (status == NSS_STATUS_RETURN
+ /* The service returned a NOTFOUND, but there are more groups that we
+ need to resolve before we give up. */
+ || (status == NSS_STATUS_NOTFOUND && datap->needed_groups != NULL))
{
/* This was the last one for this group. Look at next group
if available. */
diff --git a/resolv/arpa/nameser.h b/resolv/arpa/nameser.h
index fb8513b..372d5cd 100644
--- a/resolv/arpa/nameser.h
+++ b/resolv/arpa/nameser.h
@@ -293,6 +293,9 @@ typedef enum __ns_type {
ns_t_sink = 40, /*%< Kitchen sink (experimentatl) */
ns_t_opt = 41, /*%< EDNS0 option (meta-RR) */
ns_t_apl = 42, /*%< Address prefix list (RFC3123) */
+ ns_t_rrsig = 46, /*%< DNSSEC RRset Signature (RFC4034) */
+ ns_t_nsec = 47, /*%< DNSSEC Next-Secure Record (RFC4034)*/
+ ns_t_dnskey = 48, /*%< DNSSEC key record (RFC4034) */
ns_t_tkey = 249, /*%< Transaction key */
ns_t_tsig = 250, /*%< Transaction signature. */
ns_t_ixfr = 251, /*%< Incremental zone transfer. */
diff --git a/resolv/arpa/nameser_compat.h b/resolv/arpa/nameser_compat.h
index d59c9e4..284bff7 100644
--- a/resolv/arpa/nameser_compat.h
+++ b/resolv/arpa/nameser_compat.h
@@ -164,6 +164,9 @@ typedef struct {
#define T_NAPTR ns_t_naptr
#define T_A6 ns_t_a6
#define T_DNAME ns_t_dname
+#define T_RRSIG ns_t_rrsig
+#define T_NSEC ns_t_nsec
+#define T_DNSKEY ns_t_dnskey
#define T_TSIG ns_t_tsig
#define T_IXFR ns_t_ixfr
#define T_AXFR ns_t_axfr
diff --git a/resolv/gethnamaddr.c b/resolv/gethnamaddr.c
index a861a84..ae55fac 100644
--- a/resolv/gethnamaddr.c
+++ b/resolv/gethnamaddr.c
@@ -331,23 +331,36 @@ getanswer (const querybuf *answer, int anslen, const char *qname, int qtype)
buflen -= n;
continue;
}
- if ((type == T_SIG) || (type == T_KEY) || (type == T_NXT)) {
- /* We don't support DNSSEC yet. For now, ignore
- * the record and send a low priority message
- * to syslog.
- */
- syslog(LOG_DEBUG|LOG_AUTH,
+ if ((type == T_SIG) || (type == T_KEY) || (type == T_NXT)
+ || (type == T_RRSIG) || (type == T_NSEC)
+ || (type == T_DNSKEY)) {
+ /* We don't support DNSSEC responses yet, but we do
+ * allow setting the DO bit. If the DNS server sent us
+ * these records without us asking for it, ignore the
+ * record and send a low priority message to syslog.
+ */
+ if ((_res.options & RES_USE_DNSSEC) == 0) {
+ syslog(LOG_DEBUG|LOG_AUTH,
"gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
- qname, p_class(C_IN), p_type(qtype),
- p_type(type));
+ qname, p_class(C_IN), p_type(qtype),
+ p_type(type));
+ }
cp += n;
continue;
}
if (type != qtype) {
- syslog(LOG_NOTICE|LOG_AUTH,
+ /* Skip logging if we received a DNAME when we have set
+ * the DO bit. DNAME records are a convenient way to
+ * set up DNSSEC records and such setups can make this
+ * log message needlessly noisy.
+ */
+ if (!((_res.options & RES_USE_DNSSEC)
+ && type == T_DNAME)) {
+ syslog(LOG_NOTICE|LOG_AUTH,
"gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
- qname, p_class(C_IN), p_type(qtype),
- p_type(type));
+ qname, p_class(C_IN), p_type(qtype),
+ p_type(type));
+ }
cp += n;
continue; /* XXX - had_error++ ? */
}
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
index f715ab0..510d388 100644
--- a/resolv/nss_dns/dns-host.c
+++ b/resolv/nss_dns/dns-host.c
@@ -822,13 +822,20 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
}
if (__builtin_expect (type == T_SIG, 0)
|| __builtin_expect (type == T_KEY, 0)
- || __builtin_expect (type == T_NXT, 0))
+ || __builtin_expect (type == T_NXT, 0)
+ || __builtin_expect (type == T_RRSIG, 0)
+ || __builtin_expect (type == T_NSEC, 0)
+ || __builtin_expect (type == T_DNSKEY, 0))
{
- /* We don't support DNSSEC yet. For now, ignore the record
- and send a low priority message to syslog. */
- syslog (LOG_DEBUG | LOG_AUTH,
- "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
- qname, p_class (C_IN), p_type(qtype), p_type (type));
+ /* We don't support DNSSEC responses yet, but we do allow setting the
+ DO bit. If the DNS server sent us these records without us asking
+ for it, ignore the record and send a low priority message to
+ syslog. */
+ if ((_res.options & RES_USE_DNSSEC) == 0)
+ syslog (LOG_DEBUG | LOG_AUTH,
+ "gethostby*.getanswer: asked for \"%s %s %s\", "
+ "got type \"%s\"",
+ qname, p_class (C_IN), p_type(qtype), p_type (type));
cp += n;
continue;
}
@@ -837,9 +844,14 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
have_to_map = 1;
else if (__builtin_expect (type != qtype, 0))
{
- syslog (LOG_NOTICE | LOG_AUTH,
- "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
- qname, p_class (C_IN), p_type (qtype), p_type (type));
+ /* Skip logging if we received a DNAME when we have set the DO bit.
+ DNAME records are a convenient way to set up DNSSEC records and
+ such setups can make this log message needlessly noisy. */
+ if (!((_res.options & RES_USE_DNSSEC) && type == T_DNAME))
+ syslog (LOG_NOTICE | LOG_AUTH,
+ "gethostby*.getanswer: asked for \"%s %s %s\", "
+ "got type \"%s\"",
+ qname, p_class (C_IN), p_type (qtype), p_type (type));
cp += n;
continue; /* XXX - had_error++ ? */
}
diff --git a/resolv/res_debug.c b/resolv/res_debug.c
index 7843439..4a49629 100644
--- a/resolv/res_debug.c
+++ b/resolv/res_debug.c
@@ -450,6 +450,8 @@ const struct res_sym __p_type_syms[] = {
{ns_t_kx, "KX", "Key Exchange"},
{ns_t_cert, "CERT", "Certificate"},
{ns_t_any, "ANY", "\"any\""},
+ /* TODO Add RRSIG, NSEC and DNSKEY once we actually do something with
+ them. */
{0, NULL, NULL}
};
libresolv_hidden_data_def (__p_type_syms)
commit 3cb26316b45b23dc5cfecbafdc489b28c3a52029
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date: Thu Jan 29 10:30:09 2015 +0530
Initialize nscd stats data [BZ #17892]
The padding bytes in the statsdata struct are not initialized, due to
which valgrind throws a warning:
==11384== Memcheck, a memory error detector
==11384== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==11384== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==11384== Command: nscd -d
==11384==
Fri 25 Apr 2014 10:34:53 AM CEST - 11384: handle_request: request received (Version = 2) from PID 11396
Fri 25 Apr 2014 10:34:53 AM CEST - 11384: GETSTAT
==11384== Thread 6:
==11384== Syscall param socketcall.sendto(msg) points to uninitialised byte(s)
==11384== at 0x4E4ACDC: send (in /lib64/libpthread-2.12.so)
==11384== by 0x11AF6B: send_stats (in /usr/sbin/nscd)
==11384== by 0x112F75: nscd_run_worker (in /usr/sbin/nscd)
==11384== by 0x4E439D0: start_thread (in /lib64/libpthread-2.12.so)
==11384== by 0x599AB6C: clone (in /lib64/libc-2.12.so)
==11384== Address 0x15708395 is on thread 6's stack
Fix the warning by initializing the structure.
diff --git a/nscd/nscd_stat.c b/nscd/nscd_stat.c
index 0f1f3c0..7aaa21b 100644
--- a/nscd/nscd_stat.c
+++ b/nscd/nscd_stat.c
@@ -94,6 +94,8 @@ send_stats (int fd, struct database_dyn dbs[lastdb])
struct statdata data;
int cnt;
+ memset (&data, 0, sizeof (data));
+
memcpy (data.version, compilation, sizeof (compilation));
data.debug_level = debug_level;
data.runtime = time (NULL) - start_time;
#
# In rhel-6.x the Makerules are not entirely as mature as they are
# in glibc 2.21 (from which the example link-libc-args is taken from).
# In rhel-6.x the applications are not built like their counterpart
# real applications, and because of that compiling DSOs that use TLS
# will fail with undefined references to __tls_get_addr which resides
# in ld.so and is never included in the link. This patch enhances
# only the build-module and build-module-asneeded targets to include
# a more fully and correct link line as the compiler driver would use
# when constructing an application or DSO. We do not adjust the link
# lines used to build lib* targets.
#
diff -urN glibc-2.12-2-gc4ccff1.orig/Makerules glibc-2.12-2-gc4ccff1/Makerules
--- glibc-2.12-2-gc4ccff1.orig/Makerules 2015-02-18 19:53:00.000000000 -0500
+++ glibc-2.12-2-gc4ccff1/Makerules 2015-02-18 20:08:33.299000028 -0500
@@ -443,6 +443,25 @@
load-map-file = $(map-file:%=-Wl,--version-script=%)
endif
+# Compiler arguments to use to link a shared object with libc and
+# ld.so. This is intended to be as similar as possible to a default
+# link with an installed libc.
+link-libc-args = -Wl,--start-group \
+ $(libc-for-link) \
+ $(common-objpfx)libc_nonshared.a \
+ $(as-needed) $(elf-objpfx)ld.so $(no-as-needed) \
+ -Wl,--end-group
+
+# The corresponding shared libc to use. This may be modified for a
+# particular target.
+libc-for-link = $(common-objpfx)libc.so
+
+# The corresponding dependencies. As these are used in dependencies,
+# not just commands, they cannot use target-specific variables so need
+# to name both possible libc.so objects.
+link-libc-deps = $(common-objpfx)libc.so $(common-objpfx)linkobj/libc.so \
+ $(common-objpfx)libc_nonshared.a $(elf-objpfx)ld.so
+
# Pattern rule to build a shared object from an archive of PIC objects.
# This must come after the installation rules so Make doesn't try to
# build shared libraries in place from the installed *_pic.a files.
@@ -557,12 +576,13 @@
# not for shared objects
define build-module
$(build-module-helper) -o $@ -T $(common-objpfx)shlib.lds \
- $(csu-objpfx)abi-note.o $(build-module-objlist)
+ $(csu-objpfx)abi-note.o $(build-module-objlist) $(link-libc-args)
endef
define build-module-asneeded
$(build-module-helper) -o $@ -T $(common-objpfx)shlib.lds \
$(csu-objpfx)abi-note.o \
- -Wl,--as-needed $(build-module-objlist) -Wl,--no-as-needed
+ -Wl,--as-needed $(build-module-objlist) -Wl,--no-as-needed \
+ $(link-libc-args)
endef
else
ifneq (,$(findstring aix,$(config-os)))
#
# Based on this upstream commit:
#
# commit d8dd00805b8f3a011735d7a407097fb1c408d867
# Author: H.J. Lu <hjl.tools@gmail.com>
# Date: Fri Nov 28 07:54:07 2014 -0800
#
# Resize DTV if the current DTV isn't big enough
#
# This patch changes _dl_allocate_tls_init to resize DTV if the current DTV
# isn't big enough. Tested on X86-64, x32 and ia32.
#
# [BZ #13862]
# * elf/dl-tls.c: Include <atomic.h>.
# (oom): Remove #ifdef SHARED/#endif.
# (_dl_static_dtv, _dl_initial_dtv): Moved before ...
# (_dl_resize_dtv): This. Extracted from _dl_update_slotinfo.
# (_dl_allocate_tls_init): Resize DTV if the current DTV isn't
# big enough.
# (_dl_update_slotinfo): Call _dl_resize_dtv to resize DTV.
# * nptl/Makefile (tests): Add tst-stack4.
# (modules-names): Add tst-stack4mod.
# ($(objpfx)tst-stack4): New.
# (tst-stack4mod.sos): Likewise.
# ($(objpfx)tst-stack4.out): Likewise.
# ($(tst-stack4mod.sos)): Likewise.
# (clean): Likewise.
# * nptl/tst-stack4.c: New file.
# * nptl/tst-stack4mod.c: Likewise.
#
diff -urN glibc-2.12-2-gc4ccff1/elf/dl-tls.c glibc-2.12-2-gc4ccff1.mod/elf/dl-tls.c
--- glibc-2.12-2-gc4ccff1/elf/dl-tls.c 2015-02-18 14:15:28.078461873 -0500
+++ glibc-2.12-2-gc4ccff1.mod/elf/dl-tls.c 2015-02-18 14:38:37.630374771 -0500
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <sys/param.h>
+#include <atomic.h>
#include <tls.h>
#include <dl-tls.h>
@@ -35,14 +36,12 @@
/* Out-of-memory handler. */
-#ifdef SHARED
static void
__attribute__ ((__noreturn__))
oom (void)
{
_dl_fatal_printf ("cannot allocate memory for thread-local data: ABORT\n");
}
-#endif
size_t
@@ -392,6 +391,52 @@
return result;
}
+static dtv_t *
+_dl_resize_dtv (dtv_t *dtv)
+{
+ /* Resize the dtv. */
+ dtv_t *newp;
+ /* Load GL(dl_tls_max_dtv_idx) atomically since it may be written to by
+ other threads concurrently. -- We don't have the required atomic
+ infrastructure to load dl_tls_max_dtv_idx atomically, but on all the
+ architectures we care about it should load atomically. If this had
+ an atomic_load_acquire we would still be missing the releases for
+ the writes. */
+ size_t newsize = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS;
+ size_t oldsize = dtv[-1].counter;
+
+#if SHARED
+ if (dtv == GL(dl_initial_dtv))
+ {
+ /* This is the initial dtv that was either statically allocated in
+ __libc_setup_tls or allocated during rtld startup using the
+ dl-minimal.c malloc instead of the real malloc. We can't free
+ it, we have to abandon the old storage. */
+
+ newp = malloc ((2 + newsize) * sizeof (dtv_t));
+ if (newp == NULL)
+ oom ();
+ memcpy (newp, &dtv[-1], (2 + oldsize) * sizeof (dtv_t));
+ }
+ else
+#endif
+ {
+ newp = realloc (&dtv[-1],
+ (2 + newsize) * sizeof (dtv_t));
+ if (newp == NULL)
+ oom ();
+ }
+
+ newp[0].counter = newsize;
+
+ /* Clear the newly allocated part. */
+ memset (newp + 2 + oldsize, '\0',
+ (newsize - oldsize) * sizeof (dtv_t));
+
+ /* Return the generation counter. */
+ return &newp[1];
+}
+
void *
internal_function
@@ -406,6 +451,16 @@
size_t total = 0;
size_t maxgen = 0;
+ /* Check if the current dtv is big enough. */
+ if (dtv[-1].counter < GL(dl_tls_max_dtv_idx))
+ {
+ /* Resize the dtv. */
+ dtv = _dl_resize_dtv (dtv);
+
+ /* Install this new dtv in the thread data structures. */
+ INSTALL_DTV (result, &dtv[-1]);
+ }
+
/* We have to prepare the dtv for all currently loaded modules using
TLS. For those which are dynamically loaded we add the values
indicating deferred allocation. */
@@ -637,41 +692,10 @@
assert (total + cnt == modid);
if (dtv[-1].counter < modid)
{
- /* Reallocate the dtv. */
- dtv_t *newp;
- size_t newsize = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS;
- size_t oldsize = dtv[-1].counter;
-
- assert (map->l_tls_modid <= newsize);
-
- if (dtv == GL(dl_initial_dtv))
- {
- /* This is the initial dtv that was allocated
- during rtld startup using the dl-minimal.c
- malloc instead of the real malloc. We can't
- free it, we have to abandon the old storage. */
-
- newp = malloc ((2 + newsize) * sizeof (dtv_t));
- if (newp == NULL)
- oom ();
- memcpy (newp, &dtv[-1], (2 + oldsize) * sizeof (dtv_t));
- }
- else
- {
- newp = realloc (&dtv[-1],
- (2 + newsize) * sizeof (dtv_t));
- if (newp == NULL)
- oom ();
- }
-
- newp[0].counter = newsize;
-
- /* Clear the newly allocated part. */
- memset (newp + 2 + oldsize, '\0',
- (newsize - oldsize) * sizeof (dtv_t));
+ /* Resize the dtv. */
+ dtv = _dl_resize_dtv (dtv);
- /* Point dtv to the generation counter. */
- dtv = &newp[1];
+ assert (modid <= dtv[-1].counter);
/* Install this new dtv in the thread data
structures. */
diff -urN glibc-2.12-2-gc4ccff1/nptl/Makefile glibc-2.12-2-gc4ccff1.mod/nptl/Makefile
--- glibc-2.12-2-gc4ccff1/nptl/Makefile 2015-02-18 14:15:28.073462028 -0500
+++ glibc-2.12-2-gc4ccff1.mod/nptl/Makefile 2015-02-18 14:15:49.817786667 -0500
@@ -245,7 +245,7 @@
tst-exec1 tst-exec2 tst-exec3 tst-exec4 \
tst-exit1 tst-exit2 tst-exit3 \
tst-stdio1 tst-stdio2 \
- tst-stack1 tst-stack2 tst-stack3 \
+ tst-stack1 tst-stack2 tst-stack3 tst-stack4 \
tst-unload \
tst-dlsym1 \
tst-sysconf \
@@ -304,7 +304,7 @@
modules-names = tst-atfork2mod tst-tls3mod tst-tls4moda tst-tls4modb \
tst-tls5mod tst-tls5moda tst-tls5modb tst-tls5modc \
- tst-tls5modd tst-tls5mode tst-tls5modf \
+ tst-tls5modd tst-tls5mode tst-tls5modf tst-stack4mod \
tst-_res1mod1 tst-_res1mod2 tst-execstack-mod tst-fini1mod
extra-test-objs += $(addsuffix .os,$(strip $(modules-names))) tst-cleanup4aux.o
test-extras += $(modules-names)
@@ -459,6 +459,19 @@
$(common-objpfx)malloc/mtrace $(objpfx)tst-stack3.mtrace > $@
generated += tst-stack3-mem tst-stack3.mtrace
+$(objpfx)tst-stack4: $(libdl) $(shared-thread-library)
+tst-stack4mod.sos=$(shell for i in 0 1 2 3 4 5 6 7 8 9 10 \
+ 11 12 13 14 15 16 17 18 19; do \
+ for j in 0 1 2 3 4 5 6 7 8 9 10 \
+ 11 12 13 14 15 16 17 18 19; do \
+ echo $(objpfx)tst-stack4mod-$$i-$$j.so; \
+ done; done)
+$(objpfx)tst-stack4.out: $(tst-stack4mod.sos)
+$(tst-stack4mod.sos): $(objpfx)tst-stack4mod.so
+ cp -f $< $@
+clean:
+ rm -f $(tst-stack4mod.sos)
+
$(objpfx)tst-cleanup4: $(objpfx)tst-cleanup4aux.o $(shared-thread-library)
$(objpfx)tst-cleanupx4: $(objpfx)tst-cleanup4aux.o $(shared-thread-library)
diff -urN glibc-2.12-2-gc4ccff1/nptl/tst-stack4.c glibc-2.12-2-gc4ccff1.mod/nptl/tst-stack4.c
--- glibc-2.12-2-gc4ccff1/nptl/tst-stack4.c 1969-12-31 19:00:00.000000000 -0500
+++ glibc-2.12-2-gc4ccff1.mod/nptl/tst-stack4.c 2015-02-18 14:15:49.817786667 -0500
@@ -0,0 +1,159 @@
+/* Test DTV size oveflow when pthread_create reuses old DTV and TLS is
+ used by dlopened shared object.
+ 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 <stdio.h>
+#include <stdint.h>
+#include <dlfcn.h>
+#include <assert.h>
+#include <pthread.h>
+
+/* The choices of thread count, and file counts are arbitary.
+ The point is simply to run enough threads that an exiting
+ thread has it's stack reused by another thread at the same
+ time as new libraries have been loaded. */
+#define DSO_SHARED_FILES 20
+#define DSO_OPEN_THREADS 20
+#define DSO_EXEC_THREADS 2
+
+/* Used to make sure that only one thread is calling dlopen and dlclose
+ at a time. */
+pthread_mutex_t g_lock;
+
+typedef void (*function) (void);
+
+void *
+dso_invoke(void *dso_fun)
+{
+ function *fun_vec = (function *) dso_fun;
+ int dso;
+
+ for (dso = 0; dso < DSO_SHARED_FILES; dso++)
+ (*fun_vec[dso]) ();
+
+ pthread_exit (NULL);
+}
+
+void *
+dso_process (void * p)
+{
+ void *handle[DSO_SHARED_FILES];
+ function fun_vec[DSO_SHARED_FILES];
+ char dso_path[DSO_SHARED_FILES][100];
+ int dso;
+ uintptr_t t = (uintptr_t) p;
+
+ /* Open DSOs and get a function. */
+ for (dso = 0; dso < DSO_SHARED_FILES; dso++)
+ {
+ sprintf (dso_path[dso], "tst-stack4mod-%i-%i.so", t, dso);
+
+ pthread_mutex_lock (&g_lock);
+
+ handle[dso] = dlopen (dso_path[dso], RTLD_NOW);
+ assert (handle[dso]);
+
+ fun_vec[dso] = (function) dlsym (handle[dso], "function");
+ assert (fun_vec[dso]);
+
+ pthread_mutex_unlock (&g_lock);
+ }
+
+ /* Spawn workers. */
+ pthread_t thread[DSO_EXEC_THREADS];
+ int i, ret;
+ uintptr_t result = 0;
+ for (i = 0; i < DSO_EXEC_THREADS; i++)
+ {
+ pthread_mutex_lock (&g_lock);
+ ret = pthread_create (&thread[i], NULL, dso_invoke, (void *) fun_vec);
+ if (ret != 0)
+ {
+ printf ("pthread_create failed: %d\n", ret);
+ result = 1;
+ }
+ pthread_mutex_unlock (&g_lock);
+ }
+
+ if (!result)
+ for (i = 0; i < DSO_EXEC_THREADS; i++)
+ {
+ ret = pthread_join (thread[i], NULL);
+ if (ret != 0)
+ {
+ printf ("pthread_join failed: %d\n", ret);
+ result = 1;
+ }
+ }
+
+ /* Close all DSOs. */
+ for (dso = 0; dso < DSO_SHARED_FILES; dso++)
+ {
+ pthread_mutex_lock (&g_lock);
+ dlclose (handle[dso]);
+ pthread_mutex_unlock (&g_lock);
+ }
+
+ /* Exit. */
+ pthread_exit ((void *) result);
+}
+
+static int
+do_test (void)
+{
+ pthread_t thread[DSO_OPEN_THREADS];
+ int i,j;
+ int ret;
+ int result = 0;
+
+ pthread_mutex_init (&g_lock, NULL);
+
+ /* 100 is arbitrary here and is known to trigger PR 13862. */
+ for (j = 0; j < 100; j++)
+ {
+ for (i = 0; i < DSO_OPEN_THREADS; i++)
+ {
+ ret = pthread_create (&thread[i], NULL, dso_process,
+ (void *) (uintptr_t) i);
+ if (ret != 0)
+ {
+ printf ("pthread_create failed: %d\n", ret);
+ result = 1;
+ }
+ }
+
+ if (result)
+ break;
+
+ for (i = 0; i < DSO_OPEN_THREADS; i++)
+ {
+ ret = pthread_join (thread[i], NULL);
+ if (ret != 0)
+ {
+ printf ("pthread_join failed: %d\n", ret);
+ result = 1;
+ }
+ }
+ }
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 100
+#include "../test-skeleton.c"
diff -urN glibc-2.12-2-gc4ccff1/nptl/tst-stack4mod.c glibc-2.12-2-gc4ccff1.mod/nptl/tst-stack4mod.c
--- glibc-2.12-2-gc4ccff1/nptl/tst-stack4mod.c 1969-12-31 19:00:00.000000000 -0500
+++ glibc-2.12-2-gc4ccff1.mod/nptl/tst-stack4mod.c 2015-02-18 14:15:49.817786667 -0500
@@ -0,0 +1,28 @@
+/* This tests DTV usage with TLS in dlopened shared object.
+ 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/>. */
+
+/* 256 is arbitrary here and is known to trigger PR 13862. */
+__thread int var[256] attribute_hidden = {0};
+
+void
+function (void)
+{
+ int i;
+ for (i = 0; i < sizeof (var) / sizeof (int); i++)
+ var[i] = i;
+}
#
# Derived from this upstream commit:
#
# commit 58a1335e76a553e1cf4edeebc27f16fc9b53d6e6
# Author: Petr Baudis <pasky@ucw.cz>
# Date: Thu Mar 14 01:16:53 2013 +0100
#
# Fix __times() handling of EFAULT when buf is NULL
#
# 2013-03-14 Petr Baudis <pasky@ucw.cz>
#
# * sysdeps/unix/sysv/linux/times.c (__times): On EFAULT, test
# for non-NULL pointer before the memory validity test. Pointed
# out by Holger Brunck <holger.brunck@keymile.com>.
#
diff --git a/sysdeps/unix/sysv/linux/times.c b/sysdeps/unix/sysv/linux/times.c
index f3b5f01..e59bb4e 100644
--- a/sysdeps/unix/sysv/linux/times.c
+++ b/sysdeps/unix/sysv/linux/times.c
@@ -26,13 +26,14 @@ __times (struct tms *buf)
INTERNAL_SYSCALL_DECL (err);
clock_t ret = INTERNAL_SYSCALL (times, err, 1, buf);
if (INTERNAL_SYSCALL_ERROR_P (ret, err)
- && __builtin_expect (INTERNAL_SYSCALL_ERRNO (ret, err) == EFAULT, 0))
+ && __builtin_expect (INTERNAL_SYSCALL_ERRNO (ret, err) == EFAULT, 0)
+ && buf)
{
/* This might be an error or not. For architectures which have
no separate return value and error indicators we cannot
distinguish a return value of -1 from an error. Do it the
- hard way. We crash applications which pass in an invalid BUF
- pointer. */
+ hard way. We crash applications which pass in an invalid
+ non-NULL BUF pointer. Linux allows BUF to be NULL. */
#define touch(v) \
do { \
clock_t temp = v; \
@@ -44,7 +45,8 @@ __times (struct tms *buf)
touch (buf->tms_cutime);
touch (buf->tms_cstime);
- /* If we come here the memory is valid and the kernel did not
+ /* If we come here the memory is valid (or BUF is NULL, which is
+ * a valid condition for the kernel syscall) and the kernel did not
return an EFAULT error. Return the value given by the kernel. */
}
commit a11892631d92f594c690d0d50a642b0d1aba58b8
Author: Ondřej Bílka <neleai@seznam.cz>
Date: Wed May 7 14:08:57 2014 +0200
Fix typo in nscd/selinux.c
diff --git a/nscd/selinux.c b/nscd/selinux.c
index 9a8a5a8..eaed6dd 100644
--- a/nscd/selinux.c
+++ b/nscd/selinux.c
@@ -372,7 +372,7 @@ nscd_request_avc_has_perm (int fd, request_type req)
/* Get the security class for nscd. If this fails we will likely be
unable to do anything unless avc_deny_unknown is 0. */
sc_nscd = string_to_security_class ("nscd");
- if (perm == 0 && avc_deny_unknown == 1)
+ if (sc_nscd == 0 && avc_deny_unknown == 1)
dbg_log (_("Error getting security class for nscd."));
/* Convert permission to AVC bits. */
commit e35c53e397e7abbd41fedacdedcfa5af7b5c2c52
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date: Tue Jul 8 16:40:24 2014 +0530
Check value at resplen2 if it is not NULL
There was a typo in the previous patch due to which resplen2 was
checked for non-zero instead of the value at resplen2. Fix that and
improve the condition by checking resplen2 for non-NULL (instead of
answerp2) and also adding the check in a third place.
diff --git a/resolv/res_query.c b/resolv/res_query.c
index 4e6612c..e4ee2a6 100644
--- a/resolv/res_query.c
+++ b/resolv/res_query.c
@@ -384,7 +384,7 @@ __libc_res_nsearch(res_state statp,
answerp2, nanswerp2, resplen2);
if (ret > 0 || trailing_dot
/* If the second response is valid then we use that. */
- || (ret == 0 && answerp2 != NULL && resplen2 > 0))
+ || (ret == 0 && resplen2 != NULL && *resplen2 > 0))
return (ret);
saved_herrno = h_errno;
tried_as_is++;
@@ -424,8 +424,8 @@ __libc_res_nsearch(res_state statp,
answer, anslen, answerp,
answerp2, nanswerp2,
resplen2);
- if (ret > 0 || (ret == 0 && answerp2 != NULL
- && resplen2 > 0))
+ if (ret > 0 || (ret == 0 && resplen2 != NULL
+ && *resplen2 > 0))
return (ret);
if (answerp && *answerp != answer) {
@@ -494,7 +494,8 @@ __libc_res_nsearch(res_state statp,
ret = __libc_res_nquerydomain(statp, name, NULL, class, type,
answer, anslen, answerp,
answerp2, nanswerp2, resplen2);
- if (ret > 0)
+ if (ret > 0 || (ret == 0 && resplen2 != NULL
+ && *resplen2 > 0))
return (ret);
}
#
# Based on the following commit:
#
# commit f9d2d03254a58d92635a311a42253eeed5a40a47
# 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)
#
# 2014-06-03 Andreas Schwab <schwab@suse.de>
#
# [BZ #15946]
# * resolv/res_send.c (send_dg): Reload file descriptor after
# calling reopen.
#
diff --git a/resolv/res_send.c b/resolv/res_send.c
index 3273d55..af42b8a 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;
#
# Based on this commit:
#
# commit 62058ce612ed3459501b4c4332e268edfe977f59
# Author: Carlos O'Donell <carlos@redhat.com>
# Date: Mon Sep 29 13:14:21 2014 -0400
#
# Correctly size profiling reloc table (bug 17411)
#
# During auditing or profiling modes the dynamic loader
# builds a cache of the relocated PLT entries in order
# to reuse them when called again through the same PLT
# entry. This way the PLT entry is never completed and
# the call into the resolver always results in profiling
# or auditing code running.
#
# The problem is that the PLT relocation cache size
# is not computed correctly. The size of the cache
# should be "Size of a relocation result structure"
# x "Number of PLT-related relocations". Instead the
# code erroneously computes "Size of a relocation
# result" x "Number of bytes worth of PLT-related
# relocations". I can only assume this was a mistake
# in the understanding of the value of DT_PLTRELSZ
# which is the number of bytes of PLT-related relocs.
# We do have a DT_RELACOUNT entry, which is a count
# for dynamic relative relocs, but we have no
# DT_PLTRELCOUNT and thus we need to compute it.
#
# This patch corrects the computation of the size of the
# relocation table used by the glibc profiling code.
#
# For more details see:
# https://sourceware.org/ml/libc-alpha/2014-09/msg00513.html
#
# [BZ #17411]
# * elf/dl-reloc.c (_dl_relocate_object): Allocate correct amount for
# l_reloc_result.
#
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
index d2c6dac..97a7119 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -279,8 +279,12 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
l->l_name);
}
- l->l_reloc_result = calloc (sizeof (l->l_reloc_result[0]),
- l->l_info[DT_PLTRELSZ]->d_un.d_val);
+ size_t sizeofrel = l->l_info[DT_PLTREL]->d_un.d_val == DT_RELA
+ ? sizeof (ElfW(Rela))
+ : sizeof (ElfW(Rel));
+ size_t relcount = l->l_info[DT_PLTRELSZ]->d_un.d_val / sizeofrel;
+ l->l_reloc_result = calloc (sizeof (l->l_reloc_result[0]), relcount);
+
if (l->l_reloc_result == NULL)
{
errstring = N_("\
#
# 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"
diff --git a/sunrpc/svc.c b/sunrpc/svc.c
index ccf0902..30c3a93 100644
--- a/sunrpc/svc.c
+++ b/sunrpc/svc.c
@@ -97,8 +97,8 @@ xprt_register (SVCXPRT *xprt)
if (xports == NULL)
{
- xports = (SVCXPRT **) malloc (_rpc_dtablesize () * sizeof (SVCXPRT *));
- if (xports == NULL) /* Don´t add handle */
+ xports = (SVCXPRT **) calloc (_rpc_dtablesize (), sizeof (SVCXPRT *));
+ if (xports == NULL) /* Don't add handle */
return;
}
#
# 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,
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
commit 7d81e8d6db95c112c297930a8f2f9617c305529a
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Dec 23 16:16:32 2014 +0100
iconvdata/run-iconv-test.sh: Actually test iconv modules
Arjun Shankar noticed that this test case was not testing anything
because iconv was invoked without the required arguments.
diff --git a/iconvdata/run-iconv-test.sh b/iconvdata/run-iconv-test.sh
index 5dfb69f..1d0bf52 100755
--- a/iconvdata/run-iconv-test.sh
+++ b/iconvdata/run-iconv-test.sh
@@ -189,7 +189,7 @@ 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
+ if $PROG -f $from -t UTF8 < $temp1 >/dev/null 2>&1 ; then
: # fall through
else
status=$?
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/Makefile b/nss/Makefile
index 449a258..553eafa 100644
--- a/nss/Makefile
+++ b/nss/Makefile
@@ -37,7 +37,7 @@ install-bin := getent makedb
others := getent
install-bin := getent
-tests = test-netdb tst-nss-test1
+tests = test-netdb tst-nss-test1 test-digits-dots
xtests = bug-erange
include ../Makeconfig
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"
#
# Based on AVX-512 support for glibc, but heavaily modified for rhel-6.7.
# Without assembler support we drop all of the configure checks and simply
# output using .byte directives the minimal AVX512 instructsion required
# by the loader. Likewise testing is also impossible, so instead we use
# the Intel emulator running in `-skx` (Skylake Xeon) emulation mode and
# verify that a pre-built set of tests passes.
#
# commit 6986b98a18490e76b16911d1c6b1ba013598d40d
# Author: Ulrich Drepper <drepper@gmail.com>
# Date: Wed Jul 20 14:20:00 2011 -0400
#
# Force :a_x86_64_ymm to be 16-byte aligned
#
# commit aa4de9cea5c07d43caeaca9722c2d417e9a2919c
# Author: H.J. Lu <hjl.tools@gmail.com>
# Date: Fri Mar 14 08:51:25 2014 -0700
#
# Check AVX-512 assembler support first
#
# It checks AVX-512 assembler support first and sets libc_cv_cc_avx512 to
# $libc_cv_asm_avx512, instead of yes. GCC won't support AVX-512 if
# assembler doesn't support it.
#
# * sysdeps/x86_64/configure.ac: Check AVX-512 assembler support
# first. Disable AVX-512 GCC support if assembler doesn't support
# it.
# * sysdeps/x86_64/configure: Regenerated.
#
# commit 2d63a517e4084ec80403cd9f278690fa8b676cc4
# Author: Igor Zamyatin <igor.zamyatin@intel.com>
# Date: Thu Mar 13 11:10:22 2014 -0700
#
# Save and restore AVX-512 zmm registers to x86-64 ld.so
#
# AVX-512 ISA adds 512-bit zmm registers. This patch updates
# _dl_runtime_profile to pass zmm registers to run-time audit. It also
# changes _dl_x86_64_save_sse and _dl_x86_64_restore_sse to upport zmm
# registers, which are called when only when RTLD_PREPARE_FOREIGN_CALL
# is used. Its performance impact is minimum.
#
# * config.h.in (HAVE_AVX512_SUPPORT): New #undef.
# (HAVE_AVX512_ASM_SUPPORT): Likewise.
# * sysdeps/x86_64/bits/link.h (La_x86_64_zmm): New.
# (La_x86_64_vector): Add zmm.
# * sysdeps/x86_64/Makefile (tests): Add tst-audit10.
# (modules-names): Add tst-auditmod10a and tst-auditmod10b.
# ($(objpfx)tst-audit10): New target.
# ($(objpfx)tst-audit10.out): Likewise.
# (tst-audit10-ENV): New.
# (AVX512-CFLAGS): Likewise.
# (CFLAGS-tst-audit10.c): Likewise.
# (CFLAGS-tst-auditmod10a.c): Likewise.
# (CFLAGS-tst-auditmod10b.c): Likewise.
# * sysdeps/x86_64/configure.ac: Set config-cflags-avx512,
# HAVE_AVX512_SUPPORT and HAVE_AVX512_ASM_SUPPORT.
# * sysdeps/x86_64/configure: Regenerated.
# * sysdeps/x86_64/dl-trampoline.S (_dl_runtime_profile): Add
# AVX-512 zmm register support.
# (_dl_x86_64_save_sse): Likewise.
# (_dl_x86_64_restore_sse): Likewise.
# * sysdeps/x86_64/dl-trampoline.h: Updated to support different
# size vector registers.
# * sysdeps/x86_64/link-defines.sym (YMM_SIZE): New.
# (ZMM_SIZE): Likewise.
# * sysdeps/x86_64/tst-audit10.c: New file.
# * sysdeps/x86_64/tst-auditmod10a.c: Likewise.
# * sysdeps/x86_64/tst-auditmod10b.c: Likewise.
#
# In addition adds:
# https://sourceware.org/ml/libc-alpha/2014-09/msg00228.html
# To extend zmm register checking.
#
diff -urN glibc-2.12-2-gc4ccff1/sysdeps/x86_64/bits/link.h glibc-2.12-2-gc4ccff1.mod/sysdeps/x86_64/bits/link.h
--- glibc-2.12-2-gc4ccff1/sysdeps/x86_64/bits/link.h 2010-05-04 07:27:23.000000000 -0400
+++ glibc-2.12-2-gc4ccff1.mod/sysdeps/x86_64/bits/link.h 2015-03-03 23:03:25.041829238 -0500
@@ -65,7 +65,10 @@
/* Registers for entry into PLT on x86-64. */
# if __GNUC_PREREQ (4,0)
typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
-typedef float La_x86_64_ymm __attribute__ ((__vector_size__ (32)));
+typedef float La_x86_64_ymm __attribute__ ((__vector_size__ (32),
+ __aligned__ (16)));
+typedef double La_x86_64_zmm __attribute__ ((__vector_size__ (64),
+ __aligned__ (16)));
# else
typedef float La_x86_64_xmm __attribute__ ((__mode__ (__V4SF__)));
# endif
@@ -74,9 +77,10 @@
{
# if __GNUC_PREREQ (4,0)
La_x86_64_ymm ymm[2];
+ La_x86_64_zmm zmm[1];
# endif
La_x86_64_xmm xmm[4];
-} La_x86_64_vector __attribute__ ((aligned(16)));
+} La_x86_64_vector __attribute__ ((__aligned__(16)));
typedef struct La_x86_64_regs
{
diff -urN glibc-2.12-2-gc4ccff1/sysdeps/x86_64/dl-trampoline.h glibc-2.12-2-gc4ccff1.mod/sysdeps/x86_64/dl-trampoline.h
--- glibc-2.12-2-gc4ccff1/sysdeps/x86_64/dl-trampoline.h 2015-03-03 23:03:05.109457627 -0500
+++ glibc-2.12-2-gc4ccff1.mod/sysdeps/x86_64/dl-trampoline.h 2015-03-03 23:06:58.434101818 -0500
@@ -20,14 +20,26 @@
#ifdef RESTORE_AVX
/* This is to support AVX audit modules. */
- vmovdqu %ymm0, (LR_VECTOR_OFFSET)(%rsp)
- vmovdqu %ymm1, (LR_VECTOR_OFFSET + VECTOR_SIZE)(%rsp)
- vmovdqu %ymm2, (LR_VECTOR_OFFSET + VECTOR_SIZE*2)(%rsp)
- vmovdqu %ymm3, (LR_VECTOR_OFFSET + VECTOR_SIZE*3)(%rsp)
- vmovdqu %ymm4, (LR_VECTOR_OFFSET + VECTOR_SIZE*4)(%rsp)
- vmovdqu %ymm5, (LR_VECTOR_OFFSET + VECTOR_SIZE*5)(%rsp)
- vmovdqu %ymm6, (LR_VECTOR_OFFSET + VECTOR_SIZE*6)(%rsp)
- vmovdqu %ymm7, (LR_VECTOR_OFFSET + VECTOR_SIZE*7)(%rsp)
+# if HAVE_NO_AVX512_ASM_SUPPORT
+ /* Restore AVX-512 registers. Use .byte becaues we lack assembler support. */
+ .byte 0x62,0xf1,0xfe,0x48,0x7f,0x44,0x24,0x03 # vmovdqu64 %zmm0,0xc0(%rsp)
+ .byte 0x62,0xf1,0xfe,0x48,0x7f,0x4c,0x24,0x04 # vmovdqu64 %zmm1,0x100(%rsp)
+ .byte 0x62,0xf1,0xfe,0x48,0x7f,0x54,0x24,0x05 # vmovdqu64 %zmm2,0x140(%rsp)
+ .byte 0x62,0xf1,0xfe,0x48,0x7f,0x5c,0x24,0x06 # vmovdqu64 %zmm3,0x180(%rsp)
+ .byte 0x62,0xf1,0xfe,0x48,0x7f,0x64,0x24,0x07 # vmovdqu64 %zmm4,0x1c0(%rsp)
+ .byte 0x62,0xf1,0xfe,0x48,0x7f,0x6c,0x24,0x08 # vmovdqu64 %zmm5,0x200(%rsp)
+ .byte 0x62,0xf1,0xfe,0x48,0x7f,0x74,0x24,0x09 # vmovdqu64 %zmm6,0x240(%rsp)
+ .byte 0x62,0xf1,0xfe,0x48,0x7f,0x7c,0x24,0x0a # vmovdqu64 %zmm7,0x280(%rsp)
+# else
+ VMOV %VEC(0), (LR_VECTOR_OFFSET)(%rsp)
+ VMOV %VEC(1), (LR_VECTOR_OFFSET + VECTOR_SIZE)(%rsp)
+ VMOV %VEC(2), (LR_VECTOR_OFFSET + VECTOR_SIZE*2)(%rsp)
+ VMOV %VEC(3), (LR_VECTOR_OFFSET + VECTOR_SIZE*3)(%rsp)
+ VMOV %VEC(4), (LR_VECTOR_OFFSET + VECTOR_SIZE*4)(%rsp)
+ VMOV %VEC(5), (LR_VECTOR_OFFSET + VECTOR_SIZE*5)(%rsp)
+ VMOV %VEC(6), (LR_VECTOR_OFFSET + VECTOR_SIZE*6)(%rsp)
+ VMOV %VEC(7), (LR_VECTOR_OFFSET + VECTOR_SIZE*7)(%rsp)
+# endif
/* Save xmm0-xmm7 registers to detect if any of them are
changed by audit module. */
@@ -73,7 +85,11 @@
je 2f
vmovdqa %xmm0, (LR_VECTOR_OFFSET)(%rsp)
jmp 1f
-2: vmovdqu (LR_VECTOR_OFFSET)(%rsp), %ymm0
+# if HAVE_NO_AVX512_ASM_SUPPORT
+2: .byte 0x62,0xf1,0xfe,0x48,0x6f,0x44,0x24,0x03 # vmovdqu64 0xc0(%rsp),%zmm0
+# else
+2: VMOV (LR_VECTOR_OFFSET)(%rsp), %VEC(0)
+# endif
vmovdqa %xmm0, (LR_XMM_OFFSET)(%rsp)
1: vpcmpeqq (LR_SIZE + XMM_SIZE)(%rsp), %xmm1, %xmm8
@@ -82,7 +98,11 @@
je 2f
vmovdqa %xmm1, (LR_VECTOR_OFFSET + VECTOR_SIZE)(%rsp)
jmp 1f
-2: vmovdqu (LR_VECTOR_OFFSET + VECTOR_SIZE)(%rsp), %ymm1
+# if HAVE_NO_AVX512_ASM_SUPPORT
+2: .byte 0x62,0xf1,0xfe,0x48,0x6f,0x4c,0x24,0x04 # vmovdqu64 0x100(%rsp),%zmm1
+# else
+2: VMOV (LR_VECTOR_OFFSET + VECTOR_SIZE)(%rsp), %VEC(1)
+# endif
vmovdqa %xmm1, (LR_XMM_OFFSET + XMM_SIZE)(%rsp)
1: vpcmpeqq (LR_SIZE + XMM_SIZE*2)(%rsp), %xmm2, %xmm8
@@ -91,7 +111,11 @@
je 2f
vmovdqa %xmm2, (LR_VECTOR_OFFSET + VECTOR_SIZE*2)(%rsp)
jmp 1f
-2: vmovdqu (LR_VECTOR_OFFSET + VECTOR_SIZE*2)(%rsp), %ymm2
+# if HAVE_NO_AVX512_ASM_SUPPORT
+2: .byte 0x62,0xf1,0xfe,0x48,0x6f,0x54,0x24,0x05 # vmovdqu64 0x140(%rsp),%zmm2
+# else
+2: VMOV (LR_VECTOR_OFFSET + VECTOR_SIZE*2)(%rsp), %VEC(2)
+# endif
vmovdqa %xmm2, (LR_XMM_OFFSET + XMM_SIZE*2)(%rsp)
1: vpcmpeqq (LR_SIZE + XMM_SIZE*3)(%rsp), %xmm3, %xmm8
@@ -100,7 +124,11 @@
je 2f
vmovdqa %xmm3, (LR_VECTOR_OFFSET + VECTOR_SIZE*3)(%rsp)
jmp 1f
-2: vmovdqu (LR_VECTOR_OFFSET + VECTOR_SIZE*3)(%rsp), %ymm3
+# if HAVE_NO_AVX512_ASM_SUPPORT
+2: .byte 0x62,0xf1,0xfe,0x48,0x6f,0x5c,0x24,0x06 # vmovdqu64 0x180(%rsp),%zmm3
+# else
+2: VMOV (LR_VECTOR_OFFSET + VECTOR_SIZE*3)(%rsp), %VEC(3)
+# endif
vmovdqa %xmm3, (LR_XMM_OFFSET + XMM_SIZE*3)(%rsp)
1: vpcmpeqq (LR_SIZE + XMM_SIZE*4)(%rsp), %xmm4, %xmm8
@@ -109,7 +137,11 @@
je 2f
vmovdqa %xmm4, (LR_VECTOR_OFFSET + VECTOR_SIZE*4)(%rsp)
jmp 1f
-2: vmovdqu (LR_VECTOR_OFFSET + VECTOR_SIZE*4)(%rsp), %ymm4
+# if HAVE_NO_AVX512_ASM_SUPPORT
+2: .byte 0x62,0xf1,0xfe,0x48,0x6f,0x64,0x24,0x07 # vmovdqu64 0x1c0(%rsp),%zmm4
+# else
+2: VMOV (LR_VECTOR_OFFSET + VECTOR_SIZE*4)(%rsp), %VEC(4)
+# endif
vmovdqa %xmm4, (LR_XMM_OFFSET + XMM_SIZE*4)(%rsp)
1: vpcmpeqq (LR_SIZE + XMM_SIZE*5)(%rsp), %xmm5, %xmm8
@@ -118,7 +150,11 @@
je 2f
vmovdqa %xmm5, (LR_VECTOR_OFFSET + VECTOR_SIZE*5)(%rsp)
jmp 1f
-2: vmovdqu (LR_VECTOR_OFFSET + VECTOR_SIZE*5)(%rsp), %ymm5
+# if HAVE_NO_AVX512_ASM_SUPPORT
+2: .byte 0x62,0xf1,0xfe,0x48,0x6f,0x6c,0x24,0x08 # vmovdqu64 0x200(%rsp),%zmm5
+# else
+2: VMOV (LR_VECTOR_OFFSET + VECTOR_SIZE*5)(%rsp), %VEC(5)
+# endif
vmovdqa %xmm5, (LR_XMM_OFFSET + XMM_SIZE*5)(%rsp)
1: vpcmpeqq (LR_SIZE + XMM_SIZE*6)(%rsp), %xmm6, %xmm8
@@ -127,7 +163,11 @@
je 2f
vmovdqa %xmm6, (LR_VECTOR_OFFSET + VECTOR_SIZE*6)(%rsp)
jmp 1f
-2: vmovdqu (LR_VECTOR_OFFSET + VECTOR_SIZE*6)(%rsp), %ymm6
+# if HAVE_NO_AVX512_ASM_SUPPORT
+2: .byte 0x62,0xf1,0xfe,0x48,0x6f,0x74,0x24,0x09 # vmovdqu64 0x240(%rsp),%zmm6
+# else
+2: VMOV (LR_VECTOR_OFFSET + VECTOR_SIZE*6)(%rsp), %VEC(6)
+# endif
vmovdqa %xmm6, (LR_XMM_OFFSET + XMM_SIZE*6)(%rsp)
1: vpcmpeqq (LR_SIZE + XMM_SIZE*7)(%rsp), %xmm7, %xmm8
@@ -136,7 +176,11 @@
je 2f
vmovdqa %xmm7, (LR_VECTOR_OFFSET + VECTOR_SIZE*7)(%rsp)
jmp 1f
-2: vmovdqu (LR_VECTOR_OFFSET + VECTOR_SIZE*7)(%rsp), %ymm7
+# if HAVE_NO_AVX512_ASM_SUPPORT
+2: .byte 0x62,0xf1,0xfe,0x48,0x6f,0x7c,0x24,0x0a # vmovdqu64 0x280(%rsp),%zmm7
+# else
+2: VMOV (LR_VECTOR_OFFSET + VECTOR_SIZE*7)(%rsp), %VEC(7)
+# endif
vmovdqa %xmm7, (LR_XMM_OFFSET + XMM_SIZE*7)(%rsp)
1:
@@ -214,8 +258,13 @@
#ifdef RESTORE_AVX
/* This is to support AVX audit modules. */
- vmovdqu %ymm0, LRV_VECTOR0_OFFSET(%rcx)
- vmovdqu %ymm1, LRV_VECTOR1_OFFSET(%rcx)
+# if HAVE_NO_AVX512_ASM_SUPPORT
+ .byte 0x62,0xf1,0xfe,0x48,0x7f,0x81,0x50,0x00,0x00,0x00 # vmovdqu64 %zmm0,0x50(%rcx)
+ .byte 0x62,0xf1,0xfe,0x48,0x7f,0x89,0x90,0x00,0x00,0x00 # vmovdqu64 %zmm1,0x90(%rcx)
+# else
+ VMOV %VEC(0), LRV_VECTOR0_OFFSET(%rcx)
+ VMOV %VEC(1), LRV_VECTOR1_OFFSET(%rcx)
+# endif
/* Save xmm0/xmm1 registers to detect if they are changed
by audit module. */
@@ -244,13 +293,21 @@
vpmovmskb %xmm2, %esi
cmpl $0xffff, %esi
jne 1f
- vmovdqu LRV_VECTOR0_OFFSET(%rsp), %ymm0
+# if HAVE_NO_AVX512_ASM_SUPPORT
+ .byte 0x62,0xf1,0xfe,0x48,0x6f,0x84,0x24,0x50,0x00,0x00,0x00 # vmovdqu64 0x50(%rsp),%zmm0
+# else
+ VMOV LRV_VECTOR0_OFFSET(%rsp), %VEC(0)
+# endif
1: vpcmpeqq (LRV_SIZE + XMM_SIZE)(%rsp), %xmm1, %xmm2
vpmovmskb %xmm2, %esi
cmpl $0xffff, %esi
jne 1f
- vmovdqu LRV_VECTOR1_OFFSET(%rsp), %ymm1
+# if HAVE_NO_AVX512_ASM_SUPPORT
+ .byte 0x62,0xf1,0xfe,0x48,0x6f,0x8c,0x24,0x90,0x00,0x00,0x00 # vmovdqu64 0x90(%rsp),%zmm1
+# else
+ VMOV LRV_VECTOR1_OFFSET(%rsp), %VEC(1)
+# endif
1:
#endif
diff -urN glibc-2.12-2-gc4ccff1/sysdeps/x86_64/dl-trampoline.S glibc-2.12-2-gc4ccff1.mod/sysdeps/x86_64/dl-trampoline.S
--- glibc-2.12-2-gc4ccff1/sysdeps/x86_64/dl-trampoline.S 2015-03-03 23:03:05.108457659 -0500
+++ glibc-2.12-2-gc4ccff1.mod/sysdeps/x86_64/dl-trampoline.S 2015-03-03 23:07:31.799049953 -0500
@@ -134,7 +134,7 @@
.previous
cmpl $0, L(have_avx)(%rip)
- jne 1f
+ jne L(defined)
movq %rbx, %r11 # Save rbx
movl $1, %eax
cpuid
@@ -143,18 +143,51 @@
// AVX and XSAVE supported?
andl $((1 << 28) | (1 << 27)), %ecx
cmpl $((1 << 28) | (1 << 27)), %ecx
- jne 2f
+ jne 10f
+ // AVX512 supported in processor?
+ movq %rbx, %r11 # Save rbx
+ xorl %ecx, %ecx
+ mov $0x7, %eax
+ cpuid
+ andl $(1 << 16), %ebx
xorl %ecx, %ecx
// Get XFEATURE_ENABLED_MASK
xgetbv
- andl $0x6, %eax
-2: subl $0x5, %eax
+ test %ebx, %ebx
+ movq %r11, %rbx # Restore rbx
+ je 20f
+ // Verify that XCR0[7:5] = '111b' and
+ // XCR0[2:1] = '11b' which means
+ // that zmm state is enabled
+ andl $0xe6, %eax
+ cmpl $0xe6, %eax
+ jne 20f
+ movl %eax, L(have_avx)(%rip)
+L(avx512):
+# define RESTORE_AVX
+# define HAVE_NO_AVX512_ASM_SUPPORT 1
+# define VMOV vmovdqu64
+# define VEC(i) zmm##i
+# define MORE_CODE
+# include "dl-trampoline.h"
+# undef VMOV
+# undef VEC
+# undef RESTORE_AVX
+# undef HAVE_NO_AVX512_ASM_SUPPORT
+20: andl $0x6, %eax
+10: subl $0x5, %eax
movl %eax, L(have_avx)(%rip)
cmpl $0, %eax
-1: js L(no_avx)
+L(defined):
+ js L(no_avx)
+ cmpl $0xe6, L(have_avx)(%rip)
+ je L(avx512)
+
# define RESTORE_AVX
+# define VMOV vmovdqu
+# define VEC(i) ymm##i
# define MORE_CODE
# include "dl-trampoline.h"
@@ -178,7 +211,7 @@
_dl_x86_64_save_sse:
# ifdef HAVE_AVX_SUPPORT
cmpl $0, L(have_avx)(%rip)
- jne 1f
+ jne L(defined_5)
movq %rbx, %r11 # Save rbx
movl $1, %eax
cpuid
@@ -187,21 +220,37 @@
// AVX and XSAVE supported?
andl $((1 << 28) | (1 << 27)), %ecx
cmpl $((1 << 28) | (1 << 27)), %ecx
- jne 2f
+ jne 1f
+ // AVX512 supported in a processor?
+ movq %rbx, %r11 # Save rbx
+ xorl %ecx,%ecx
+ mov $0x7,%eax
+ cpuid
+ andl $(1 << 16), %ebx
xorl %ecx, %ecx
// Get XFEATURE_ENABLED_MASK
xgetbv
- andl $0x6, %eax
- cmpl $0x6, %eax
- // Nonzero if SSE and AVX state saving is enabled.
- sete %al
-2: leal -1(%eax,%eax), %eax
+ test %ebx, %ebx
+ movq %r11, %rbx # Restore rbx
+ je 2f
+ // Verify that XCR0[7:5] = '111b' and
+ // XCR0[2:1] = '11b' which means
+ // that zmm state is enabled
+ andl $0xe6, %eax
movl %eax, L(have_avx)(%rip)
- cmpl $0, %eax
+ cmpl $0xe6, %eax
+ je L(avx512_5)
-1: js L(no_avx5)
+2: andl $0x6, %eax
+1: subl $0x5, %eax
+ movl %eax, L(have_avx)(%rip)
+ cmpl $0, %eax
-# define YMM_SIZE 32
+L(defined_5):
+ js L(no_avx5)
+ cmpl $0xe6, L(have_avx)(%rip)
+ je L(avx512_5)
+
vmovdqa %ymm0, %fs:RTLD_SAVESPACE_SSE+0*YMM_SIZE
vmovdqa %ymm1, %fs:RTLD_SAVESPACE_SSE+1*YMM_SIZE
vmovdqa %ymm2, %fs:RTLD_SAVESPACE_SSE+2*YMM_SIZE
@@ -211,6 +260,26 @@
vmovdqa %ymm6, %fs:RTLD_SAVESPACE_SSE+6*YMM_SIZE
vmovdqa %ymm7, %fs:RTLD_SAVESPACE_SSE+7*YMM_SIZE
ret
+L(avx512_5):
+# Original instructions:
+# vmovdqu64 %zmm0, %fs:RTLD_SAVESPACE_SSE+0*ZMM_SIZE
+# vmovdqu64 %zmm1, %fs:RTLD_SAVESPACE_SSE+1*ZMM_SIZE
+# vmovdqu64 %zmm2, %fs:RTLD_SAVESPACE_SSE+2*ZMM_SIZE
+# vmovdqu64 %zmm3, %fs:RTLD_SAVESPACE_SSE+3*ZMM_SIZE
+# vmovdqu64 %zmm4, %fs:RTLD_SAVESPACE_SSE+4*ZMM_SIZE
+# vmovdqu64 %zmm5, %fs:RTLD_SAVESPACE_SSE+5*ZMM_SIZE
+# vmovdqu64 %zmm6, %fs:RTLD_SAVESPACE_SSE+6*ZMM_SIZE
+# vmovdqu64 %zmm7, %fs:RTLD_SAVESPACE_SSE+7*ZMM_SIZE
+# Assembled instructions:
+ .byte 0x64,0x62,0xf1,0xfe,0x48,0x7f,0x04,0x25,0x80,0x00,0x00,0x00 # vmovdqu64 %zmm0,%fs:0x80
+ .byte 0x64,0x62,0xf1,0xfe,0x48,0x7f,0x0c,0x25,0xc0,0x00,0x00,0x00 # vmovdqu64 %zmm1,%fs:0xc0
+ .byte 0x64,0x62,0xf1,0xfe,0x48,0x7f,0x14,0x25,0x00,0x01,0x00,0x00 # vmovdqu64 %zmm2,%fs:0x100
+ .byte 0x64,0x62,0xf1,0xfe,0x48,0x7f,0x1c,0x25,0x40,0x01,0x00,0x00 # vmovdqu64 %zmm3,%fs:0x140
+ .byte 0x64,0x62,0xf1,0xfe,0x48,0x7f,0x24,0x25,0x80,0x01,0x00,0x00 # vmovdqu64 %zmm4,%fs:0x180
+ .byte 0x64,0x62,0xf1,0xfe,0x48,0x7f,0x2c,0x25,0xc0,0x01,0x00,0x00 # vmovdqu64 %zmm5,%fs:0x1c0
+ .byte 0x64,0x62,0xf1,0xfe,0x48,0x7f,0x34,0x25,0x00,0x02,0x00,0x00 # vmovdqu64 %zmm6,%fs:0x200
+ .byte 0x64,0x62,0xf1,0xfe,0x48,0x7f,0x3c,0x25,0x40,0x02,0x00,0x00 # vmovdqu64 %zmm7,%fs:0x240
+ ret
L(no_avx5):
# endif
movdqa %xmm0, %fs:RTLD_SAVESPACE_SSE+0*XMM_SIZE
@@ -234,6 +303,8 @@
# ifdef HAVE_AVX_SUPPORT
cmpl $0, L(have_avx)(%rip)
js L(no_avx6)
+ cmpl $0xe6, L(have_avx)(%rip)
+ je L(avx512_6)
vmovdqa %fs:RTLD_SAVESPACE_SSE+0*YMM_SIZE, %ymm0
vmovdqa %fs:RTLD_SAVESPACE_SSE+1*YMM_SIZE, %ymm1
@@ -244,6 +315,26 @@
vmovdqa %fs:RTLD_SAVESPACE_SSE+6*YMM_SIZE, %ymm6
vmovdqa %fs:RTLD_SAVESPACE_SSE+7*YMM_SIZE, %ymm7
ret
+L(avx512_6):
+# Original instructions:
+# vmovdqu64 %fs:RTLD_SAVESPACE_SSE+0*ZMM_SIZE, %zmm0
+# vmovdqu64 %fs:RTLD_SAVESPACE_SSE+1*ZMM_SIZE, %zmm1
+# vmovdqu64 %fs:RTLD_SAVESPACE_SSE+2*ZMM_SIZE, %zmm2
+# vmovdqu64 %fs:RTLD_SAVESPACE_SSE+3*ZMM_SIZE, %zmm3
+# vmovdqu64 %fs:RTLD_SAVESPACE_SSE+4*ZMM_SIZE, %zmm4
+# vmovdqu64 %fs:RTLD_SAVESPACE_SSE+5*ZMM_SIZE, %zmm5
+# vmovdqu64 %fs:RTLD_SAVESPACE_SSE+6*ZMM_SIZE, %zmm6
+# vmovdqu64 %fs:RTLD_SAVESPACE_SSE+7*ZMM_SIZE, %zmm7
+# Assembled instructions:
+ .byte 0x64,0x62,0xf1,0xfe,0x48,0x6f,0x04,0x25,0x80,0x00,0x00,0x00 # vmovdqu64 %fs:0x80,%zmm0
+ .byte 0x64,0x62,0xf1,0xfe,0x48,0x6f,0x0c,0x25,0xc0,0x00,0x00,0x00 # vmovdqu64 %fs:0xc0,%zmm1
+ .byte 0x64,0x62,0xf1,0xfe,0x48,0x6f,0x14,0x25,0x00,0x01,0x00,0x00 # vmovdqu64 %fs:0x100,%zmm2
+ .byte 0x64,0x62,0xf1,0xfe,0x48,0x6f,0x1c,0x25,0x40,0x01,0x00,0x00 # vmovdqu64 %fs:0x140,%zmm3
+ .byte 0x64,0x62,0xf1,0xfe,0x48,0x6f,0x24,0x25,0x80,0x01,0x00,0x00 # vmovdqu64 %fs:0x180,%zmm4
+ .byte 0x64,0x62,0xf1,0xfe,0x48,0x6f,0x2c,0x25,0xc0,0x01,0x00,0x00 # vmovdqu64 %fs:0x1c0,%zmm5
+ .byte 0x64,0x62,0xf1,0xfe,0x48,0x6f,0x34,0x25,0x00,0x02,0x00,0x00 # vmovdqu64 %fs:0x200,%zmm6
+ .byte 0x64,0x62,0xf1,0xfe,0x48,0x6f,0x3c,0x25,0x40,0x02,0x00,0x00 # vmovdqu64 %fs:0x240,%zmm7
+ ret
L(no_avx6):
# endif
movdqa %fs:RTLD_SAVESPACE_SSE+0*XMM_SIZE, %xmm0
diff -urN glibc-2.12-2-gc4ccff1/sysdeps/x86_64/link-defines.sym glibc-2.12-2-gc4ccff1.mod/sysdeps/x86_64/link-defines.sym
--- glibc-2.12-2-gc4ccff1/sysdeps/x86_64/link-defines.sym 2010-05-04 07:27:23.000000000 -0400
+++ glibc-2.12-2-gc4ccff1.mod/sysdeps/x86_64/link-defines.sym 2015-03-03 23:03:25.042829206 -0500
@@ -4,6 +4,8 @@
--
VECTOR_SIZE sizeof (La_x86_64_vector)
XMM_SIZE sizeof (La_x86_64_xmm)
+YMM_SIZE sizeof (La_x86_64_ymm)
+ZMM_SIZE sizeof (La_x86_64_zmm)
LR_SIZE sizeof (struct La_x86_64_regs)
LR_RDX_OFFSET offsetof (struct La_x86_64_regs, lr_rdx)
diff -pruN glibc-2.12-2-gc4ccff1/malloc/malloc.c glibc-2.12-2-gc4ccff1.new/malloc/malloc.c
--- glibc-2.12-2-gc4ccff1/malloc/malloc.c 2015-04-10 12:02:54.011106386 +0530
+++ glibc-2.12-2-gc4ccff1.new/malloc/malloc.c 2015-04-10 12:02:35.867958292 +0530
@@ -5850,7 +5850,7 @@ _int_valloc(av, bytes) mstate av; size_t
#endif
{
/* Ensure initialization/consolidation */
- if (have_fastchunks(av)) malloc_consolidate(av);
+ if (av && have_fastchunks(av)) malloc_consolidate(av);
return _int_memalign(av, mp_.pagesize, bytes);
}
@@ -, +, @@
resolv/nss_dns/dns-host.c:getanswer_r.
---
resolv/nss_dns/dns-host.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/resolv/nss_dns/dns-host.c
+++ a/resolv/nss_dns/dns-host.c
@@ -615,7 +615,8 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
int have_to_map = 0;
uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data);
buffer += pad;
- if (__builtin_expect (buflen < sizeof (struct host_data) + pad, 0))
+ buflen = buflen > pad ? buflen - pad : 0;
+ if (__builtin_expect (buflen < sizeof (struct host_data), 0))
{
/* The buffer is too small. */
too_small:
--
#
# Author: Carlos O'Donell
# Upstream status: Needs to go upstream (2015-05-07)
#
diff --git a/inet/rcmd.c b/inet/rcmd.c
index acacaa0..9f2443b 100644
--- a/inet/rcmd.c
+++ b/inet/rcmd.c
@@ -803,29 +803,38 @@ __validuser2_sa(hostf, ra, ralen, luser, ruser, rhost)
*p = '\0'; /* <nul> terminate username (+host?) */
/* buf -> host(?) ; user -> username(?) */
+ if (*buf == '\0')
+ break;
+ if (*user == '\0')
+ user = luser;
+
+ /* First check the user part. This is an optimization, since
+ one should always check the host first in order to detect
+ negative host checks (which we check for later). */
+ ucheck = __icheckuser (user, ruser);
+
+ /* Either we found the user, or we didn't and this is a
+ negative host check. We must do the negative host lookup
+ in order to preserve the semantics of stopping on this line
+ before processing others. */
+ if (ucheck != 0 || *buf == '-') {
+
+ /* Next check host part */
+ hcheck = __checkhost_sa (ra, ralen, buf, rhost);
+
+ /* Negative '-host user(?)' match? */
+ if (hcheck < 0)
+ break;
- /* First check host part */
- hcheck = __checkhost_sa (ra, ralen, buf, rhost);
-
- if (hcheck < 0)
- break;
-
- if (hcheck) {
- /* Then check user part */
- if (! (*user))
- user = luser;
-
- ucheck = __icheckuser (user, ruser);
-
- /* Positive 'host user' match? */
- if (ucheck > 0) {
+ /* Positive 'host user' match? */
+ if (hcheck > 0 && ucheck > 0) {
retval = 0;
break;
}
- /* Negative 'host -user' match? */
- if (ucheck < 0)
- break;
+ /* Negative 'host -user' match? */
+ if (hcheck > 0 && ucheck < 0)
+ break;
/* Neither, go on looking for match */
}
#
# Based on the following patch:
#
# Upstream bug: https://sourceware.org/bugzilla/show_bug.cgi?id=14906
# URL: https://sourceware.org/ml/libc-alpha/2015-02/msg00504.html
#
# 2015-02-17 Carlos O'Donell <carlos@redhat.com>
#
# [BZ #14906]
# * nscd/cache.c (prune_cache): Use TRACED_FILE. Compare and update
# traced file mtime. Use consistent log message.
# * nscd/connections.c [HAVE_INOTIFY] (install_watches): New function.
# (register_traced_file): Call install_watches. Always set mtime.
# (invalidate_cache): Iterate over all trace files. Call install_watches.
# (inotify_check_files): Don't inline. Handle watching parent
# directories and configuration file movement in and out.
# (handle_inotify_events): New function.
# (main_loop_poll): Call handle_inotify_events.
# (main_loop_epoll): Likewise.
# * nscd/nscd.h: Define TRACED_FILE, TRACED_DIR, and PATH_MAX.
# (struct traced_file): Use array of inotify fds. Add parent directory,
# and basename.
# (struct database_dyn): Remove unused file_mtime.
# (init_traced_file): New inline function.
# (define_traced_file): New macro.
# * nss/nss_db/db-init.c: Use define_traced_file.
# (_nss_db_init): Use init_traced_file.
# * nss/nss_files/files-init.c: Use define_traced_file.
# (_nss_files_init): Use init_traced_file.
#
diff -urN glibc-2.12-2-gc4ccff1.orig/misc/sys/cdefs.h glibc-2.12-2-gc4ccff1.mod1/misc/sys/cdefs.h
--- glibc-2.12-2-gc4ccff1.orig/misc/sys/cdefs.h 2015-02-18 04:42:12.115187116 -0500
+++ glibc-2.12-2-gc4ccff1.mod1/misc/sys/cdefs.h 2015-02-18 04:02:03.635159090 -0500
@@ -362,6 +362,14 @@
# endif
#endif
+#if __GNUC__ >= 3
+# define __glibc_unlikely(cond) __builtin_expect ((cond), 0)
+# define __glibc_likely(cond) __builtin_expect ((cond), 1)
+#else
+# define __glibc_unlikely(cond) (cond)
+# define __glibc_likely(cond) (cond)
+#endif
+
#include <bits/wordsize.h>
#if defined __LONG_DOUBLE_MATH_OPTIONAL && defined __NO_LONG_DOUBLE_MATH
diff -urN glibc-2.12-2-gc4ccff1.orig/nscd/cache.c glibc-2.12-2-gc4ccff1.mod1/nscd/cache.c
--- glibc-2.12-2-gc4ccff1.orig/nscd/cache.c 2015-02-18 04:42:12.329180362 -0500
+++ glibc-2.12-2-gc4ccff1.mod1/nscd/cache.c 2015-02-18 04:02:03.635159090 -0500
@@ -266,29 +266,52 @@
/* If we check for the modification of the underlying file we invalidate
the entries also in this case. */
- if (table->inotify_descr < 0 && table->check_file && now != LONG_MAX)
+ if (table->check_file && now != LONG_MAX)
{
- struct stat64 st;
+ struct traced_file *runp = table->traced_files;
- if (stat64 (table->filename, &st) < 0)
+ while (runp != NULL)
{
- char buf[128];
- /* We cannot stat() the file, disable file checking if the
- file does not exist. */
- dbg_log (_("cannot stat() file `%s': %s"),
- table->filename, strerror_r (errno, buf, sizeof (buf)));
- if (errno == ENOENT)
- table->check_file = 0;
- }
- else
- {
- if (st.st_mtime != table->file_mtime)
+#ifdef HAVE_INOTIFY
+ if (runp->inotify_descr[TRACED_FILE] == -1)
+#endif
{
- /* The file changed. Invalidate all entries. */
- now = LONG_MAX;
- table->file_mtime = st.st_mtime;
+ struct stat64 st;
+
+ if (stat64 (runp->fname, &st) < 0)
+ {
+ /* Print a diagnostic that the traced file was missing.
+ We must not disable tracing since the file might return
+ shortly and we want to reload it at the next pruning.
+ Disabling tracing here would go against the configuration
+ as specified by the user via check-files. */
+ char buf[128];
+ dbg_log (_("checking for monitored file `%s': %s"),
+ runp->fname, strerror_r (errno, buf, sizeof (buf)));
+ }
+ else
+ {
+ /* This must be `!=` to catch cases where users turn the
+ clocks back and we still want to detect any time difference
+ in mtime. */
+ if (st.st_mtime != runp->mtime)
+ {
+ dbg_log (_("monitored file `%s` changed (mtime)"),
+ runp->fname);
+ /* The file changed. Invalidate all entries. */
+ now = LONG_MAX;
+ runp->mtime = st.st_mtime;
+#ifdef HAVE_INOTIFY
+ /* Attempt to install a watch on the file. */
+ install_watches (runp);
+#endif
+ }
+ }
}
+
+ runp = runp->next;
}
+
}
/* We run through the table and find values which are not valid anymore.
diff -urN glibc-2.12-2-gc4ccff1.orig/nscd/connections.c glibc-2.12-2-gc4ccff1.mod1/nscd/connections.c
--- glibc-2.12-2-gc4ccff1.orig/nscd/connections.c 2015-02-18 04:42:12.333180236 -0500
+++ glibc-2.12-2-gc4ccff1.mod1/nscd/connections.c 2015-02-18 04:40:51.674726008 -0500
@@ -74,6 +74,25 @@
static void begin_drop_privileges (void);
static void finish_drop_privileges (void);
+/* Define the traced files. */
+#define PWD_FILENAME "/etc/passwd"
+define_traced_file (pwd, PWD_FILENAME);
+
+#define GRP_FILENAME "/etc/group"
+define_traced_file (grp, GRP_FILENAME);
+
+#define HST_FILENAME "/etc/hosts"
+define_traced_file (hst, HST_FILENAME);
+
+#define RESOLV_FILENAME "/etc/resolv.conf"
+define_traced_file (resolv, RESOLV_FILENAME);
+
+#define SERV_FILENAME "/etc/services"
+define_traced_file (serv, SERV_FILENAME);
+
+#define NETGR_FILENAME "/etc/netgroup"
+define_traced_file (netgr, NETGR_FILENAME);
+
/* Map request type to a string. */
const char *const serv2str[LASTREQ] =
{
@@ -115,8 +134,6 @@
.shared = 0,
.max_db_size = DEFAULT_MAX_DB_SIZE,
.suggested_module = DEFAULT_SUGGESTED_MODULE,
- .reset_res = 0,
- .filename = "/etc/passwd",
.db_filename = _PATH_NSCD_PASSWD_DB,
.disabled_iov = &pwd_iov_disabled,
.postimeout = 3600,
@@ -136,8 +153,6 @@
.shared = 0,
.max_db_size = DEFAULT_MAX_DB_SIZE,
.suggested_module = DEFAULT_SUGGESTED_MODULE,
- .reset_res = 0,
- .filename = "/etc/group",
.db_filename = _PATH_NSCD_GROUP_DB,
.disabled_iov = &grp_iov_disabled,
.postimeout = 3600,
@@ -157,8 +172,6 @@
.shared = 0,
.max_db_size = DEFAULT_MAX_DB_SIZE,
.suggested_module = DEFAULT_SUGGESTED_MODULE,
- .reset_res = 1,
- .filename = "/etc/hosts",
.db_filename = _PATH_NSCD_HOSTS_DB,
.disabled_iov = &hst_iov_disabled,
.postimeout = 3600,
@@ -178,8 +191,6 @@
.shared = 0,
.max_db_size = DEFAULT_MAX_DB_SIZE,
.suggested_module = DEFAULT_SUGGESTED_MODULE,
- .reset_res = 0,
- .filename = "/etc/services",
.db_filename = _PATH_NSCD_SERVICES_DB,
.disabled_iov = &serv_iov_disabled,
.postimeout = 28800,
@@ -199,8 +210,6 @@
.shared = 0,
.max_db_size = DEFAULT_MAX_DB_SIZE,
.suggested_module = DEFAULT_SUGGESTED_MODULE,
- .reset_res = 0,
- .filename = "/etc/netgroup",
.db_filename = _PATH_NSCD_NETGROUP_DB,
.disabled_iov = &netgroup_iov_disabled,
.postimeout = 28800,
@@ -863,41 +872,26 @@
dbs[cnt].shared = 0;
assert (dbs[cnt].ro_fd == -1);
}
+ }
- dbs[cnt].inotify_descr = -1;
- if (dbs[cnt].check_file)
- {
-#ifdef HAVE_INOTIFY
- if (inotify_fd < 0
- || (dbs[cnt].inotify_descr
- = inotify_add_watch (inotify_fd, dbs[cnt].filename,
- IN_DELETE_SELF | IN_MODIFY)) < 0)
- /* We cannot notice changes in the main thread. */
-#endif
- {
- /* We need the modification date of the file. */
- struct stat64 st;
+ /* Initialize and register the traced files. */
+ init_traced_file (&pwd_traced_file.file, PWD_FILENAME, 0);
+ register_traced_file (pwddb, &pwd_traced_file.file);
- if (stat64 (dbs[cnt].filename, &st) < 0)
- {
- /* We cannot stat() the file, disable file checking. */
- dbg_log (_("cannot stat() file `%s': %s"),
- dbs[cnt].filename, strerror (errno));
- dbs[cnt].check_file = 0;
- }
- else
- dbs[cnt].file_mtime = st.st_mtime;
- }
- }
+ init_traced_file (&grp_traced_file.file, GRP_FILENAME, 0);
+ register_traced_file (grpdb, &grp_traced_file.file);
-#ifdef HAVE_INOTIFY
- if (cnt == hstdb && inotify_fd >= -1)
- /* We also monitor the resolver configuration file. */
- resolv_conf_descr = inotify_add_watch (inotify_fd,
- _PATH_RESCONF,
- IN_DELETE_SELF | IN_MODIFY);
-#endif
- }
+ init_traced_file (&hst_traced_file.file, HST_FILENAME, 0);
+ register_traced_file (hstdb, &hst_traced_file.file);
+
+ init_traced_file (&resolv_traced_file.file, RESOLV_FILENAME, 1);
+ register_traced_file (hstdb, &resolv_traced_file.file);
+
+ init_traced_file (&serv_traced_file.file, SERV_FILENAME, 0);
+ register_traced_file (servdb, &serv_traced_file.file);
+
+ init_traced_file (&netgr_traced_file.file, NETGR_FILENAME, 0);
+ register_traced_file (netgrdb, &netgr_traced_file.file);
/* Create the socket. */
#ifndef __ASSUME_SOCK_CLOEXEC
@@ -968,6 +962,92 @@
finish_drop_privileges ();
}
+#ifdef HAVE_INOTIFY
+#define TRACED_FILE_MASK (IN_DELETE_SELF | IN_CLOSE_WRITE | IN_MOVE_SELF)
+#define TRACED_DIR_MASK (IN_DELETE_SELF | IN_CREATE | IN_MOVED_TO | IN_MOVE_SELF)
+void
+install_watches (struct traced_file *finfo)
+{
+ /* If we have inotify support use it exclusively with no fallback
+ to stat. This is a design decision to make the implementation
+ sipmler. Either we use fstat for the file name or we use inotify
+ for both the file and parent directory. */
+ if (finfo->inotify_descr[TRACED_FILE] < 0)
+ finfo->inotify_descr[TRACED_FILE] = inotify_add_watch (inotify_fd,
+ finfo->fname,
+ TRACED_FILE_MASK);
+ if (finfo->inotify_descr[TRACED_FILE] < 0)
+ {
+ dbg_log (_("disabled inotify-based monitoring for file `%s': %s"),
+ finfo->fname, strerror (errno));
+ return;
+ }
+ dbg_log (_("monitoring file `%s` (%d)"),
+ finfo->fname, finfo->inotify_descr[TRACED_FILE]);
+ /* Additionally listen for IN_CREATE events in the files parent
+ directory. We do this because the file to be watched might be
+ deleted and then added back again. When it is added back again
+ we must re-add the watch. We must also cover IN_MOVED_TO to
+ detect a file being moved into the directory. */
+ if (finfo->inotify_descr[TRACED_DIR] < 0)
+ finfo->inotify_descr[TRACED_DIR] = inotify_add_watch (inotify_fd,
+ finfo->dname,
+ TRACED_DIR_MASK);
+ if (finfo->inotify_descr[TRACED_DIR] < 0)
+ {
+ dbg_log (_("disabled inotify-based monitoring for directory `%s': %s"),
+ finfo->fname, strerror (errno));
+ return;
+ }
+ dbg_log (_("monitoring directory `%s` (%d)"),
+ finfo->dname, finfo->inotify_descr[TRACED_DIR]);
+}
+#endif
+
+/* Register the file in FINFO as a traced file for the database DBS[DBIX].
+
+ We support registering multiple files per database. Each call to
+ register_traced_file adds to the list of registered files.
+
+ When we prune the database, either through timeout or a request to
+ invalidate, we will check to see if any of the registered files has changed.
+ When we accept new connections to handle a cache request we will also
+ check to see if any of the registered files has changed.
+
+ If we have inotify support then we install an inotify fd to notify us of
+ file deletion or modification, both of which will require we invalidate
+ the cache for the database. Without inotify support we stat the file and
+ store st_mtime to determine if the file has been modified. */
+void
+register_traced_file (size_t dbidx, struct traced_file *finfo)
+{
+ /* If the database is disabled or file checking is disabled
+ then ignore the registration. */
+ if (! dbs[dbidx].enabled || ! dbs[dbidx].check_file)
+ return;
+
+ if (__glibc_unlikely (debug_level > 0))
+ dbg_log (_("monitoring file %s for database %s"),
+ finfo->fname, dbnames[dbidx]);
+
+#ifdef HAVE_INOTIFY
+ install_watches (finfo);
+#endif
+ struct stat64 st;
+ if (stat64 (finfo->fname, &st) < 0)
+ {
+ /* We cannot stat() the file, disable file checking. */
+ dbg_log (_("disabled monitoring for file `%s': %s"),
+ finfo->fname, strerror (errno));
+ finfo->mtime = 0;
+ }
+ else
+ finfo->mtime = st.st_mtime;
+
+ /* Queue up the file name. */
+ finfo->next = dbs[dbidx].traced_files;
+ dbs[dbidx].traced_files = finfo;
+}
/* Close the connections. */
void
@@ -986,9 +1066,25 @@
for (number = pwddb; number < lastdb; ++number)
if (strcmp (key, dbnames[number]) == 0)
{
- if (dbs[number].reset_res)
- res_init ();
-
+ struct traced_file *runp = dbs[number].traced_files;
+ while (runp != NULL)
+ {
+ /* Make sure we reload from file when checking mtime. */
+ runp->mtime = 0;
+#ifdef HAVE_INOTIFY
+ /* During an invalidation we try to reload the traced
+ file watches. This allows the user to re-sync if
+ inotify events were lost. Similar to what we do during
+ pruning. */
+ install_watches (runp);
+#endif
+ if (runp->call_res_init)
+ {
+ res_init ();
+ break;
+ }
+ runp = runp->next;
+ }
break;
}
@@ -1817,6 +1913,231 @@
/* Array for times a connection was accepted. */
static time_t *starttime;
+#ifdef HAVE_INOTIFY
+/* Inotify event for changed file. */
+union __inev
+{
+ struct inotify_event i;
+# ifndef PATH_MAX
+# define PATH_MAX 1024
+# endif
+ char buf[sizeof (struct inotify_event) + PATH_MAX];
+};
+
+/* Returns 0 if the file is there and matches the last mtime
+ on record, otherwise -1. */
+int
+check_file (struct traced_file *finfo)
+{
+ struct stat64 st;
+ if (stat64 (finfo->fname, &st) < 0)
+ return -1;
+ return 0;
+}
+
+/* Process the inotify event in INEV. If the event matches any of the files
+ registered with a database then mark that database as requiring its cache
+ to be cleared. We indicate the cache needs clearing by setting
+ TO_CLEAR[DBCNT] to true for the matching database. */
+static void
+inotify_check_files (bool *to_clear, union __inev *inev)
+{
+ /* Check which of the files changed. */
+ for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
+ {
+ struct traced_file *finfo = dbs[dbcnt].traced_files;
+
+ while (finfo != NULL)
+ {
+ /* The configuration file was moved or deleted.
+ We stop watching it at that point, and reinitialize. */
+ if (finfo->inotify_descr[TRACED_FILE] == inev->i.wd
+ && ((inev->i.mask & IN_MOVE_SELF)
+ || (inev->i.mask & IN_DELETE_SELF)
+ || (inev->i.mask & IN_IGNORED)))
+ {
+ int ret;
+ bool moved = (inev->i.mask & IN_MOVE_SELF) != 0;
+
+ if (check_file (finfo) == 0)
+ {
+ dbg_log (_("ignored out of order inotify event for `%s`"),
+ finfo->fname);
+ return;
+ }
+
+ dbg_log (_("monitored file `%s` was %s, removing watch"),
+ finfo->fname, moved ? "moved" : "deleted");
+ /* File was moved out, remove the watch. Watches are
+ automatically removed when the file is deleted. */
+ if (moved)
+ {
+ ret = inotify_rm_watch (inotify_fd, inev->i.wd);
+ if (ret < 0)
+ dbg_log (_("failed to remove file watch `%s`: %s"),
+ finfo->fname, strerror (errno));
+ }
+ finfo->inotify_descr[TRACED_FILE] = -1;
+ to_clear[dbcnt] = true;
+ if (finfo->call_res_init)
+ res_init ();
+ return;
+ }
+ /* The configuration file was open for writing and has just closed.
+ We reset the cache and reinitialize. */
+ if (finfo->inotify_descr[TRACED_FILE] == inev->i.wd
+ && inev->i.mask & IN_CLOSE_WRITE)
+ {
+ /* Mark cache as needing to be cleared and reinitialize. */
+ dbg_log (_("monitored file `%s` was written to"), finfo->fname);
+ to_clear[dbcnt] = true;
+ if (finfo->call_res_init)
+ res_init ();
+ return;
+ }
+ /* The parent directory was moved or deleted. There is no coming
+ back from this. We do not track the parent of the parent, and
+ once this happens we trigger one last invalidation. You must
+ restart nscd to track subsequent changes. We track this to
+ do one last robust re-initialization and then we're done. */
+ if (finfo->inotify_descr[TRACED_DIR] == inev->i.wd
+ && ((inev->i.mask & IN_DELETE_SELF)
+ || (inev->i.mask & IN_MOVE_SELF)
+ || (inev->i.mask & IN_IGNORED)))
+ {
+ bool moved = (inev->i.mask & IN_MOVE_SELF) != 0;
+ /* The directory watch may have already been removed
+ but we don't know so we just remove it again and
+ ignore the error. Then we remove the file watch.
+ Note: watches are automatically removed for deleted
+ files. */
+ if (moved)
+ inotify_rm_watch (inotify_fd, inev->i.wd);
+ if (finfo->inotify_descr[TRACED_FILE] != -1)
+ {
+ dbg_log (_("monitored parent directory `%s` was %s, removing watch on `%s`"),
+ finfo->dname, moved ? "moved" : "deleted", finfo->fname);
+ if (inotify_rm_watch (inotify_fd, finfo->inotify_descr[TRACED_FILE]) < 0)
+ dbg_log (_("failed to remove file watch `%s`: %s"),
+ finfo->dname, strerror (errno));
+ }
+ finfo->inotify_descr[TRACED_FILE] = -1;
+ finfo->inotify_descr[TRACED_DIR] = -1;
+ to_clear[dbcnt] = true;
+ if (finfo->call_res_init)
+ res_init ();
+ /* Continue to the next entry since this might be the
+ parent directory for multiple registered files and
+ we want to remove watches for all registered files. */
+ continue;
+ }
+ /* The parent directory had a create or moved to event. */
+ if (finfo->inotify_descr[TRACED_DIR] == inev->i.wd
+ && ((inev->i.mask & IN_MOVED_TO)
+ || (inev->i.mask & IN_CREATE))
+ && strcmp (inev->i.name, finfo->sfname) == 0)
+ {
+ /* We detected a directory change. We look for the creation
+ of the file we are tracking or the move of the same file
+ into the directory. */
+ int ret;
+ dbg_log (_("monitored file `%s` was %s, adding watch"),
+ finfo->fname,
+ inev->i.mask & IN_CREATE ? "created" : "moved into place");
+ /* File was moved in or created. Regenerate the watch. */
+ if (finfo->inotify_descr[TRACED_FILE] != -1)
+ inotify_rm_watch (inotify_fd,
+ finfo->inotify_descr[TRACED_FILE]);
+
+ ret = inotify_add_watch (inotify_fd,
+ finfo->fname,
+ TRACED_FILE_MASK);
+ if (ret < 0)
+ dbg_log (_("failed to add file watch `%s`: %s"),
+ finfo->fname, strerror (errno));
+
+ finfo->inotify_descr[TRACED_FILE] = ret;
+
+ /* The file is new or moved so mark cache as needing to
+ be cleared and reinitialize. */
+ to_clear[dbcnt] = true;
+ if (finfo->call_res_init)
+ res_init ();
+
+ /* Done re-adding the watch. Don't return, we may still
+ have other files in this same directory, same watch
+ descriptor, and need to process them. */
+ }
+ /* Other events are ignored, and we move on to the next file. */
+ finfo = finfo->next;
+ }
+ }
+}
+
+/* If an entry in the array of booleans TO_CLEAR is TRUE then clear the cache
+ for the associated database, otherwise do nothing. The TO_CLEAR array must
+ have LASTDB entries. */
+static inline void
+clear_db_cache (bool *to_clear)
+{
+ for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
+ if (to_clear[dbcnt])
+ {
+ pthread_mutex_lock (&dbs[dbcnt].prune_lock);
+ dbs[dbcnt].clear_cache = 1;
+ pthread_mutex_unlock (&dbs[dbcnt].prune_lock);
+ pthread_cond_signal (&dbs[dbcnt].prune_cond);
+ }
+}
+
+int
+handle_inotify_events (void)
+{
+ bool to_clear[lastdb] = { false, };
+ union __inev inev;
+
+ /* Read all inotify events for files registered via
+ register_traced_file(). */
+ while (1)
+ {
+ /* Potentially read multiple events into buf. */
+ ssize_t nb = TEMP_FAILURE_RETRY (read (inotify_fd,
+ &inev.buf,
+ sizeof (inev)));
+ if (nb < (ssize_t) sizeof (struct inotify_event))
+ {
+ /* Not even 1 event. */
+ if (__glibc_unlikely (nb == -1 && errno != EAGAIN))
+ return -1;
+ /* Done reading events that are ready. */
+ break;
+ }
+ /* Process all events. The normal inotify interface delivers
+ complete events on a read and never a partial event. */
+ char *eptr = &inev.buf[0];
+ ssize_t count;
+ while (1)
+ {
+ /* Check which of the files changed. */
+ inotify_check_files (to_clear, &inev);
+ count = sizeof (struct inotify_event) + inev.i.len;
+ eptr += count;
+ nb -= count;
+ if (nb >= (ssize_t) sizeof (struct inotify_event))
+ memcpy (&inev, eptr, nb);
+ else
+ break;
+ }
+ continue;
+ }
+ /* Actually perform the cache clearing. */
+ clear_db_cache (to_clear);
+ return 0;
+}
+
+
+#endif
+
static void
__attribute__ ((__noreturn__))
@@ -1910,66 +2231,21 @@
{
if (conns[1].revents != 0)
{
- bool to_clear[lastdb] = { false, };
- union
- {
-# ifndef PATH_MAX
-# define PATH_MAX 1024
-# endif
- struct inotify_event i;
- char buf[sizeof (struct inotify_event) + PATH_MAX];
- } inev;
+ int ret;
+ ret = handle_inotify_events ();
- while (1)
+ if (ret == -1)
{
- ssize_t nb = TEMP_FAILURE_RETRY (read (inotify_fd, &inev,
- sizeof (inev)));
- if (nb < (ssize_t) sizeof (struct inotify_event))
- {
- if (__builtin_expect (nb == -1 && errno != EAGAIN,
- 0))
- {
- /* Something went wrong when reading the inotify
- data. Better disable inotify. */
- dbg_log (_("\
-disabled inotify after read error %d"),
- errno);
- conns[1].fd = -1;
- firstfree = 1;
- if (nused == 2)
- nused = 1;
- close (inotify_fd);
- inotify_fd = -1;
- }
- break;
- }
-
- /* Check which of the files changed. */
- for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
- if (inev.i.wd == dbs[dbcnt].inotify_descr)
- {
- to_clear[dbcnt] = true;
- goto next;
- }
-
- if (inev.i.wd == resolv_conf_descr)
- {
- res_init ();
- to_clear[hstdb] = true;
- }
- next:;
+ /* Something went wrong when reading the inotify
+ data. Better disable inotify. */
+ dbg_log (_("disabled inotify-based monitoring after read error %d"), errno);
+ conns[1].fd = -1;
+ firstfree = 1;
+ if (nused == 2)
+ nused = 1;
+ close (inotify_fd);
+ inotify_fd = -1;
}
-
- /* Actually perform the cache clearing. */
- for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
- if (to_clear[dbcnt])
- {
- pthread_mutex_lock (&dbs[dbcnt].prune_lock);
- dbs[dbcnt].clear_cache = 1;
- pthread_mutex_unlock (&dbs[dbcnt].prune_lock);
- pthread_cond_signal (&dbs[dbcnt].prune_cond);
- }
-
--n;
}
@@ -2112,58 +2388,18 @@
# ifdef HAVE_INOTIFY
else if (revs[cnt].data.fd == inotify_fd)
{
- bool to_clear[lastdb] = { false, };
- union
- {
- struct inotify_event i;
- char buf[sizeof (struct inotify_event) + PATH_MAX];
- } inev;
-
- while (1)
+ int ret;
+ ret = handle_inotify_events ();
+ if (ret == -1)
{
- ssize_t nb = TEMP_FAILURE_RETRY (read (inotify_fd, &inev,
- sizeof (inev)));
- if (nb < (ssize_t) sizeof (struct inotify_event))
- {
- if (__builtin_expect (nb == -1 && errno != EAGAIN, 0))
- {
- /* Something went wrong when reading the inotify
- data. Better disable inotify. */
- dbg_log (_("disabled inotify after read error %d"),
- errno);
- (void) epoll_ctl (efd, EPOLL_CTL_DEL, inotify_fd,
- NULL);
- close (inotify_fd);
- inotify_fd = -1;
- }
- break;
- }
-
- /* Check which of the files changed. */
- for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
- if (inev.i.wd == dbs[dbcnt].inotify_descr)
- {
- to_clear[dbcnt] = true;
- goto next;
- }
-
- if (inev.i.wd == resolv_conf_descr)
- {
- res_init ();
- to_clear[hstdb] = true;
- }
- next:;
+ /* Something went wrong when reading the inotify
+ data. Better disable inotify. */
+ dbg_log (_("disabled inotify-based monitoring after read error %d"), errno);
+ (void) epoll_ctl (efd, EPOLL_CTL_DEL, inotify_fd, NULL);
+ close (inotify_fd);
+ inotify_fd = -1;
+ break;
}
-
- /* Actually perform the cache clearing. */
- for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
- if (to_clear[dbcnt])
- {
- pthread_mutex_lock (&dbs[dbcnt].prune_lock);
- dbs[dbcnt].clear_cache = 1;
- pthread_mutex_unlock (&dbs[dbcnt].prune_lock);
- pthread_cond_signal (&dbs[dbcnt].prune_cond);
- }
}
# endif
else
diff -urN glibc-2.12-2-gc4ccff1.orig/nscd/nscd.h glibc-2.12-2-gc4ccff1.mod1/nscd/nscd.h
--- glibc-2.12-2-gc4ccff1.orig/nscd/nscd.h 2015-02-18 04:42:12.329180362 -0500
+++ glibc-2.12-2-gc4ccff1.mod1/nscd/nscd.h 2015-02-18 04:02:03.636159059 -0500
@@ -62,6 +62,67 @@
80% of the thread stack size. */
#define MAX_STACK_USE ((8 * NSCD_THREAD_STACKSIZE) / 10)
+/* Records the file registered per database that when changed
+ or modified requires invalidating the database. */
+struct traced_file
+{
+ /* Tracks the last modified time of the traced file. */
+ time_t mtime;
+ /* Support multiple registered files per database. */
+ struct traced_file *next;
+ int call_res_init;
+ /* Requires Inotify support to do anything useful. */
+#define TRACED_FILE 0
+#define TRACED_DIR 1
+ int inotify_descr[2];
+# ifndef PATH_MAX
+# define PATH_MAX 1024
+# endif
+ /* The parent directory is used to scan for creation/deletion. */
+ char dname[PATH_MAX];
+ /* Just the name of the file with no directory component. */
+ char *sfname;
+ /* The full-path name of the registered file. */
+ char fname[];
+};
+
+/* Initialize a `struct traced_file`. As input we need the name
+ of the file, and if invalidation requires calling res_init.
+ If CRINIT is 1 then res_init will be called after invalidation
+ or if the traced file is changed in any way, otherwise it will
+ not. */
+static inline void
+init_traced_file(struct traced_file *file, const char *fname, int crinit)
+{
+ char *dname;
+ file->mtime = 0;
+ file->inotify_descr[TRACED_FILE] = -1;
+ file->inotify_descr[TRACED_DIR] = -1;
+ strcpy (file->fname, fname);
+ /* Compute the parent directory name and store a copy. The copy makes
+ it much faster to add/remove watches while nscd is running instead
+ of computing this over and over again in a temp buffer. */
+ file->dname[0] = '\0';
+ dname = strrchr (fname, '/');
+ if (dname != NULL)
+ {
+ size_t len = (size_t)(dname - fname);
+ if (len > sizeof (file->dname))
+ abort ();
+ strncpy (file->dname, file->fname, len);
+ file->dname[len] = '\0';
+ }
+ /* The basename is the name just after the last forward slash. */
+ file->sfname = &dname[1];
+ file->call_res_init = crinit;
+}
+
+#define define_traced_file(id, filename) \
+static union \
+{ \
+ struct traced_file file; \
+ char buf[sizeof (struct traced_file) + sizeof (filename)]; \
+} id##_traced_file;
/* Structure describing dynamic part of one database. */
struct database_dyn
@@ -74,15 +135,12 @@
int enabled;
int check_file;
- int inotify_descr;
int clear_cache;
int persistent;
int shared;
int propagate;
- int reset_res;
- const char filename[16];
+ struct traced_file *traced_files;
const char *db_filename;
- time_t file_mtime;
size_t suggested_module;
size_t max_db_size;
@@ -199,6 +257,10 @@
/* connections.c */
extern void nscd_init (void);
+extern void register_traced_file (size_t dbidx, struct traced_file *finfo);
+#ifdef HAVE_INOTIFY
+extern void install_watches (struct traced_file *finfo);
+#endif
extern void close_sockets (void);
extern void start_threads (void) __attribute__ ((__noreturn__));
commit 9fab36eb583c0e585e83a01253299afed9ea9a11
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date: Tue Sep 25 14:10:29 2012 +0530
Shrink heap on linux when overcommit_memory == 2
Using madvise with MADV_DONTNEED to release memory back to the kernel
is not sufficient to change the commit charge accounted against the
process on Linux. It is OK however, when overcommit is enabled or is
heuristic. However, when overcommit is restricted to a percentage of
memory setting the contents of /proc/sys/vm/overcommit_memory as 2, it
makes a difference since memory requests will fail. Hence, we do what
we do with secure exec binaries, which is to call mmap on the region
to be dropped with MAP_FIXED. This internally unmaps the pages in
question and reduces the amount of memory accounted against the
process.
diff --git a/malloc/arena.c b/malloc/arena.c
index f24e76c..b209e3b 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -19,6 +19,9 @@
#include <stdbool.h>
+/* Get the implementation for check_may_shrink_heap. */
+#include <malloc-sysdep.h>
+
/* Compile-time constants. */
#define HEAP_MIN_SIZE (32*1024)
@@ -621,10 +624,10 @@ shrink_heap(heap_info *h, long diff)
new_size = (long)h->size - diff;
if(new_size < (long)sizeof(*h))
return -1;
- /* Try to re-map the extra heap space freshly to save memory, and
- make it inaccessible. */
#ifdef _LIBC
- if (__builtin_expect (__libc_enable_secure, 0))
+ /* Try to re-map the extra heap space freshly to save memory, and make it
+ inaccessible. See malloc-sysdep.h to know when this is true. */
+ if (__builtin_expect (check_may_shrink_heap (), 0))
#else
if (1)
#endif
diff --git a/sysdeps/generic/malloc-sysdep.h b/sysdeps/generic/malloc-sysdep.h
new file mode 100644
index 0000000..bbc48c0
--- /dev/null
+++ b/sysdeps/generic/malloc-sysdep.h
@@ -0,0 +1,25 @@
+/* System-specific malloc support functions. Generic version.
+ Copyright (C) 2012 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/>. */
+
+/* Force an unmap when the heap shrinks in a secure exec. This ensures that
+ the old data pages immediately cease to be accessible. */
+static inline bool
+check_may_shrink_heap (void)
+{
+ return __libc_enable_secure;
+}
diff --git a/sysdeps/unix/sysv/linux/malloc-sysdep.h b/sysdeps/unix/sysv/linux/malloc-sysdep.h
new file mode 100644
index 0000000..f926aea
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/malloc-sysdep.h
@@ -0,0 +1,57 @@
+/* System-specific malloc support functions. Linux version.
+ Copyright (C) 2012 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 <fcntl.h>
+#include <not-cancel.h>
+
+/* The Linux kernel overcommits address space by default and if there is not
+ enough memory available, it uses various parameters to decide the process to
+ kill. It is however possible to disable or curb this overcommit behavior
+ by setting the proc sysctl vm.overcommit_memory to the value '2' and with
+ that, a process is only allowed to use the maximum of a pre-determined
+ fraction of the total address space. In such a case, we want to make sure
+ that we are judicious with our heap usage as well, and explicitly give away
+ the freed top of the heap to reduce our commit charge. See the proc(5) man
+ page to know more about overcommit behavior.
+
+ Other than that, we also force an unmap in a secure exec. */
+static inline bool
+check_may_shrink_heap (void)
+{
+ static int may_shrink_heap = -1;
+
+ if (__builtin_expect (may_shrink_heap >= 0, 1))
+ return may_shrink_heap;
+
+ may_shrink_heap = __libc_enable_secure;
+
+ if (__builtin_expect (may_shrink_heap == 0, 1))
+ {
+ int fd = open_not_cancel_2 ("/proc/sys/vm/overcommit_memory",
+ O_RDONLY | O_CLOEXEC);
+ if (fd >= 0)
+ {
+ char val;
+ ssize_t n = read_not_cancel (fd, &val, 1);
+ may_shrink_heap = n > 0 && val == '2';
+ close_not_cancel_no_status (fd);
+ }
+ }
+
+ return may_shrink_heap;
+}
#
# Based on commit e6c61494125126d2ba77e5d99f83887a2ed49783.
#
# 2011-04-10 Ulrich Drepper <drepper@gmail.com>
#
# [BZ #12650]
# * sysdeps/i386/dl-tls.h: Define TLS_DTV_UNALLOCATED.
# * sysdeps/ia64/dl-tls.h: Likewise.
# * sysdeps/powerpc/dl-tls.h: Likewise.
# * sysdeps/s390/dl-tls.h: Likewise.
# * sysdeps/sh/dl-tls.h: Likewise.
# * sysdeps/sparc/dl-tls.h: Likewise.
# * sysdeps/x86_64/dl-tls.h: Likewise.
# * elf/dl-tls.c: Don't define TLS_DTV_UNALLOCATED here.
#
diff -urN glibc-2.12-2-gc4ccff1/elf/dl-tls.c glibc-2.12-2-gc4ccff1.mod/elf/dl-tls.c
--- glibc-2.12-2-gc4ccff1/elf/dl-tls.c 2015-02-18 05:16:56.087096028 -0500
+++ glibc-2.12-2-gc4ccff1.mod/elf/dl-tls.c 2015-02-18 05:21:04.018424445 -0500
@@ -33,9 +33,6 @@
to allow dynamic loading of modules defining IE-model TLS data. */
#define TLS_STATIC_SURPLUS 64 + DL_NNS * 100
-/* Value used for dtv entries for which the allocation is delayed. */
-#define TLS_DTV_UNALLOCATED ((void *) -1l)
-
/* Out-of-memory handler. */
#ifdef SHARED
diff -urN glibc-2.12-2-gc4ccff1/nptl/allocatestack.c glibc-2.12-2-gc4ccff1.mod/nptl/allocatestack.c
--- glibc-2.12-2-gc4ccff1/nptl/allocatestack.c 2015-02-18 05:16:56.101095594 -0500
+++ glibc-2.12-2-gc4ccff1.mod/nptl/allocatestack.c 2015-02-18 05:21:04.019424414 -0500
@@ -26,6 +26,7 @@
#include <sys/mman.h>
#include <sys/param.h>
#include <dl-sysdep.h>
+#include <dl-tls.h>
#include <tls.h>
#include <list.h>
#include <lowlevellock.h>
@@ -242,6 +243,10 @@
/* Clear the DTV. */
dtv_t *dtv = GET_DTV (TLS_TPADJ (result));
+ for (size_t cnt = 0; cnt < dtv[-1].counter; ++cnt)
+ if (! dtv[1 + cnt].pointer.is_static
+ && dtv[1 + cnt].pointer.val != TLS_DTV_UNALLOCATED)
+ free (dtv[1 + cnt].pointer.val);
memset (dtv, '\0', (dtv[-1].counter + 1) * sizeof (dtv_t));
/* Re-initialize the TLS. */
diff -urN glibc-2.12-2-gc4ccff1/sysdeps/i386/dl-tls.h glibc-2.12-2-gc4ccff1.mod/sysdeps/i386/dl-tls.h
--- glibc-2.12-2-gc4ccff1/sysdeps/i386/dl-tls.h 2010-05-04 07:27:23.000000000 -0400
+++ glibc-2.12-2-gc4ccff1.mod/sysdeps/i386/dl-tls.h 2015-02-18 05:21:04.019424414 -0500
@@ -58,3 +58,6 @@
# endif
#endif
+
+/* Value used for dtv entries for which the allocation is delayed. */
+#define TLS_DTV_UNALLOCATED ((void *) -1l)
diff -urN glibc-2.12-2-gc4ccff1/sysdeps/ia64/dl-tls.h glibc-2.12-2-gc4ccff1.mod/sysdeps/ia64/dl-tls.h
--- glibc-2.12-2-gc4ccff1/sysdeps/ia64/dl-tls.h 2010-05-04 07:27:23.000000000 -0400
+++ glibc-2.12-2-gc4ccff1.mod/sysdeps/ia64/dl-tls.h 2015-02-18 05:21:04.019424414 -0500
@@ -28,3 +28,6 @@
#define DONT_USE_TLS_INDEX 1
extern void *__tls_get_addr (size_t m, size_t offset);
+
+/* Value used for dtv entries for which the allocation is delayed. */
+#define TLS_DTV_UNALLOCATED ((void *) -1l)
diff -urN glibc-2.12-2-gc4ccff1/sysdeps/powerpc/dl-tls.h glibc-2.12-2-gc4ccff1.mod/sysdeps/powerpc/dl-tls.h
--- glibc-2.12-2-gc4ccff1/sysdeps/powerpc/dl-tls.h 2010-05-04 07:27:23.000000000 -0400
+++ glibc-2.12-2-gc4ccff1.mod/sysdeps/powerpc/dl-tls.h 2015-02-18 05:21:04.019424414 -0500
@@ -47,3 +47,6 @@
# define GET_ADDR_OFFSET (ti->ti_offset + TLS_DTV_OFFSET)
# define __TLS_GET_ADDR(__ti) (__tls_get_addr (__ti) - TLS_DTV_OFFSET)
#endif
+
+/* Value used for dtv entries for which the allocation is delayed. */
+#define TLS_DTV_UNALLOCATED ((void *) -1l)
diff -urN glibc-2.12-2-gc4ccff1/sysdeps/s390/dl-tls.h glibc-2.12-2-gc4ccff1.mod/sysdeps/s390/dl-tls.h
--- glibc-2.12-2-gc4ccff1/sysdeps/s390/dl-tls.h 2010-05-04 07:27:23.000000000 -0400
+++ glibc-2.12-2-gc4ccff1.mod/sysdeps/s390/dl-tls.h 2015-02-18 05:21:04.019424414 -0500
@@ -72,6 +72,9 @@
# define __TLS_GET_ADDR(__ti) \
({ extern char _GLOBAL_OFFSET_TABLE_[] attribute_hidden; \
(void *) __tls_get_offset ((char *) (__ti) - _GLOBAL_OFFSET_TABLE_) \
- + (unsigned long) __builtin_thread_pointer (); })
+ + (unsigned long) __builtin_thread_pointer (); })
#endif
+
+/* Value used for dtv entries for which the allocation is delayed. */
+#define TLS_DTV_UNALLOCATED ((void *) -1l)
diff -urN glibc-2.12-2-gc4ccff1/sysdeps/sh/dl-tls.h glibc-2.12-2-gc4ccff1.mod/sysdeps/sh/dl-tls.h
--- glibc-2.12-2-gc4ccff1/sysdeps/sh/dl-tls.h 2010-05-04 07:27:23.000000000 -0400
+++ glibc-2.12-2-gc4ccff1.mod/sysdeps/sh/dl-tls.h 2015-02-18 05:21:04.019424414 -0500
@@ -27,3 +27,6 @@
extern void *__tls_get_addr (tls_index *ti);
+
+/* Value used for dtv entries for which the allocation is delayed. */
+#define TLS_DTV_UNALLOCATED ((void *) -1l)
diff -urN glibc-2.12-2-gc4ccff1/sysdeps/sparc/dl-tls.h glibc-2.12-2-gc4ccff1.mod/sysdeps/sparc/dl-tls.h
--- glibc-2.12-2-gc4ccff1/sysdeps/sparc/dl-tls.h 2010-05-04 07:27:23.000000000 -0400
+++ glibc-2.12-2-gc4ccff1.mod/sysdeps/sparc/dl-tls.h 2015-02-18 05:21:04.019424414 -0500
@@ -27,3 +27,6 @@
extern void *__tls_get_addr (tls_index *ti);
+
+/* Value used for dtv entries for which the allocation is delayed. */
+#define TLS_DTV_UNALLOCATED ((void *) -1l)
diff -urN glibc-2.12-2-gc4ccff1/sysdeps/x86_64/dl-tls.h glibc-2.12-2-gc4ccff1.mod/sysdeps/x86_64/dl-tls.h
--- glibc-2.12-2-gc4ccff1/sysdeps/x86_64/dl-tls.h 2010-05-04 07:27:23.000000000 -0400
+++ glibc-2.12-2-gc4ccff1.mod/sysdeps/x86_64/dl-tls.h 2015-02-18 05:21:04.019424414 -0500
@@ -27,3 +27,6 @@
extern void *__tls_get_addr (tls_index *ti);
+
+/* Value used for dtv entries for which the allocation is delayed. */
+#define TLS_DTV_UNALLOCATED ((void *) -1l)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment