|
|
08a176 |
From 4a4ecc32b160e93ee1e37e5617a0197e2d022643 Mon Sep 17 00:00:00 2001
|
|
|
08a176 |
From: Armin Novak <armin.novak@thincast.com>
|
|
|
08a176 |
Date: Thu, 4 Nov 2021 11:07:41 +0100
|
|
|
08a176 |
Subject: [PATCH] Add checks for bitmap and glyph width/heigth values
|
|
|
08a176 |
|
|
|
08a176 |
CVE-2021-41160
|
|
|
08a176 |
|
|
|
08a176 |
https://github.com/FreeRDP/FreeRDP/pull/7349
|
|
|
08a176 |
|
|
|
08a176 |
Signed-off-by: Felipe Borges <felipeborges@gnome.org>
|
|
|
08a176 |
---
|
|
|
08a176 |
libfreerdp/core/orders.c | 14 ++++++++++++
|
|
|
08a176 |
libfreerdp/core/surface.c | 45 +++++++++++++++++++++++++++++++++++++++
|
|
|
08a176 |
libfreerdp/core/update.c | 7 ++++++
|
|
|
08a176 |
3 files changed, 66 insertions(+)
|
|
|
08a176 |
|
|
|
08a176 |
diff --git a/libfreerdp/core/orders.c b/libfreerdp/core/orders.c
|
|
|
08a176 |
index 74870fae6..44d23a61a 100644
|
|
|
08a176 |
--- a/libfreerdp/core/orders.c
|
|
|
08a176 |
+++ b/libfreerdp/core/orders.c
|
|
|
08a176 |
@@ -1848,6 +1848,13 @@ static BOOL update_read_fast_glyph_order(wStream* s, const ORDER_INFO* orderInfo
|
|
|
08a176 |
new_cb = ((glyph->cx + 7) / 8) * glyph->cy;
|
|
|
08a176 |
new_cb += ((new_cb % 4) > 0) ? 4 - (new_cb % 4) : 0;
|
|
|
08a176 |
|
|
|
08a176 |
+ if ((glyph->cx == 0) || (glyph->cy == 0))
|
|
|
08a176 |
+ {
|
|
|
08a176 |
+ WLog_ERR(TAG, "GLYPH_DATA_V2::cx=%" PRIu32 ", GLYPH_DATA_V2::cy=%" PRIu32,
|
|
|
08a176 |
+ glyph->cx, glyph->cy);
|
|
|
08a176 |
+ return FALSE;
|
|
|
08a176 |
+ }
|
|
|
08a176 |
+
|
|
|
08a176 |
if (fastGlyph->cbData < new_cb)
|
|
|
08a176 |
return FALSE;
|
|
|
08a176 |
|
|
|
08a176 |
@@ -2825,6 +2832,13 @@ update_read_create_offscreen_bitmap_order(wStream* s,
|
|
|
08a176 |
Stream_Read_UINT16(s, create_offscreen_bitmap->cy); /* cy (2 bytes) */
|
|
|
08a176 |
deleteList = &(create_offscreen_bitmap->deleteList);
|
|
|
08a176 |
|
|
|
08a176 |
+ if ((create_offscreen_bitmap->cx == 0) || (create_offscreen_bitmap->cy == 0))
|
|
|
08a176 |
+ {
|
|
|
08a176 |
+ WLog_ERR(TAG, "Invalid OFFSCREEN_DELETE_LIST: cx=%" PRIu16 ", cy=%" PRIu16,
|
|
|
08a176 |
+ create_offscreen_bitmap->cx, create_offscreen_bitmap->cy);
|
|
|
08a176 |
+ return FALSE;
|
|
|
08a176 |
+ }
|
|
|
08a176 |
+
|
|
|
08a176 |
if (deleteListPresent)
|
|
|
08a176 |
{
|
|
|
08a176 |
UINT32 i;
|
|
|
08a176 |
diff --git a/libfreerdp/core/surface.c b/libfreerdp/core/surface.c
|
|
|
08a176 |
index d5c709885..ca89d230c 100644
|
|
|
08a176 |
--- a/libfreerdp/core/surface.c
|
|
|
08a176 |
+++ b/libfreerdp/core/surface.c
|
|
|
08a176 |
@@ -21,6 +21,8 @@
|
|
|
08a176 |
#include "config.h"
|
|
|
08a176 |
#endif
|
|
|
08a176 |
|
|
|
08a176 |
+#include <assert.h>
|
|
|
08a176 |
+
|
|
|
08a176 |
#include <freerdp/utils/pcap.h>
|
|
|
08a176 |
#include <freerdp/log.h>
|
|
|
08a176 |
|
|
|
08a176 |
@@ -62,6 +64,13 @@ static BOOL update_recv_surfcmd_bitmap_ex(wStream* s, TS_BITMAP_DATA_EX* bmp)
|
|
|
08a176 |
Stream_Read_UINT16(s, bmp->height);
|
|
|
08a176 |
Stream_Read_UINT32(s, bmp->bitmapDataLength);
|
|
|
08a176 |
|
|
|
08a176 |
+ if ((bmp->width == 0) || (bmp->height == 0))
|
|
|
08a176 |
+ {
|
|
|
08a176 |
+ WLog_ERR(TAG, "invalid size value width=%" PRIu16 ", height=%" PRIu16, bmp->width,
|
|
|
08a176 |
+ bmp->height);
|
|
|
08a176 |
+ return FALSE;
|
|
|
08a176 |
+ }
|
|
|
08a176 |
+
|
|
|
08a176 |
if ((bmp->bpp < 1) || (bmp->bpp > 32))
|
|
|
08a176 |
{
|
|
|
08a176 |
WLog_ERR(TAG, "invalid bpp value %" PRIu32 "", bmp->bpp);
|
|
|
08a176 |
@@ -85,6 +94,39 @@ static BOOL update_recv_surfcmd_bitmap_ex(wStream* s, TS_BITMAP_DATA_EX* bmp)
|
|
|
08a176 |
return TRUE;
|
|
|
08a176 |
}
|
|
|
08a176 |
|
|
|
08a176 |
+static BOOL update_recv_surfcmd_is_rect_valid(const rdpContext* context,
|
|
|
08a176 |
+ const SURFACE_BITS_COMMAND* cmd)
|
|
|
08a176 |
+{
|
|
|
08a176 |
+ assert(context);
|
|
|
08a176 |
+ assert(context->settings);
|
|
|
08a176 |
+ assert(cmd);
|
|
|
08a176 |
+
|
|
|
08a176 |
+ /* We need a rectangle with left/top being smaller than right/bottom.
|
|
|
08a176 |
+ * Also do not allow empty rectangles. */
|
|
|
08a176 |
+ if ((cmd->destTop >= cmd->destBottom) || (cmd->destLeft >= cmd->destRight))
|
|
|
08a176 |
+ {
|
|
|
08a176 |
+ WLog_WARN(TAG,
|
|
|
08a176 |
+ "Empty surface bits command rectangle: %" PRIu16 "x%" PRIu16 "-%" PRIu16
|
|
|
08a176 |
+ "x%" PRIu16,
|
|
|
08a176 |
+ cmd->destLeft, cmd->destTop, cmd->destRight, cmd->destBottom);
|
|
|
08a176 |
+ return FALSE;
|
|
|
08a176 |
+ }
|
|
|
08a176 |
+
|
|
|
08a176 |
+ /* The rectangle needs to fit into our session size */
|
|
|
08a176 |
+ if ((cmd->destRight > context->settings->DesktopWidth) ||
|
|
|
08a176 |
+ (cmd->destBottom > context->settings->DesktopHeight))
|
|
|
08a176 |
+ {
|
|
|
08a176 |
+ WLog_WARN(TAG,
|
|
|
08a176 |
+ "Invalid surface bits command rectangle: %" PRIu16 "x%" PRIu16 "-%" PRIu16
|
|
|
08a176 |
+ "x%" PRIu16 " does not fit %" PRIu32 "x%" PRIu32,
|
|
|
08a176 |
+ cmd->destLeft, cmd->destTop, cmd->destRight, cmd->destBottom,
|
|
|
08a176 |
+ context->settings->DesktopWidth, context->settings->DesktopHeight);
|
|
|
08a176 |
+ return FALSE;
|
|
|
08a176 |
+ }
|
|
|
08a176 |
+
|
|
|
08a176 |
+ return TRUE;
|
|
|
08a176 |
+}
|
|
|
08a176 |
+
|
|
|
08a176 |
static BOOL update_recv_surfcmd_surface_bits(rdpUpdate* update, wStream* s, UINT16 cmdType)
|
|
|
08a176 |
{
|
|
|
08a176 |
SURFACE_BITS_COMMAND cmd = { 0 };
|
|
|
08a176 |
@@ -98,6 +140,9 @@ static BOOL update_recv_surfcmd_surface_bits(rdpUpdate* update, wStream* s, UINT
|
|
|
08a176 |
Stream_Read_UINT16(s, cmd.destRight);
|
|
|
08a176 |
Stream_Read_UINT16(s, cmd.destBottom);
|
|
|
08a176 |
|
|
|
08a176 |
+ if (!update_recv_surfcmd_is_rect_valid(update->context, &cmd))
|
|
|
08a176 |
+ goto fail;
|
|
|
08a176 |
+
|
|
|
08a176 |
if (!update_recv_surfcmd_bitmap_ex(s, &cmd.bmp))
|
|
|
08a176 |
goto fail;
|
|
|
08a176 |
|
|
|
08a176 |
diff --git a/libfreerdp/core/update.c b/libfreerdp/core/update.c
|
|
|
08a176 |
index ebb82fc2d..e137c3de8 100644
|
|
|
08a176 |
--- a/libfreerdp/core/update.c
|
|
|
08a176 |
+++ b/libfreerdp/core/update.c
|
|
|
08a176 |
@@ -99,6 +99,13 @@ static BOOL update_read_bitmap_data(rdpUpdate* update, wStream* s, BITMAP_DATA*
|
|
|
08a176 |
Stream_Read_UINT16(s, bitmapData->flags);
|
|
|
08a176 |
Stream_Read_UINT16(s, bitmapData->bitmapLength);
|
|
|
08a176 |
|
|
|
08a176 |
+ if ((bitmapData->width == 0) || (bitmapData->height == 0))
|
|
|
08a176 |
+ {
|
|
|
08a176 |
+ WLog_ERR(TAG, "Invalid BITMAP_DATA: width=%" PRIu16 ", height=%" PRIu16, bitmapData->width,
|
|
|
08a176 |
+ bitmapData->height);
|
|
|
08a176 |
+ return FALSE;
|
|
|
08a176 |
+ }
|
|
|
08a176 |
+
|
|
|
08a176 |
if (bitmapData->flags & BITMAP_COMPRESSION)
|
|
|
08a176 |
{
|
|
|
08a176 |
if (!(bitmapData->flags & NO_BITMAP_COMPRESSION_HDR))
|
|
|
08a176 |
--
|
|
|
08a176 |
2.32.0
|
|
|
08a176 |
|