debian/patches: add security related patches from upstream

Back ported patches of multiple security issues were added.
Including the following CVEs:
*  CVE-2020-11521
*  CVE-2020-11522
*  CVE-2020-11523
*  CVE-2020-11524
*  CVE-2020-11525
*  CVE-2020-11526
This commit is contained in:
Bernhard Miklautz 2020-04-13 21:40:02 +00:00 committed by Mike Gabriel
parent 85341458bc
commit 163efd4c7d
20 changed files with 2817 additions and 0 deletions

30
debian/changelog vendored
View File

@ -1,3 +1,33 @@
freerdp2 (2.0.0~git20190204.1.2693389a+dfsg1-1+deb10u2) buster-security; urgency=medium
* debian/patches - security releated backports from upstream
* Add 0003-Fixed-6007-Boundary-checks-in-rdp_read_flow_control.patch
* Add 0004-Fixed-6009-Bounds-checks-in-autodetect_recv_bandwidt.patch
* Add 0005-Fixed-6006-bounds-checks-in-update_read_synchronize.patch
* Add 0006-Fixed-6005-Bounds-checks-in-update_read_bitmap_data.patch
* Add 0007-Fixed-6011-Bounds-check-in-rdp_read_font_capability.patch
* Add 0008-Fixed-6013-Check-new-length-is-0.patch
* Add 0009-Fix-6010-Check-length-in-read_icon_info.patch
* Add 0010-Use-substreams-to-parse-gcc_read_server_data_blocks.patch
* Add 0011-Fixed-Stream_-macros-bracing-arguments.patch
* Add 0012-Use-safe-seek-for-capability-parsing.patch
* Add 0013-Fixed-CVE-2020-11525-Out-of-bounds-read-in-bitmap_ca.patch
(CVE-2020-11525).
* Add 0014-Fixed-6012-CVE-2020-11526-Out-of-bounds-read-in-upda.patch
(CVE-2020-11526).
* Add 0015-Fix-CVE-2020-11523-clamp-invalid-rectangles-to-size-.patch
(CVE-2020-11523).
* Add 0016-Fix-CVE-2020-11524-out-of-bounds-access-in-interleav.patch
(CVE-2020-11524).
* Add 0017-Fixed-CVE-2020-11522-Limit-number-of-DELTA_RECT-to-4.patch
(CVE-2020-11522).
* Add 0018-Fixed-CVE-2020-11521-Out-of-bounds-write-in-planar-c.patch
(CVE-2020-11521).
* Add 0019-Fixed-possible-NULL-access.patch
* Add 0020-Check-for-int-overflow-in-gdi_InvalidateRegion.patch
-- Bernhard Miklautz <bernhard.miklautz@shacknet.at> Mon, 13 Apr 2020 21:31:35 +0000
freerdp2 (2.0.0~git20190204.1.2693389a+dfsg1-1+deb10u1) buster; urgency=medium
* debian/patches:

View File

@ -0,0 +1,81 @@
--- a/libfreerdp/core/rdp.c
+++ b/libfreerdp/core/rdp.c
@@ -110,29 +110,33 @@ void rdp_write_security_header(wStream* s, UINT16 flags)
BOOL rdp_read_share_control_header(wStream* s, UINT16* length, UINT16* type, UINT16* channel_id)
{
+ UINT16 len;
if (Stream_GetRemainingLength(s) < 2)
return FALSE;
/* Share Control Header */
- Stream_Read_UINT16(s, *length); /* totalLength */
+ Stream_Read_UINT16(s, len); /* totalLength */
+
+ *length = len;
/* If length is 0x8000 then we actually got a flow control PDU that we should ignore
http://msdn.microsoft.com/en-us/library/cc240576.aspx */
- if (*length == 0x8000)
+ if (len == 0x8000)
{
- rdp_read_flow_control_pdu(s, type);
+ if (!rdp_read_flow_control_pdu(s, type))
+ return FALSE;
*channel_id = 0;
*length = 8; /* Flow control PDU is 8 bytes */
return TRUE;
}
- if (((size_t) *length - 2) > Stream_GetRemainingLength(s))
+ if ((len < 4) || ((len - 2) > Stream_GetRemainingLength(s)))
return FALSE;
Stream_Read_UINT16(s, *type); /* pduType */
*type &= 0x0F; /* type is in the 4 least significant bits */
- if (*length > 4)
+ if (len > 4)
Stream_Read_UINT16(s, *channel_id); /* pduSource */
else
*channel_id = 0; /* Windows XP can send such short DEACTIVATE_ALL PDUs. */
@@ -1088,7 +1092,7 @@ int rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s)
}
}
-void rdp_read_flow_control_pdu(wStream* s, UINT16* type)
+BOOL rdp_read_flow_control_pdu(wStream* s, UINT16* type)
{
/*
* Read flow control PDU - documented in FlowPDU section in T.128
@@ -1098,12 +1102,17 @@ void rdp_read_flow_control_pdu(wStream* s, UINT16* type)
* Switched the order of these two fields to match this observation.
*/
UINT8 pduType;
+ if (!type)
+ return FALSE;
+ if (Stream_GetRemainingLength(s) < 6)
+ return FALSE;
Stream_Read_UINT8(s, pduType); /* pduTypeFlow */
*type = pduType;
Stream_Seek_UINT8(s); /* pad8bits */
Stream_Seek_UINT8(s); /* flowIdentifier */
Stream_Seek_UINT8(s); /* flowNumber */
Stream_Seek_UINT16(s); /* pduSource */
+ return TRUE;
}
/**
diff --git a/libfreerdp/core/rdp.h b/libfreerdp/core/rdp.h
index 9df6c0a..24d062d 100644
--- a/libfreerdp/core/rdp.h
+++ b/libfreerdp/core/rdp.h
@@ -221,7 +221,7 @@ FREERDP_LOCAL int rdp_recv_message_channel_pdu(rdpRdp* rdp, wStream* s,
FREERDP_LOCAL int rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s);
-FREERDP_LOCAL void rdp_read_flow_control_pdu(wStream* s, UINT16* type);
+FREERDP_LOCAL BOOL rdp_read_flow_control_pdu(wStream* s, UINT16* type);
FREERDP_LOCAL BOOL rdp_write_monitor_layout_pdu(wStream* s, UINT32 monitorCount,
const rdpMonitor* monitorDefArray);

View File

@ -0,0 +1,11 @@
--- a/libfreerdp/core/autodetect.c
+++ b/libfreerdp/core/autodetect.c
@@ -454,6 +454,8 @@ static BOOL autodetect_recv_bandwidth_measure_results(rdpRdp* rdp, wStream* s,
return FALSE;
WLog_VRB(AUTODETECT_TAG, "received Bandwidth Measure Results PDU");
+ if (Stream_GetRemainingLength(s) < 8)
+ return -1;
Stream_Read_UINT32(s, rdp->autodetect->bandwidthMeasureTimeDelta); /* timeDelta (4 bytes) */
Stream_Read_UINT32(s, rdp->autodetect->bandwidthMeasureByteCount); /* byteCount (4 bytes) */

