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