new file mode 100644
@@ -0,0 +1,319 @@
+From 2bbed980cf8cf9066d96e9aa29afcedc540ee47c Mon Sep 17 00:00:00 2001
+From: Armin Novak <armin.novak@thincast.com>
+Date: Mon, 28 Aug 2023 09:06:42 +0200
+Subject: [PATCH] fix index checks
+
+properly verify all offsets while decoding data.
+
+(cherry picked from commit 880285c332a1d98334fd8fa4b06c10fba0fb6959)
+
+CVE: CVE-2023-40589
+Upstream-Status: Backport [https://github.com/FreeRDP/FreeRDP/commit/c659973bb4cd65c065f2fe1a807dbc6805c684c6]
+Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com>
+---
+ libfreerdp/codec/ncrush.c | 137 ++++++++++++++++++++++++++++++--------
+ 1 file changed, 108 insertions(+), 29 deletions(-)
+
+diff --git a/libfreerdp/codec/ncrush.c b/libfreerdp/codec/ncrush.c
+index 3d6a216d3..c1d622a9c 100644
+--- a/libfreerdp/codec/ncrush.c
++++ b/libfreerdp/codec/ncrush.c
+@@ -1994,15 +1994,9 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY
+ UINT32* pDstSize, UINT32 flags)
+ {
+ UINT32 index;
+- UINT32 bits;
+- INT32 nbits;
+- const BYTE* SrcPtr;
+- const BYTE* SrcEnd;
+- UINT16 Mask;
+ BYTE Literal;
+ UINT32 IndexLEC;
+ UINT32 BitLength;
+- UINT32 MaskedBits;
+ UINT32 CopyOffset;
+ UINT32 CopyLength;
+ UINT32 OldCopyOffset;
+@@ -2010,9 +2004,6 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY
+ UINT32 LengthOfMatch;
+ UINT32 CopyOffsetIndex;
+ UINT32 OffsetCacheIndex;
+- BYTE* HistoryPtr;
+- BYTE* HistoryBuffer;
+- BYTE* HistoryBufferEnd;
+ UINT32 CopyOffsetBits;
+ UINT32 CopyOffsetBase;
+ UINT32 LengthOfMatchBits;
+@@ -2021,8 +2012,8 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY
+ if (ncrush->HistoryEndOffset != 65535)
+ return -1001;
+
+- HistoryBuffer = ncrush->HistoryBuffer;
+- HistoryBufferEnd = &HistoryBuffer[ncrush->HistoryEndOffset];
++ BYTE* HistoryBuffer = ncrush->HistoryBuffer;
++ const BYTE* HistoryBufferEnd = &HistoryBuffer[ncrush->HistoryEndOffset];
+
+ if (flags & PACKET_AT_FRONT)
+ {
+@@ -2041,7 +2032,7 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY
+ ZeroMemory(&(ncrush->OffsetCache), sizeof(ncrush->OffsetCache));
+ }
+
+- HistoryPtr = ncrush->HistoryPtr;
++ BYTE* HistoryPtr = ncrush->HistoryPtr;
+
+ if (!(flags & PACKET_COMPRESSED))
+ {
+@@ -2050,17 +2041,19 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY
+ return 1;
+ }
+
+- SrcEnd = &pSrcData[SrcSize];
+- nbits = 32;
+- bits = get_dword(pSrcData);
+- SrcPtr = pSrcData + 4;
++ const BYTE* SrcEnd = &pSrcData[SrcSize];
++ const BYTE* SrcPtr = pSrcData + 4;
+
++ INT32 nbits = 32;
++ UINT32 bits = get_dword(pSrcData);
+ while (1)
+ {
+ while (1)
+ {
+- Mask = get_word(&HuffTableMask[29]);
+- MaskedBits = bits & Mask;
++ const UINT16 Mask = get_word(&HuffTableMask[29]);
++ const UINT32 MaskedBits = bits & Mask;
++ if (MaskedBits >= ARRAYSIZE(HuffTableLEC))
++ return -1;
+ IndexLEC = HuffTableLEC[MaskedBits] & 0xFFF;
+ BitLength = HuffTableLEC[MaskedBits] >> 12;
+ bits >>= BitLength;
+@@ -2096,8 +2089,10 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY
+ return -1004;
+
+ CopyOffset = ncrush->OffsetCache[OffsetCacheIndex];
+- Mask = get_word(&HuffTableMask[21]);
+- MaskedBits = bits & Mask;
++ const UINT16 Mask = get_word(&HuffTableMask[21]);
++ const UINT32 MaskedBits = bits & Mask;
++ if (MaskedBits > ARRAYSIZE(HuffTableLOM))
++ return -1;
+ LengthOfMatch = HuffTableLOM[MaskedBits] & 0xFFF;
+ BitLength = HuffTableLOM[MaskedBits] >> 12;
+ bits >>= BitLength;
+@@ -2106,13 +2101,23 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY
+ if (!NCrushFetchBits(&SrcPtr, &SrcEnd, &nbits, &bits))
+ return -1;
+
++ if (LengthOfMatch >= ARRAYSIZE(LOMBitsLUT))
++ return -1;
++
+ LengthOfMatchBits = LOMBitsLUT[LengthOfMatch];
++
++ if (LengthOfMatch >= ARRAYSIZE(LOMBaseLUT))
++ return -1;
+ LengthOfMatchBase = LOMBaseLUT[LengthOfMatch];
+
+ if (LengthOfMatchBits)
+ {
+- Mask = get_word(&HuffTableMask[(2 * LengthOfMatchBits) + 3]);
+- MaskedBits = bits & Mask;
++ const size_t idx = (2ull * LengthOfMatchBits) + 3ull;
++ if (idx >= ARRAYSIZE(HuffTableMask))
++ return -1;
++
++ const UINT16 Mask = get_word(&HuffTableMask[idx]);
++ const UINT32 MaskedBits = bits & Mask;
+ bits >>= LengthOfMatchBits;
+ nbits -= LengthOfMatchBits;
+ LengthOfMatchBase += MaskedBits;
+@@ -2127,15 +2132,28 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY
+ }
+ else
+ {
++ if (CopyOffsetIndex >= ARRAYSIZE(CopyOffsetBitsLUT))
++ return -1;
++
+ CopyOffsetBits = CopyOffsetBitsLUT[CopyOffsetIndex];
++
++ if (CopyOffsetIndex >= ARRAYSIZE(CopyOffsetBaseLUT))
++ return -1;
+ CopyOffsetBase = CopyOffsetBaseLUT[CopyOffsetIndex];
+ CopyOffset = CopyOffsetBase - 1;
+
+ if (CopyOffsetBits)
+ {
+- Mask = get_word(&HuffTableMask[(2 * CopyOffsetBits) + 3]);
+- MaskedBits = bits & Mask;
+- CopyOffset = CopyOffsetBase + MaskedBits - 1;
++ const size_t idx = (2ull * CopyOffsetBits) + 3ull;
++ if (idx >= ARRAYSIZE(HuffTableMask))
++ return -1;
++
++ const UINT16 Mask = get_word(&HuffTableMask[idx]);
++ const UINT32 MaskedBits = bits & Mask;
++ const UINT32 tmp = CopyOffsetBase + MaskedBits;
++ if (tmp < 1)
++ return -1;
++ CopyOffset = tmp - 1;
+ bits >>= CopyOffsetBits;
+ nbits -= CopyOffsetBits;
+
+@@ -2143,8 +2161,11 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY
+ return -1;
+ }
+
+- Mask = get_word(&HuffTableMask[21]);
+- MaskedBits = bits & Mask;
++ const UINT16 Mask = get_word(&HuffTableMask[21]);
++ const UINT32 MaskedBits = bits & Mask;
++ if (MaskedBits >= ARRAYSIZE(HuffTableLOM))
++ return -1;
++
+ LengthOfMatch = HuffTableLOM[MaskedBits] & 0xFFF;
+ BitLength = HuffTableLOM[MaskedBits] >> 12;
+ bits >>= BitLength;
+@@ -2153,13 +2174,23 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY
+ if (!NCrushFetchBits(&SrcPtr, &SrcEnd, &nbits, &bits))
+ return -1;
+
++ if (LengthOfMatch >= ARRAYSIZE(LOMBitsLUT))
++ return -1;
++
+ LengthOfMatchBits = LOMBitsLUT[LengthOfMatch];
++
++ if (LengthOfMatch >= ARRAYSIZE(LOMBaseLUT))
++ return -1;
+ LengthOfMatchBase = LOMBaseLUT[LengthOfMatch];
+
+ if (LengthOfMatchBits)
+ {
+- Mask = get_word(&HuffTableMask[(2 * LengthOfMatchBits) + 3]);
+- MaskedBits = bits & Mask;
++ const size_t idx = (2ull * LengthOfMatchBits) + 3ull;
++ if (idx >= ARRAYSIZE(HuffTableMask))
++ return -1;
++
++ const UINT16 Mask = get_word(&HuffTableMask[idx]);
++ const UINT32 MaskedBits = bits & Mask;
+ bits >>= LengthOfMatchBits;
+ nbits -= LengthOfMatchBits;
+ LengthOfMatchBase += MaskedBits;
+@@ -2583,7 +2614,12 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE
+ }
+
+ IndexLEC = Literal;
++ if (IndexLEC >= ARRAYSIZE(HuffLengthLEC))
++ return -1;
+ BitLength = HuffLengthLEC[IndexLEC];
++
++ if (IndexLEC * 2ull >= ARRAYSIZE(HuffCodeLEC))
++ return -1;
+ CodeLEC = get_word(&HuffCodeLEC[IndexLEC * 2]);
+
+ if (BitLength > 15)
+@@ -2666,9 +2702,18 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE
+ bits = CopyOffset;
+
+ CopyOffsetIndex = ncrush->HuffTableCopyOffset[bits + 2];
++
++ if (CopyOffsetIndex >= ARRAYSIZE(CopyOffsetBitsLUT))
++ return -1;
++
+ CopyOffsetBits = CopyOffsetBitsLUT[CopyOffsetIndex];
+ IndexLEC = 257 + CopyOffsetIndex;
++ if (IndexLEC >= ARRAYSIZE(HuffLengthLEC))
++ return -1;
+ BitLength = HuffLengthLEC[IndexLEC];
++
++ if (IndexLEC * 2ull >= ARRAYSIZE(HuffCodeLEC))
++ return -1;
+ CodeLEC = get_word(&HuffCodeLEC[IndexLEC * 2]);
+
+ if (BitLength > 15)
+@@ -2687,13 +2732,23 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE
+ else
+ IndexCO = ncrush->HuffTableLOM[MatchLength];
+
++ if (IndexCO >= ARRAYSIZE(HuffLengthLOM))
++ return -1;
+ BitLength = HuffLengthLOM[IndexCO];
++
++ if (IndexCO >= ARRAYSIZE(LOMBitsLUT))
++ return -1;
+ IndexLOM = LOMBitsLUT[IndexCO];
++
++ if (IndexCO >= ARRAYSIZE(HuffCodeLOM))
++ return -1;
+ NCrushWriteBits(&DstPtr, &accumulator, &offset, HuffCodeLOM[IndexCO], BitLength);
+ Mask = ((1 << IndexLOM) - 1);
+ MaskedBits = (MatchLength - 2) & Mask;
+ NCrushWriteBits(&DstPtr, &accumulator, &offset, MaskedBits, IndexLOM);
+
++ if (IndexCO >= ARRAYSIZE(LOMBaseLUT))
++ return -1;
+ if ((MaskedBits + LOMBaseLUT[IndexCO]) != MatchLength)
+ return -1010;
+ }
+@@ -2701,7 +2756,11 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE
+ {
+ /* CopyOffset in OffsetCache */
+ IndexLEC = 289 + OffsetCacheIndex;
++ if (IndexLEC >= ARRAYSIZE(HuffLengthLEC))
++ return -1;
+ BitLength = HuffLengthLEC[IndexLEC];
++ if (IndexLEC * 2ull >= ARRAYSIZE(HuffCodeLEC))
++ return -1;
+ CodeLEC = get_word(&HuffCodeLEC[IndexLEC * 2]);
+
+ if (BitLength >= 15)
+@@ -2714,13 +2773,24 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE
+ else
+ IndexCO = ncrush->HuffTableLOM[MatchLength];
+
++ if (IndexCO >= ARRAYSIZE(HuffLengthLOM))
++ return -1;
++
+ BitLength = HuffLengthLOM[IndexCO];
++
++ if (IndexCO >= ARRAYSIZE(LOMBitsLUT))
++ return -1;
+ IndexLOM = LOMBitsLUT[IndexCO];
++
++ if (IndexCO >= ARRAYSIZE(HuffCodeLOM))
++ return -1;
+ NCrushWriteBits(&DstPtr, &accumulator, &offset, HuffCodeLOM[IndexCO], BitLength);
+ Mask = ((1 << IndexLOM) - 1);
+ MaskedBits = (MatchLength - 2) & Mask;
+ NCrushWriteBits(&DstPtr, &accumulator, &offset, MaskedBits, IndexLOM);
+
++ if (IndexCO >= ARRAYSIZE(LOMBaseLUT))
++ return -1;
+ if ((MaskedBits + LOMBaseLUT[IndexCO]) != MatchLength)
+ return -1012;
+ }
+@@ -2745,6 +2815,10 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE
+ Literal = *SrcPtr++;
+ HistoryPtr++;
+ IndexLEC = Literal;
++ if (IndexLEC >= ARRAYSIZE(HuffLengthLEC))
++ return -1;
++ if (IndexLEC * 2ull >= ARRAYSIZE(HuffCodeLEC))
++ return -1;
+ BitLength = HuffLengthLEC[IndexLEC];
+ CodeLEC = get_word(&HuffCodeLEC[IndexLEC * 2]);
+
+@@ -2817,6 +2891,11 @@ static int ncrush_generate_tables(NCRUSH_CONTEXT* context)
+ else
+ i = context->HuffTableLOM[k];
+
++ if (i >= ARRAYSIZE(LOMBitsLUT))
++ return -1;
++ if (i >= ARRAYSIZE(LOMBaseLUT))
++ return -1;
++
+ if (((((1 << LOMBitsLUT[i]) - 1) & (k - 2)) + LOMBaseLUT[i]) != k)
+ return -1;
+ }
@@ -30,6 +30,7 @@ SRC_URI = "git://github.com/FreeRDP/FreeRDP.git;branch=stable-2.0;protocol=https
file://CVE-2023-39353.patch \
file://CVE-2023-40181.patch \
file://CVE-2023-40569.patch \
+ file://CVE-2023-40589.patch \
"
S = "${WORKDIR}/git"
Details: https://nvd.nist.gov/vuln/detail/CVE-2023-40589 Pick the patch that was identified[1] by Debian to solve the issue on the 2.x branch. [1]: https://security-tracker.debian.org/tracker/CVE-2023-40589 Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com> --- .../freerdp/freerdp/CVE-2023-40589.patch | 319 ++++++++++++++++++ .../recipes-support/freerdp/freerdp_2.6.1.bb | 1 + 2 files changed, 320 insertions(+) create mode 100644 meta-oe/recipes-support/freerdp/freerdp/CVE-2023-40589.patch