Browse code

Apply related patches for glibc CVE-2017-1000366

Change-Id: I0f0c6289d284d375224c9c4ed3f5c182a991a48f
Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/3456
Tested-by: gerrit-photon <photon-checkins@vmware.com>
Reviewed-by: Anish Swaminathan <anishs@vmware.com>

suezzelur authored on 2017/08/09 08:00:20
Showing 2 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,344 @@
0
+From f6110a8fee2ca36f8e2d2abecf3cba9fa7b8ea7d Mon Sep 17 00:00:00 2001
1
+From: Florian Weimer <fweimer@redhat.com>
2
+Date: Mon, 19 Jun 2017 17:09:55 +0200
3
+Subject: [PATCH 1/1] CVE-2017-1000366: Ignore LD_LIBRARY_PATH for AT_SECURE=1
4
+ programs [BZ #21624]
5
+
6
+LD_LIBRARY_PATH can only be used to reorder system search paths, which
7
+is not useful functionality.
8
+
9
+This makes an exploitable unbounded alloca in _dl_init_paths unreachable
10
+for AT_SECURE=1 programs.
11
+---
12
+ elf/rtld.c | 3 ++-
13
+ 1 files changed, 2 insertions(+), 1 deletion(-)
14
+
15
+diff --git a/elf/rtld.c b/elf/rtld.c
16
+index 2446a87..2269dbe 100644
17
+--- a/elf/rtld.c
18
+@@ -2422,7 +2422,8 @@ process_envvars (enum mode *modep)
19
+ 
20
+ 	case 12:
21
+ 	  /* The library search path.  */
22
+-	  if (memcmp (envline, "LIBRARY_PATH", 12) == 0)
23
++	  if (!__libc_enable_secure
24
++	      && memcmp (envline, "LIBRARY_PATH", 12) == 0)
25
+ 	    {
26
+ 	      library_path = &envline[13];
27
+ 	      break;
28
+From 6d0ba622891bed9d8394eef1935add53003b12e8 Mon Sep 17 00:00:00 2001
29
+From: Florian Weimer <fweimer@redhat.com>
30
+Date: Mon, 19 Jun 2017 22:31:04 +0200
31
+Subject: [PATCH] ld.so: Reject overly long LD_PRELOAD path elements
32
+
33
+---
34
+ elf/rtld.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++------------
35
+ 1 files changed, 73 insertions(+), 16 deletions(-)
36
+
37
+diff --git a/elf/rtld.c b/elf/rtld.c
38
+index 2269dbe..86ae20c 100644
39
+--- a/elf/rtld.c
40
+@@ -99,6 +99,35 @@ uintptr_t __pointer_chk_guard_local
41
+ strong_alias (__pointer_chk_guard_local, __pointer_chk_guard)
42
+ #endif
43
+ 
44
++/* Length limits for names and paths, to protect the dynamic linker,
45
++   particularly when __libc_enable_secure is active.  */
46
++#ifdef NAME_MAX
47
++# define SECURE_NAME_LIMIT NAME_MAX
48
++#else
49
++# define SECURE_NAME_LIMIT 255
50
++#endif
51
++#ifdef PATH_MAX
52
++# define SECURE_PATH_LIMIT PATH_MAX
53
++#else
54
++# define SECURE_PATH_LIMIT 1024
55
++#endif
56
++
57
++/* Check that AT_SECURE=0, or that the passed name does not contain
58
++   directories and is not overly long.  Reject empty names
59
++   unconditionally.  */
60
++static bool
61
++dso_name_valid_for_suid (const char *p)
62
++{
63
++  if (__glibc_unlikely (__libc_enable_secure))
64
++    {
65
++      /* Ignore pathnames with directories for AT_SECURE=1
66
++	 programs, and also skip overlong names.  */
67
++      size_t len = strlen (p);
68
++      if (len >= SECURE_NAME_LIMIT || memchr (p, '/', len) != NULL)
69
++	return false;
70
++    }
71
++  return *p != '\0';
72
++}
73
+ 
74
+ /* List of auditing DSOs.  */
75
+ static struct audit_list
76
+@@ -718,6 +747,42 @@ static const char *preloadlist attribute_relro;
77
+ /* Nonzero if information about versions has to be printed.  */
78
+ static int version_info attribute_relro;
79
+ 
80
++/* The LD_PRELOAD environment variable gives list of libraries
81
++   separated by white space or colons that are loaded before the
82
++   executable's dependencies and prepended to the global scope list.
83
++   (If the binary is running setuid all elements containing a '/' are
84
++   ignored since it is insecure.)  Return the number of preloads
85
++   performed.  */
86
++unsigned int
87
++handle_ld_preload (const char *preloadlist, struct link_map *main_map)
88
++{
89
++  unsigned int npreloads = 0;
90
++  const char *p = preloadlist;
91
++  char fname[SECURE_PATH_LIMIT];
92
++
93
++  while (*p != '\0')
94
++    {
95
++      /* Split preload list at space/colon.  */
96
++      size_t len = strcspn (p, " :");
97
++      if (len > 0 && len < sizeof (fname))
98
++	{
99
++	  memcpy (fname, p, len);
100
++	  fname[len] = '\0';
101
++	}
102
++      else
103
++	fname[0] = '\0';
104
++
105
++      /* Skip over the substring and the following delimiter.  */
106
++      p += len;
107
++      if (*p != '\0')
108
++	++p;
109
++
110
++      if (dso_name_valid_for_suid (fname))
111
++	npreloads += do_preload (fname, main_map, "LD_PRELOAD");
112
++    }
113
++  return npreloads;
114
++}
115
++
116
+ static void
117
+ dl_main (const ElfW(Phdr) *phdr,
118
+ 	 ElfW(Word) phnum,
119
+@@ -1464,23 +1529,8 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
120
+ 
121
+   if (__glibc_unlikely (preloadlist != NULL))
122
+     {
123
+-      /* The LD_PRELOAD environment variable gives list of libraries
124
+-	 separated by white space or colons that are loaded before the
125
+-	 executable's dependencies and prepended to the global scope
126
+-	 list.  If the binary is running setuid all elements
127
+-	 containing a '/' are ignored since it is insecure.  */
128
+-      char *list = strdupa (preloadlist);
129
+-      char *p;
130
+-
131
+       HP_TIMING_NOW (start);
132
+-
133
+-      /* Prevent optimizing strsep.  Speed is not important here.  */
134
+-      while ((p = (strsep) (&list, " :")) != NULL)
135
+-	if (p[0] != '\0'
136
+-	    && (__builtin_expect (! __libc_enable_secure, 1)
137
+-		|| strchr (p, '/') == NULL))
138
+-	  npreloads += do_preload (p, main_map, "LD_PRELOAD");
139
+-
140
++      npreloads += handle_ld_preload (preloadlist, main_map);
141
+       HP_TIMING_NOW (stop);
142
+       HP_TIMING_DIFF (diff, start, stop);
143
+       HP_TIMING_ACCUM_NT (load_time, diff);
144
+From 81b82fb966ffbd94353f793ad17116c6088dedd9 Mon Sep 17 00:00:00 2001
145
+From: Florian Weimer <fweimer@redhat.com>
146
+Date: Mon, 19 Jun 2017 22:32:12 +0200
147
+Subject: [PATCH] ld.so: Reject overly long LD_AUDIT path elements
148
+
149
+Also only process the last LD_AUDIT entry.
150
+---
151
+ elf/rtld.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++---------
152
+ 1 files changed, 106 insertions(+), 15 deletions(-)
153
+
154
+diff --git a/elf/rtld.c b/elf/rtld.c
155
+index 86ae20c..65647fb 100644
156
+--- a/elf/rtld.c
157
+@@ -129,13 +129,91 @@ dso_name_valid_for_suid (const char *p)
158
+   return *p != '\0';
159
+ }
160
+ 
161
+-/* List of auditing DSOs.  */
162
++/* LD_AUDIT variable contents.  Must be processed before the
163
++   audit_list below.  */
164
++const char *audit_list_string;
165
++
166
++/* Cyclic list of auditing DSOs.  audit_list->next is the first
167
++   element.  */
168
+ static struct audit_list
169
+ {
170
+   const char *name;
171
+   struct audit_list *next;
172
+ } *audit_list;
173
+ 
174
++/* Iterator for audit_list_string followed by audit_list.  */
175
++struct audit_list_iter
176
++{
177
++  /* Tail of audit_list_string still needing processing, or NULL.  */
178
++  const char *audit_list_tail;
179
++
180
++  /* The list element returned in the previous iteration.  NULL before
181
++     the first element.  */
182
++  struct audit_list *previous;
183
++
184
++  /* Scratch buffer for returning a name which is part of
185
++     audit_list_string.  */
186
++  char fname[SECURE_NAME_LIMIT];
187
++};
188
++
189
++/* Initialize an audit list iterator.  */
190
++static void
191
++audit_list_iter_init (struct audit_list_iter *iter)
192
++{
193
++  iter->audit_list_tail = audit_list_string;
194
++  iter->previous = NULL;
195
++}
196
++
197
++/* Iterate through both audit_list_string and audit_list.  */
198
++static const char *
199
++audit_list_iter_next (struct audit_list_iter *iter)
200
++{
201
++  if (iter->audit_list_tail != NULL)
202
++    {
203
++      /* First iterate over audit_list_string.  */
204
++      while (*iter->audit_list_tail != '\0')
205
++	{
206
++	  /* Split audit list at colon.  */
207
++	  size_t len = strcspn (iter->audit_list_tail, ":");
208
++	  if (len > 0 && len < sizeof (iter->fname))
209
++	    {
210
++	      memcpy (iter->fname, iter->audit_list_tail, len);
211
++	      iter->fname[len] = '\0';
212
++	    }
213
++	  else
214
++	    /* Do not return this name to the caller.  */
215
++	    iter->fname[0] = '\0';
216
++
217
++	  /* Skip over the substring and the following delimiter.  */
218
++	  iter->audit_list_tail += len;
219
++	  if (*iter->audit_list_tail == ':')
220
++	    ++iter->audit_list_tail;
221
++
222
++	  /* If the name is valid, return it.  */
223
++	  if (dso_name_valid_for_suid (iter->fname))
224
++	    return iter->fname;
225
++	  /* Otherwise, wrap around and try the next name.  */
226
++	}
227
++      /* Fall through to the procesing of audit_list.  */
228
++    }
229
++
230
++  if (iter->previous == NULL)
231
++    {
232
++      if (audit_list == NULL)
233
++	/* No pre-parsed audit list.  */
234
++	return NULL;
235
++      /* Start of audit list.  The first list element is at
236
++	 audit_list->next (cyclic list).  */
237
++      iter->previous = audit_list->next;
238
++      return iter->previous->name;
239
++    }
240
++  if (iter->previous == audit_list)
241
++    /* Cyclic list wrap-around.  */
242
++    return NULL;
243
++  iter->previous = iter->previous->next;
244
++  return iter->previous->name;
245
++}
246
++
247
+ #ifndef HAVE_INLINED_SYSCALLS
248
+ /* Set nonzero during loading and initialization of executable and
249
+    libraries, cleared before the executable's entry point runs.  This
250
+@@ -1305,11 +1383,13 @@ of this helper program; chances are you did not intend to run this program.\n\
251
+     GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid ();
252
+ 
253
+   /* If we have auditing DSOs to load, do it now.  */
254
+-  if (__glibc_unlikely (audit_list != NULL))
255
++  bool need_security_init = true;
256
++  if (__glibc_unlikely (audit_list != NULL)
257
++      || __glibc_unlikely (audit_list_string != NULL))
258
+     {
259
+-      /* Iterate over all entries in the list.  The order is important.  */
260
+       struct audit_ifaces *last_audit = NULL;
261
+-      struct audit_list *al = audit_list->next;
262
++      struct audit_list_iter al_iter;
263
++      audit_list_iter_init (&al_iter);
264
+ 
265
+       /* Since we start using the auditing DSOs right away we need to
266
+ 	 initialize the data structures now.  */
267
+@@ -1320,9 +1400,14 @@ of this helper program; chances are you did not intend to run this program.\n\
268
+ 	 use different values (especially the pointer guard) and will
269
+ 	 fail later on.  */
270
+       security_init ();
271
++      need_security_init = false;
272
+ 
273
+-      do
274
++      while (true)
275
+ 	{
276
++	  const char *name = audit_list_iter_next (&al_iter);
277
++	  if (name == NULL)
278
++	    break;
279
++
280
+ 	  int tls_idx = GL(dl_tls_max_dtv_idx);
281
+ 
282
+ 	  /* Now it is time to determine the layout of the static TLS
283
+@@ -1331,7 +1416,7 @@ of this helper program; chances are you did not intend to run this program.\n\
284
+ 	     no DF_STATIC_TLS bit is set.  The reason is that we know
285
+ 	     glibc will use the static model.  */
286
+ 	  struct dlmopen_args dlmargs;
287
+-	  dlmargs.fname = al->name;
288
++	  dlmargs.fname = name;
289
+ 	  dlmargs.map = NULL;
290
+ 
291
+ 	  const char *objname;
292
+@@ -1344,7 +1429,7 @@ of this helper program; chances are you did not intend to run this program.\n\
293
+ 	    not_loaded:
294
+ 	      _dl_error_printf ("\
295
+ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
296
+-				al->name, err_str);
297
++				name, err_str);
298
+ 	      if (malloced)
299
+ 		free ((char *) err_str);
300
+ 	    }
301
+@@ -1448,10 +1533,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
302
+ 		  goto not_loaded;
303
+ 		}
304
+ 	    }
305
+-
306
+-	  al = al->next;
307
+ 	}
308
+-      while (al != audit_list->next);
309
+ 
310
+       /* If we have any auditing modules, announce that we already
311
+ 	 have two objects loaded.  */
312
+@@ -1715,7 +1797,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
313
+   if (tcbp == NULL)
314
+     tcbp = init_tls ();
315
+ 
316
+-  if (__glibc_likely (audit_list == NULL))
317
++  if (__glibc_likely (need_security_init))
318
+     /* Initialize security features.  But only if we have not done it
319
+        earlier.  */
320
+     security_init ();
321
+@@ -2346,9 +2428,7 @@ process_dl_audit (char *str)
322
+   char *p;
323
+ 
324
+   while ((p = (strsep) (&str, ":")) != NULL)
325
+-    if (p[0] != '\0'
326
+-	&& (__builtin_expect (! __libc_enable_secure, 1)
327
+-	    || strchr (p, '/') == NULL))
328
++    if (dso_name_valid_for_suid (p))
329
+       {
330
+ 	/* This is using the local malloc, not the system malloc.  The
331
+ 	   memory can never be freed.  */
332
+@@ -2412,7 +2492,7 @@ process_envvars (enum mode *modep)
333
+ 	      break;
334
+ 	    }
335
+ 	  if (memcmp (envline, "AUDIT", 5) == 0)
336
+-	    process_dl_audit (&envline[6]);
337
++	    audit_list_string = &envline[6];
338
+ 	  break;
339
+ 
340
+ 	case 7:
... ...
@@ -4,7 +4,7 @@
4 4
 Summary:	Main C library
