File freerdp-CVE-2020-15103.patch of Package freerdp.27686

From efdc99528f6fb6d56537a5420bfa8e735219eba0 Mon Sep 17 00:00:00 2001
From: Bernhard Miklautz <bernhard.miklautz@thincast.com>
Date: Wed, 15 Jul 2020 18:04:02 +0200
Subject: [PATCH 1/3] new [orders]: BMF_24BPP support and some comments

* cached brush orders missed the BMF_24BPP documented case
  ([MS-RDPEGDI] 2.2.2.2.1.2.7)
* add some comments on secondary (brush) order details
---
 libfreerdp/core/orders.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/libfreerdp/core/orders.c b/libfreerdp/core/orders.c
index 74870fae6..1608b7ccb 100644
--- a/libfreerdp/core/orders.c
+++ b/libfreerdp/core/orders.c
@@ -2676,6 +2676,7 @@ static CACHE_BRUSH_ORDER* update_read_cache_brush_order(rdpUpdate* update, wStre
 
 	Stream_Read_UINT8(s, cache_brush->cx);     /* cx (1 byte) */
 	Stream_Read_UINT8(s, cache_brush->cy);     /* cy (1 byte) */
+	/* according to  Section 2.2.2.2.1.2.7 errata the windows implementation sets this filed is set to 0x00 */
 	Stream_Read_UINT8(s, cache_brush->style);  /* style (1 byte) */
 	Stream_Read_UINT8(s, cache_brush->length); /* iBytes (1 byte) */
 
@@ -2690,14 +2691,12 @@ static CACHE_BRUSH_ORDER* update_read_cache_brush_order(rdpUpdate* update, wStre
 				goto fail;
 			}
 
-			/* rows are encoded in reverse order */
 			if (Stream_GetRemainingLength(s) < 8)
 				goto fail;
 
+			/* rows are encoded in reverse order */
 			for (i = 7; i >= 0; i--)
-			{
 				Stream_Read_UINT8(s, cache_brush->data[i]);
-			}
 		}
 		else
 		{
@@ -2705,6 +2704,8 @@ static CACHE_BRUSH_ORDER* update_read_cache_brush_order(rdpUpdate* update, wStre
 				compressed = TRUE;
 			else if ((iBitmapFormat == BMF_16BPP) && (cache_brush->length == 24))
 				compressed = TRUE;
+			else if ((iBitmapFormat == BMF_24BPP) && (cache_brush->length == 28))
+				compressed = TRUE;
 			else if ((iBitmapFormat == BMF_32BPP) && (cache_brush->length == 32))
 				compressed = TRUE;
 
@@ -3635,6 +3636,10 @@ static BOOL update_recv_secondary_order(rdpUpdate* update, wStream* s, BYTE flag
 	Stream_Read_UINT16(s, orderLength); /* orderLength (2 bytes) */
 	Stream_Read_UINT16(s, extraFlags);  /* extraFlags (2 bytes) */
 	Stream_Read_UINT8(s, orderType);    /* orderType (1 byte) */
+	/*
+	 * According to [MS-RDPEGDI] 2.2.2.2.1.2.1.1 the order length must be increased by 13 bytes
+	 * including the header. As we already read the header 7 left
+	 */
 	if (Stream_GetRemainingLength(s) < orderLength + 7U)
 	{
 		WLog_Print(update->log, WLOG_ERROR, "Stream_GetRemainingLength(s) %" PRIuz " < %" PRIu16,
-- 
2.28.0


From 40393700642ad38437982e8a3afc34ff33ccf28e Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Fri, 3 Jul 2020 10:26:38 +0200
Subject: [PATCH 2/3] Fixed input sanitation in rdpgfx_recv_solid_fill_pdu

The input rectangle must be checked for plausibility.

Thanks to Sunglin and HuanGMz of the Knownsec 404 security team and pangzi of pwnzen
---
 channels/rdpgfx/rdpgfx_common.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/channels/rdpgfx/rdpgfx_common.c b/channels/rdpgfx/rdpgfx_common.c
index 090aa50ab..e0a50a606 100644
--- a/channels/rdpgfx/rdpgfx_common.c
+++ b/channels/rdpgfx/rdpgfx_common.c
@@ -182,6 +182,10 @@ UINT rdpgfx_read_rect16(wStream* s, RECTANGLE_16* rect16)
 	Stream_Read_UINT16(s, rect16->top);    /* top (2 bytes) */
 	Stream_Read_UINT16(s, rect16->right);  /* right (2 bytes) */
 	Stream_Read_UINT16(s, rect16->bottom); /* bottom (2 bytes) */
+	if (rect16->left >= rect16->right)
+		return ERROR_INVALID_DATA;
+	if (rect16->top >= rect16->bottom)
+		return ERROR_INVALID_DATA;
 	return CHANNEL_RC_OK;
 }
 
-- 
2.28.0


From e08a23f93136f59a52651f66d064b8d4303872e1 Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Fri, 3 Jul 2020 10:29:13 +0200
Subject: [PATCH 3/3] Fixed missing input sanitation for GFX surfaces.

Thanks to Sunglin and HuanGMz of the Knownsec 404 security team and pangzi of pwnzen
---
 libfreerdp/gdi/gfx.c | 31 +++++++++++++++++++++++++++----
 1 file changed, 27 insertions(+), 4 deletions(-)

diff --git a/libfreerdp/gdi/gfx.c b/libfreerdp/gdi/gfx.c
index e3a6e66e0..f368165b6 100644
--- a/libfreerdp/gdi/gfx.c
+++ b/libfreerdp/gdi/gfx.c
@@ -31,6 +31,17 @@
 
 #define TAG FREERDP_TAG("gdi")
 
+static BOOL is_rect_valid(const RECTANGLE_16* rect, size_t width, size_t height)
+{
+	if (!rect)
+		return FALSE;
+	if ((rect->left > rect->right) || (rect->right > width))
+		return FALSE;
+	if ((rect->top > rect->bottom) || (rect->bottom > height))
+		return FALSE;
+	return TRUE;
+}
+
 static DWORD gfx_align_scanline(DWORD widthInBytes, DWORD alignment)
 {
 	const UINT32 align = alignment;
@@ -1114,7 +1125,6 @@ static UINT gdi_SurfaceToSurface(RdpgfxClientContext* context,
 	BOOL sameSurface;
 	UINT32 nWidth, nHeight;
 	const RECTANGLE_16* rectSrc;
-	RDPGFX_POINT16* destPt;
 	RECTANGLE_16 invalidRect;
 	gdiGfxSurface* surfaceSrc;
 	gdiGfxSurface* surfaceDst;
@@ -1134,12 +1144,18 @@ static UINT gdi_SurfaceToSurface(RdpgfxClientContext* context,
 	if (!surfaceSrc || !surfaceDst)
 		goto fail;
 
+	if (!is_rect_valid(rectSrc, surfaceSrc->width, surfaceSrc->height))
+		goto fail;
+
 	nWidth = rectSrc->right - rectSrc->left;
 	nHeight = rectSrc->bottom - rectSrc->top;
 
 	for (index = 0; index < surfaceToSurface->destPtsCount; index++)
 	{
-		destPt = &surfaceToSurface->destPts[index];
+		const RDPGFX_POINT16* destPt = &surfaceToSurface->destPts[index];
+		const RECTANGLE_16 rect = { destPt->x, destPt->y, destPt->x + nWidth, destPt->y + nHeight };
+		if (!is_rect_valid(&rect, surfaceDst->width, surfaceDst->height))
+			goto fail;
 
 		if (!freerdp_image_copy(surfaceDst->data, surfaceDst->format, surfaceDst->scanline,
 		                        destPt->x, destPt->y, nWidth, nHeight, surfaceSrc->data,
@@ -1192,6 +1208,9 @@ static UINT gdi_SurfaceToCache(RdpgfxClientContext* context,
 	if (!surface)
 		goto fail;
 
+	if (!is_rect_valid(rect, surface->width, surface->height))
+		goto fail;
+
 	cacheEntry = (gdiGfxCacheEntry*)calloc(1, sizeof(gdiGfxCacheEntry));
 
 	if (!cacheEntry)
@@ -1234,7 +1253,6 @@ static UINT gdi_CacheToSurface(RdpgfxClientContext* context,
 {
 	UINT status = ERROR_INTERNAL_ERROR;
 	UINT16 index;
-	RDPGFX_POINT16* destPt;
 	gdiGfxSurface* surface;
 	gdiGfxCacheEntry* cacheEntry;
 	RECTANGLE_16 invalidRect;
@@ -1248,7 +1266,12 @@ static UINT gdi_CacheToSurface(RdpgfxClientContext* context,
 
 	for (index = 0; index < cacheToSurface->destPtsCount; index++)
 	{
-		destPt = &cacheToSurface->destPts[index];
+		const RDPGFX_POINT16* destPt = &cacheToSurface->destPts[index];
+		const RECTANGLE_16 rect = { destPt->x, destPt->y, destPt->x + cacheEntry->width,
+			                        destPt->y + cacheEntry->height };
+
+		if (!is_rect_valid(&rect, surface->width, surface->height))
+			goto fail;
 
 		if (!freerdp_image_copy(surface->data, surface->format, surface->scanline, destPt->x,
 		                        destPt->y, cacheEntry->width, cacheEntry->height, cacheEntry->data,
-- 
2.28.0

openSUSE Build Service is sponsored by