new file mode 100644
@@ -0,0 +1,124 @@
+From 5fbd3aa27780d4c1e4610d1e5f1515f50fc3674b Mon Sep 17 00:00:00 2001
+From: Gyorgy Sarvari <skandigraun@gmail.com>
+Date: Mon, 22 May 2023 16:03:54 +0800
+Subject: [PATCH] add bound check in gdi_SolidFill
+
+From: houchengqiu <houchengqiu@uniontech.com>
+
+In Windows remote run vulnerabillities exe program, to create
+Micorosoft::Windows::RDS::Graphics channel, case Remmina crash.
+So, add bound check, limit the size of the requested rect, no larger than the surface data buffer.
+
+(cherry picked from commit 6a63441e4ee8e2bf333361f5d24156a183b14ecd)
+
+CVE: CVE-2023-39352
+Upstream-Status: Backport [https://github.com/FreeRDP/FreeRDP/commit/856ecaa463e963ecfebc9734423d69139e7b3916]
+Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com>
+---
+ libfreerdp/gdi/gfx.c | 70 ++++++++++++++++++++++++++++----------------
+ 1 file changed, 45 insertions(+), 25 deletions(-)
+
+diff --git a/libfreerdp/gdi/gfx.c b/libfreerdp/gdi/gfx.c
+index a3b7505c5..d2ca9cb63 100644
+--- a/libfreerdp/gdi/gfx.c
++++ b/libfreerdp/gdi/gfx.c
+@@ -25,6 +25,8 @@
+
+ #include "../core/update.h"
+
++#include <assert.h>
++
+ #include <freerdp/log.h>
+ #include <freerdp/gdi/gfx.h>
+ #include <freerdp/gdi/region.h>
+@@ -1079,6 +1081,28 @@ static UINT gdi_DeleteSurface(RdpgfxClientContext* context,
+ return rc;
+ }
+
++static BOOL intersect_rect(const RECTANGLE_16* rect, const gdiGfxSurface* surface,
++ RECTANGLE_16* prect)
++{
++ assert((rect) && "Assert fail: rect");
++ assert((surface) && "Assert fail: surface");
++ assert((prect) && "Assert fail: prect");
++
++ if (rect->left > rect->right)
++ return FALSE;
++ if (rect->left > surface->width)
++ return FALSE;
++ if (rect->top > rect->bottom)
++ return FALSE;
++ if (rect->top > surface->height)
++ return FALSE;
++ prect->left = rect->left;
++ prect->top = rect->top;
++ prect->right = MIN(rect->right, surface->width);
++ prect->bottom = MIN(rect->bottom, surface->height);
++ return TRUE;
++}
++
+ /**
+ * Function description
+ *
+@@ -1087,40 +1111,36 @@ static UINT gdi_DeleteSurface(RdpgfxClientContext* context,
+ static UINT gdi_SolidFill(RdpgfxClientContext* context, const RDPGFX_SOLID_FILL_PDU* solidFill)
+ {
+ UINT status = ERROR_INTERNAL_ERROR;
+- UINT16 index;
+- UINT32 color;
+- BYTE a, r, g, b;
+- UINT32 nWidth, nHeight;
+- RECTANGLE_16* rect;
+- gdiGfxSurface* surface;
+- RECTANGLE_16 invalidRect;
++ BYTE a = 0;
++ RECTANGLE_16 invalidRect = { 0 };
+ rdpGdi* gdi = (rdpGdi*)context->custom;
++
+ EnterCriticalSection(&context->mux);
+- surface = (gdiGfxSurface*)context->GetSurfaceData(context, solidFill->surfaceId);
++
++ assert((context->GetSurfaceData) && "Assert fail: context->GetSurfaceData");
++ gdiGfxSurface* surface = (gdiGfxSurface*)context->GetSurfaceData(context, solidFill->surfaceId);
+
+ if (!surface)
+ goto fail;
+
+- b = solidFill->fillPixel.B;
+- g = solidFill->fillPixel.G;
+- r = solidFill->fillPixel.R;
+- /* a = solidFill->fillPixel.XA;
+- * Ignore alpha channel, this is a solid fill. */
++ const BYTE b = solidFill->fillPixel.B;
++ const BYTE g = solidFill->fillPixel.G;
++ const BYTE r = solidFill->fillPixel.R;
+ a = 0xFF;
+- color = FreeRDPGetColor(surface->format, r, g, b, a);
++ const UINT32 color = FreeRDPGetColor(surface->format, r, g, b, a);
+
+- for (index = 0; index < solidFill->fillRectCount; index++)
++ for (UINT16 index = 0; index < solidFill->fillRectCount; index++)
+ {
+- rect = &(solidFill->fillRects[index]);
+- nWidth = rect->right - rect->left;
+- nHeight = rect->bottom - rect->top;
+- invalidRect.left = rect->left;
+- invalidRect.top = rect->top;
+- invalidRect.right = rect->right;
+- invalidRect.bottom = rect->bottom;
+-
+- if (!freerdp_image_fill(surface->data, surface->format, surface->scanline, rect->left,
+- rect->top, nWidth, nHeight, color))
++ const RECTANGLE_16* rect = &(solidFill->fillRects[index]);
++
++ if (!intersect_rect(rect, surface, &invalidRect))
++ goto fail;
++
++ const UINT32 nWidth = invalidRect.right - invalidRect.left;
++ const UINT32 nHeight = invalidRect.bottom - invalidRect.top;
++
++ if (!freerdp_image_fill(surface->data, surface->format, surface->scanline, invalidRect.left,
++ invalidRect.top, nWidth, nHeight, color))
+ goto fail;
+
+ region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect);
@@ -23,6 +23,7 @@ SRC_URI = "git://github.com/FreeRDP/FreeRDP.git;branch=stable-2.0;protocol=https
file://CVE-2022-39320.patch \
file://CVE-2023-39350.patch \
file://CVE-2023-39351.patch \
+ file://CVE-2023-39352.patch \
"
S = "${WORKDIR}/git"
Details: https://nvd.nist.gov/vuln/detail/CVE-2023-39352 Backport the commit that was identified[1] by Debian as the solution. Note: WINPR_ASSERT macro calls have been changed to assert calls, as this macro doesn't exist yet in this version. Looking at the implementation[2], it is basically an assert call with a bit verbose logs. Even though the original implementation also defines a no-op version, the assert version is enabled by default. [1]: https://security-tracker.debian.org/tracker/CVE-2023-39352 [2]: https://github.com/FreeRDP/FreeRDP/blob/2.11.0/winpr/include/winpr/assert.h#L31 Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com> --- .../freerdp/freerdp/CVE-2023-39352.patch | 124 ++++++++++++++++++ .../recipes-support/freerdp/freerdp_2.6.1.bb | 1 + 2 files changed, 125 insertions(+) create mode 100644 meta-oe/recipes-support/freerdp/freerdp/CVE-2023-39352.patch