1 |
From 5bd80bfe9ca0d955bfbbc002781bc7b01b6bcb06 Mon Sep 17 00:00:00 2001 |
2 |
From: Paul Pluzhnikov <ppluzhnikov@google.com> |
3 |
Date: Fri, 6 Feb 2015 00:30:42 -0500 |
4 |
Subject: [PATCH] CVE-2015-1472: wscanf allocates too little memory |
5 |
|
6 |
BZ #16618 |
7 |
|
8 |
Under certain conditions wscanf can allocate too little memory for the |
9 |
to-be-scanned arguments and overflow the allocated buffer. The |
10 |
implementation now correctly computes the required buffer size when |
11 |
using malloc. |
12 |
|
13 |
A regression test was added to tst-sscanf. |
14 |
--- |
15 |
ChangeLog | 8 ++++++++ |
16 |
NEWS | 24 +++++++++++++++--------- |
17 |
stdio-common/tst-sscanf.c | 33 +++++++++++++++++++++++++++++++++ |
18 |
stdio-common/vfscanf.c | 12 ++++++------ |
19 |
4 files changed, 62 insertions(+), 15 deletions(-) |
20 |
|
21 |
#diff --git a/ChangeLog b/ChangeLog |
22 |
#index 4916b03..d23d3ae 100644 |
23 |
#--- a/ChangeLog |
24 |
#+++ b/ChangeLog |
25 |
#@@ -1,3 +1,11 @@ |
26 |
#+2015-02-05 Paul Pluzhnikov <ppluzhnikov@google.com> |
27 |
#+ |
28 |
#+ [BZ #16618] |
29 |
#+ * stdio-common/tst-sscanf.c (main): Test for buffer overflow. |
30 |
#+ * stdio-common/vfscanf.c (_IO_vfscanf_internal): Compute needed |
31 |
#+ size in bytes. Store needed elements in wpmax. Use needed size |
32 |
#+ in bytes for extend_alloca. |
33 |
#+ |
34 |
# 2015-02-05 Carlos O'Donell <carlos@systemhalted.org> |
35 |
# |
36 |
# * manual/install.texi: Latest tested versions are GCC 4.9.2, |
37 |
#diff --git a/NEWS b/NEWS |
38 |
#index c91b9fc..617cdbb 100644 |
39 |
#--- a/NEWS |
40 |
#+++ b/NEWS |
41 |
#@@ -10,15 +10,21 @@ Version 2.21 |
42 |
# * The following bugs are resolved with this release: |
43 |
# |
44 |
# 6652, 10672, 12674, 12847, 12926, 13862, 14132, 14138, 14171, 14498, |
45 |
#- 15215, 15378, 15884, 16009, 16418, 16191, 16469, 16576, 16617, 16619, |
46 |
#- 16657, 16740, 16857, 17192, 17266, 17273, 17344, 17363, 17370, 17371, |
47 |
#- 17411, 17460, 17475, 17485, 17501, 17506, 17508, 17522, 17555, 17570, |
48 |
#- 17571, 17572, 17573, 17574, 17582, 17583, 17584, 17585, 17589, 17594, |
49 |
#- 17601, 17608, 17616, 17625, 17630, 17633, 17634, 17635, 17647, 17653, |
50 |
#- 17657, 17658, 17664, 17665, 17668, 17682, 17702, 17717, 17719, 17722, |
51 |
#- 17723, 17724, 17725, 17732, 17733, 17744, 17745, 17746, 17747, 17748, |
52 |
#- 17775, 17777, 17780, 17781, 17782, 17791, 17793, 17796, 17797, 17801, |
53 |
#- 17803, 17806, 17834, 17844, 17848, 17868, 17869, 17870, 17885, 17892. |
54 |
#+ 15215, 15378, 15884, 16009, 16418, 16191, 16469, 16576, 16617, 16618, |
55 |
#+ 16619, 16657, 16740, 16857, 17192, 17266, 17273, 17344, 17363, 17370, |
56 |
#+ 17371, 17411, 17460, 17475, 17485, 17501, 17506, 17508, 17522, 17555, |
57 |
#+ 17570, 17571, 17572, 17573, 17574, 17582, 17583, 17584, 17585, 17589, |
58 |
#+ 17594, 17601, 17608, 17616, 17625, 17630, 17633, 17634, 17635, 17647, |
59 |
#+ 17653, 17657, 17658, 17664, 17665, 17668, 17682, 17702, 17717, 17719, |
60 |
#+ 17722, 17723, 17724, 17725, 17732, 17733, 17744, 17745, 17746, 17747, |
61 |
#+ 17748, 17775, 17777, 17780, 17781, 17782, 17791, 17793, 17796, 17797, |
62 |
#+ 17801, 17803, 17806, 17834, 17844, 17848, 17868, 17869, 17870, 17885, |
63 |
#+ 17892. |
64 |
#+ |
65 |
#+* CVE-2015-1472 Under certain conditions wscanf can allocate too little |
66 |
#+ memory for the to-be-scanned arguments and overflow the allocated |
67 |
#+ buffer. The implementation now correctly computes the required buffer |
68 |
#+ size when using malloc. |
69 |
# |
70 |
# * A new semaphore algorithm has been implemented in generic C code for all |
71 |
# machines. Previous custom assembly implementations of semaphore were |
72 |
diff --git a/stdio-common/tst-sscanf.c b/stdio-common/tst-sscanf.c |
73 |
index aece3f2..8a2eb9e 100644 |
74 |
--- a/stdio-common/tst-sscanf.c |
75 |
+++ b/stdio-common/tst-sscanf.c |
76 |
@@ -233,5 +233,38 @@ main (void) |
77 |
} |
78 |
} |
79 |
|
80 |
+ /* BZ #16618 |
81 |
+ The test will segfault during SSCANF if the buffer overflow |
82 |
+ is not fixed. The size of `s` is such that it forces the use |
83 |
+ of malloc internally and this triggers the incorrect computation. |
84 |
+ Thus the value for SIZE is arbitrariy high enough that malloc |
85 |
+ is used. */ |
86 |
+ { |
87 |
+#define SIZE 131072 |
88 |
+ CHAR *s = malloc ((SIZE + 1) * sizeof (*s)); |
89 |
+ if (s == NULL) |
90 |
+ abort (); |
91 |
+ for (size_t i = 0; i < SIZE; i++) |
92 |
+ s[i] = L('0'); |
93 |
+ s[SIZE] = L('\0'); |
94 |
+ int i = 42; |
95 |
+ /* Scan multi-digit zero into `i`. */ |
96 |
+ if (SSCANF (s, L("%d"), &i) != 1) |
97 |
+ { |
98 |
+ printf ("FAIL: bug16618: SSCANF did not read one input item.\n"); |
99 |
+ result = 1; |
100 |
+ } |
101 |
+ if (i != 0) |
102 |
+ { |
103 |
+ printf ("FAIL: bug16618: Value of `i` was not zero as expected.\n"); |
104 |
+ result = 1; |
105 |
+ } |
106 |
+ free (s); |
107 |
+ if (result != 1) |
108 |
+ printf ("PASS: bug16618: Did not crash.\n"); |
109 |
+#undef SIZE |
110 |
+ } |
111 |
+ |
112 |
+ |
113 |
return result; |
114 |
} |
115 |
diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c |
116 |
index cd129a8..0e204e7 100644 |
117 |
--- a/stdio-common/vfscanf.c |
118 |
+++ b/stdio-common/vfscanf.c |
119 |
@@ -272,9 +272,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, |
120 |
if (__glibc_unlikely (wpsize == wpmax)) \ |
121 |
{ \ |
122 |
CHAR_T *old = wp; \ |
123 |
- size_t newsize = (UCHAR_MAX + 1 > 2 * wpmax \ |
124 |
- ? UCHAR_MAX + 1 : 2 * wpmax); \ |
125 |
- if (use_malloc || !__libc_use_alloca (newsize)) \ |
126 |
+ bool fits = __glibc_likely (wpmax <= SIZE_MAX / sizeof (CHAR_T) / 2); \ |
127 |
+ size_t wpneed = MAX (UCHAR_MAX + 1, 2 * wpmax); \ |
128 |
+ size_t newsize = fits ? wpneed * sizeof (CHAR_T) : SIZE_MAX; \ |
129 |
+ if (!__libc_use_alloca (newsize)) \ |
130 |
{ \ |
131 |
wp = realloc (use_malloc ? wp : NULL, newsize); \ |
132 |
if (wp == NULL) \ |
133 |
@@ -286,14 +287,13 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, |
134 |
} \ |
135 |
if (! use_malloc) \ |
136 |
MEMCPY (wp, old, wpsize); \ |
137 |
- wpmax = newsize; \ |
138 |
+ wpmax = wpneed; \ |
139 |
use_malloc = true; \ |
140 |
} \ |
141 |
else \ |
142 |
{ \ |
143 |
size_t s = wpmax * sizeof (CHAR_T); \ |
144 |
- wp = (CHAR_T *) extend_alloca (wp, s, \ |
145 |
- newsize * sizeof (CHAR_T)); \ |
146 |
+ wp = (CHAR_T *) extend_alloca (wp, s, newsize); \ |
147 |
wpmax = s / sizeof (CHAR_T); \ |
148 |
if (old != NULL) \ |
149 |
MEMCPY (wp, old, wpsize); \ |
150 |
-- |
151 |
2.3.0 |
152 |
|