View File

@ -0,0 +1,28 @@
--- a/libfreerdp/core/update.c
+++ b/libfreerdp/core/update.c
@@ -292,13 +292,13 @@ fail:
return NULL;
}
-static void update_read_synchronize(rdpUpdate* update, wStream* s)
+static BOOL update_read_synchronize(rdpUpdate* update, wStream* s)
{
- Stream_Seek_UINT16(s); /* pad2Octets (2 bytes) */
/**
* The Synchronize Update is an artifact from the
* T.128 protocol and should be ignored.
*/
+ return Stream_SafeSeek(s, 2); /* pad2Octets (2 bytes) */
}
static BOOL update_read_play_sound(wStream* s, PLAY_SOUND_UPDATE* play_sound)
@@ -676,7 +676,8 @@ BOOL update_recv(rdpUpdate* update, wStream* s)
break;
case UPDATE_TYPE_SYNCHRONIZE:
- update_read_synchronize(update, s);
+ if (!update_read_synchronize(update, s))
+ return FALSE;
rc = IFCALLRESULT(TRUE, update->Synchronize, context);
break;

View File

@ -0,0 +1,12 @@
--- a/libfreerdp/core/update.c
+++ b/libfreerdp/core/update.c
@@ -109,6 +109,9 @@ static BOOL update_read_bitmap_data(rdpUpdate* update, wStream* s,
{
if (!(bitmapData->flags & NO_BITMAP_COMPRESSION_HDR))
{
+ if (Stream_GetRemainingLength(s) < 8)
+ return FALSE;
+
Stream_Read_UINT16(s,
bitmapData->cbCompFirstRowSize); /* cbCompFirstRowSize (2 bytes) */
Stream_Read_UINT16(s,

View File

@ -0,0 +1,16 @@
--- a/libfreerdp/core/capabilities.c
+++ b/libfreerdp/core/capabilities.c
@@ -1379,10 +1379,10 @@ static BOOL rdp_print_input_capability_set(wStream* s, UINT16 length)
static BOOL rdp_read_font_capability_set(wStream* s, UINT16 length,
rdpSettings* settings)
{
- if (length > 4)
+ if (length > 5)
Stream_Seek_UINT16(s); /* fontSupportFlags (2 bytes) */
- if (length > 6)
+ if (length > 7)
Stream_Seek_UINT16(s); /* pad2Octets (2 bytes) */
return TRUE;

View File

@ -0,0 +1,11 @@
--- a/libfreerdp/core/orders.c
+++ b/libfreerdp/core/orders.c
@@ -2237,7 +2237,7 @@ static CACHE_BITMAP_V3_ORDER* update_read_cache_bitmap_v3_order(rdpUpdate* updat
Stream_Read_UINT16(s, bitmapData->height); /* height (2 bytes) */
Stream_Read_UINT32(s, new_len); /* length (4 bytes) */
- if (Stream_GetRemainingLength(s) < new_len)
+ if ((new_len == 0) || (Stream_GetRemainingLength(s) < new_len))
goto fail;
new_data = (BYTE*) realloc(bitmapData->data, new_len);

View File

@ -0,0 +1,43 @@
--- a/libfreerdp/core/window.c
+++ b/libfreerdp/core/window.c
@@ -110,9 +110,6 @@ static BOOL update_read_icon_info(wStream* s, ICON_INFO* iconInfo)
Stream_Read_UINT16(s, iconInfo->cbBitsMask); /* cbBitsMask (2 bytes) */
Stream_Read_UINT16(s, iconInfo->cbBitsColor); /* cbBitsColor (2 bytes) */
- if (Stream_GetRemainingLength(s) < iconInfo->cbBitsMask + iconInfo->cbBitsColor)
- return FALSE;
-
/* bitsMask */
newBitMask = (BYTE*) realloc(iconInfo->bitsMask, iconInfo->cbBitsMask);
@@ -124,6 +121,8 @@ static BOOL update_read_icon_info(wStream* s, ICON_INFO* iconInfo)
}
iconInfo->bitsMask = newBitMask;
+ if (Stream_GetRemainingLength(s) < iconInfo->cbBitsMask)
+ return FALSE;
Stream_Read(s, iconInfo->bitsMask, iconInfo->cbBitsMask);
/* colorTable */
@@ -158,7 +157,11 @@ static BOOL update_read_icon_info(wStream* s, ICON_INFO* iconInfo)
}
if (iconInfo->colorTable)
+ {
+ if (Stream_GetRemainingLength(s) < iconInfo->cbColorTable)
+ return FALSE;
Stream_Read(s, iconInfo->colorTable, iconInfo->cbColorTable);
+ }
/* bitsColor */
newBitMask = (BYTE*)realloc(iconInfo->bitsColor, iconInfo->cbBitsColor);
@@ -171,6 +174,8 @@ static BOOL update_read_icon_info(wStream* s, ICON_INFO* iconInfo)
}
iconInfo->bitsColor = newBitMask;
+ if (Stream_GetRemainingLength(s) < iconInfo->cbBitsColor)
+ return FALSE;
Stream_Read(s, iconInfo->bitsColor, iconInfo->cbBitsColor);
return TRUE;
}

View File

@ -0,0 +1,94 @@
--- a/libfreerdp/core/gcc.c
+++ b/libfreerdp/core/gcc.c
@@ -494,18 +494,27 @@ BOOL gcc_read_server_data_blocks(wStream* s, rdpMcs* mcs, int length)
while (offset < length)
{
- holdp = Stream_Pointer(s);
+ size_t rest;
+ wStream sub;
if (!gcc_read_user_data_header(s, &type, &blockLength))
{
WLog_ERR(TAG, "gcc_read_server_data_blocks: gcc_read_user_data_header failed");
return FALSE;
}
+ holdp = Stream_Pointer(s);
+ Stream_StaticInit(&sub, holdp, blockLength - 4);
+ if (!Stream_SafeSeek(s, blockLength - 4))
+ {
+ WLog_ERR(TAG, "gcc_read_server_data_blocks: stream too short");
+ return FALSE;
+ }
+ offset += blockLength;
switch (type)
{
case SC_CORE:
- if (!gcc_read_server_core_data(s, mcs))
+ if (!gcc_read_server_core_data(&sub, mcs))
{
WLog_ERR(TAG, "gcc_read_server_data_blocks: gcc_read_server_core_data failed");
return FALSE;
@@ -514,7 +523,7 @@ BOOL gcc_read_server_data_blocks(wStream* s, rdpMcs* mcs, int length)
break;
case SC_SECURITY:
- if (!gcc_read_server_security_data(s, mcs))
+ if (!gcc_read_server_security_data(&sub, mcs))
{
WLog_ERR(TAG,
"gcc_read_server_data_blocks: gcc_read_server_security_data failed");
@@ -524,7 +533,7 @@ BOOL gcc_read_server_data_blocks(wStream* s, rdpMcs* mcs, int length)
break;
case SC_NET:
- if (!gcc_read_server_network_data(s, mcs))
+ if (!gcc_read_server_network_data(&sub, mcs))
{
WLog_ERR(TAG,
"gcc_read_server_data_blocks: gcc_read_server_network_data failed");
@@ -534,7 +543,7 @@ BOOL gcc_read_server_data_blocks(wStream* s, rdpMcs* mcs, int length)
break;
case SC_MCS_MSGCHANNEL:
- if (!gcc_read_server_message_channel_data(s, mcs))
+ if (!gcc_read_server_message_channel_data(&sub, mcs))
{
WLog_ERR(TAG,
"gcc_read_server_data_blocks: gcc_read_server_message_channel_data failed");
@@ -544,7 +553,7 @@ BOOL gcc_read_server_data_blocks(wStream* s, rdpMcs* mcs, int length)
break;
case SC_MULTITRANSPORT:
- if (!gcc_read_server_multitransport_channel_data(s, mcs))
+ if (!gcc_read_server_multitransport_channel_data(&sub, mcs))
{
WLog_ERR(TAG,
"gcc_read_server_data_blocks: gcc_read_server_multitransport_channel_data failed");
@@ -558,8 +567,13 @@ BOOL gcc_read_server_data_blocks(wStream* s, rdpMcs* mcs, int length)
break;
}
- offset += blockLength;
- Stream_SetPointer(s, holdp + blockLength);
+ rest = Stream_GetRemainingLength(&sub);
+ if (rest > 0)
+ {
+ WLog_WARN(
+ TAG, "gcc_read_server_data_blocks: ignoring %" PRIuz " bytes with type=%" PRIu16 "",
+ rest, type);
+ }
}
return TRUE;
@@ -583,7 +597,7 @@ BOOL gcc_read_user_data_header(wStream* s, UINT16* type, UINT16* length)
Stream_Read_UINT16(s, *type); /* type */
Stream_Read_UINT16(s, *length); /* length */
- if (Stream_GetRemainingLength(s) < (size_t)(*length - 4))
+ if ((*length < 4) || (Stream_GetRemainingLength(s) < (size_t)(*length - 4)))
return FALSE;
return TRUE;

View File

@ -0,0 +1,109 @@
--- a/winpr/include/winpr/stream.h
+++ b/winpr/include/winpr/stream.h
@@ -52,7 +52,7 @@ WINPR_API BOOL Stream_EnsureCapacity(wStream* s, size_t size);
WINPR_API BOOL Stream_EnsureRemainingCapacity(wStream* s, size_t size);
WINPR_API wStream* Stream_New(BYTE* buffer, size_t size);
-WINPR_API void Stream_StaticInit(wStream *s, BYTE *buffer, size_t size);
+WINPR_API void Stream_StaticInit(wStream* s, BYTE* buffer, size_t size);
WINPR_API void Stream_Free(wStream* s, BOOL bFreeBuffer);
static INLINE void Stream_Seek(wStream* s, size_t _offset)
@@ -66,60 +66,60 @@ static INLINE void Stream_Rewind(wStream* s, size_t _offset)
}
#define _stream_read_n8(_t, _s, _v, _p) do { \
- _v = \
- (_t)(*_s->pointer); \
+ (_v) = \
+ (_t)(*(_s)->pointer); \
if (_p) Stream_Seek(_s, sizeof(_t)); } while (0)
#define _stream_read_n16_le(_t, _s, _v, _p) do { \
- _v = \
- (_t)(*_s->pointer) + \
- (_t)(((_t)(*(_s->pointer + 1))) << 8); \
+ (_v) = \
+ (_t)(*(_s)->pointer) + \
+ (_t)(((_t)(*((_s)->pointer + 1))) << 8); \
if (_p) Stream_Seek(_s, sizeof(_t)); } while (0)
#define _stream_read_n16_be(_t, _s, _v, _p) do { \
- _v = \
- (_t)(((_t)(*_s->pointer)) << 8) + \
- (_t)(*(_s->pointer + 1)); \
+ (_v) = \
+ (_t)(((_t)(*(_s)->pointer)) << 8) + \
+ (_t)(*((_s)->pointer + 1)); \
if (_p) Stream_Seek(_s, sizeof(_t)); } while (0)
#define _stream_read_n32_le(_t, _s, _v, _p) do { \
- _v = \
- (_t)(*_s->pointer) + \
- (((_t)(*(_s->pointer + 1))) << 8) + \
- (((_t)(*(_s->pointer + 2))) << 16) + \
- (((_t)(*(_s->pointer + 3))) << 24); \
+ (_v) = \
+ (_t)(*(_s)->pointer) + \
+ (((_t)(*((_s)->pointer + 1))) << 8) + \
+ (((_t)(*((_s)->pointer + 2))) << 16) + \
+ (((_t)(*((_s)->pointer + 3))) << 24); \
if (_p) Stream_Seek(_s, sizeof(_t)); } while (0)
#define _stream_read_n32_be(_t, _s, _v, _p) do { \
- _v = \
- (((_t)(*(_s->pointer))) << 24) + \
- (((_t)(*(_s->pointer + 1))) << 16) + \
- (((_t)(*(_s->pointer + 2))) << 8) + \
- (((_t)(*(_s->pointer + 3)))); \
+ (_v) = \
+ (((_t)(*((_s)->pointer))) << 24) + \
+ (((_t)(*((_s)->pointer + 1))) << 16) + \
+ (((_t)(*((_s)->pointer + 2))) << 8) + \
+ (((_t)(*((_s)->pointer + 3)))); \
if (_p) Stream_Seek(_s, sizeof(_t)); } while (0)
#define _stream_read_n64_le(_t, _s, _v, _p) do { \
- _v = \
- (_t)(*_s->pointer) + \
- (((_t)(*(_s->pointer + 1))) << 8) + \
- (((_t)(*(_s->pointer + 2))) << 16) + \
- (((_t)(*(_s->pointer + 3))) << 24) + \
- (((_t)(*(_s->pointer + 4))) << 32) + \
- (((_t)(*(_s->pointer + 5))) << 40) + \
- (((_t)(*(_s->pointer + 6))) << 48) + \
- (((_t)(*(_s->pointer + 7))) << 56); \
+ (_v) = \
+ (_t)(*(_s)->pointer) + \
+ (((_t)(*((_s)->pointer + 1))) << 8) + \
+ (((_t)(*((_s)->pointer + 2))) << 16) + \
+ (((_t)(*((_s)->pointer + 3))) << 24) + \
+ (((_t)(*((_s)->pointer + 4))) << 32) + \
+ (((_t)(*((_s)->pointer + 5))) << 40) + \
+ (((_t)(*((_s)->pointer + 6))) << 48) + \
+ (((_t)(*((_s)->pointer + 7))) << 56); \
if (_p) Stream_Seek(_s, sizeof(_t)); } while (0)
#define _stream_read_n64_be(_t, _s, _v, _p) do { \
- _v = \
- (((_t)(*(_s->pointer))) << 56) + \
- (((_t)(*(_s->pointer + 1))) << 48) + \
- (((_t)(*(_s->pointer + 2))) << 40) + \
- (((_t)(*(_s->pointer + 3))) << 32) + \
- (((_t)(*(_s->pointer + 4))) << 24) + \
- (((_t)(*(_s->pointer + 5))) << 16) + \
- (((_t)(*(_s->pointer + 6))) << 8) + \
- (((_t)(*(_s->pointer + 7)))); \
+ (_v) = \
+ (((_t)(*((_s)->pointer))) << 56) + \
+ (((_t)(*((_s)->pointer + 1))) << 48) + \
+ (((_t)(*((_s)->pointer + 2))) << 40) + \
+ (((_t)(*((_s)->pointer + 3))) << 32) + \
+ (((_t)(*((_s)->pointer + 4))) << 24) + \
+ (((_t)(*((_s)->pointer + 5))) << 16) + \
+ (((_t)(*((_s)->pointer + 6))) << 8) + \
+ (((_t)(*((_s)->pointer + 7)))); \
if (_p) Stream_Seek(_s, sizeof(_t)); } while (0)
#define Stream_Read_UINT8(_s, _v) _stream_read_n8(UINT8, _s, _v, TRUE)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,61 @@
--- a/libfreerdp/cache/bitmap.c
+++ b/libfreerdp/cache/bitmap.c
@@ -236,7 +236,7 @@ rdpBitmap* bitmap_cache_get(rdpBitmapCache* bitmapCache, UINT32 id,
{
rdpBitmap* bitmap;
- if (id > bitmapCache->maxCells)
+ if (id >= bitmapCache->maxCells)
{
WLog_ERR(TAG, "get invalid bitmap cell id: %"PRIu32"", id);
return NULL;
@@ -294,7 +294,7 @@ void bitmap_cache_register_callbacks(rdpUpdate* update)
rdpBitmapCache* bitmap_cache_new(rdpSettings* settings)
{
- int i;
+ UINT32 i;
rdpBitmapCache* bitmapCache;
bitmapCache = (rdpBitmapCache*) calloc(1, sizeof(rdpBitmapCache));
@@ -311,7 +311,7 @@ rdpBitmapCache* bitmap_cache_new(rdpSettings* settings)
if (!bitmapCache->cells)
goto fail;
- for (i = 0; i < (int) bitmapCache->maxCells; i++)
+ for (i = 0; i < bitmapCache->maxCells; i++)
{
bitmapCache->cells[i].number = settings->BitmapCacheV2CellInfo[i].numEntries;
/* allocate an extra entry for BITMAP_CACHE_WAITING_LIST_INDEX */
@@ -325,26 +325,20 @@ rdpBitmapCache* bitmap_cache_new(rdpSettings* settings)
return bitmapCache;
fail:
- if (bitmapCache->cells)
- {
- for (i = 0; i < (int) bitmapCache->maxCells; i++)
- free(bitmapCache->cells[i].entries);
- }
-
- free(bitmapCache);
+ bitmap_cache_free(bitmapCache);
return NULL;
}
void bitmap_cache_free(rdpBitmapCache* bitmapCache)
{
- int i, j;
+ UINT32 i, j;
rdpBitmap* bitmap;
if (bitmapCache)
{
- for (i = 0; i < (int) bitmapCache->maxCells; i++)
+ for (i = 0; i < bitmapCache->maxCells; i++)
{
- for (j = 0; j < (int) bitmapCache->cells[i].number + 1; j++)
+ for (j = 0; j < bitmapCache->cells[i].number + 1; j++)
{
bitmap = bitmapCache->cells[i].entries[j];
Bitmap_Free(bitmapCache->context, bitmap);

View File

@ -0,0 +1,19 @@
--- a/libfreerdp/core/orders.c
+++ b/libfreerdp/core/orders.c
@@ -3612,7 +3612,14 @@ static BOOL update_recv_secondary_order(rdpUpdate* update, wStream* s,
Stream_Read_UINT16(s, orderLength); /* orderLength (2 bytes) */
Stream_Read_UINT16(s, extraFlags); /* extraFlags (2 bytes) */
Stream_Read_UINT8(s, orderType); /* orderType (1 byte) */
- next = Stream_Pointer(s) + ((INT16) orderLength) + 7;
+ if (Stream_GetRemainingLength(s) < orderLength + 7)
+ {
+ WLog_Print(update->log, WLOG_ERROR, "Stream_GetRemainingLength(s) %" PRIuz " < %" PRIu16,
+ Stream_GetRemainingLength(s), orderLength + 7);
+ return FALSE;
+ }
+
+ next = Stream_Pointer(s) + orderLength + 7;
name = secondary_order_string(orderType);
WLog_Print(update->log, WLOG_DEBUG, "Secondary Drawing Order %s", name);

View File

@ -0,0 +1,214 @@
--- a/libfreerdp/gdi/region.c
+++ b/libfreerdp/gdi/region.c
@@ -37,6 +37,27 @@
#define TAG FREERDP_TAG("gdi.region")
+static char* gdi_rect_str(char* buffer, size_t size, const HGDI_RECT rect)
+{
+ _snprintf(buffer, size - 1,
+ "[top/left=%" PRId32 "x%" PRId32 "-bottom/right%" PRId32 "x%" PRId32 "]", rect->top,
+ rect->left, rect->bottom, rect->right);
+ if (size > 1)
+ buffer[size - 1] = '\0';
+
+ return buffer;
+}
+
+static char* gdi_regn_str(char* buffer, size_t size, const HGDI_RGN rgn)
+{
+ _snprintf(buffer, size - 1, "[%" PRId32 "x%" PRId32 "-%" PRId32 "x%" PRId32 "]", rgn->x, rgn->y,
+ rgn->w, rgn->h);
+ if (size > 1)
+ buffer[size - 1] = '\0';
+
+ return buffer;
+}
+
/**
* Create a region from rectangular coordinates.\n
* @msdn{dd183514}
@@ -50,7 +71,20 @@
HGDI_RGN gdi_CreateRectRgn(INT32 nLeftRect, INT32 nTopRect,
INT32 nRightRect, INT32 nBottomRect)
{
- HGDI_RGN hRgn = (HGDI_RGN) calloc(1, sizeof(GDI_RGN));
+ INT64 w, h;
+ HGDI_RGN hRgn;
+
+ w = nRightRect - nLeftRect + 1ll;
+ h = nBottomRect - nTopRect + 1ll;
+ if ((w < 0) || (h < 0) || (w > INT32_MAX) || (h > INT32_MAX))
+ {
+ WLog_ERR(TAG,
+ "Can not create region top/left=%" PRId32 "x%" PRId32 "-bottom/right=%" PRId32
+ "x%" PRId32,
+ nTopRect, nLeftRect, nBottomRect, nRightRect);
+ return NULL;
+ }
+ hRgn = (HGDI_RGN)calloc(1, sizeof(GDI_RGN));
if (!hRgn)
return NULL;
@@ -58,8 +92,8 @@ HGDI_RGN gdi_CreateRectRgn(INT32 nLeftRect, INT32 nTopRect,
hRgn->objectType = GDIOBJECT_REGION;
hRgn->x = nLeftRect;
hRgn->y = nTopRect;
- hRgn->w = nRightRect - nLeftRect + 1;
- hRgn->h = nBottomRect - nTopRect + 1;
+ hRgn->w = w;
+ hRgn->h = h;
hRgn->null = FALSE;
return hRgn;
}
@@ -97,10 +131,24 @@ HGDI_RECT gdi_CreateRect(INT32 xLeft, INT32 yTop,
INLINE void gdi_RectToRgn(HGDI_RECT rect, HGDI_RGN rgn)
{
+ INT64 w, h;
+ w = rect->right - rect->left + 1ll;
+ h = rect->bottom - rect->top + 1ll;
+
+ if ((w < 0) || (h < 0) || (w > INT32_MAX) || (h > INT32_MAX))
+ {
+ WLog_ERR(TAG,
+ "Can not create region top/left=%" PRId32 "x%" PRId32 "-bottom/right=%" PRId32
+ "x%" PRId32,
+ rect->top, rect->left, rect->bottom, rect->right);
+ w = 0;
+ h = 0;
+ }
+
rgn->x = rect->left;
rgn->y = rect->top;
- rgn->w = rect->right - rect->left + 1;
- rgn->h = rect->bottom - rect->top + 1;
+ rgn->w = w;
+ rgn->h = h;
}
/**
@@ -115,10 +163,24 @@ INLINE void gdi_RectToRgn(HGDI_RECT rect, HGDI_RGN rgn)
INLINE void gdi_CRectToRgn(INT32 left, INT32 top,
INT32 right, INT32 bottom, HGDI_RGN rgn)
{
+ INT64 w, h;
+ w = right - left + 1ll;
+ h = bottom - top + 1ll;
+
+ if ((w < 0) || (h < 0) || (w > INT32_MAX) || (h > INT32_MAX))
+ {
+ WLog_ERR(TAG,
+ "Can not create region top/left=%" PRId32 "x%" PRId32 "-bottom/right=%" PRId32
+ "x%" PRId32,
+ top, left, bottom, right);
+ w = 0;
+ h = 0;
+ }
+
rgn->x = left;
rgn->y = top;
- rgn->w = right - left + 1;
- rgn->h = bottom - top + 1;
+ rgn->w = w;
+ rgn->h = h;
}
/**
@@ -134,10 +196,29 @@ INLINE void gdi_RectToCRgn(const HGDI_RECT rect,
INT32* x, INT32* y,
INT32* w, INT32* h)
{
+ INT64 tmp;
*x = rect->left;
*y = rect->top;
- *w = rect->right - rect->left + 1;
- *h = rect->bottom - rect->top + 1;
+ tmp = rect->right - rect->left + 1;
+ if ((tmp < 0) || (tmp > INT32_MAX))
+ {
+ char buffer[256];
+ WLog_ERR(TAG, "[%s] rectangle invalid %s", __FUNCTION__,
+ gdi_rect_str(buffer, sizeof(buffer), rect));
+ *w = 0;
+ }
+ else
+ *w = tmp;
+ tmp = rect->bottom - rect->top + 1;
+ if ((tmp < 0) || (tmp > INT32_MAX))
+ {
+ char buffer[256];
+ WLog_ERR(TAG, "[%s] rectangle invalid %s", __FUNCTION__,
+ gdi_rect_str(buffer, sizeof(buffer), rect));
+ *h = 0;
+ }
+ else
+ *h = tmp;
}
/**
@@ -156,10 +237,24 @@ INLINE void gdi_CRectToCRgn(INT32 left, INT32 top, INT32 right,
INT32 bottom,
INT32* x, INT32* y, INT32* w, INT32* h)
{
+ INT64 wl, hl;
+ wl = right - left + 1ll;
+ hl = bottom - top + 1ll;
+
+ if ((wl < 0) || (hl < 0) || (wl > INT32_MAX) || (hl > INT32_MAX))
+ {
+ WLog_ERR(TAG,
+ "Can not create region top/left=%" PRId32 "x%" PRId32 "-bottom/right=%" PRId32
+ "x%" PRId32,
+ top, left, bottom, right);
+ w = 0;
+ h = 0;
+ }
+
*x = left;
*y = top;
- *w = right - left + 1;
- *h = bottom - top + 1;
+ *w = wl;
+ *h = hl;
}
/**
@@ -170,10 +265,21 @@ INLINE void gdi_CRectToCRgn(INT32 left, INT32 top, INT32 right,
INLINE void gdi_RgnToRect(HGDI_RGN rgn, HGDI_RECT rect)
{
+ INT64 r, b;
+ r = rgn->x + rgn->w - 1ll;
+ b = rgn->y + rgn->h - 1ll;
+
+ if ((r < INT32_MIN) || (r > INT32_MAX) || (b < INT32_MIN) || (b > INT32_MAX))
+ {
+ char buffer[256];
+ WLog_ERR(TAG, "Can not create region %s", gdi_regn_str(buffer, sizeof(buffer), rgn));
+ r = rgn->x;
+ b = rgn->y;
+ }
rect->left = rgn->x;
rect->top = rgn->y;
- rect->right = rgn->x + rgn->w - 1;
- rect->bottom = rgn->y + rgn->h - 1;
+ rect->right = r;
+ rect->bottom = b;
}
/**
@@ -225,6 +331,12 @@ INLINE void gdi_CRgnToRect(INT64 x, INT64 y, INT32 w, INT32 h,
INLINE void gdi_RgnToCRect(HGDI_RGN rgn, INT32* left, INT32* top,
INT32* right, INT32* bottom)
{
+ if ((rgn->w < 0) || (rgn->h < 0))
+ {
+ char buffer[256];
+ WLog_ERR(TAG, "Can not create region %s", gdi_regn_str(buffer, sizeof(buffer), rgn));
+ }
+
*left = rgn->x;
*top = rgn->y;
*right = rgn->x + rgn->w - 1;

View File

@ -0,0 +1,26 @@
--- a/libfreerdp/codec/include/bitmap.c
+++ b/libfreerdp/codec/include/bitmap.c
@@ -338,6 +338,9 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer,
case MEGA_MEGA_COLOR_IMAGE:
runLength = ExtractRunLength(code, pbSrc, &advance);
pbSrc = pbSrc + advance;
+ if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength))
+ return FALSE;
+
UNROLL(runLength,
{
SRCREADPIXEL(temp, pbSrc);
diff --git a/libfreerdp/codec/interleaved.c b/libfreerdp/codec/interleaved.c
index a3fe7dd..0d36e9b 100644
--- a/libfreerdp/codec/interleaved.c
+++ b/libfreerdp/codec/interleaved.c
@@ -215,7 +215,7 @@ static INLINE BOOL ensure_capacity(const BYTE* start, const BYTE* end, size_t si
{
const size_t available = (uintptr_t)end - (uintptr_t)start;
const BOOL rc = available >= size * base;
- return rc;
+ return rc && (start <= end);
}
static INLINE void write_pixel_8(BYTE* _buf, BYTE _pix)

View File

@ -0,0 +1,70 @@
--- a/libfreerdp/core/orders.c
+++ b/libfreerdp/core/orders.c
@@ -888,15 +888,19 @@ static INLINE BOOL update_write_brush(wStream* s, rdpBrush* brush,
return TRUE;
}
static INLINE BOOL update_read_delta_rects(wStream* s, DELTA_RECT* rectangles,
- UINT32 number)
+ UINT32 *nr)
{
+ UINT32 number = *nr;
UINT32 i;
BYTE flags = 0;
BYTE* zeroBits;
UINT32 zeroBitsSize;
if (number > 45)
- number = 45;
+ {
+ WLog_WARN(TAG, "Invalid number of delta rectangles %" PRIu32, number);
+ return FALSE;
+ }
zeroBitsSize = ((number + 1) / 2);
@@ -1293,7 +1297,7 @@ static BOOL update_read_multi_dstblt_order(wStream* s, const ORDER_INFO* orderIn
Stream_Read_UINT16(s, multi_dstblt->cbData);
return update_read_delta_rects(s, multi_dstblt->rectangles,
- multi_dstblt->numRectangles);
+ &multi_dstblt->numRectangles);
}
return TRUE;
@@ -1322,7 +1326,7 @@ static BOOL update_read_multi_patblt_order(wStream* s, const ORDER_INFO* orderIn
Stream_Read_UINT16(s, multi_patblt->cbData);
if (!update_read_delta_rects(s, multi_patblt->rectangles,
- multi_patblt->numRectangles))
+ &multi_patblt->numRectangles))
return FALSE;
}
@@ -1347,7 +1351,7 @@ static BOOL update_read_multi_scrblt_order(wStream* s, const ORDER_INFO* orderIn
Stream_Read_UINT16(s, multi_scrblt->cbData);
return update_read_delta_rects(s, multi_scrblt->rectangles,
- multi_scrblt->numRectangles);
+ &multi_scrblt->numRectangles);
}
return TRUE;
@@ -1401,7 +1405,7 @@ static BOOL update_read_multi_opaque_rect_order(wStream* s,
Stream_Read_UINT16(s, multi_opaque_rect->cbData);
return update_read_delta_rects(s, multi_opaque_rect->rectangles,
- multi_opaque_rect->numRectangles);
+ &multi_opaque_rect->numRectangles);
}
return TRUE;
@@ -1424,7 +1428,7 @@ static BOOL update_read_multi_draw_nine_grid_order(wStream* s,
Stream_Read_UINT16(s, multi_draw_nine_grid->cbData);
return update_read_delta_rects(s, multi_draw_nine_grid->rectangles,
- multi_draw_nine_grid->nDeltaEntries);
+ &multi_draw_nine_grid->nDeltaEntries);
}
return TRUE;

View File

@ -0,0 +1,77 @@
--- a/libfreerdp/codec/planar.c
+++ b/libfreerdp/codec/planar.c
@@ -42,10 +42,9 @@ static INLINE BYTE* freerdp_bitmap_planar_delta_encode_plane(
static INLINE INT32 planar_skip_plane_rle(const BYTE* pSrcData, UINT32 SrcSize,
UINT32 nWidth, UINT32 nHeight)
{
+ UINT32 used = 0;
UINT32 x, y;
BYTE controlByte;
- const BYTE* pRLE = pSrcData;
- const BYTE* pEnd = &pSrcData[SrcSize];
for (y = 0; y < nHeight; y++)
{
@@ -54,10 +53,10 @@ static INLINE INT32 planar_skip_plane_rle(const BYTE* pSrcData, UINT32 SrcSize,
int cRawBytes;
int nRunLength;
- if (pRLE >= pEnd)
+ if (used >= SrcSize)
return -1;
- controlByte = *pRLE++;
+ controlByte = pSrcData[used++];
nRunLength = PLANAR_CONTROL_BYTE_RUN_LENGTH(controlByte);
cRawBytes = PLANAR_CONTROL_BYTE_RAW_BYTES(controlByte);
@@ -72,19 +71,21 @@ static INLINE INT32 planar_skip_plane_rle(const BYTE* pSrcData, UINT32 SrcSize,
cRawBytes = 0;
}
- pRLE += cRawBytes;
+ used += cRawBytes;
x += cRawBytes;
x += nRunLength;
if (x > nWidth)
return -1;
- if (pRLE > pEnd)
+ if (used > SrcSize)
return -1;
}
}
- return (INT32)(pRLE - pSrcData);
+ if (used > INT32_MAX)
+ return -1;
+ return (INT32)used;
}
static INLINE INT32 planar_decompress_plane_rle(const BYTE* pSrcData, UINT32 SrcSize,
diff --git a/libfreerdp/core/orders.c b/libfreerdp/core/orders.c
index d004289..d4707ba 100644
--- a/libfreerdp/core/orders.c
+++ b/libfreerdp/core/orders.c
@@ -1965,6 +1965,9 @@ static CACHE_BITMAP_ORDER* update_read_cache_bitmap_order(rdpUpdate* update, wSt
}
}
+ if (cache_bitmap->bitmapLength == 0)
+ goto fail;
+
if (Stream_GetRemainingLength(s) < cache_bitmap->bitmapLength)
goto fail;
@@ -2099,6 +2102,9 @@ static CACHE_BITMAP_V2_ORDER* update_read_cache_bitmap_v2_order(rdpUpdate* updat
}
}
+ if (cache_bitmap_v2->bitmapLength == 0)
+ goto fail;
+
if (Stream_GetRemainingLength(s) < cache_bitmap_v2->bitmapLength)
goto fail;

View File

@ -0,0 +1,45 @@
--- a/libfreerdp/cache/bitmap.c
+++ b/libfreerdp/cache/bitmap.c
@@ -314,12 +314,13 @@ rdpBitmapCache* bitmap_cache_new(rdpSettings* settings)
for (i = 0; i < bitmapCache->maxCells; i++)
{
bitmapCache->cells[i].number = settings->BitmapCacheV2CellInfo[i].numEntries;
+ BITMAP_V2_CELL* cell = &bitmapCache->cells[i];
+ UINT32 nr = settings->BitmapCacheV2CellInfo[i].numEntries;
/* allocate an extra entry for BITMAP_CACHE_WAITING_LIST_INDEX */
- bitmapCache->cells[i].entries = (rdpBitmap**) calloc((
- bitmapCache->cells[i].number + 1), sizeof(rdpBitmap*));
-
- if (!bitmapCache->cells[i].entries)
+ cell->entries = (rdpBitmap**)calloc((nr + 1), sizeof(rdpBitmap*));
+ if (!cell->entries)
goto fail;
+ cell->number = nr;
}
return bitmapCache;
@@ -331,16 +332,18 @@ fail:
void bitmap_cache_free(rdpBitmapCache* bitmapCache)
{
- UINT32 i, j;
- rdpBitmap* bitmap;
-
if (bitmapCache)
{
+ UINT32 i;
for (i = 0; i < bitmapCache->maxCells; i++)
{
- for (j = 0; j < bitmapCache->cells[i].number + 1; j++)
+ UINT32 j;
+ BITMAP_V2_CELL* cell = &bitmapCache->cells[i];
+ if (!cell->entries)
+ continue;
+ for (j = 0; j < cell->number + 1; j++)
{
- bitmap = bitmapCache->cells[i].entries[j];
+ rdpBitmap* bitmap = cell->entries[j];
Bitmap_Free(bitmapCache->context, bitmap);
}

View File

@ -0,0 +1,16 @@
--- a/libfreerdp/gdi/region.c
+++ b/libfreerdp/gdi/region.c
@@ -553,9 +553,11 @@ INLINE BOOL gdi_InvalidateRegion(HGDI_DC hdc, INT32 x, INT32 y, INT32 w,
if ((hdc->hwnd->ninvalid + 1) > hdc->hwnd->count)
{
- int new_cnt;
+ size_t new_cnt;
HGDI_RGN new_rgn;
new_cnt = hdc->hwnd->count * 2;
+ if (new_cnt > UINT32_MAX)
+ return FALSE;
new_rgn = (HGDI_RGN) realloc(cinvalid, sizeof(GDI_RGN) * new_cnt);
if (!new_rgn)

19
debian/patches/series vendored
View File

@ -1,2 +1,21 @@
1001_spelling-fixes.patch
0001_CVE-2019-17177.patch
0002_fix-channels-smartcard-fix-statusw-call.patch
0003-Fixed-6007-Boundary-checks-in-rdp_read_flow_control.patch
0004-Fixed-6009-Bounds-checks-in-autodetect_recv_bandwidt.patch
0005-Fixed-6006-bounds-checks-in-update_read_synchronize.patch
0006-Fixed-6005-Bounds-checks-in-update_read_bitmap_data.patch
0007-Fixed-6011-Bounds-check-in-rdp_read_font_capability.patch
0008-Fixed-6013-Check-new-length-is-0.patch
0009-Fix-6010-Check-length-in-read_icon_info.patch
0010-Use-substreams-to-parse-gcc_read_server_data_blocks.patch
0011-Fixed-Stream_-macros-bracing-arguments.patch
0012-Use-safe-seek-for-capability-parsing.patch
0013-Fixed-CVE-2020-11525-Out-of-bounds-read-in-bitmap_ca.patch
0014-Fixed-6012-CVE-2020-11526-Out-of-bounds-read-in-upda.patch
0015-Fix-CVE-2020-11523-clamp-invalid-rectangles-to-size-.patch
0016-Fix-CVE-2020-11524-out-of-bounds-access-in-interleav.patch
0017-Fixed-CVE-2020-11522-Limit-number-of-DELTA_RECT-to-4.patch
0018-Fixed-CVE-2020-11521-Out-of-bounds-write-in-planar-c.patch
0019-Fixed-possible-NULL-access.patch
0020-Check-for-int-overflow-in-gdi_InvalidateRegion.patch