5 5
 Name:		glibc
6 6
 Version:	2.25
7
-Release:	3%{?dist}
7
+Release:	4%{?dist}
8 8
 License:	LGPLv2+
9 9
 URL:		http://www.gnu.org/software/libc
10 10
 Group:		Applications/System
... ...
@@ -16,6 +16,7 @@ Source1:	locale-gen.sh
16 16
 Source2:	locale-gen.conf
17 17
 Patch0:   	http://www.linuxfromscratch.org/patches/downloads/glibc/glibc-2.25-fhs-1.patch
18 18
 Patch1:		glibc-2.24-bindrsvport-blacklist.patch
19
+Patch2:         glibc-fix-CVE-2017-1000366.patch
19 20
 Provides:	rtld(GNU_HASH)
20 21
 Requires:       filesystem
21 22
 %description
... ...
@@ -71,6 +72,7 @@ Name Service Cache Daemon
71 71
 sed -i 's/\\$$(pwd)/`pwd`/' timezone/Makefile
72 72
 %patch0 -p1
73 73
 %patch1 -p1
74
+%patch2 -p1
74 75
 install -vdm 755 %{_builddir}/%{name}-build
75 76
 # do not try to explicitly provide GLIBC_PRIVATE versioned libraries
76 77
 %define __find_provides %{_builddir}/%{name}-%{version}/find_provides.sh
... ...
@@ -253,6 +255,8 @@ sed -i 's@#!/bin/bash@#!/bin/sh@' %{buildroot}/usr/bin/tzselect
253 253
 
254 254
 
255 255
 %changelog
256
+*   Tue Aug 08 2017 Anish Swaminathan <anishs@vmware.com> 2.25-4
257
+-   Apply fix for CVE-2017-1000366
256 258
 *   Thu May 4  2017 Bo Gan <ganb@vmware.com> 2.25-3
257 259
 -   Remove bash dependency in post/postun script
258 260
 *   Fri Apr 21 2017 Alexey Makhalov <amakhalov@vmware.com> 2.25-2