CRUX-ARM : Home

Home :: Documentation :: Download :: Development :: Community :: Ports :: Packages :: Bugs :: Links :: About :: Donors
glibc: updated to 2.19-5 Added CVE patches
[ports/core-arm.git] / glibc / CVE-2012-3406-Stack-overflow-in-vfprintf-BZ-16617.patch
CommitLineData
3d9e9aa9
VM
1From 6143805bb45e716829d86851e9372f55a136064b Mon Sep 17 00:00:00 2001
2From: Jeff Law <law@redhat.com>
3Date: Mon, 15 Dec 2014 10:09:32 +0100
4Subject: [PATCH 35/37] CVE-2012-3406: Stack overflow in vfprintf [BZ #16617]
5
6A larger number of format specifiers coudld cause a stack overflow,
7potentially allowing to bypass _FORTIFY_SOURCE format string
8protection.
9
10Conflicts:
11 ChangeLog
12 NEWS
13---
14 ChangeLog | 13 +++++++++
15 NEWS | 57 ++++++++++++++++++++++++++++++++++++++++
16 stdio-common/Makefile | 2 +-
17 stdio-common/bug23-2.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++
18 stdio-common/bug23-3.c | 50 +++++++++++++++++++++++++++++++++++
19 stdio-common/bug23-4.c | 31 ++++++++++++++++++++++
20 stdio-common/vfprintf.c | 40 ++++++++++++++++++++++++++--
21 7 files changed, 260 insertions(+), 3 deletions(-)
22 create mode 100644 stdio-common/bug23-2.c
23 create mode 100644 stdio-common/bug23-3.c
24 create mode 100644 stdio-common/bug23-4.c
25
26diff --git a/stdio-common/bug23-2.c b/stdio-common/bug23-2.c
27new file mode 100644
28index 0000000..9e0cfe6
29--- /dev/null
30+++ b/stdio-common/bug23-2.c
31@@ -0,0 +1,70 @@
32+#include <stdio.h>
33+#include <string.h>
34+#include <stdlib.h>
35+
36+static const char expected[] = "\
37+\n\
38+a\n\
39+abbcd55\
40+\n\
41+a\n\
42+abbcd55\
43+\n\
44+a\n\
45+abbcd55\
46+\n\
47+a\n\
48+abbcd55\
49+\n\
50+a\n\
51+abbcd55\
52+\n\
53+a\n\
54+abbcd55\
55+\n\
56+a\n\
57+abbcd55\
58+\n\
59+a\n\
60+abbcd55\
61+\n\
62+a\n\
63+abbcd55\
64+\n\
65+a\n\
66+abbcd55\
67+\n\
68+a\n\
69+abbcd55\
70+\n\
71+a\n\
72+abbcd55\
73+\n\
74+a\n\
75+abbcd55%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
76+
77+static int
78+do_test (void)
79+{
80+ char *buf = malloc (strlen (expected) + 1);
81+ snprintf (buf, strlen (expected) + 1,
82+ "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
83+ "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
84+ "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
85+ "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
86+ "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
87+ "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
88+ "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
89+ "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
90+ "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
91+ "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
92+ "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
93+ "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
94+ "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
95+ "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n",
96+ "a", "b", "c", "d", 5);
97+ return strcmp (buf, expected) != 0;
98+}
99+
100+#define TEST_FUNCTION do_test ()
101+#include "../test-skeleton.c"
102diff --git a/stdio-common/bug23-3.c b/stdio-common/bug23-3.c
103new file mode 100644
104index 0000000..57c8cef
105--- /dev/null
106+++ b/stdio-common/bug23-3.c
107@@ -0,0 +1,50 @@
108+#include <stdio.h>
109+#include <string.h>
110+#include <stdlib.h>
111+
112+int
113+do_test (void)
114+{
115+ size_t instances = 16384;
116+#define X0 "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
117+ const char *item = "\na\nabbcd55";
118+#define X3 X0 X0 X0 X0 X0 X0 X0 X0
119+#define X6 X3 X3 X3 X3 X3 X3 X3 X3
120+#define X9 X6 X6 X6 X6 X6 X6 X6 X6
121+#define X12 X9 X9 X9 X9 X9 X9 X9 X9
122+#define X14 X12 X12 X12 X12
123+#define TRAILER "%%%%%%%%%%%%%%%%%%%%%%%%%%"
124+#define TRAILER2 TRAILER TRAILER
125+ size_t length = instances * strlen (item) + strlen (TRAILER) + 1;
126+
127+ char *buf = malloc (length + 1);
128+ snprintf (buf, length + 1,
129+ X14 TRAILER2 "\n",
130+ "a", "b", "c", "d", 5);
131+
132+ const char *p = buf;
133+ size_t i;
134+ for (i = 0; i < instances; ++i)
135+ {
136+ const char *expected;
137+ for (expected = item; *expected; ++expected)
138+ {
139+ if (*p != *expected)
140+ {
141+ printf ("mismatch at offset %zu (%zu): expected %d, got %d\n",
142+ (size_t) (p - buf), i, *expected & 0xFF, *p & 0xFF);
143+ return 1;
144+ }
145+ ++p;
146+ }
147+ }
148+ if (strcmp (p, TRAILER "\n") != 0)
149+ {
150+ printf ("mismatch at trailer: [%s]\n", p);
151+ return 1;
152+ }
153+ free (buf);
154+ return 0;
155+}
156+#define TEST_FUNCTION do_test ()
157+#include "../test-skeleton.c"
158diff --git a/stdio-common/bug23-4.c b/stdio-common/bug23-4.c
159new file mode 100644
160index 0000000..a478564
161--- /dev/null
162+++ b/stdio-common/bug23-4.c
163@@ -0,0 +1,31 @@
164+#include <stdio.h>
165+#include <stdlib.h>
166+#include <string.h>
167+#include <sys/resource.h>
168+
169+#define LIMIT 1000000
170+
171+int
172+main (void)
173+{
174+ struct rlimit lim;
175+ getrlimit (RLIMIT_STACK, &lim);
176+ lim.rlim_cur = 1048576;
177+ setrlimit (RLIMIT_STACK, &lim);
178+ char *fmtstr = malloc (4 * LIMIT + 1);
179+ if (fmtstr == NULL)
180+ abort ();
181+ char *output = malloc (LIMIT + 1);
182+ if (output == NULL)
183+ abort ();
184+ for (size_t i = 0; i < LIMIT; i++)
185+ memcpy (fmtstr + 4 * i, "%1$d", 4);
186+ fmtstr[4 * LIMIT] = '\0';
187+ int ret = snprintf (output, LIMIT + 1, fmtstr, 0);
188+ if (ret != LIMIT)
189+ abort ();
190+ for (size_t i = 0; i < LIMIT; i++)
191+ if (output[i] != '0')
192+ abort ();
193+ return 0;
194+}
195diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c
196index f7e5f61..f423be6 100644
197--- a/stdio-common/vfprintf.c
198+++ b/stdio-common/vfprintf.c
199@@ -263,6 +263,12 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
200 /* For the argument descriptions, which may be allocated on the heap. */
201 void *args_malloced = NULL;
202
203+ /* For positional argument handling. */
204+ struct printf_spec *specs;
205+
206+ /* Track if we malloced the SPECS array and thus must free it. */
207+ bool specs_malloced = false;
208+
209 /* This table maps a character into a number representing a
210 class. In each step there is a destination label for each
211 class. */
212@@ -1678,8 +1684,8 @@ do_positional:
213 size_t nspecs = 0;
214 /* A more or less arbitrary start value. */
215 size_t nspecs_size = 32 * sizeof (struct printf_spec);
216- struct printf_spec *specs = alloca (nspecs_size);
217
218+ specs = alloca (nspecs_size);
219 /* The number of arguments the format string requests. This will
220 determine the size of the array needed to store the argument
221 attributes. */
222@@ -1720,11 +1726,39 @@ do_positional:
223 if (nspecs * sizeof (*specs) >= nspecs_size)
224 {
225 /* Extend the array of format specifiers. */
226+ if (nspecs_size * 2 < nspecs_size)
227+ {
228+ __set_errno (ENOMEM);
229+ done = -1;
230+ goto all_done;
231+ }
232 struct printf_spec *old = specs;
233- specs = extend_alloca (specs, nspecs_size, 2 * nspecs_size);
234+ if (__libc_use_alloca (2 * nspecs_size))
235+ specs = extend_alloca (specs, nspecs_size, 2 * nspecs_size);
236+ else
237+ {
238+ nspecs_size *= 2;
239+ specs = malloc (nspecs_size);
240+ if (specs == NULL)
241+ {
242+ __set_errno (ENOMEM);
243+ specs = old;
244+ done = -1;
245+ goto all_done;
246+ }
247+ }
248
249 /* Copy the old array's elements to the new space. */
250 memmove (specs, old, nspecs * sizeof (*specs));
251+
252+ /* If we had previously malloc'd space for SPECS, then
253+ release it after the copy is complete. */
254+ if (specs_malloced)
255+ free (old);
256+
257+ /* Now set SPECS_MALLOCED if needed. */
258+ if (!__libc_use_alloca (nspecs_size))
259+ specs_malloced = true;
260 }
261
262 /* Parse the format specifier. */
263@@ -2045,6 +2079,8 @@ do_positional:
264 }
265
266 all_done:
267+ if (specs_malloced)
268+ free (specs);
269 if (__glibc_unlikely (args_malloced != NULL))
270 free (args_malloced);
271 if (__glibc_unlikely (workstart != NULL))
272--
2732.2.1
274