1 |
floppym 14/06/21 01:55:09 |
2 |
|
3 |
Added: freerdp-1.1-CVE-2014-0250.patch |
4 |
Log: |
5 |
Add fix for CVE-2014-0250, bug 511688. |
6 |
|
7 |
(Portage version: 2.2.10/cvs/Linux x86_64, signed Manifest commit with key 0BBEEA1FEA4843A4) |
8 |
|
9 |
Revision Changes Path |
10 |
1.1 net-misc/freerdp/files/freerdp-1.1-CVE-2014-0250.patch |
11 |
|
12 |
file : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/net-misc/freerdp/files/freerdp-1.1-CVE-2014-0250.patch?rev=1.1&view=markup |
13 |
plain: http://sources.gentoo.org/viewvc.cgi/gentoo-x86/net-misc/freerdp/files/freerdp-1.1-CVE-2014-0250.patch?rev=1.1&content-type=text/plain |
14 |
|
15 |
Index: freerdp-1.1-CVE-2014-0250.patch |
16 |
=================================================================== |
17 |
From 5ad707ddf33d1d785a8ca1fbeec91d2eee985820 Mon Sep 17 00:00:00 2001 |
18 |
From: Hardening <rdp.effort@×××××.com> |
19 |
Date: Fri, 6 Jun 2014 23:24:16 +0200 |
20 |
Subject: [PATCH] Fix CVE-2014-0250 |
21 |
|
22 |
This patch fixes CVE-2014-0250 by checking width, height and bpp when |
23 |
receiving a new pointer. |
24 |
--- |
25 |
client/X11/xf_cliprdr.c | 11 +++++-- |
26 |
libfreerdp/core/fastpath.c | 2 +- |
27 |
libfreerdp/core/orders.c | 21 ++++++++++++ |
28 |
libfreerdp/core/surface.c | 6 ++++ |
29 |
libfreerdp/core/update.c | 82 +++++++++++++++++++++++++++++++++++++++------- |
30 |
libfreerdp/core/update.h | 2 +- |
31 |
libfreerdp/core/window.c | 5 +++ |
32 |
7 files changed, 114 insertions(+), 15 deletions(-) |
33 |
|
34 |
diff --git a/client/X11/xf_cliprdr.c b/client/X11/xf_cliprdr.c |
35 |
index 19c4332..8fb49f9 100644 |
36 |
--- a/client/X11/xf_cliprdr.c |
37 |
+++ b/client/X11/xf_cliprdr.c |
38 |
@@ -914,7 +914,7 @@ static void xf_cliprdr_process_unicodetext(clipboardContext* cb, BYTE* data, int |
39 |
crlf2lf(cb->data, &cb->data_length); |
40 |
} |
41 |
|
42 |
-static void xf_cliprdr_process_dib(clipboardContext* cb, BYTE* data, int size) |
43 |
+static BOOL xf_cliprdr_process_dib(clipboardContext* cb, BYTE* data, int size) |
44 |
{ |
45 |
wStream* s; |
46 |
UINT16 bpp; |
47 |
@@ -926,12 +926,18 @@ static void xf_cliprdr_process_dib(clipboardContext* cb, BYTE* data, int size) |
48 |
if (size < 40) |
49 |
{ |
50 |
DEBUG_X11_CLIPRDR("dib size %d too short", size); |
51 |
- return; |
52 |
+ return FALSE; |
53 |
} |
54 |
|
55 |
s = Stream_New(data, size); |
56 |
Stream_Seek(s, 14); |
57 |
Stream_Read_UINT16(s, bpp); |
58 |
+ if ((bpp < 1) || (bpp > 32)) |
59 |
+ { |
60 |
+ fprintf(stderr, "%s: invalid bpp value %d", __FUNCTION__, bpp); |
61 |
+ return FALSE; |
62 |
+ } |
63 |
+ |
64 |
Stream_Read_UINT32(s, ncolors); |
65 |
offset = 14 + 40 + (bpp <= 8 ? (ncolors == 0 ? (1 << bpp) : ncolors) * 4 : 0); |
66 |
Stream_Free(s, FALSE); |
67 |
@@ -949,6 +955,7 @@ static void xf_cliprdr_process_dib(clipboardContext* cb, BYTE* data, int size) |
68 |
cb->data = Stream_Buffer(s); |
69 |
cb->data_length = Stream_GetPosition(s); |
70 |
Stream_Free(s, FALSE); |
71 |
+ return TRUE; |
72 |
} |
73 |
|
74 |
static void xf_cliprdr_process_html(clipboardContext* cb, BYTE* data, int size) |
75 |
diff --git a/libfreerdp/core/fastpath.c b/libfreerdp/core/fastpath.c |
76 |
index 8448160..dcc7117 100644 |
77 |
--- a/libfreerdp/core/fastpath.c |
78 |
+++ b/libfreerdp/core/fastpath.c |
79 |
@@ -254,7 +254,7 @@ static int fastpath_recv_update(rdpFastPath* fastpath, BYTE updateCode, UINT32 s |
80 |
break; |
81 |
|
82 |
case FASTPATH_UPDATETYPE_COLOR: |
83 |
- if (!update_read_pointer_color(s, &pointer->pointer_color)) |
84 |
+ if (!update_read_pointer_color(s, &pointer->pointer_color, 24)) |
85 |
return -1; |
86 |
IFCALL(pointer->PointerColor, context, &pointer->pointer_color); |
87 |
break; |
88 |
diff --git a/libfreerdp/core/orders.c b/libfreerdp/core/orders.c |
89 |
index e5cc520..f22407f 100644 |
90 |
--- a/libfreerdp/core/orders.c |
91 |
+++ b/libfreerdp/core/orders.c |
92 |
@@ -1830,6 +1830,11 @@ BOOL update_read_cache_bitmap_order(wStream* s, CACHE_BITMAP_ORDER* cache_bitmap |
93 |
Stream_Read_UINT8(s, cache_bitmap->bitmapWidth); /* bitmapWidth (1 byte) */ |
94 |
Stream_Read_UINT8(s, cache_bitmap->bitmapHeight); /* bitmapHeight (1 byte) */ |
95 |
Stream_Read_UINT8(s, cache_bitmap->bitmapBpp); /* bitmapBpp (1 byte) */ |
96 |
+ if ((cache_bitmap->bitmapBpp < 1) || (cache_bitmap->bitmapBpp > 32)) |
97 |
+ { |
98 |
+ fprintf(stderr, "%s: invalid bitmap bpp %d\n", __FUNCTION__, cache_bitmap->bitmapBpp); |
99 |
+ return FALSE; |
100 |
+ } |
101 |
Stream_Read_UINT16(s, cache_bitmap->bitmapLength); /* bitmapLength (2 bytes) */ |
102 |
Stream_Read_UINT16(s, cache_bitmap->cacheIndex); /* cacheIndex (2 bytes) */ |
103 |
|
104 |
@@ -2068,6 +2073,11 @@ BOOL update_read_cache_bitmap_v3_order(wStream* s, CACHE_BITMAP_V3_ORDER* cache_ |
105 |
bitmapData = &cache_bitmap_v3->bitmapData; |
106 |
|
107 |
Stream_Read_UINT8(s, bitmapData->bpp); |
108 |
+ if ((bitmapData->bpp < 1) || (bitmapData->bpp > 32)) |
109 |
+ { |
110 |
+ fprintf(stderr, "%s: invalid bpp value %d", __FUNCTION__, bitmapData->bpp); |
111 |
+ return FALSE; |
112 |
+ } |
113 |
Stream_Seek_UINT8(s); /* reserved1 (1 byte) */ |
114 |
Stream_Seek_UINT8(s); /* reserved2 (1 byte) */ |
115 |
Stream_Read_UINT8(s, bitmapData->codecID); /* codecID (1 byte) */ |
116 |
@@ -2672,6 +2682,11 @@ BOOL update_read_create_nine_grid_bitmap_order(wStream* s, CREATE_NINE_GRID_BITM |
117 |
return FALSE; |
118 |
|
119 |
Stream_Read_UINT8(s, create_nine_grid_bitmap->bitmapBpp); /* bitmapBpp (1 byte) */ |
120 |
+ if ((create_nine_grid_bitmap->bitmapBpp < 1) || (create_nine_grid_bitmap->bitmapBpp > 32)) |
121 |
+ { |
122 |
+ fprintf(stderr, "%s: invalid bpp value %d", __FUNCTION__, create_nine_grid_bitmap->bitmapBpp); |
123 |
+ return FALSE; |
124 |
+ } |
125 |
Stream_Read_UINT16(s, create_nine_grid_bitmap->bitmapId); /* bitmapId (2 bytes) */ |
126 |
|
127 |
nineGridInfo = &(create_nine_grid_bitmap->nineGridInfo); |
128 |
@@ -2707,6 +2722,12 @@ BOOL update_read_stream_bitmap_first_order(wStream* s, STREAM_BITMAP_FIRST_ORDER |
129 |
|
130 |
Stream_Read_UINT8(s, stream_bitmap_first->bitmapFlags); /* bitmapFlags (1 byte) */ |
131 |
Stream_Read_UINT8(s, stream_bitmap_first->bitmapBpp); /* bitmapBpp (1 byte) */ |
132 |
+ if ((stream_bitmap_first->bitmapBpp < 1) || (stream_bitmap_first->bitmapBpp > 32)) |
133 |
+ { |
134 |
+ fprintf(stderr, "%s: invalid bpp value %d", __FUNCTION__, stream_bitmap_first->bitmapBpp); |
135 |
+ return FALSE; |
136 |
+ } |
137 |
+ |
138 |
Stream_Read_UINT16(s, stream_bitmap_first->bitmapType); /* bitmapType (2 bytes) */ |
139 |
Stream_Read_UINT16(s, stream_bitmap_first->bitmapWidth); /* bitmapWidth (2 bytes) */ |
140 |
Stream_Read_UINT16(s, stream_bitmap_first->bitmapHeight); /* bitmapHeigth (2 bytes) */ |
141 |
diff --git a/libfreerdp/core/surface.c b/libfreerdp/core/surface.c |
142 |
index 7d0fb22..992a3dd 100644 |
143 |
--- a/libfreerdp/core/surface.c |
144 |
+++ b/libfreerdp/core/surface.c |
145 |
@@ -38,6 +38,12 @@ static int update_recv_surfcmd_surface_bits(rdpUpdate* update, wStream* s, UINT3 |
146 |
Stream_Read_UINT16(s, cmd->destRight); |
147 |
Stream_Read_UINT16(s, cmd->destBottom); |
148 |
Stream_Read_UINT8(s, cmd->bpp); |
149 |
+ if ((cmd->bpp < 1) || (cmd->bpp > 32)) |
150 |
+ { |
151 |
+ fprintf(stderr, "%s: invalid bpp value %d", __FUNCTION__, cmd->bpp); |
152 |
+ return FALSE; |
153 |
+ } |
154 |
+ |
155 |
Stream_Seek(s, 2); /* reserved1, reserved2 */ |
156 |
Stream_Read_UINT8(s, cmd->codecID); |
157 |
Stream_Read_UINT16(s, cmd->width); |
158 |
diff --git a/libfreerdp/core/update.c b/libfreerdp/core/update.c |
159 |
index c4eaede..27c36e3 100644 |
160 |
--- a/libfreerdp/core/update.c |
161 |
+++ b/libfreerdp/core/update.c |
162 |
@@ -219,16 +219,32 @@ BOOL update_read_pointer_system(wStream* s, POINTER_SYSTEM_UPDATE* pointer_syste |
163 |
return TRUE; |
164 |
} |
165 |
|
166 |
-BOOL update_read_pointer_color(wStream* s, POINTER_COLOR_UPDATE* pointer_color) |
167 |
+BOOL update_read_pointer_color(wStream* s, POINTER_COLOR_UPDATE* pointer_color, int xorBpp) |
168 |
{ |
169 |
+ BYTE *newMask; |
170 |
+ int scanlineSize; |
171 |
+ |
172 |
if (Stream_GetRemainingLength(s) < 14) |
173 |
return FALSE; |
174 |
|
175 |
Stream_Read_UINT16(s, pointer_color->cacheIndex); /* cacheIndex (2 bytes) */ |
176 |
Stream_Read_UINT16(s, pointer_color->xPos); /* xPos (2 bytes) */ |
177 |
Stream_Read_UINT16(s, pointer_color->yPos); /* yPos (2 bytes) */ |
178 |
+ |
179 |
+ /** |
180 |
+ * As stated in 2.2.9.1.1.4.4 Color Pointer Update: |
181 |
+ * The maximum allowed pointer width/height is 96 pixels if the client indicated support |
182 |
+ * for large pointers by setting the LARGE_POINTER_FLAG (0x00000001) in the Large |
183 |
+ * Pointer Capability Set (section 2.2.7.2.7). If the LARGE_POINTER_FLAG was not |
184 |
+ * set, the maximum allowed pointer width/height is 32 pixels. |
185 |
+ * |
186 |
+ * So we check for a maximum of 96 for CVE-2014-0250. |
187 |
+ */ |
188 |
Stream_Read_UINT16(s, pointer_color->width); /* width (2 bytes) */ |
189 |
Stream_Read_UINT16(s, pointer_color->height); /* height (2 bytes) */ |
190 |
+ if ((pointer_color->width > 96) || (pointer_color->height > 96)) |
191 |
+ return FALSE; |
192 |
+ |
193 |
Stream_Read_UINT16(s, pointer_color->lengthAndMask); /* lengthAndMask (2 bytes) */ |
194 |
Stream_Read_UINT16(s, pointer_color->lengthXorMask); /* lengthXorMask (2 bytes) */ |
195 |
|
196 |
@@ -245,26 +261,65 @@ BOOL update_read_pointer_color(wStream* s, POINTER_COLOR_UPDATE* pointer_color) |
197 |
|
198 |
if (pointer_color->lengthXorMask > 0) |
199 |
{ |
200 |
+ /** |
201 |
+ * Spec states that: |
202 |
+ * |
203 |
+ * xorMaskData (variable): A variable-length array of bytes. Contains the 24-bpp, bottom-up |
204 |
+ * XOR mask scan-line data. The XOR mask is padded to a 2-byte boundary for each encoded |
205 |
+ * scan-line. For example, if a 3x3 pixel cursor is being sent, then each scan-line will consume 10 |
206 |
+ * bytes (3 pixels per scan-line multiplied by 3 bytes per pixel, rounded up to the next even |
207 |
+ * number of bytes). |
208 |
+ * |
209 |
+ * In fact instead of 24-bpp, the bpp parameter is given by the containing packet. |
210 |
+ */ |
211 |
if (Stream_GetRemainingLength(s) < pointer_color->lengthXorMask) |
212 |
return FALSE; |
213 |
|
214 |
- if (!pointer_color->xorMaskData) |
215 |
- pointer_color->xorMaskData = malloc(pointer_color->lengthXorMask); |
216 |
- else |
217 |
- pointer_color->xorMaskData = realloc(pointer_color->xorMaskData, pointer_color->lengthXorMask); |
218 |
+ scanlineSize = (7 + xorBpp * pointer_color->width) / 8; |
219 |
+ scanlineSize = ((scanlineSize + 1) / 2) * 2; |
220 |
+ if (scanlineSize * pointer_color->height != pointer_color->lengthXorMask) |
221 |
+ { |
222 |
+ fprintf(stderr, "%s: invalid lengthXorMask: width=%d height=%d, %d instead of %d\n", __FUNCTION__, |
223 |
+ pointer_color->width, pointer_color->height, |
224 |
+ pointer_color->lengthXorMask, scanlineSize * pointer_color->height); |
225 |
+ return FALSE; |
226 |
+ } |
227 |
+ |
228 |
+ newMask = realloc(pointer_color->xorMaskData, pointer_color->lengthXorMask); |
229 |
+ if (!newMask) |
230 |
+ return FALSE; |
231 |
+ |
232 |
+ pointer_color->xorMaskData = newMask; |
233 |
|
234 |
Stream_Read(s, pointer_color->xorMaskData, pointer_color->lengthXorMask); |
235 |
} |
236 |
|
237 |
if (pointer_color->lengthAndMask > 0) |
238 |
{ |
239 |
+ /** |
240 |
+ * andMaskData (variable): A variable-length array of bytes. Contains the 1-bpp, bottom-up |
241 |
+ * AND mask scan-line data. The AND mask is padded to a 2-byte boundary for each encoded |
242 |
+ * scan-line. For example, if a 7x7 pixel cursor is being sent, then each scan-line will consume 2 |
243 |
+ * bytes (7 pixels per scan-line multiplied by 1 bpp, rounded up to the next even number of |
244 |
+ * bytes). |
245 |
+ */ |
246 |
if (Stream_GetRemainingLength(s) < pointer_color->lengthAndMask) |
247 |
return FALSE; |
248 |
|
249 |
- if (!pointer_color->andMaskData) |
250 |
- pointer_color->andMaskData = malloc(pointer_color->lengthAndMask); |
251 |
- else |
252 |
- pointer_color->andMaskData = realloc(pointer_color->andMaskData, pointer_color->lengthAndMask); |
253 |
+ scanlineSize = ((7 + pointer_color->width) / 8); |
254 |
+ scanlineSize = ((1 + scanlineSize) / 2) * 2; |
255 |
+ if (scanlineSize * pointer_color->height != pointer_color->lengthAndMask) |
256 |
+ { |
257 |
+ fprintf(stderr, "%s: invalid lengthAndMask: %d instead of %d\n", __FUNCTION__, |
258 |
+ pointer_color->lengthAndMask, scanlineSize * pointer_color->height); |
259 |
+ return FALSE; |
260 |
+ } |
261 |
+ |
262 |
+ newMask = realloc(pointer_color->andMaskData, pointer_color->lengthAndMask); |
263 |
+ if (!newMask) |
264 |
+ return FALSE; |
265 |
+ |
266 |
+ pointer_color->andMaskData = newMask; |
267 |
|
268 |
Stream_Read(s, pointer_color->andMaskData, pointer_color->lengthAndMask); |
269 |
} |
270 |
@@ -281,7 +336,12 @@ BOOL update_read_pointer_new(wStream* s, POINTER_NEW_UPDATE* pointer_new) |
271 |
return FALSE; |
272 |
|
273 |
Stream_Read_UINT16(s, pointer_new->xorBpp); /* xorBpp (2 bytes) */ |
274 |
- return update_read_pointer_color(s, &pointer_new->colorPtrAttr); /* colorPtrAttr */ |
275 |
+ if ((pointer_new->xorBpp < 1) || (pointer_new->xorBpp > 32)) |
276 |
+ { |
277 |
+ fprintf(stderr, "%s: invalid xorBpp %d\n", __FUNCTION__, pointer_new->xorBpp); |
278 |
+ return FALSE; |
279 |
+ } |
280 |
+ return update_read_pointer_color(s, &pointer_new->colorPtrAttr, pointer_new->xorBpp); /* colorPtrAttr */ |
281 |
} |
282 |
|
283 |
BOOL update_read_pointer_cached(wStream* s, POINTER_CACHED_UPDATE* pointer_cached) |
284 |
@@ -320,7 +380,7 @@ BOOL update_recv_pointer(rdpUpdate* update, wStream* s) |
285 |
break; |
286 |
|
287 |
case PTR_MSG_TYPE_COLOR: |
288 |
- if (!update_read_pointer_color(s, &pointer->pointer_color)) |
289 |
+ if (!update_read_pointer_color(s, &pointer->pointer_color, 24)) |
290 |
return FALSE; |
291 |
IFCALL(pointer->PointerColor, context, &pointer->pointer_color); |
292 |
break; |
293 |
diff --git a/libfreerdp/core/update.h b/libfreerdp/core/update.h |
294 |
index c3088f2..d6c2d59 100644 |
295 |
--- a/libfreerdp/core/update.h |
296 |
+++ b/libfreerdp/core/update.h |
297 |
@@ -53,7 +53,7 @@ BOOL update_recv(rdpUpdate* update, wStream* s); |
298 |
|
299 |
BOOL update_read_pointer_position(wStream* s, POINTER_POSITION_UPDATE* pointer_position); |
300 |
BOOL update_read_pointer_system(wStream* s, POINTER_SYSTEM_UPDATE* pointer_system); |
301 |
-BOOL update_read_pointer_color(wStream* s, POINTER_COLOR_UPDATE* pointer_color); |
302 |
+BOOL update_read_pointer_color(wStream* s, POINTER_COLOR_UPDATE* pointer_color, int xorBpp); |
303 |
BOOL update_read_pointer_new(wStream* s, POINTER_NEW_UPDATE* pointer_new); |
304 |
BOOL update_read_pointer_cached(wStream* s, POINTER_CACHED_UPDATE* pointer_cached); |
305 |
|
306 |
diff --git a/libfreerdp/core/window.c b/libfreerdp/core/window.c |
307 |
index 7422f5b..c10fa33 100644 |
308 |
--- a/libfreerdp/core/window.c |
309 |
+++ b/libfreerdp/core/window.c |
310 |
@@ -35,6 +35,11 @@ BOOL update_read_icon_info(wStream* s, ICON_INFO* icon_info) |
311 |
Stream_Read_UINT16(s, icon_info->cacheEntry); /* cacheEntry (2 bytes) */ |
312 |
Stream_Read_UINT8(s, icon_info->cacheId); /* cacheId (1 byte) */ |
313 |
Stream_Read_UINT8(s, icon_info->bpp); /* bpp (1 byte) */ |
314 |
+ if ((icon_info->bpp < 1) || (icon_info->bpp > 32)) |
315 |
+ { |
316 |
+ fprintf(stderr, "%s: invalid bpp %d\n", __FUNCTION__, icon_info->bpp); |
317 |
+ return FALSE; |
318 |
+ } |
319 |
Stream_Read_UINT16(s, icon_info->width); /* width (2 bytes) */ |
320 |
Stream_Read_UINT16(s, icon_info->height); /* height (2 bytes) */ |
321 |
|
322 |
-- |
323 |
1.9.3 |