From 733ee3208306b1ea32697b356c0215180fc3f049 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Tue, 26 May 2020 07:28:33 +0200 Subject: [PATCH] Fixed invalid access in update_recv_primary_order CVE-2020-11095 thanks @antonio-morales for finding this. --- libfreerdp/core/orders.c | 107 +++++++++++++++++++++++++++------------ libfreerdp/core/orders.h | 2 +- libfreerdp/core/update.c | 4 +- 3 files changed, 78 insertions(+), 35 deletions(-) diff --git a/libfreerdp/core/orders.c b/libfreerdp/core/orders.c index 87e0959642c3..90d79f54d6e1 100644 --- a/libfreerdp/core/orders.c +++ b/libfreerdp/core/orders.c @@ -43,36 +43,75 @@ #define TAG FREERDP_TAG("core.orders") -const BYTE PRIMARY_DRAWING_ORDER_FIELD_BYTES[] = { DSTBLT_ORDER_FIELD_BYTES, - PATBLT_ORDER_FIELD_BYTES, - SCRBLT_ORDER_FIELD_BYTES, - 0, - 0, - 0, - 0, - DRAW_NINE_GRID_ORDER_FIELD_BYTES, - MULTI_DRAW_NINE_GRID_ORDER_FIELD_BYTES, - LINE_TO_ORDER_FIELD_BYTES, - OPAQUE_RECT_ORDER_FIELD_BYTES, - SAVE_BITMAP_ORDER_FIELD_BYTES, - 0, - MEMBLT_ORDER_FIELD_BYTES, - MEM3BLT_ORDER_FIELD_BYTES, - MULTI_DSTBLT_ORDER_FIELD_BYTES, - MULTI_PATBLT_ORDER_FIELD_BYTES, - MULTI_SCRBLT_ORDER_FIELD_BYTES, - MULTI_OPAQUE_RECT_ORDER_FIELD_BYTES, - FAST_INDEX_ORDER_FIELD_BYTES, - POLYGON_SC_ORDER_FIELD_BYTES, - POLYGON_CB_ORDER_FIELD_BYTES, - POLYLINE_ORDER_FIELD_BYTES, - 0, - FAST_GLYPH_ORDER_FIELD_BYTES, - ELLIPSE_SC_ORDER_FIELD_BYTES, - ELLIPSE_CB_ORDER_FIELD_BYTES, - GLYPH_INDEX_ORDER_FIELD_BYTES }; - -#define PRIMARY_DRAWING_ORDER_COUNT (ARRAYSIZE(PRIMARY_DRAWING_ORDER_FIELD_BYTES)) +BYTE get_primary_drawing_order_field_bytes(UINT32 orderType, BOOL* pValid) +{ + if (pValid) + *pValid = TRUE; + switch (orderType) + { + case 0: + return DSTBLT_ORDER_FIELD_BYTES; + case 1: + return PATBLT_ORDER_FIELD_BYTES; + case 2: + return SCRBLT_ORDER_FIELD_BYTES; + case 3: + return 0; + case 4: + return 0; + case 5: + return 0; + case 6: + return 0; + case 7: + return DRAW_NINE_GRID_ORDER_FIELD_BYTES; + case 8: + return MULTI_DRAW_NINE_GRID_ORDER_FIELD_BYTES; + case 9: + return LINE_TO_ORDER_FIELD_BYTES; + case 10: + return OPAQUE_RECT_ORDER_FIELD_BYTES; + case 11: + return SAVE_BITMAP_ORDER_FIELD_BYTES; + case 12: + return 0; + case 13: + return MEMBLT_ORDER_FIELD_BYTES; + case 14: + return MEM3BLT_ORDER_FIELD_BYTES; + case 15: + return MULTI_DSTBLT_ORDER_FIELD_BYTES; + case 16: + return MULTI_PATBLT_ORDER_FIELD_BYTES; + case 17: + return MULTI_SCRBLT_ORDER_FIELD_BYTES; + case 18: + return MULTI_OPAQUE_RECT_ORDER_FIELD_BYTES; + case 19: + return FAST_INDEX_ORDER_FIELD_BYTES; + case 20: + return POLYGON_SC_ORDER_FIELD_BYTES; + case 21: + return POLYGON_CB_ORDER_FIELD_BYTES; + case 22: + return POLYLINE_ORDER_FIELD_BYTES; + case 23: + return 0; + case 24: + return FAST_GLYPH_ORDER_FIELD_BYTES; + case 25: + return ELLIPSE_SC_ORDER_FIELD_BYTES; + case 26: + return ELLIPSE_CB_ORDER_FIELD_BYTES; + case 27: + return GLYPH_INDEX_ORDER_FIELD_BYTES; + default: + if (pValid) + *pValid = FALSE; + WLog_WARN(TAG, "Invalid orderType 0x%08X received", orderType); + return 0; + } +} static const BYTE CBR2_BPP[] = { 0, 0, 0, 8, 16, 24, 32 }; @@ -3240,6 +3279,7 @@ static BOOL read_primary_order(wLog* log, const char* orderName, wStream* s, static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) { + BYTE field; BOOL rc = FALSE; rdpContext* context = update->context; rdpPrimaryUpdate* primary = update->primary; @@ -3263,8 +3303,11 @@ static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) if (!check_primary_order_supported(update->log, settings, orderInfo->orderType, orderName)) return FALSE; - if (!update_read_field_flags(s, &(orderInfo->fieldFlags), flags, - PRIMARY_DRAWING_ORDER_FIELD_BYTES[orderInfo->orderType])) + field = get_primary_drawing_order_field_bytes(orderInfo->orderType, &rc); + if (!rc) + return FALSE; + + if (!update_read_field_flags(s, &(orderInfo->fieldFlags), flags, field)) { WLog_Print(update->log, WLOG_ERROR, "update_read_field_flags() failed"); return FALSE; diff --git a/libfreerdp/core/orders.h b/libfreerdp/core/orders.h index 76e3d3fe3455..d429dff7046f 100644 --- a/libfreerdp/core/orders.h +++ b/libfreerdp/core/orders.h @@ -189,7 +189,7 @@ #define CG_GLYPH_UNICODE_PRESENT 0x0010 -FREERDP_LOCAL extern const BYTE PRIMARY_DRAWING_ORDER_FIELD_BYTES[]; +FREERDP_LOCAL BYTE get_primary_drawing_order_field_bytes(UINT32 orderType, BOOL* pValid); FREERDP_LOCAL BOOL update_recv_order(rdpUpdate* update, wStream* s); diff --git a/libfreerdp/core/update.c b/libfreerdp/core/update.c index aac58819fdf9..ebb82fc2df7e 100644 --- a/libfreerdp/core/update.c +++ b/libfreerdp/core/update.c @@ -1087,7 +1087,7 @@ static int update_prepare_order_info(rdpContext* context, ORDER_INFO* orderInfo, orderInfo->controlFlags = ORDER_STANDARD; orderInfo->controlFlags |= ORDER_TYPE_CHANGE; length += 1; - length += PRIMARY_DRAWING_ORDER_FIELD_BYTES[orderInfo->orderType]; + length += get_primary_drawing_order_field_bytes(orderInfo->orderType, NULL); length += update_prepare_bounds(context, orderInfo); return length; } @@ -1105,7 +1105,7 @@ static int update_write_order_info(rdpContext* context, wStream* s, ORDER_INFO* Stream_Write_UINT8(s, orderInfo->orderType); /* orderType (1 byte) */ update_write_field_flags(s, orderInfo->fieldFlags, orderInfo->controlFlags, - PRIMARY_DRAWING_ORDER_FIELD_BYTES[orderInfo->orderType]); + get_primary_drawing_order_field_bytes(orderInfo->orderType, NULL)); update_write_bounds(s, orderInfo); Stream_SetPosition(s, position); return 0;