From 178137f13d313b0d78bd81731da0747c0e4dd498 Mon Sep 17 00:00:00 2001 From: duyyb Date: Tue, 3 Dec 2019 14:35:04 +0800 Subject: [PATCH] freerdp: modified spec add patch file --- CVE-2018-1000852.patch | 162 ++++++++++++++++++ CVE-2018-8784.patch | 71 ++++++++ CVE-2018-8785.patch | 182 ++++++++++++++++++++ CVE-2018-8786.patch | 17 ++ CVE-2018-8787.patch | 23 +++ CVE-2018-8788.patch | 368 +++++++++++++++++++++++++++++++++++++++++ CVE-2018-8789.patch | 107 ++++++++++++ freerdp.spec | 12 +- 8 files changed, 939 insertions(+), 3 deletions(-) create mode 100644 CVE-2018-1000852.patch create mode 100644 CVE-2018-8784.patch create mode 100644 CVE-2018-8785.patch create mode 100644 CVE-2018-8786.patch create mode 100644 CVE-2018-8787.patch create mode 100644 CVE-2018-8788.patch create mode 100644 CVE-2018-8789.patch diff --git a/CVE-2018-1000852.patch b/CVE-2018-1000852.patch new file mode 100644 index 0000000..ee7397a --- /dev/null +++ b/CVE-2018-1000852.patch @@ -0,0 +1,162 @@ +From baee520e3dd9be6511c45a14c5f5e77784de1471 Mon Sep 17 00:00:00 2001 +From: Armin Novak +Date: Thu, 20 Sep 2018 09:06:01 +0200 +Subject: [PATCH] Fix for #4866: Added additional length checks + +--- + channels/drdynvc/client/drdynvc_main.c | 61 ++++++++++++++++++++++---- + 1 file changed, 53 insertions(+), 8 deletions(-) + +diff --git a/channels/drdynvc/client/drdynvc_main.c b/channels/drdynvc/client/drdynvc_main.c +index 631b6f1cc6..6924546fba 100644 +--- a/channels/drdynvc/client/drdynvc_main.c ++++ b/channels/drdynvc/client/drdynvc_main.c +@@ -639,8 +639,7 @@ static UINT dvcman_receive_channel_data(drdynvcPlugin* drdynvc, + if (channel->dvc_data) + { + /* Fragmented data */ +- if (Stream_GetPosition(channel->dvc_data) + dataSize > (UINT32) Stream_Capacity( +- channel->dvc_data)) ++ if (Stream_GetPosition(channel->dvc_data) + dataSize > Stream_Capacity(channel->dvc_data)) + { + WLog_Print(drdynvc->log, WLOG_ERROR, "data exceeding declared length!"); + Stream_Release(channel->dvc_data); +@@ -648,7 +647,7 @@ static UINT dvcman_receive_channel_data(drdynvcPlugin* drdynvc, + return ERROR_INVALID_DATA; + } + +- Stream_Write(channel->dvc_data, Stream_Pointer(data), dataSize); ++ Stream_Copy(data, channel->dvc_data, dataSize); + + if (Stream_GetPosition(channel->dvc_data) >= channel->dvc_data_length) + { +@@ -880,6 +879,9 @@ static UINT drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp, + if (!drdynvc) + return CHANNEL_RC_BAD_INIT_HANDLE; + ++ if (Stream_GetRemainingLength(s) < 3) ++ return ERROR_INVALID_DATA; ++ + WLog_Print(drdynvc->log, WLOG_TRACE, "capability_request Sp=%d cbChId=%d", Sp, cbChId); + Stream_Seek(s, 1); /* pad */ + Stream_Read_UINT16(s, drdynvc->version); +@@ -889,6 +891,9 @@ static UINT drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp, + */ + if ((drdynvc->version == 2) || (drdynvc->version == 3)) + { ++ if (Stream_GetRemainingLength(s) < 8) ++ return ERROR_INVALID_DATA; ++ + Stream_Read_UINT16(s, drdynvc->PriorityCharge0); + Stream_Read_UINT16(s, drdynvc->PriorityCharge1); + Stream_Read_UINT16(s, drdynvc->PriorityCharge2); +@@ -900,6 +905,21 @@ static UINT drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp, + return status; + } + ++static UINT32 drdynvc_cblen_to_bytes(int cbLen) ++{ ++ switch (cbLen) ++ { ++ case 0: ++ return 1; ++ ++ case 1: ++ return 2; ++ ++ default: ++ return 4; ++ } ++} ++ + static UINT32 drdynvc_read_variable_uint(wStream* s, int cbLen) + { + UINT32 val; +@@ -935,6 +955,8 @@ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, + UINT32 ChannelId; + wStream* data_out; + UINT channel_status; ++ char* name; ++ size_t length; + + if (!drdynvc) + return CHANNEL_RC_BAD_CHANNEL_HANDLE; +@@ -957,13 +979,20 @@ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, + drdynvc->state = DRDYNVC_STATE_READY; + } + ++ if (Stream_GetRemainingLength(s) < drdynvc_cblen_to_bytes(cbChId)) ++ return ERROR_INVALID_DATA; ++ + ChannelId = drdynvc_read_variable_uint(s, cbChId); + pos = Stream_GetPosition(s); ++ name = Stream_Pointer(s); ++ length = Stream_GetRemainingLength(s); ++ ++ if (strnlen(name, length) >= length) ++ return ERROR_INVALID_DATA; ++ + WLog_Print(drdynvc->log, WLOG_DEBUG, "process_create_request: ChannelId=%"PRIu32" ChannelName=%s", +- ChannelId, +- Stream_Pointer(s)); +- channel_status = dvcman_create_channel(drdynvc, drdynvc->channel_mgr, ChannelId, +- (char*) Stream_Pointer(s)); ++ ChannelId, name); ++ channel_status = dvcman_create_channel(drdynvc, drdynvc->channel_mgr, ChannelId, name); + data_out = Stream_New(NULL, pos + 4); + + if (!data_out) +@@ -1024,6 +1053,10 @@ static UINT drdynvc_process_data_first(drdynvcPlugin* drdynvc, int Sp, + UINT status; + UINT32 Length; + UINT32 ChannelId; ++ ++ if (Stream_GetRemainingLength(s) < drdynvc_cblen_to_bytes(cbChId) + drdynvc_cblen_to_bytes(Sp)) ++ return ERROR_INVALID_DATA; ++ + ChannelId = drdynvc_read_variable_uint(s, cbChId); + Length = drdynvc_read_variable_uint(s, Sp); + WLog_Print(drdynvc->log, WLOG_DEBUG, +@@ -1047,6 +1080,10 @@ static UINT drdynvc_process_data(drdynvcPlugin* drdynvc, int Sp, int cbChId, + wStream* s) + { + UINT32 ChannelId; ++ ++ if (Stream_GetRemainingLength(s) < drdynvc_cblen_to_bytes(cbChId)) ++ return ERROR_INVALID_DATA; ++ + ChannelId = drdynvc_read_variable_uint(s, cbChId); + WLog_Print(drdynvc->log, WLOG_TRACE, "process_data: Sp=%d cbChId=%d, ChannelId=%"PRIu32"", Sp, + cbChId, +@@ -1066,6 +1103,10 @@ static UINT drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp, + UINT error; + UINT32 ChannelId; + wStream* data_out; ++ ++ if (Stream_GetRemainingLength(s) < drdynvc_cblen_to_bytes(cbChId)) ++ return ERROR_INVALID_DATA; ++ + ChannelId = drdynvc_read_variable_uint(s, cbChId); + WLog_Print(drdynvc->log, WLOG_DEBUG, "process_close_request: Sp=%d cbChId=%d, ChannelId=%"PRIu32"", + Sp, +@@ -1108,6 +1149,10 @@ static UINT drdynvc_order_recv(drdynvcPlugin* drdynvc, wStream* s) + int Cmd; + int Sp; + int cbChId; ++ ++ if (Stream_GetRemainingLength(s) < 1) ++ return ERROR_INVALID_DATA; ++ + Stream_Read_UINT8(s, value); + Cmd = (value & 0xf0) >> 4; + Sp = (value & 0x0c) >> 2; +@@ -1166,7 +1211,7 @@ static UINT drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc, + return CHANNEL_RC_NO_MEMORY; + } + +- if (!Stream_EnsureRemainingCapacity(data_in, (int) dataLength)) ++ if (!Stream_EnsureRemainingCapacity(data_in, dataLength)) + { + WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!"); + Stream_Free(drdynvc->data_in, TRUE); + diff --git a/CVE-2018-8784.patch b/CVE-2018-8784.patch new file mode 100644 index 0000000..dd47129 --- /dev/null +++ b/CVE-2018-8784.patch @@ -0,0 +1,71 @@ +--- FreeRDP-2.0.0-rc3/libfreerdp/codec/zgfx.c 2018-08-01 09:27:31.000000000 -0400 ++++ FreeRDP-2.0.0-rc3/libfreerdp/codec/zgfx_1.c 2019-06-05 01:16:46.159000000 -0400 +@@ -109,6 +109,7 @@ static const ZGFX_TOKEN ZGFX_TOKEN_TABLE + _zgfx->cBitsCurrent -= _nbits; \ + _zgfx->bits = _zgfx->BitsCurrent >> _zgfx->cBitsCurrent; \ + _zgfx->BitsCurrent &= ((1 << _zgfx->cBitsCurrent) - 1); ++ return TRUE; + + static void zgfx_history_buffer_ring_write(ZGFX_CONTEXT* zgfx, const BYTE* src, size_t count) + { +@@ -200,9 +201,15 @@ static BOOL zgfx_decompress_segment(ZGFX + UINT32 count; + UINT32 distance; + BYTE* pbSegment; +- size_t cbSegment = segmentSize - 1; ++ size_t cbSegment; + +- if ((Stream_GetRemainingLength(stream) < segmentSize) || (segmentSize < 1)) ++ if (!zgfx || !stream) ++ return FALSE; ++ ++ cbSegment = segmentSize - 1; ++ ++ if ((Stream_GetRemainingLength(stream) < segmentSize) || (segmentSize < 1) || ++ (segmentSize > UINT32_MAX)) + return FALSE; + + Stream_Read_UINT8(stream, flags); /* header (1 byte) */ +@@ -213,6 +220,10 @@ static BOOL zgfx_decompress_segment(ZGFX + if (!(flags & PACKET_COMPRESSED)) + { + zgfx_history_buffer_ring_write(zgfx, pbSegment, cbSegment); ++ ++ if (cbSegment > sizeof(zgfx->OutputBuffer)) ++ return FALSE; ++ + CopyMemory(zgfx->OutputBuffer, pbSegment, cbSegment); + zgfx->OutputCount = cbSegment; + return TRUE; +@@ -251,6 +262,9 @@ static BOOL zgfx_decompress_segment(ZGFX + if (++zgfx->HistoryIndex == zgfx->HistoryBufferSize) + zgfx->HistoryIndex = 0; + ++ if (zgfx->OutputCount >= sizeof(zgfx->OutputBuffer)) ++ return FALSE; ++ + zgfx->OutputBuffer[zgfx->OutputCount++] = c; + } + else +@@ -284,6 +298,9 @@ static BOOL zgfx_decompress_segment(ZGFX + count += zgfx->bits; + } + ++ if (count > sizeof(zgfx->OutputBuffer) - zgfx->OutputCount) ++ return FALSE; ++ + zgfx_history_buffer_ring_read(zgfx, distance, &(zgfx->OutputBuffer[zgfx->OutputCount]), count); + zgfx_history_buffer_ring_write(zgfx, &(zgfx->OutputBuffer[zgfx->OutputCount]), count); + zgfx->OutputCount += count; +@@ -296,6 +313,10 @@ static BOOL zgfx_decompress_segment(ZGFX + zgfx->cBitsRemaining -= zgfx->cBitsCurrent; + zgfx->cBitsCurrent = 0; + zgfx->BitsCurrent = 0; ++ ++ if (count > sizeof(zgfx->OutputBuffer) - zgfx->OutputCount) ++ return FALSE; ++ + CopyMemory(&(zgfx->OutputBuffer[zgfx->OutputCount]), zgfx->pbInputCurrent, count); + zgfx_history_buffer_ring_write(zgfx, zgfx->pbInputCurrent, count); + zgfx->pbInputCurrent += count; + diff --git a/CVE-2018-8785.patch b/CVE-2018-8785.patch new file mode 100644 index 0000000..11ab8f7 --- /dev/null +++ b/CVE-2018-8785.patch @@ -0,0 +1,182 @@ +--- FreeRDP-2.0.0-rc3/libfreerdp/codec/zgfx.c 2019-06-05 01:21:31.264000000 -0400 ++++ FreeRDP-2.0.0-rc3/libfreerdp/codec/zgfx_2.c 2019-06-05 01:28:52.362000000 -0400 +@@ -44,14 +44,34 @@ + + struct _ZGFX_TOKEN + { +- int prefixLength; +- int prefixCode; +- int valueBits; +- int tokenType; ++ UINT32 prefixLength; ++ UINT32 prefixCode; ++ UINT32 valueBits; ++ UINT32 tokenType; + UINT32 valueBase; + }; + typedef struct _ZGFX_TOKEN ZGFX_TOKEN; + ++struct _ZGFX_CONTEXT ++{ ++ BOOL Compressor; ++ ++ const BYTE* pbInputCurrent; ++ const BYTE* pbInputEnd; ++ ++ UINT32 bits; ++ UINT32 cBitsRemaining; ++ UINT32 BitsCurrent; ++ UINT32 cBitsCurrent; ++ ++ BYTE OutputBuffer[65536]; ++ UINT32 OutputCount; ++ ++ BYTE HistoryBuffer[2500000]; ++ UINT32 HistoryIndex; ++ UINT32 HistoryBufferSize; ++}; ++ + static const ZGFX_TOKEN ZGFX_TOKEN_TABLE[] = + { + // len code vbits type vbase +@@ -98,18 +118,26 @@ static const ZGFX_TOKEN ZGFX_TOKEN_TABLE + { 0 } + }; + +-#define zgfx_GetBits(_zgfx, _nbits) \ +- while (_zgfx->cBitsCurrent < _nbits) { \ +- _zgfx->BitsCurrent <<= 8; \ +- if (_zgfx->pbInputCurrent < _zgfx->pbInputEnd) \ +- _zgfx->BitsCurrent += *(_zgfx->pbInputCurrent)++; \ +- _zgfx->cBitsCurrent += 8; \ +- } \ +- _zgfx->cBitsRemaining -= _nbits; \ +- _zgfx->cBitsCurrent -= _nbits; \ +- _zgfx->bits = _zgfx->BitsCurrent >> _zgfx->cBitsCurrent; \ ++static INLINE BOOL zgfx_GetBits(ZGFX_CONTEXT* _zgfx, UINT32 _nbits) ++{ ++ if (!_zgfx) ++ return FALSE; ++ ++ while (_zgfx->cBitsCurrent < _nbits) ++ { ++ _zgfx->BitsCurrent <<= 8; ++ ++ if (_zgfx->pbInputCurrent < _zgfx->pbInputEnd) ++ _zgfx->BitsCurrent += *(_zgfx->pbInputCurrent)++; ++ ++ _zgfx->cBitsCurrent += 8; ++ } ++ ++ _zgfx->cBitsRemaining -= _nbits; ++ _zgfx->cBitsCurrent -= _nbits; ++ _zgfx->bits = _zgfx->BitsCurrent >> _zgfx->cBitsCurrent; + _zgfx->BitsCurrent &= ((1 << _zgfx->cBitsCurrent) - 1); +- return TRUE; ++} + + static void zgfx_history_buffer_ring_write(ZGFX_CONTEXT* zgfx, const BYTE* src, size_t count) + { +@@ -194,7 +222,7 @@ static BOOL zgfx_decompress_segment(ZGFX + { + BYTE c; + BYTE flags; +- int extra; ++ UINT32 extra = 0; + int opIndex; + int haveBits; + int inPrefix; +@@ -338,8 +366,8 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, + { + int status = -1; + BYTE descriptor; +- + wStream* stream = Stream_New((BYTE*)pSrcData, SrcSize); ++ + if (!stream) + return -1; + +@@ -354,6 +382,7 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, + goto fail; + + *ppDstData = NULL; ++ + if (zgfx->OutputCount > 0) + *ppDstData = (BYTE*) malloc(zgfx->OutputCount); + +@@ -370,6 +399,7 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, + UINT16 segmentCount; + UINT32 uncompressedSize; + BYTE* pConcatenated; ++ size_t used = 0; + + if (Stream_GetRemainingLength(stream) < 6) + goto fail; +@@ -398,8 +428,15 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, + if (!zgfx_decompress_segment(zgfx, stream, segmentSize)) + goto fail; + ++ if (zgfx->OutputCount > UINT32_MAX - used) ++ goto fail; ++ ++ if (used + zgfx->OutputCount > uncompressedSize) ++ goto fail; ++ + CopyMemory(pConcatenated, zgfx->OutputBuffer, zgfx->OutputCount); + pConcatenated += zgfx->OutputCount; ++ used += zgfx->OutputCount; + } + } + else +diff --git a/include/freerdp/codec/zgfx.h b/include/freerdp/codec/zgfx.h +index b5c65319cb..b0faf6e0de 100644 +--- a/include/freerdp/codec/zgfx.h ++++ b/include/freerdp/codec/zgfx.h +@@ -32,34 +32,18 @@ + + #define ZGFX_SEGMENTED_MAXSIZE 65535 + +-struct _ZGFX_CONTEXT +-{ +- BOOL Compressor; +- +- const BYTE* pbInputCurrent; +- const BYTE* pbInputEnd; +- +- UINT32 bits; +- UINT32 cBitsRemaining; +- UINT32 BitsCurrent; +- UINT32 cBitsCurrent; +- +- BYTE OutputBuffer[65536]; +- UINT32 OutputCount; +- +- BYTE HistoryBuffer[2500000]; +- UINT32 HistoryIndex; +- UINT32 HistoryBufferSize; +-}; + typedef struct _ZGFX_CONTEXT ZGFX_CONTEXT; + + #ifdef __cplusplus + extern "C" { + #endif + +-FREERDP_API int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags); +-FREERDP_API int zgfx_compress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags); +-FREERDP_API int zgfx_compress_to_stream(ZGFX_CONTEXT* zgfx, wStream* sDst, const BYTE* pUncompressed, UINT32 uncompressedSize, UINT32* pFlags); ++FREERDP_API int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, ++ BYTE** ppDstData, UINT32* pDstSize, UINT32 flags); ++FREERDP_API int zgfx_compress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, ++ BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags); ++FREERDP_API int zgfx_compress_to_stream(ZGFX_CONTEXT* zgfx, wStream* sDst, ++ const BYTE* pUncompressed, UINT32 uncompressedSize, UINT32* pFlags); + + FREERDP_API void zgfx_context_reset(ZGFX_CONTEXT* zgfx, BOOL flush); + +@@ -71,4 +55,4 @@ FREERDP_API void zgfx_context_free(ZGFX_CONTEXT* zgfx); + #endif + + #endif /* FREERDP_CODEC_ZGFX_H */ +- ++ + diff --git a/CVE-2018-8786.patch b/CVE-2018-8786.patch new file mode 100644 index 0000000..d37958f --- /dev/null +++ b/CVE-2018-8786.patch @@ -0,0 +1,17 @@ +--- a/libfreerdp/core/update.c 2018-08-01 21:27:31.000000000 +0800 ++++ b/libfreerdp/core/update.c 2019-04-04 19:20:35.213000000 +0800 +@@ -205,11 +205,9 @@ BITMAP_UPDATE* update_read_bitmap_update + + if (bitmapUpdate->number > bitmapUpdate->count) + { +- UINT16 count; +- BITMAP_DATA* newdata; +- count = bitmapUpdate->number * 2; +- newdata = (BITMAP_DATA*) realloc(bitmapUpdate->rectangles, +- sizeof(BITMAP_DATA) * count); ++ UINT32 count = bitmapUpdate->number * 2; ++ BITMAP_DATA* newdata = (BITMAP_DATA*) realloc(bitmapUpdate->rectangles, ++ sizeof(BITMAP_DATA) * count); + + if (!newdata) + goto fail; diff --git a/CVE-2018-8787.patch b/CVE-2018-8787.patch new file mode 100644 index 0000000..82ac965 --- /dev/null +++ b/CVE-2018-8787.patch @@ -0,0 +1,23 @@ +--- a/libfreerdp/gdi/graphics.c 2018-08-01 21:27:31.000000000 +0800 ++++ b/libfreerdp/gdi/graphics.c 2019-04-04 18:48:18.411000000 +0800 +@@ -141,11 +141,19 @@ static BOOL gdi_Bitmap_Decompress(rdpCon + UINT32 SrcSize = length; + UINT32 SrcFormat; + rdpGdi* gdi = context->gdi; ++ UINT32 size = DstWidth * DstHeight; + bitmap->compressed = FALSE; + bitmap->format = gdi->dstFormat; +- bitmap->length = DstWidth * DstHeight * GetBytesPerPixel(bitmap->format); + bitmap->data = (BYTE*) _aligned_malloc(bitmap->length, 16); + ++ if ((GetBytesPerPixel(bitmap->format) == 0) || ++ (DstWidth == 0) || (DstHeight == 0) || (DstWidth > UINT32_MAX / DstHeight) || ++ (size > (UINT32_MAX / GetBytesPerPixel(bitmap->format)))) ++ return FALSE; ++ ++ size *= GetBytesPerPixel(bitmap->format); ++ bitmap->length = size; ++ + if (!bitmap->data) + return FALSE; + diff --git a/CVE-2018-8788.patch b/CVE-2018-8788.patch new file mode 100644 index 0000000..8e97346 --- /dev/null +++ b/CVE-2018-8788.patch @@ -0,0 +1,368 @@ +From d1112c279bd1a327e8e4d0b5f371458bf2579659 Mon Sep 17 00:00:00 2001 +From: Armin Novak +Date: Mon, 22 Oct 2018 16:52:21 +0200 +Subject: [PATCH] Fixed CVE-2018-8788 + +Thanks to Eyal Itkin from Check Point Software Technologies. +--- + include/freerdp/codec/nsc.h | 4 +- + libfreerdp/codec/nsc.c | 94 +++++++++++++++++++++++++++++------ + libfreerdp/codec/nsc_encode.c | 62 ++++++++++++++++------- + libfreerdp/codec/nsc_encode.h | 2 +- + libfreerdp/codec/nsc_sse2.c | 4 +- + 5 files changed, 130 insertions(+), 36 deletions(-) + +diff --git a/include/freerdp/codec/nsc.h b/include/freerdp/codec/nsc.h +index 21e575ad27..cb16570db8 100644 +--- a/include/freerdp/codec/nsc.h ++++ b/include/freerdp/codec/nsc.h +@@ -77,8 +77,8 @@ struct _NSC_CONTEXT + /* color palette allocated by the application */ + const BYTE* palette; + +- void (*decode)(NSC_CONTEXT* context); +- void (*encode)(NSC_CONTEXT* context, const BYTE* BitmapData, ++ BOOL (*decode)(NSC_CONTEXT* context); ++ BOOL (*encode)(NSC_CONTEXT* context, const BYTE* BitmapData, + UINT32 rowstride); + + NSC_CONTEXT_PRIV* priv; +diff --git a/libfreerdp/codec/nsc.c b/libfreerdp/codec/nsc.c +index d0547cd333..bad0aec1c9 100644 +--- a/libfreerdp/codec/nsc.c ++++ b/libfreerdp/codec/nsc.c +@@ -42,13 +42,24 @@ + #define NSC_INIT_SIMD(_nsc_context) do { } while (0) + #endif + +-static void nsc_decode(NSC_CONTEXT* context) ++static BOOL nsc_decode(NSC_CONTEXT* context) + { + UINT16 x; + UINT16 y; +- UINT16 rw = ROUND_UP_TO(context->width, 8); +- BYTE shift = context->ColorLossLevel - 1; /* colorloss recovery + YCoCg shift */ +- BYTE* bmpdata = context->BitmapData; ++ UINT16 rw; ++ BYTE shift; ++ BYTE* bmpdata; ++ size_t pos = 0; ++ ++ if (!context) ++ return FALSE; ++ ++ rw = ROUND_UP_TO(context->width, 8); ++ shift = context->ColorLossLevel - 1; /* colorloss recovery + YCoCg shift */ ++ bmpdata = context->BitmapData; ++ ++ if (!bmpdata) ++ return FALSE; + + for (y = 0; y < context->height; y++) + { +@@ -80,6 +91,11 @@ static void nsc_decode(NSC_CONTEXT* context) + INT16 r_val = y_val + co_val - cg_val; + INT16 g_val = y_val + cg_val; + INT16 b_val = y_val - co_val - cg_val; ++ ++ if (pos + 4 > context->BitmapDataLength) ++ return FALSE; ++ ++ pos += 4; + *bmpdata++ = MINMAX(b_val, 0, 0xFF); + *bmpdata++ = MINMAX(g_val, 0, 0xFF); + *bmpdata++ = MINMAX(r_val, 0, 0xFF); +@@ -90,9 +106,11 @@ static void nsc_decode(NSC_CONTEXT* context) + aplane++; + } + } ++ ++ return TRUE; + } + +-static void nsc_rle_decode(BYTE* in, BYTE* out, UINT32 originalSize) ++static BOOL nsc_rle_decode(BYTE* in, BYTE* out, UINT32 outSize, UINT32 originalSize) + { + UINT32 len; + UINT32 left; +@@ -105,6 +123,10 @@ static void nsc_rle_decode(BYTE* in, BYTE* out, UINT32 originalSize) + + if (left == 5) + { ++ if (outSize < 1) ++ return FALSE; ++ ++ outSize--; + *out++ = value; + left--; + } +@@ -124,26 +146,42 @@ static void nsc_rle_decode(BYTE* in, BYTE* out, UINT32 originalSize) + in += 4; + } + ++ if (outSize < len) ++ return FALSE; ++ ++ outSize -= len; + FillMemory(out, len, value); + out += len; + left -= len; + } + else + { ++ if (outSize < 1) ++ return FALSE; ++ ++ outSize--; + *out++ = value; + left--; + } + } + +- *((UINT32*)out) = *((UINT32*)in); ++ if ((outSize < 4) || (left < 4)) ++ return FALSE; ++ ++ memcpy(out, in, 4); ++ return TRUE; + } + +-static void nsc_rle_decompress_data(NSC_CONTEXT* context) ++static BOOL nsc_rle_decompress_data(NSC_CONTEXT* context) + { + UINT16 i; + BYTE* rle; + UINT32 planeSize; + UINT32 originalSize; ++ ++ if (!context) ++ return FALSE; ++ + rle = context->Planes; + + for (i = 0; i < 4; i++) +@@ -152,14 +190,30 @@ static void nsc_rle_decompress_data(NSC_CONTEXT* context) + planeSize = context->PlaneByteCount[i]; + + if (planeSize == 0) ++ { ++ if (context->priv->PlaneBuffersLength < originalSize) ++ return FALSE; ++ + FillMemory(context->priv->PlaneBuffers[i], originalSize, 0xFF); ++ } + else if (planeSize < originalSize) +- nsc_rle_decode(rle, context->priv->PlaneBuffers[i], originalSize); ++ { ++ if (!nsc_rle_decode(rle, context->priv->PlaneBuffers[i], context->priv->PlaneBuffersLength, ++ originalSize)) ++ return FALSE; ++ } + else ++ { ++ if (context->priv->PlaneBuffersLength < originalSize) ++ return FALSE; ++ + CopyMemory(context->priv->PlaneBuffers[i], rle, originalSize); ++ } + + rle += planeSize; + } ++ ++ return TRUE; + } + + static BOOL nsc_stream_initialize(NSC_CONTEXT* context, wStream* s) +@@ -396,13 +450,25 @@ BOOL nsc_process_message(NSC_CONTEXT* context, UINT16 bpp, + return FALSE; + + /* RLE decode */ +- PROFILER_ENTER(context->priv->prof_nsc_rle_decompress_data) +- nsc_rle_decompress_data(context); +- PROFILER_EXIT(context->priv->prof_nsc_rle_decompress_data) ++ { ++ BOOL rc; ++ PROFILER_ENTER(context->priv->prof_nsc_rle_decompress_data) ++ rc = nsc_rle_decompress_data(context); ++ PROFILER_EXIT(context->priv->prof_nsc_rle_decompress_data) ++ ++ if (!rc) ++ return FALSE; ++ } + /* Colorloss recover, Chroma supersample and AYCoCg to ARGB Conversion in one step */ +- PROFILER_ENTER(context->priv->prof_nsc_decode) +- context->decode(context); +- PROFILER_EXIT(context->priv->prof_nsc_decode) ++ { ++ BOOL rc; ++ PROFILER_ENTER(context->priv->prof_nsc_decode) ++ rc = context->decode(context); ++ PROFILER_EXIT(context->priv->prof_nsc_decode) ++ ++ if (!rc) ++ return FALSE; ++ } + + if (!freerdp_image_copy(pDstData, DstFormat, nDstStride, nXDst, nYDst, + width, height, context->BitmapData, +diff --git a/libfreerdp/codec/nsc_encode.c b/libfreerdp/codec/nsc_encode.c +index 492f170dc8..d2456fb939 100644 +--- a/libfreerdp/codec/nsc_encode.c ++++ b/libfreerdp/codec/nsc_encode.c +@@ -51,6 +51,7 @@ static BOOL nsc_context_initialize_encode(NSC_CONTEXT* context) + for (i = 0; i < 5; i++) + { + BYTE* tmp = (BYTE*) realloc(context->priv->PlaneBuffers[i], length); ++ + if (!tmp) + goto fail; + +@@ -87,7 +88,7 @@ static BOOL nsc_context_initialize_encode(NSC_CONTEXT* context) + return FALSE; + } + +-static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, const BYTE* data, ++static BOOL nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, const BYTE* data, + UINT32 scanline) + { + UINT16 x; +@@ -104,10 +105,20 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, const BYTE* data, + INT16 b_val; + BYTE a_val; + UINT32 tempWidth; ++ ++ if (!context || data || (scanline == 0)) ++ return FALSE; ++ + tempWidth = ROUND_UP_TO(context->width, 8); + rw = (context->ChromaSubsamplingLevel ? tempWidth : context->width); + ccl = context->ColorLossLevel; + ++ if (context->priv->PlaneBuffersLength < rw * scanline) ++ return FALSE; ++ ++ if (rw < scanline * 2) ++ return FALSE; ++ + for (y = 0; y < context->height; y++) + { + src = data + (context->height - 1 - y) * scanline; +@@ -242,31 +253,37 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, const BYTE* data, + CopyMemory(coplane, coplane - rw, rw); + CopyMemory(cgplane, cgplane - rw, rw); + } ++ ++ return TRUE; + } + +-static void nsc_encode_subsampling(NSC_CONTEXT* context) ++static BOOL nsc_encode_subsampling(NSC_CONTEXT* context) + { + UINT16 x; + UINT16 y; +- BYTE* co_dst; +- BYTE* cg_dst; +- INT8* co_src0; +- INT8* co_src1; +- INT8* cg_src0; +- INT8* cg_src1; + UINT32 tempWidth; + UINT32 tempHeight; ++ ++ if (!context) ++ return FALSE; ++ + tempWidth = ROUND_UP_TO(context->width, 8); + tempHeight = ROUND_UP_TO(context->height, 2); + ++ if (tempHeight == 0) ++ return FALSE; ++ ++ if (tempWidth > context->priv->PlaneBuffersLength / tempHeight) ++ return FALSE; ++ + for (y = 0; y < tempHeight >> 1; y++) + { +- co_dst = context->priv->PlaneBuffers[1] + y * (tempWidth >> 1); +- cg_dst = context->priv->PlaneBuffers[2] + y * (tempWidth >> 1); +- co_src0 = (INT8*) context->priv->PlaneBuffers[1] + (y << 1) * tempWidth; +- co_src1 = co_src0 + tempWidth; +- cg_src0 = (INT8*) context->priv->PlaneBuffers[2] + (y << 1) * tempWidth; +- cg_src1 = cg_src0 + tempWidth; ++ BYTE* co_dst = context->priv->PlaneBuffers[1] + y * (tempWidth >> 1); ++ BYTE* cg_dst = context->priv->PlaneBuffers[2] + y * (tempWidth >> 1); ++ const INT8* co_src0 = (INT8*) context->priv->PlaneBuffers[1] + (y << 1) * tempWidth; ++ const INT8* co_src1 = co_src0 + tempWidth; ++ const INT8* cg_src0 = (INT8*) context->priv->PlaneBuffers[2] + (y << 1) * tempWidth; ++ const INT8* cg_src1 = cg_src0 + tempWidth; + + for (x = 0; x < tempWidth >> 1; x++) + { +@@ -280,19 +297,28 @@ static void nsc_encode_subsampling(NSC_CONTEXT* context) + cg_src1 += 2; + } + } ++ ++ return TRUE; + } + +-void nsc_encode(NSC_CONTEXT* context, const BYTE* bmpdata, UINT32 rowstride) ++BOOL nsc_encode(NSC_CONTEXT* context, const BYTE* bmpdata, UINT32 rowstride) + { +- nsc_encode_argb_to_aycocg(context, bmpdata, rowstride); ++ if (!context || !bmpdata || (rowstride == 0)) ++ return FALSE; ++ ++ if (!nsc_encode_argb_to_aycocg(context, bmpdata, rowstride)) ++ return FALSE; + + if (context->ChromaSubsamplingLevel) + { +- nsc_encode_subsampling(context); ++ if (!nsc_encode_subsampling(context)) ++ return FALSE; + } ++ ++ return TRUE; + } + +-static UINT32 nsc_rle_encode(BYTE* in, BYTE* out, UINT32 originalSize) ++static UINT32 nsc_rle_encode(const BYTE* in, BYTE* out, UINT32 originalSize) + { + UINT32 left; + UINT32 runlength = 1; +diff --git a/libfreerdp/codec/nsc_encode.h b/libfreerdp/codec/nsc_encode.h +index e220de4072..784ccb6e35 100644 +--- a/libfreerdp/codec/nsc_encode.h ++++ b/libfreerdp/codec/nsc_encode.h +@@ -24,7 +24,7 @@ + + #include + +-FREERDP_LOCAL void nsc_encode(NSC_CONTEXT* context, const BYTE* bmpdata, ++FREERDP_LOCAL BOOL nsc_encode(NSC_CONTEXT* context, const BYTE* bmpdata, + UINT32 rowstride); + + #endif /* FREERDP_LIB_CODEC_NSC_ENCODE_H */ +diff --git a/libfreerdp/codec/nsc_sse2.c b/libfreerdp/codec/nsc_sse2.c +index 149e80a83c..966525f16d 100644 +--- a/libfreerdp/codec/nsc_sse2.c ++++ b/libfreerdp/codec/nsc_sse2.c +@@ -385,7 +385,7 @@ static void nsc_encode_subsampling_sse2(NSC_CONTEXT* context) + } + } + +-static void nsc_encode_sse2(NSC_CONTEXT* context, const BYTE* data, ++static BOOL nsc_encode_sse2(NSC_CONTEXT* context, const BYTE* data, + UINT32 scanline) + { + nsc_encode_argb_to_aycocg_sse2(context, data, scanline); +@@ -394,6 +394,8 @@ static void nsc_encode_sse2(NSC_CONTEXT* context, const BYTE* data, + { + nsc_encode_subsampling_sse2(context); + } ++ ++ return TRUE; + } + + void nsc_init_sse2(NSC_CONTEXT* context) diff --git a/CVE-2018-8789.patch b/CVE-2018-8789.patch new file mode 100644 index 0000000..9ffa5db --- /dev/null +++ b/CVE-2018-8789.patch @@ -0,0 +1,107 @@ +From 2ee663f39dc8dac3d9988e847db19b2d7e3ac8c6 Mon Sep 17 00:00:00 2001 +From: Armin Novak +Date: Mon, 22 Oct 2018 16:00:03 +0200 +Subject: [PATCH] Fixed CVE-2018-8789 + +Thanks to Eyal Itkin from Check Point Software Technologies. +--- + winpr/libwinpr/sspi/NTLM/ntlm_message.c | 24 +++++++++++++----------- + 1 file changed, 13 insertions(+), 11 deletions(-) + +diff --git a/winpr/libwinpr/sspi/NTLM/ntlm_message.c b/winpr/libwinpr/sspi/NTLM/ntlm_message.c +index d785604976..ab42dc7377 100644 +--- a/winpr/libwinpr/sspi/NTLM/ntlm_message.c ++++ b/winpr/libwinpr/sspi/NTLM/ntlm_message.c +@@ -74,7 +74,7 @@ static const char* const NTLM_NEGOTIATE_STRINGS[] = + "NTLMSSP_NEGOTIATE_UNICODE" + }; + +-void ntlm_print_negotiate_flags(UINT32 flags) ++static void ntlm_print_negotiate_flags(UINT32 flags) + { + int i; + const char* str; +@@ -90,7 +90,7 @@ void ntlm_print_negotiate_flags(UINT32 flags) + } + } + +-int ntlm_read_message_header(wStream* s, NTLM_MESSAGE_HEADER* header) ++static int ntlm_read_message_header(wStream* s, NTLM_MESSAGE_HEADER* header) + { + if (Stream_GetRemainingLength(s) < 12) + return -1; +@@ -104,19 +104,19 @@ int ntlm_read_message_header(wStream* s, NTLM_MESSAGE_HEADER* header) + return 1; + } + +-void ntlm_write_message_header(wStream* s, NTLM_MESSAGE_HEADER* header) ++static void ntlm_write_message_header(wStream* s, NTLM_MESSAGE_HEADER* header) + { + Stream_Write(s, header->Signature, sizeof(NTLM_SIGNATURE)); + Stream_Write_UINT32(s, header->MessageType); + } + +-void ntlm_populate_message_header(NTLM_MESSAGE_HEADER* header, UINT32 MessageType) ++static void ntlm_populate_message_header(NTLM_MESSAGE_HEADER* header, UINT32 MessageType) + { + CopyMemory(header->Signature, NTLM_SIGNATURE, sizeof(NTLM_SIGNATURE)); + header->MessageType = MessageType; + } + +-int ntlm_read_message_fields(wStream* s, NTLM_MESSAGE_FIELDS* fields) ++static int ntlm_read_message_fields(wStream* s, NTLM_MESSAGE_FIELDS* fields) + { + if (Stream_GetRemainingLength(s) < 8) + return -1; +@@ -127,7 +127,7 @@ int ntlm_read_message_fields(wStream* s, NTLM_MESSAGE_FIELDS* fields) + return 1; + } + +-void ntlm_write_message_fields(wStream* s, NTLM_MESSAGE_FIELDS* fields) ++static void ntlm_write_message_fields(wStream* s, NTLM_MESSAGE_FIELDS* fields) + { + if (fields->MaxLen < 1) + fields->MaxLen = fields->Len; +@@ -137,11 +137,13 @@ void ntlm_write_message_fields(wStream* s, NTLM_MESSAGE_FIELDS* fields) + Stream_Write_UINT32(s, fields->BufferOffset); /* BufferOffset (4 bytes) */ + } + +-int ntlm_read_message_fields_buffer(wStream* s, NTLM_MESSAGE_FIELDS* fields) ++static int ntlm_read_message_fields_buffer(wStream* s, NTLM_MESSAGE_FIELDS* fields) + { + if (fields->Len > 0) + { +- if ((fields->BufferOffset + fields->Len) > Stream_Length(s)) ++ const UINT64 offset = (UINT64)fields->BufferOffset + (UINT64)fields->Len; ++ ++ if (offset > Stream_Length(s)) + return -1; + + fields->Buffer = (PBYTE) malloc(fields->Len); +@@ -156,7 +158,7 @@ int ntlm_read_message_fields_buffer(wStream* s, NTLM_MESSAGE_FIELDS* fields) + return 1; + } + +-void ntlm_write_message_fields_buffer(wStream* s, NTLM_MESSAGE_FIELDS* fields) ++static void ntlm_write_message_fields_buffer(wStream* s, NTLM_MESSAGE_FIELDS* fields) + { + if (fields->Len > 0) + { +@@ -165,7 +167,7 @@ void ntlm_write_message_fields_buffer(wStream* s, NTLM_MESSAGE_FIELDS* fields) + } + } + +-void ntlm_free_message_fields_buffer(NTLM_MESSAGE_FIELDS* fields) ++static void ntlm_free_message_fields_buffer(NTLM_MESSAGE_FIELDS* fields) + { + if (fields) + { +@@ -180,7 +182,7 @@ void ntlm_free_message_fields_buffer(NTLM_MESSAGE_FIELDS* fields) + } + } + +-void ntlm_print_message_fields(NTLM_MESSAGE_FIELDS* fields, const char* name) ++static void ntlm_print_message_fields(NTLM_MESSAGE_FIELDS* fields, const char* name) + { + WLog_DBG(TAG, "%s (Len: %"PRIu16" MaxLen: %"PRIu16" BufferOffset: %"PRIu32")", + name, fields->Len, fields->MaxLen, fields->BufferOffset); diff --git a/freerdp.spec b/freerdp.spec index 89425fc..3adcc0b 100644 --- a/freerdp.spec +++ b/freerdp.spec @@ -72,7 +72,6 @@ Man pages and other related help documents for freerdp. find . -name "*.h" -exec chmod 664 {} \; find . -name "*.c" -exec chmod 664 {} \; - %build %cmake %{?_cmake_skip_rpath} \ -DCMAKE_INSTALL_LIBDIR:PATH=%{_lib} -DWITH_ALSA=ON -DWITH_CUPS=ON -DWITH_CHANNELS=ON \ @@ -83,7 +82,14 @@ find . -name "*.c" -exec chmod 664 {} \; -DWITH_OPENSSL=ON -DWITH_PCSC=ON -DWITH_PULSE=ON -DWITH_SERVER=ON -DWITH_SERVER_INTERFACE=ON \ -DWITH_SHADOW_X11=ON -DWITH_SHADOW_MAC=ON -DWITH_WAYLAND=ON -DWITH_X11=ON \ -DWITH_X264=OFF -DWITH_XCURSOR=ON -DWITH_XEXT=ON \ - -DWITH_XKBFILE=ON -DWITH_XI=ON -DWITH_X + -DWITH_XKBFILE=ON -DWITH_XI=ON -DWITH_XINERAMA=ON -DWITH_XRENDER=ON -DWITH_XTEST=OFF \ + -DWITH_XV=ON -DWITH_ZLIB=ON \ +%ifarch x86_64 + -DWITH_SSE2=ON \ +%else + -DWITH_SSE2=OFF \ +%endif + . %make_build cd winpr/tools/makecert-cli @@ -120,7 +126,7 @@ find %{buildroot} -name "*.a" -delete %files -n libwinpr %{!?_licensedir:%global license %%doc} -%license LICENSE:q!:q +%license LICENSE %doc README ChangeLog %{_libdir}/{libwinpr2.so.*,libwinpr-tools2.so.*} -- Gitee