gnu: glibc: Fix replacement on i686.
[jackhill/guix/guix.git] / gnu / packages / patches / glibc-CVE-2017-1000366-pt3.patch
1 From 81b82fb966ffbd94353f793ad17116c6088dedd9 Mon Sep 17 00:00:00 2001
2 From: Florian Weimer <fweimer@redhat.com>
3 Date: Mon, 19 Jun 2017 22:32:12 +0200
4 Subject: [PATCH] ld.so: Reject overly long LD_AUDIT path elements
5
6 Also only process the last LD_AUDIT entry.
7
8 patch from:
9 https://sourceware.org/git/?p=glibc.git;a=commit;h=81b82fb966ffbd94353f793ad17116c6088dedd9
10
11 ---
12 ChangeLog | 11 +++++++
13 elf/rtld.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++---------
14 2 files changed, 106 insertions(+), 15 deletions(-)
15
16 diff --git a/elf/rtld.c b/elf/rtld.c
17 index 86ae20c..65647fb 100644
18 --- a/elf/rtld.c
19 +++ b/elf/rtld.c
20 @@ -129,13 +129,91 @@ dso_name_valid_for_suid (const char *p)
21 return *p != '\0';
22 }
23
24 -/* List of auditing DSOs. */
25 +/* LD_AUDIT variable contents. Must be processed before the
26 + audit_list below. */
27 +const char *audit_list_string;
28 +
29 +/* Cyclic list of auditing DSOs. audit_list->next is the first
30 + element. */
31 static struct audit_list
32 {
33 const char *name;
34 struct audit_list *next;
35 } *audit_list;
36
37 +/* Iterator for audit_list_string followed by audit_list. */
38 +struct audit_list_iter
39 +{
40 + /* Tail of audit_list_string still needing processing, or NULL. */
41 + const char *audit_list_tail;
42 +
43 + /* The list element returned in the previous iteration. NULL before
44 + the first element. */
45 + struct audit_list *previous;
46 +
47 + /* Scratch buffer for returning a name which is part of
48 + audit_list_string. */
49 + char fname[SECURE_NAME_LIMIT];
50 +};
51 +
52 +/* Initialize an audit list iterator. */
53 +static void
54 +audit_list_iter_init (struct audit_list_iter *iter)
55 +{
56 + iter->audit_list_tail = audit_list_string;
57 + iter->previous = NULL;
58 +}
59 +
60 +/* Iterate through both audit_list_string and audit_list. */
61 +static const char *
62 +audit_list_iter_next (struct audit_list_iter *iter)
63 +{
64 + if (iter->audit_list_tail != NULL)
65 + {
66 + /* First iterate over audit_list_string. */
67 + while (*iter->audit_list_tail != '\0')
68 + {
69 + /* Split audit list at colon. */
70 + size_t len = strcspn (iter->audit_list_tail, ":");
71 + if (len > 0 && len < sizeof (iter->fname))
72 + {
73 + memcpy (iter->fname, iter->audit_list_tail, len);
74 + iter->fname[len] = '\0';
75 + }
76 + else
77 + /* Do not return this name to the caller. */
78 + iter->fname[0] = '\0';
79 +
80 + /* Skip over the substring and the following delimiter. */
81 + iter->audit_list_tail += len;
82 + if (*iter->audit_list_tail == ':')
83 + ++iter->audit_list_tail;
84 +
85 + /* If the name is valid, return it. */
86 + if (dso_name_valid_for_suid (iter->fname))
87 + return iter->fname;
88 + /* Otherwise, wrap around and try the next name. */
89 + }
90 + /* Fall through to the procesing of audit_list. */
91 + }
92 +
93 + if (iter->previous == NULL)
94 + {
95 + if (audit_list == NULL)
96 + /* No pre-parsed audit list. */
97 + return NULL;
98 + /* Start of audit list. The first list element is at
99 + audit_list->next (cyclic list). */
100 + iter->previous = audit_list->next;
101 + return iter->previous->name;
102 + }
103 + if (iter->previous == audit_list)
104 + /* Cyclic list wrap-around. */
105 + return NULL;
106 + iter->previous = iter->previous->next;
107 + return iter->previous->name;
108 +}
109 +
110 #ifndef HAVE_INLINED_SYSCALLS
111 /* Set nonzero during loading and initialization of executable and
112 libraries, cleared before the executable's entry point runs. This
113 @@ -1305,11 +1383,13 @@ of this helper program; chances are you did not intend to run this program.\n\
114 GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid ();
115
116 /* If we have auditing DSOs to load, do it now. */
117 - if (__glibc_unlikely (audit_list != NULL))
118 + bool need_security_init = true;
119 + if (__glibc_unlikely (audit_list != NULL)
120 + || __glibc_unlikely (audit_list_string != NULL))
121 {
122 - /* Iterate over all entries in the list. The order is important. */
123 struct audit_ifaces *last_audit = NULL;
124 - struct audit_list *al = audit_list->next;
125 + struct audit_list_iter al_iter;
126 + audit_list_iter_init (&al_iter);
127
128 /* Since we start using the auditing DSOs right away we need to
129 initialize the data structures now. */
130 @@ -1320,9 +1400,14 @@ of this helper program; chances are you did not intend to run this program.\n\
131 use different values (especially the pointer guard) and will
132 fail later on. */
133 security_init ();
134 + need_security_init = false;
135
136 - do
137 + while (true)
138 {
139 + const char *name = audit_list_iter_next (&al_iter);
140 + if (name == NULL)
141 + break;
142 +
143 int tls_idx = GL(dl_tls_max_dtv_idx);
144
145 /* Now it is time to determine the layout of the static TLS
146 @@ -1331,7 +1416,7 @@ of this helper program; chances are you did not intend to run this program.\n\
147 no DF_STATIC_TLS bit is set. The reason is that we know
148 glibc will use the static model. */
149 struct dlmopen_args dlmargs;
150 - dlmargs.fname = al->name;
151 + dlmargs.fname = name;
152 dlmargs.map = NULL;
153
154 const char *objname;
155 @@ -1344,7 +1429,7 @@ of this helper program; chances are you did not intend to run this program.\n\
156 not_loaded:
157 _dl_error_printf ("\
158 ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
159 - al->name, err_str);
160 + name, err_str);
161 if (malloced)
162 free ((char *) err_str);
163 }
164 @@ -1448,10 +1533,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
165 goto not_loaded;
166 }
167 }
168 -
169 - al = al->next;
170 }
171 - while (al != audit_list->next);
172
173 /* If we have any auditing modules, announce that we already
174 have two objects loaded. */
175 @@ -1715,7 +1797,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
176 if (tcbp == NULL)
177 tcbp = init_tls ();
178
179 - if (__glibc_likely (audit_list == NULL))
180 + if (__glibc_likely (need_security_init))
181 /* Initialize security features. But only if we have not done it
182 earlier. */
183 security_init ();
184 @@ -2346,9 +2428,7 @@ process_dl_audit (char *str)
185 char *p;
186
187 while ((p = (strsep) (&str, ":")) != NULL)
188 - if (p[0] != '\0'
189 - && (__builtin_expect (! __libc_enable_secure, 1)
190 - || strchr (p, '/') == NULL))
191 + if (dso_name_valid_for_suid (p))
192 {
193 /* This is using the local malloc, not the system malloc. The
194 memory can never be freed. */
195 @@ -2412,7 +2492,7 @@ process_envvars (enum mode *modep)
196 break;
197 }
198 if (memcmp (envline, "AUDIT", 5) == 0)
199 - process_dl_audit (&envline[6]);
200 + audit_list_string = &envline[6];
201 break;
202
203 case 7:
204 --
205 2.9.3
206