diff --git a/debian/changelog b/debian/changelog index 5b22e7b..d92d4a9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -15,7 +15,7 @@ freerdp2 (2.3.0+dfsg1-2~deb10u3) UNRELEASED; urgency=medium CVE-2020-15103 (Closes: #965979) * Backporting/Importing upstream patches for (Closes: #1051638): CVE-2023-39350 CVE-2023-39351 CVE-2023-39352 CVE-2023-39353 - CVE-2023-39354 + CVE-2023-39354 CVE-2023-39355 CVE-2023-39356 -- Tobias Frost Mon, 02 Oct 2023 17:10:48 +0200 diff --git a/debian/patches/0038-CVE-2023-39355.patch b/debian/patches/0041-CVE-2023-39355.patch similarity index 100% rename from debian/patches/0038-CVE-2023-39355.patch rename to debian/patches/0041-CVE-2023-39355.patch diff --git a/debian/patches/0042-CVE-2023-39356-part1.patch b/debian/patches/0042-CVE-2023-39356-part1.patch new file mode 100644 index 0000000..b1a85cf --- /dev/null +++ b/debian/patches/0042-CVE-2023-39356-part1.patch @@ -0,0 +1,82 @@ +Description: Upstream fix for CVE-2023-39356 - Missing offset validation leading to Out-of-Bounds Read in gdi_multi_opaque_rect + commit 1 of 2. +Origin: https://github.com/FreeRDP/FreeRDP/commit/889348a86e49bc8f1351ed6496d847b32db5f86e +Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-q5v5-qhj5-mh6m +Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1051638 +From 889348a86e49bc8f1351ed6496d847b32db5f86e Mon Sep 17 00:00:00 2001 +From: Armin Novak +Date: Sat, 5 Aug 2023 11:31:08 +0200 +Subject: [PATCH] [core,orders] fix checks for multi opaque rect + +(cherry picked from commit 567847066278ec112abb99707902818b282059ad) +--- + libfreerdp/core/orders.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +--- a/libfreerdp/core/orders.c ++++ b/libfreerdp/core/orders.c +@@ -28,6 +28,9 @@ + #include + #include + ++#include ++#define WINPR_ASSERT assert ++ + #include + #include + #include +@@ -1390,7 +1393,7 @@ + return update_read_delta_rects(s, multi_dstblt->rectangles, &multi_dstblt->numRectangles); + } + +- return TRUE; ++ return multi_dstblt->numRectangles == 0; + } + static BOOL update_read_multi_patblt_order(wStream* s, const ORDER_INFO* orderInfo, + MULTI_PATBLT_ORDER* multi_patblt) +@@ -1420,12 +1423,18 @@ + if (!update_read_delta_rects(s, multi_patblt->rectangles, &multi_patblt->numRectangles)) + return FALSE; + } ++ else if (multi_patblt->numRectangles != 0) ++ return FALSE; + + return TRUE; + } + static BOOL update_read_multi_scrblt_order(wStream* s, const ORDER_INFO* orderInfo, + MULTI_SCRBLT_ORDER* multi_scrblt) + { ++ WINPR_ASSERT(orderInfo); ++ WINPR_ASSERT(multi_scrblt); ++ ++ multi_scrblt->numRectangles = 0; + if (!read_order_field_coord(orderInfo, s, 1, &multi_scrblt->nLeftRect, FALSE) || + !read_order_field_coord(orderInfo, s, 2, &multi_scrblt->nTopRect, FALSE) || + !read_order_field_coord(orderInfo, s, 3, &multi_scrblt->nWidth, FALSE) || +@@ -1445,7 +1454,7 @@ + return update_read_delta_rects(s, multi_scrblt->rectangles, &multi_scrblt->numRectangles); + } + +- return TRUE; ++ return multi_scrblt->numRectangles == 0; + } + static BOOL update_read_multi_opaque_rect_order(wStream* s, const ORDER_INFO* orderInfo, + MULTI_OPAQUE_RECT_ORDER* multi_opaque_rect) +@@ -1497,7 +1506,7 @@ + &multi_opaque_rect->numRectangles); + } + +- return TRUE; ++ return multi_opaque_rect->numRectangles == 0; + } + static BOOL update_read_multi_draw_nine_grid_order(wStream* s, const ORDER_INFO* orderInfo, + MULTI_DRAW_NINE_GRID_ORDER* multi_draw_nine_grid) +@@ -1520,7 +1529,7 @@ + &multi_draw_nine_grid->nDeltaEntries); + } + +- return TRUE; ++ return multi_draw_nine_grid->nDeltaEntries == 0; + } + static BOOL update_read_line_to_order(wStream* s, const ORDER_INFO* orderInfo, + LINE_TO_ORDER* line_to) diff --git a/debian/patches/0043-CVE-2023-39356-part2.patch b/debian/patches/0043-CVE-2023-39356-part2.patch new file mode 100644 index 0000000..4156fd2 --- /dev/null +++ b/debian/patches/0043-CVE-2023-39356-part2.patch @@ -0,0 +1,246 @@ +Description: Upstream fix for CVE-2023-39356 - Missing offset validation leading to Out-of-Bounds Read in gdi_multi_opaque_rect + commit 2 of 2. +Origin: https://github.com/FreeRDP/FreeRDP/commit/23db2f4e6ba71f1c10c543f24de595d7340adb46 +Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-q5v5-qhj5-mh6m +From 23db2f4e6ba71f1c10c543f24de595d7340adb46 Mon Sep 17 00:00:00 2001 +From: Armin Novak +Date: Mon, 4 Sep 2023 09:43:32 +0200 +Subject: [PATCH] [core,orders] fix reading order number field + +the field for delta rectangles/points/... are only transmitted if they +changed from the previous order of the same type. So keep the original +value and update only if a new one is read. + +(cherry picked from commit 5b7cf4acc6b4138c513287a2eaa2c7fb9dfbf5c8) +--- + libfreerdp/core/orders.c | 97 +++++++++++++++++++++++++++++++++++----- + 1 file changed, 85 insertions(+), 12 deletions(-) + +--- a/libfreerdp/core/orders.c ++++ b/libfreerdp/core/orders.c +@@ -1376,12 +1376,13 @@ + static BOOL update_read_multi_dstblt_order(wStream* s, const ORDER_INFO* orderInfo, + MULTI_DSTBLT_ORDER* multi_dstblt) + { ++ UINT32 numRectangles = multi_dstblt->numRectangles; + if (!read_order_field_coord(orderInfo, s, 1, &multi_dstblt->nLeftRect, FALSE) || + !read_order_field_coord(orderInfo, s, 2, &multi_dstblt->nTopRect, FALSE) || + !read_order_field_coord(orderInfo, s, 3, &multi_dstblt->nWidth, FALSE) || + !read_order_field_coord(orderInfo, s, 4, &multi_dstblt->nHeight, FALSE) || + !read_order_field_byte(orderInfo, s, 5, &multi_dstblt->bRop, TRUE) || +- !read_order_field_byte(orderInfo, s, 6, &multi_dstblt->numRectangles, TRUE)) ++ !read_order_field_byte(orderInfo, s, 6, &numRectangles, TRUE)) + return FALSE; + + if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0) +@@ -1389,12 +1390,21 @@ + if (Stream_GetRemainingLength(s) < 2) + return FALSE; + ++ multi_dstblt->numRectangles = numRectangles; + Stream_Read_UINT16(s, multi_dstblt->cbData); + return update_read_delta_rects(s, multi_dstblt->rectangles, &multi_dstblt->numRectangles); + } +- +- return multi_dstblt->numRectangles == 0; ++ if (numRectangles > multi_dstblt->numRectangles) ++ { ++ const char* orderName = __func__; ++ WLog_ERR(TAG, "%s numRectangles %" PRIu32 " > %" PRIu32, orderName, numRectangles, ++ multi_dstblt->numRectangles); ++ return FALSE; ++ } ++ multi_dstblt->numRectangles = numRectangles; ++ return TRUE; + } ++ + static BOOL update_read_multi_patblt_order(wStream* s, const ORDER_INFO* orderInfo, + MULTI_PATBLT_ORDER* multi_patblt) + { +@@ -1410,7 +1420,8 @@ + if (!update_read_brush(s, &multi_patblt->brush, orderInfo->fieldFlags >> 7)) + return FALSE; + +- if (!read_order_field_byte(orderInfo, s, 13, &multi_patblt->numRectangles, TRUE)) ++ UINT32 numRectangles = multi_patblt->numRectangles; ++ if (!read_order_field_byte(orderInfo, s, 13, &numRectangles, TRUE)) + return FALSE; + + if ((orderInfo->fieldFlags & ORDER_FIELD_14) != 0) +@@ -1418,13 +1429,21 @@ + if (Stream_GetRemainingLength(s) < 2) + return FALSE; + ++ multi_patblt->numRectangles = numRectangles; + Stream_Read_UINT16(s, multi_patblt->cbData); + + if (!update_read_delta_rects(s, multi_patblt->rectangles, &multi_patblt->numRectangles)) + return FALSE; + } +- else if (multi_patblt->numRectangles != 0) ++ ++ if (numRectangles > multi_patblt->numRectangles) ++ { ++ const char* orderName = __func__; ++ WLog_ERR(TAG, "%s numRectangles %" PRIu32 " > %" PRIu32, orderName, numRectangles, ++ multi_patblt->numRectangles); + return FALSE; ++ } ++ multi_patblt->numRectangles = numRectangles; + + return TRUE; + } +@@ -1434,7 +1453,7 @@ + WINPR_ASSERT(orderInfo); + WINPR_ASSERT(multi_scrblt); + +- multi_scrblt->numRectangles = 0; ++ UINT32 numRectangles = multi_scrblt->numRectangles; + if (!read_order_field_coord(orderInfo, s, 1, &multi_scrblt->nLeftRect, FALSE) || + !read_order_field_coord(orderInfo, s, 2, &multi_scrblt->nTopRect, FALSE) || + !read_order_field_coord(orderInfo, s, 3, &multi_scrblt->nWidth, FALSE) || +@@ -1442,7 +1461,7 @@ + !read_order_field_byte(orderInfo, s, 5, &multi_scrblt->bRop, TRUE) || + !read_order_field_coord(orderInfo, s, 6, &multi_scrblt->nXSrc, FALSE) || + !read_order_field_coord(orderInfo, s, 7, &multi_scrblt->nYSrc, FALSE) || +- !read_order_field_byte(orderInfo, s, 8, &multi_scrblt->numRectangles, TRUE)) ++ !read_order_field_byte(orderInfo, s, 8, &numRectangles, TRUE)) + return FALSE; + + if ((orderInfo->fieldFlags & ORDER_FIELD_09) != 0) +@@ -1450,11 +1469,21 @@ + if (Stream_GetRemainingLength(s) < 2) + return FALSE; + ++ multi_scrblt->numRectangles = numRectangles; + Stream_Read_UINT16(s, multi_scrblt->cbData); + return update_read_delta_rects(s, multi_scrblt->rectangles, &multi_scrblt->numRectangles); + } + +- return multi_scrblt->numRectangles == 0; ++ if (numRectangles > multi_scrblt->numRectangles) ++ { ++ const char* orderName = __func__; ++ WLog_ERR(TAG, "%s numRectangles %" PRIu32 " > %" PRIu32, orderName, numRectangles, ++ multi_scrblt->numRectangles); ++ return FALSE; ++ } ++ multi_scrblt->numRectangles = numRectangles; ++ ++ return TRUE; + } + static BOOL update_read_multi_opaque_rect_order(wStream* s, const ORDER_INFO* orderInfo, + MULTI_OPAQUE_RECT_ORDER* multi_opaque_rect) +@@ -1493,7 +1522,8 @@ + multi_opaque_rect->color = (multi_opaque_rect->color & 0x0000FFFF) | ((UINT32)byte << 16); + } + +- if (!read_order_field_byte(orderInfo, s, 8, &multi_opaque_rect->numRectangles, TRUE)) ++ UINT32 numRectangles = multi_opaque_rect->numRectangles; ++ if (!read_order_field_byte(orderInfo, s, 8, &numRectangles, TRUE)) + return FALSE; + + if ((orderInfo->fieldFlags & ORDER_FIELD_09) != 0) +@@ -1501,22 +1531,32 @@ + if (Stream_GetRemainingLength(s) < 2) + return FALSE; + ++ multi_opaque_rect->numRectangles = numRectangles; + Stream_Read_UINT16(s, multi_opaque_rect->cbData); + return update_read_delta_rects(s, multi_opaque_rect->rectangles, + &multi_opaque_rect->numRectangles); + } ++ if (numRectangles > multi_opaque_rect->numRectangles) ++ { ++ const char* orderName = __func__; ++ WLog_ERR(TAG, "%s numRectangles %" PRIu32 " > %" PRIu32, orderName, numRectangles, ++ multi_opaque_rect->numRectangles); ++ return FALSE; ++ } ++ multi_opaque_rect->numRectangles = numRectangles; + +- return multi_opaque_rect->numRectangles == 0; ++ return TRUE; + } + static BOOL update_read_multi_draw_nine_grid_order(wStream* s, const ORDER_INFO* orderInfo, + MULTI_DRAW_NINE_GRID_ORDER* multi_draw_nine_grid) + { ++ UINT32 nDeltaEntries = multi_draw_nine_grid->nDeltaEntries; + if (!read_order_field_coord(orderInfo, s, 1, &multi_draw_nine_grid->srcLeft, FALSE) || + !read_order_field_coord(orderInfo, s, 2, &multi_draw_nine_grid->srcTop, FALSE) || + !read_order_field_coord(orderInfo, s, 3, &multi_draw_nine_grid->srcRight, FALSE) || + !read_order_field_coord(orderInfo, s, 4, &multi_draw_nine_grid->srcBottom, FALSE) || + !read_order_field_uint16(orderInfo, s, 5, &multi_draw_nine_grid->bitmapId, TRUE) || +- !read_order_field_byte(orderInfo, s, 6, &multi_draw_nine_grid->nDeltaEntries, TRUE)) ++ !read_order_field_byte(orderInfo, s, 6, &nDeltaEntries, TRUE)) + return FALSE; + + if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0) +@@ -1524,12 +1564,22 @@ + if (Stream_GetRemainingLength(s) < 2) + return FALSE; + ++ multi_draw_nine_grid->nDeltaEntries = nDeltaEntries; + 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); + } + +- return multi_draw_nine_grid->nDeltaEntries == 0; ++ if (nDeltaEntries > multi_draw_nine_grid->nDeltaEntries) ++ { ++ const char* orderName = __func__; ++ WLog_ERR(TAG, "%s nDeltaEntries %" PRIu32 " > %" PRIu32, orderName, nDeltaEntries, ++ multi_draw_nine_grid->nDeltaEntries); ++ return FALSE; ++ } ++ multi_draw_nine_grid->nDeltaEntries = nDeltaEntries; ++ ++ return TRUE; + } + static BOOL update_read_line_to_order(wStream* s, const ORDER_INFO* orderInfo, + LINE_TO_ORDER* line_to) +@@ -1619,6 +1669,14 @@ + return update_read_delta_points(s, polyline->points, polyline->numDeltaEntries, + polyline->xStart, polyline->yStart); + } ++ if (new_num > polyline->numDeltaEntries) ++ { ++ const char* orderName = __func__; ++ WLog_ERR(TAG, "%s numDeltaEntries %" PRIu32 " > %" PRIu32, orderName, new_num, ++ polyline->numDeltaEntries); ++ return FALSE; ++ } ++ polyline->numDeltaEntries = new_num; + + return TRUE; + } +@@ -1944,6 +2002,13 @@ + return update_read_delta_points(s, polygon_sc->points, polygon_sc->numPoints, + polygon_sc->xStart, polygon_sc->yStart); + } ++ if (num > polygon_sc->numPoints) ++ { ++ const char* orderName = __func__; ++ WLog_ERR(TAG, "%s numPoints %" PRIu32 " > %" PRIu32, orderName, num, polygon_sc->numPoints); ++ return FALSE; ++ } ++ polygon_sc->numPoints = num; + + return TRUE; + } +@@ -1989,6 +2054,14 @@ + return FALSE; + } + ++ if (num > polygon_cb->numPoints) ++ { ++ const char* orderName = __func__; ++ WLog_ERR(TAG, "%s numPoints %" PRIu32 " > %" PRIu32, orderName, num, polygon_cb->numPoints); ++ return FALSE; ++ } ++ polygon_cb->numPoints = num; ++ + polygon_cb->backMode = (polygon_cb->bRop2 & 0x80) ? BACKMODE_TRANSPARENT : BACKMODE_OPAQUE; + polygon_cb->bRop2 = (polygon_cb->bRop2 & 0x1F); + return TRUE; diff --git a/debian/patches/series b/debian/patches/series index 01dea59..18296e9 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -30,3 +30,6 @@ 0039-CVE-2023-39353-part2.patch 0040-CVE-2023-39354-part1.patch 0040-CVE-2023-39354-part2.patch +0041-CVE-2023-39355.patch +0042-CVE-2023-39356-part1.patch +0043-CVE-2023-39356-part2.patch