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
6 Also only process the last LD_AUDIT entry.
9 https://sourceware.org/git/?p=glibc.git;a=commit;h=81b82fb966ffbd94353f793ad17116c6088dedd9
12 ChangeLog | 11 +++++++
13 elf/rtld.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++---------
14 2 files changed, 106 insertions(+), 15 deletions(-)
16 diff --git a/elf/rtld.c b/elf/rtld.c
17 index 86ae20c..65647fb 100644
20 @@ -129,13 +129,91 @@ dso_name_valid_for_suid (const char *p)
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;
29 +/* Cyclic list of auditing DSOs. audit_list->next is the first
31 static struct audit_list
34 struct audit_list *next;
37 +/* Iterator for audit_list_string followed by audit_list. */
38 +struct audit_list_iter
40 + /* Tail of audit_list_string still needing processing, or NULL. */
41 + const char *audit_list_tail;
43 + /* The list element returned in the previous iteration. NULL before
44 + the first element. */
45 + struct audit_list *previous;
47 + /* Scratch buffer for returning a name which is part of
48 + audit_list_string. */
49 + char fname[SECURE_NAME_LIMIT];
52 +/* Initialize an audit list iterator. */
54 +audit_list_iter_init (struct audit_list_iter *iter)
56 + iter->audit_list_tail = audit_list_string;
57 + iter->previous = NULL;
60 +/* Iterate through both audit_list_string and audit_list. */
62 +audit_list_iter_next (struct audit_list_iter *iter)
64 + if (iter->audit_list_tail != NULL)
66 + /* First iterate over audit_list_string. */
67 + while (*iter->audit_list_tail != '\0')
69 + /* Split audit list at colon. */
70 + size_t len = strcspn (iter->audit_list_tail, ":");
71 + if (len > 0 && len < sizeof (iter->fname))
73 + memcpy (iter->fname, iter->audit_list_tail, len);
74 + iter->fname[len] = '\0';
77 + /* Do not return this name to the caller. */
78 + iter->fname[0] = '\0';
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;
85 + /* If the name is valid, return it. */
86 + if (dso_name_valid_for_suid (iter->fname))
88 + /* Otherwise, wrap around and try the next name. */
90 + /* Fall through to the procesing of audit_list. */
93 + if (iter->previous == NULL)
95 + if (audit_list == NULL)
96 + /* No pre-parsed audit list. */
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;
103 + if (iter->previous == audit_list)
104 + /* Cyclic list wrap-around. */
106 + iter->previous = iter->previous->next;
107 + return iter->previous->name;
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 ();
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))
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);
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
134 + need_security_init = false;
139 + const char *name = audit_list_iter_next (&al_iter);
143 int tls_idx = GL(dl_tls_max_dtv_idx);
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;
155 @@ -1344,7 +1429,7 @@ of this helper program; chances are you did not intend to run this program.\n\
158 ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
159 - al->name, err_str);
162 free ((char *) err_str);
164 @@ -1448,10 +1533,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
171 - while (al != audit_list->next);
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",
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
184 @@ -2346,9 +2428,7 @@ process_dl_audit (char *str)
187 while ((p = (strsep) (&str, ":")) != NULL)
189 - && (__builtin_expect (! __libc_enable_secure, 1)
190 - || strchr (p, '/') == NULL))
191 + if (dso_name_valid_for_suid (p))
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)
198 if (memcmp (envline, "AUDIT", 5) == 0)
199 - process_dl_audit (&envline[6]);
200 + audit_list_string = &envline[6];