···11+From ba67ba3275d47e0080f0e5f09d9f5102c000c97e Mon Sep 17 00:00:00 2001
22+Message-Id: <ba67ba3275d47e0080f0e5f09d9f5102c000c97e.1495998948.git.fweimer@redhat.com>
33+In-Reply-To: <cover.1495998948.git.fweimer@redhat.com>
44+References: <cover.1495998948.git.fweimer@redhat.com>
55+From: Florian Weimer <fweimer@redhat.com>
66+Date: Sun, 28 May 2017 20:44:52 +0200
77+Subject: [PATCH 3/3] rtld: Reject overly long LD_AUDIT path elements
88+To: libc-alpha@sourceware.org
99+1010+Also only process the last LD_AUDIT entry.
1111+---
1212+ elf/rtld.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++---------
1313+ 1 file changed, 95 insertions(+), 15 deletions(-)
1414+1515+diff --git a/elf/rtld.c b/elf/rtld.c
1616+index 30f0cae..89d8573 100644
1717+--- a/elf/rtld.c
1818++++ b/elf/rtld.c
1919+@@ -116,13 +116,95 @@ dso_name_valid_for_suid (const char *p)
2020+ return *p != '\0';
2121+ }
2222+2323+-/* List of auditing DSOs. */
2424++/* LD_AUDIT variable contents. Must be processed before the
2525++ audit_list below. */
2626++const char *audit_list_string;
2727++
2828++/* Cyclic list of auditing DSOs. audit_list->next is the first
2929++ element. */
3030+ static struct audit_list
3131+ {
3232+ const char *name;
3333+ struct audit_list *next;
3434+ } *audit_list;
3535+3636++/* Iterator for audit_list_string followed by audit_list. */
3737++struct audit_list_iter
3838++{
3939++ /* Tail of audit_list_string still needing processing, or NULL. */
4040++ const char *audit_list_tail;
4141++
4242++ /* The list element returned in the previous iteration. NULL before
4343++ the first element. */
4444++ struct audit_list *previous;
4545++
4646++ /* Scratch buffer for returning a name which is part of
4747++ audit_list_string. */
4848++#ifdef PATH_MAX
4949++ char fname[PATH_MAX];
5050++#else
5151++ char fname[4096];
5252++#endif
5353++};
5454++
5555++/* Initialize an audit list iterator. */
5656++static void
5757++audit_list_iter_init (struct audit_list_iter *iter)
5858++{
5959++ iter->audit_list_tail = audit_list_string;
6060++ iter->previous = NULL;
6161++}
6262++
6363++/* Iterate through both audit_list_string and audit_list. */
6464++static const char *
6565++audit_list_iter_next (struct audit_list_iter *iter)
6666++{
6767++ if (iter->audit_list_tail != NULL)
6868++ {
6969++ /* First iterate over audit_list_string. */
7070++ while (*iter->audit_list_tail != '\0')
7171++ {
7272++ /* Split audit list at colon. */
7373++ size_t len = strcspn (iter->audit_list_tail, ":");
7474++ if (len > 0 && len < sizeof(iter->fname))
7575++ {
7676++ memcpy (iter->fname, iter->audit_list_tail, len);
7777++ iter->fname[len] = '\0';
7878++ }
7979++ else
8080++ /* Do not return this name to the caller. */
8181++ iter->fname[0] = '\0';
8282++
8383++ /* Skip over the substring and the following delimiter. */
8484++ iter->audit_list_tail += len;
8585++ if (*iter->audit_list_tail == ':')
8686++ ++iter->audit_list_tail;
8787++
8888++ /* If the name is valid, return it. */
8989++ if (dso_name_valid_for_suid (iter->fname))
9090++ return iter->fname;
9191++ /* Otherwise, wrap around and try the next name. */
9292++ }
9393++ /* Fall through to the procesing of audit_list. */
9494++ }
9595++
9696++ if (iter->previous == NULL)
9797++ {
9898++ if (audit_list == NULL)
9999++ /* No pre-parsed audit list. */
100100++ return NULL;
101101++ /* Start of audit list. The first list element is at
102102++ audit_list->next (cyclic list). */
103103++ iter->previous = audit_list->next;
104104++ return iter->previous->name;
105105++ }
106106++ if (iter->previous == audit_list)
107107++ /* Cyclic list wrap-around. */
108108++ return NULL;
109109++ iter->previous = iter->previous->next;
110110++ return iter->previous->name;
111111++}
112112++
113113+ #ifndef HAVE_INLINED_SYSCALLS
114114+ /* Set nonzero during loading and initialization of executable and
115115+ libraries, cleared before the executable's entry point runs. This
116116+@@ -1290,11 +1368,13 @@ of this helper program; chances are you did not intend to run this program.\n\
117117+ GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid ();
118118+119119+ /* If we have auditing DSOs to load, do it now. */
120120+- if (__glibc_unlikely (audit_list != NULL))
121121++ bool need_security_init = true;
122122++ if (__glibc_unlikely (audit_list != NULL)
123123++ || __glibc_unlikely (audit_list_string != NULL))
124124+ {
125125+- /* Iterate over all entries in the list. The order is important. */
126126+ struct audit_ifaces *last_audit = NULL;
127127+- struct audit_list *al = audit_list->next;
128128++ struct audit_list_iter al_iter;
129129++ audit_list_iter_init (&al_iter);
130130+131131+ /* Since we start using the auditing DSOs right away we need to
132132+ initialize the data structures now. */
133133+@@ -1305,9 +1385,14 @@ of this helper program; chances are you did not intend to run this program.\n\
134134+ use different values (especially the pointer guard) and will
135135+ fail later on. */
136136+ security_init ();
137137++ need_security_init = false;
138138+139139+- do
140140++ while (true)
141141+ {
142142++ const char *name = audit_list_iter_next (&al_iter);
143143++ if (name == NULL)
144144++ break;
145145++
146146+ int tls_idx = GL(dl_tls_max_dtv_idx);
147147+148148+ /* Now it is time to determine the layout of the static TLS
149149+@@ -1316,7 +1401,7 @@ of this helper program; chances are you did not intend to run this program.\n\
150150+ no DF_STATIC_TLS bit is set. The reason is that we know
151151+ glibc will use the static model. */
152152+ struct dlmopen_args dlmargs;
153153+- dlmargs.fname = al->name;
154154++ dlmargs.fname = name;
155155+ dlmargs.map = NULL;
156156+157157+ const char *objname;
158158+@@ -1329,7 +1414,7 @@ of this helper program; chances are you did not intend to run this program.\n\
159159+ not_loaded:
160160+ _dl_error_printf ("\
161161+ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
162162+- al->name, err_str);
163163++ name, err_str);
164164+ if (malloced)
165165+ free ((char *) err_str);
166166+ }
167167+@@ -1433,10 +1518,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
168168+ goto not_loaded;
169169+ }
170170+ }
171171+-
172172+- al = al->next;
173173+ }
174174+- while (al != audit_list->next);
175175+176176+ /* If we have any auditing modules, announce that we already
177177+ have two objects loaded. */
178178+@@ -1700,7 +1782,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
179179+ if (tcbp == NULL)
180180+ tcbp = init_tls ();
181181+182182+- if (__glibc_likely (audit_list == NULL))
183183++ if (__glibc_likely (need_security_init))
184184+ /* Initialize security features. But only if we have not done it
185185+ earlier. */
186186+ security_init ();
187187+@@ -2331,9 +2413,7 @@ process_dl_audit (char *str)
188188+ char *p;
189189+190190+ while ((p = (strsep) (&str, ":")) != NULL)
191191+- if (p[0] != '\0'
192192+- && (__builtin_expect (! __libc_enable_secure, 1)
193193+- || strchr (p, '/') == NULL))
194194++ if (dso_name_valid_for_suid (p))
195195+ {
196196+ /* This is using the local malloc, not the system malloc. The
197197+ memory can never be freed. */
198198+@@ -2397,7 +2477,7 @@ process_envvars (enum mode *modep)
199199+ break;
200200+ }
201201+ if (memcmp (envline, "AUDIT", 5) == 0)
202202+- process_dl_audit (&envline[6]);
203203++ audit_list_string = &envline[6];
204204+ break;
205205+206206+ case 7:
207207+--
208208+2.9.4
209209+