summaryrefslogtreecommitdiffstats
path: root/meta/recipes-core/glibc/glibc/0002-ld.so-Reject-overly-long-LD_PRELOAD-path-elements.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-core/glibc/glibc/0002-ld.so-Reject-overly-long-LD_PRELOAD-path-elements.patch')
-rw-r--r--meta/recipes-core/glibc/glibc/0002-ld.so-Reject-overly-long-LD_PRELOAD-path-elements.patch145
1 files changed, 145 insertions, 0 deletions
diff --git a/meta/recipes-core/glibc/glibc/0002-ld.so-Reject-overly-long-LD_PRELOAD-path-elements.patch b/meta/recipes-core/glibc/glibc/0002-ld.so-Reject-overly-long-LD_PRELOAD-path-elements.patch
new file mode 100644
index 0000000000..7f81ed1566
--- /dev/null
+++ b/meta/recipes-core/glibc/glibc/0002-ld.so-Reject-overly-long-LD_PRELOAD-path-elements.patch
@@ -0,0 +1,145 @@
1From 6d49272e6d6741496e3456f2cc22ebc2b9f7f989 Mon Sep 17 00:00:00 2001
2From: Florian Weimer <fweimer@redhat.com>
3Date: Mon, 19 Jun 2017 22:31:04 +0200
4Subject: [PATCH] ld.so: Reject overly long LD_PRELOAD path elements
5
6(cherry picked from commit 6d0ba622891bed9d8394eef1935add53003b12e8)
7
8Upstream-Status: Backport
9https://sourceware.org/git/?p=glibc.git;a=commit;h=aab04ca5d359150e17631e6a9b44b65e93bdc467
10https://anonscm.debian.org/cgit/pkg-glibc/glibc.git/commit/?h=stretch&id=2755c57269f24e9d59c22c49788f92515346c1bb
11
12CVE: CVE-2017-1000366
13
14Signed-off-by: George McCollister <george.mccollister@gmail.com>
15---
16 ChangeLog | 7 ++++++
17 elf/rtld.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++------------
18 2 files changed, 73 insertions(+), 16 deletions(-)
19
20diff --git a/ChangeLog b/ChangeLog
21index 7a999802dd..ea5ecd4a1e 100644
22--- a/ChangeLog
23+++ b/ChangeLog
24@@ -1,3 +1,10 @@
25+2017-06-19 Florian Weimer <fweimer@redhat.com>
26+
27+ * elf/rtld.c (SECURE_NAME_LIMIT, SECURE_PATH_LIMIT): Define.
28+ (dso_name_valid_for_suid): New function.
29+ (handle_ld_preload): Likewise.
30+ (dl_main): Call it. Remove alloca.
31+
32 2017-06-19 Florian Weimer <fweimer@redhat.com>
33
34 [BZ #21624]
35diff --git a/elf/rtld.c b/elf/rtld.c
36index 215a9aec8f..1d8eab9fe2 100644
37--- a/elf/rtld.c
38+++ b/elf/rtld.c
39@@ -99,6 +99,35 @@ uintptr_t __pointer_chk_guard_local
40 strong_alias (__pointer_chk_guard_local, __pointer_chk_guard)
41 #endif
42
43+/* Length limits for names and paths, to protect the dynamic linker,
44+ particularly when __libc_enable_secure is active. */
45+#ifdef NAME_MAX
46+# define SECURE_NAME_LIMIT NAME_MAX
47+#else
48+# define SECURE_NAME_LIMIT 255
49+#endif
50+#ifdef PATH_MAX
51+# define SECURE_PATH_LIMIT PATH_MAX
52+#else
53+# define SECURE_PATH_LIMIT 1024
54+#endif
55+
56+/* Check that AT_SECURE=0, or that the passed name does not contain
57+ directories and is not overly long. Reject empty names
58+ unconditionally. */
59+static bool
60+dso_name_valid_for_suid (const char *p)
61+{
62+ if (__glibc_unlikely (__libc_enable_secure))
63+ {
64+ /* Ignore pathnames with directories for AT_SECURE=1
65+ programs, and also skip overlong names. */
66+ size_t len = strlen (p);
67+ if (len >= SECURE_NAME_LIMIT || memchr (p, '/', len) != NULL)
68+ return false;
69+ }
70+ return *p != '\0';
71+}
72
73 /* List of auditing DSOs. */
74 static struct audit_list
75@@ -730,6 +759,42 @@ static const char *preloadlist attribute_relro;
76 /* Nonzero if information about versions has to be printed. */
77 static int version_info attribute_relro;
78
79+/* The LD_PRELOAD environment variable gives list of libraries
80+ separated by white space or colons that are loaded before the
81+ executable's dependencies and prepended to the global scope list.
82+ (If the binary is running setuid all elements containing a '/' are
83+ ignored since it is insecure.) Return the number of preloads
84+ performed. */
85+unsigned int
86+handle_ld_preload (const char *preloadlist, struct link_map *main_map)
87+{
88+ unsigned int npreloads = 0;
89+ const char *p = preloadlist;
90+ char fname[SECURE_PATH_LIMIT];
91+
92+ while (*p != '\0')
93+ {
94+ /* Split preload list at space/colon. */
95+ size_t len = strcspn (p, " :");
96+ if (len > 0 && len < sizeof (fname))
97+ {
98+ memcpy (fname, p, len);
99+ fname[len] = '\0';
100+ }
101+ else
102+ fname[0] = '\0';
103+
104+ /* Skip over the substring and the following delimiter. */
105+ p += len;
106+ if (*p != '\0')
107+ ++p;
108+
109+ if (dso_name_valid_for_suid (fname))
110+ npreloads += do_preload (fname, main_map, "LD_PRELOAD");
111+ }
112+ return npreloads;
113+}
114+
115 static void
116 dl_main (const ElfW(Phdr) *phdr,
117 ElfW(Word) phnum,
118@@ -1481,23 +1546,8 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
119
120 if (__glibc_unlikely (preloadlist != NULL))
121 {
122- /* The LD_PRELOAD environment variable gives list of libraries
123- separated by white space or colons that are loaded before the
124- executable's dependencies and prepended to the global scope
125- list. If the binary is running setuid all elements
126- containing a '/' are ignored since it is insecure. */
127- char *list = strdupa (preloadlist);
128- char *p;
129-
130 HP_TIMING_NOW (start);
131-
132- /* Prevent optimizing strsep. Speed is not important here. */
133- while ((p = (strsep) (&list, " :")) != NULL)
134- if (p[0] != '\0'
135- && (__builtin_expect (! __libc_enable_secure, 1)
136- || strchr (p, '/') == NULL))
137- npreloads += do_preload (p, main_map, "LD_PRELOAD");
138-
139+ npreloads += handle_ld_preload (preloadlist, main_map);
140 HP_TIMING_NOW (stop);
141 HP_TIMING_DIFF (diff, start, stop);
142 HP_TIMING_ACCUM_NT (load_time, diff);
143--
1442.15.0
145