summaryrefslogtreecommitdiffstats
path: root/meta/recipes-core/eglibc/eglibc-2.19/CVE-2014-7817-wordexp-fails-to-honour-WRDE_NOCMD.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-core/eglibc/eglibc-2.19/CVE-2014-7817-wordexp-fails-to-honour-WRDE_NOCMD.patch')
-rw-r--r--meta/recipes-core/eglibc/eglibc-2.19/CVE-2014-7817-wordexp-fails-to-honour-WRDE_NOCMD.patch216
1 files changed, 216 insertions, 0 deletions
diff --git a/meta/recipes-core/eglibc/eglibc-2.19/CVE-2014-7817-wordexp-fails-to-honour-WRDE_NOCMD.patch b/meta/recipes-core/eglibc/eglibc-2.19/CVE-2014-7817-wordexp-fails-to-honour-WRDE_NOCMD.patch
new file mode 100644
index 0000000000..2741ce621b
--- /dev/null
+++ b/meta/recipes-core/eglibc/eglibc-2.19/CVE-2014-7817-wordexp-fails-to-honour-WRDE_NOCMD.patch
@@ -0,0 +1,216 @@
1From a39208bd7fb76c1b01c127b4c61f9bfd915bfe7c Mon Sep 17 00:00:00 2001
2From: Carlos O'Donell <carlos@redhat.com>
3Date: Wed, 19 Nov 2014 11:44:12 -0500
4Subject: [PATCH] CVE-2014-7817: wordexp fails to honour WRDE_NOCMD.
5
6The function wordexp() fails to properly handle the WRDE_NOCMD
7flag when processing arithmetic inputs in the form of "$((... ``))"
8where "..." can be anything valid. The backticks in the arithmetic
9epxression are evaluated by in a shell even if WRDE_NOCMD forbade
10command substitution. This allows an attacker to attempt to pass
11dangerous commands via constructs of the above form, and bypass
12the WRDE_NOCMD flag. This patch fixes this by checking for WRDE_NOCMD
13in exec_comm(), the only place that can execute a shell. All other
14checks for WRDE_NOCMD are superfluous and removed.
15
16We expand the testsuite and add 3 new regression tests of roughly
17the same form but with a couple of nested levels.
18
19On top of the 3 new tests we add fork validation to the WRDE_NOCMD
20testing. If any forks are detected during the execution of a wordexp()
21call with WRDE_NOCMD, the test is marked as failed. This is slightly
22heuristic since vfork might be used in the future, but it provides a
23higher level of assurance that no shells were executed as part of
24command substitution with WRDE_NOCMD in effect. In addition it doesn't
25require libpthread or libdl, instead we use the public implementation
26namespace function __register_atfork (already part of the public ABI
27for libpthread).
28
29Tested on x86_64 with no regressions.
30---
31 ChangeLog | 22 ++++++++++++++++++++++
32 NEWS | 8 +++++++-
33 posix/wordexp-test.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
34 posix/wordexp.c | 16 ++++------------
35 4 files changed, 77 insertions(+), 13 deletions(-)
36
37Index: libc/ChangeLog
38===================================================================
39--- libc.orig/ChangeLog
40+++ libc/ChangeLog
41@@ -1,3 +1,25 @@
42+2014-11-19 Carlos O'Donell <carlos@redhat.com>
43+ Florian Weimer <fweimer@redhat.com>
44+ Joseph Myers <joseph@codesourcery.com>
45+ Adam Conrad <adconrad@0c3.net>
46+ Andreas Schwab <schwab@suse.de>
47+ Brooks <bmoses@google.com>
48+
49+ [BZ #17625]
50+ * wordexp-test.c (__dso_handle): Add prototype.
51+ (__register_atfork): Likewise.
52+ (__app_register_atfork): New function.
53+ (registered_forks): New global.
54+ (register_fork): New function.
55+ (test_case): Add 3 new tests for WRDE_CMDSUB.
56+ (main): Call __app_register_atfork.
57+ (testit): If WRDE_NOCMD set registered_forks to zero, run test, and if
58+ fork count is non-zero fail the test.
59+ * posix/wordexp.c (exec_comm): Return WRDE_CMDSUB if WRDE_NOCMD flag
60+ is set.
61+ (parse_dollars): Remove check for WRDE_NOCMD.
62+ (parse_dquote): Likewise.
63+
64 2014-08-26 Florian Weimer <fweimer@redhat.com>
65
66 [BZ #17187]
67Index: libc/posix/wordexp-test.c
68===================================================================
69--- libc.orig/posix/wordexp-test.c
70+++ libc/posix/wordexp-test.c
71@@ -27,6 +27,25 @@
72
73 #define IFS " \n\t"
74
75+extern void *__dso_handle __attribute__ ((__weak__, __visibility__ ("hidden")));
76+extern int __register_atfork (void (*) (void), void (*) (void), void (*) (void), void *);
77+
78+static int __app_register_atfork (void (*prepare) (void), void (*parent) (void), void (*child) (void))
79+{
80+ return __register_atfork (prepare, parent, child,
81+ &__dso_handle == NULL ? NULL : __dso_handle);
82+}
83+
84+/* Number of forks seen. */
85+static int registered_forks;
86+
87+/* For each fork increment the fork count. */
88+static void
89+register_fork (void)
90+{
91+ registered_forks++;
92+}
93+
94 struct test_case_struct
95 {
96 int retval;
97@@ -206,6 +225,12 @@ struct test_case_struct
98 { WRDE_SYNTAX, NULL, "$((2+))", 0, 0, { NULL, }, IFS },
99 { WRDE_SYNTAX, NULL, "`", 0, 0, { NULL, }, IFS },
100 { WRDE_SYNTAX, NULL, "$((010+4+))", 0, 0, { NULL }, IFS },
101+ /* Test for CVE-2014-7817. We test 3 combinations of command
102+ substitution inside an arithmetic expression to make sure that
103+ no commands are executed and error is returned. */
104+ { WRDE_CMDSUB, NULL, "$((`echo 1`))", WRDE_NOCMD, 0, { NULL, }, IFS },
105+ { WRDE_CMDSUB, NULL, "$((1+`echo 1`))", WRDE_NOCMD, 0, { NULL, }, IFS },
106+ { WRDE_CMDSUB, NULL, "$((1+$((`echo 1`))))", WRDE_NOCMD, 0, { NULL, }, IFS },
107
108 { -1, NULL, NULL, 0, 0, { NULL, }, IFS },
109 };
110@@ -258,6 +283,15 @@ main (int argc, char *argv[])
111 return -1;
112 }
113
114+ /* If we are not allowed to do command substitution, we install
115+ fork handlers to verify that no forks happened. No forks should
116+ happen at all if command substitution is disabled. */
117+ if (__app_register_atfork (register_fork, NULL, NULL) != 0)
118+ {
119+ printf ("Failed to register fork handler.\n");
120+ return -1;
121+ }
122+
123 for (test = 0; test_case[test].retval != -1; test++)
124 if (testit (&test_case[test]))
125 ++fail;
126@@ -367,6 +401,9 @@ testit (struct test_case_struct *tc)
127
128 printf ("Test %d (%s): ", ++tests, tc->words);
129
130+ if (tc->flags & WRDE_NOCMD)
131+ registered_forks = 0;
132+
133 if (tc->flags & WRDE_APPEND)
134 {
135 /* initial wordexp() call, to be appended to */
136@@ -378,6 +415,13 @@ testit (struct test_case_struct *tc)
137 }
138 retval = wordexp (tc->words, &we, tc->flags);
139
140+ if ((tc->flags & WRDE_NOCMD)
141+ && (registered_forks > 0))
142+ {
143+ printf ("FAILED fork called for WRDE_NOCMD\n");
144+ return 1;
145+ }
146+
147 if (tc->flags & WRDE_DOOFFS)
148 start_offs = sav_we.we_offs;
149
150Index: libc/posix/wordexp.c
151===================================================================
152--- libc.orig/posix/wordexp.c
153+++ libc/posix/wordexp.c
154@@ -893,6 +893,10 @@ exec_comm (char *comm, char **word, size
155 pid_t pid;
156 int noexec = 0;
157
158+ /* Do nothing if command substitution should not succeed. */
159+ if (flags & WRDE_NOCMD)
160+ return WRDE_CMDSUB;
161+
162 /* Don't fork() unless necessary */
163 if (!comm || !*comm)
164 return 0;
165@@ -2082,9 +2086,6 @@ parse_dollars (char **word, size_t *word
166 }
167 }
168
169- if (flags & WRDE_NOCMD)
170- return WRDE_CMDSUB;
171-
172 (*offset) += 2;
173 return parse_comm (word, word_length, max_length, words, offset, flags,
174 quoted? NULL : pwordexp, ifs, ifs_white);
175@@ -2196,9 +2197,6 @@ parse_dquote (char **word, size_t *word_
176 break;
177
178 case '`':
179- if (flags & WRDE_NOCMD)
180- return WRDE_CMDSUB;
181-
182 ++(*offset);
183 error = parse_backtick (word, word_length, max_length, words,
184 offset, flags, NULL, NULL, NULL);
185@@ -2357,12 +2355,6 @@ wordexp (const char *words, wordexp_t *p
186 break;
187
188 case '`':
189- if (flags & WRDE_NOCMD)
190- {
191- error = WRDE_CMDSUB;
192- goto do_error;
193- }
194-
195 ++words_offset;
196 error = parse_backtick (&word, &word_length, &max_length, words,
197 &words_offset, flags, pwordexp, ifs,
198Index: libc/NEWS
199===================================================================
200--- libc.orig/NEWS
201+++ libc/NEWS
202@@ -26,7 +26,13 @@ Version 2.19
203 16271, 16274, 16283, 16289, 16293, 16314, 16316, 16330, 16337, 16338,
204 16356, 16365, 16366, 16369, 16372, 16375, 16379, 16384, 16385, 16386,
205 16387, 16390, 16394, 16398, 16400, 16407, 16408, 16414, 16430, 16431,
206- 16453, 16474, 16506, 16510, 16529, 17187
207+ 16453, 16474, 16506, 16510, 16529, 17187, 17625.
208+
209+* CVE-2104-7817 The wordexp function could ignore the WRDE_NOCMD flag
210+ under certain input conditions resulting in the execution of a shell for
211+ command substitution when the applicaiton did not request it. The
212+ implementation now checks WRDE_NOCMD immediately before executing the
213+ shell and returns the error WRDE_CMDSUB as expected.
214
215 * Slovenian translations for glibc messages have been contributed by the
216 Translation Project's Slovenian team of translators.