Compare commits

...

49 Commits

Author SHA1 Message Date
Tobias Frost
a62ef46b9b Fix typo found post upload. 2023-11-17 18:38:48 +01:00
Tobias Frost
528ad1ee7f Prepare changelog for upload. 2023-11-17 17:29:55 +01:00
Tobias Frost
9c2cb890eb Import fix for CVE-2022-39283 - closes also #1021659 2023-11-12 13:08:09 +01:00
Tobias Frost
1cddd4643a Import fix for CVE-2022-39282 (Closes: #1021659) 2023-11-12 12:44:19 +01:00
Tobias Frost
ad925990b3 Fix changelog date. 2023-11-12 12:24:32 +01:00
Tobias Frost
cb0fee7d81 Prepare changelog for upload to LTS. 2023-11-12 12:23:35 +01:00
Tobias Frost
343a6e9965 Fixing whitespaces in d/changelog and a typo in a patch. 2023-11-12 12:08:01 +01:00
Tobias Frost
180fc8f332 fix 0052-CVE-2022-24883.patch -- it stopped applying after dropping patch 0051. 2023-10-29 14:23:10 +01:00
Tobias Frost
326341043d Drop patch for CVE-2022-24882
the patch does not work with 2.3.0, needs more investiagion.
2023-10-29 14:22:13 +01:00
Tobias Frost
b7fad42bde CVE-2022-41877 - Missing input length validation in drive channel 2023-10-29 00:12:43 +02:00
Tobias Frost
eb2c3e598e CVE-2022-39347 - Missing path sanitation with drive channel 2023-10-28 23:26:25 +02:00
Tobias Frost
ae332a9e65 CVE-2022-39319 - Missing length validation in urbdrc channel 2023-10-29 10:45:28 +01:00
Tobias Frost
9abf5f033b Import fix for CVE-2022-39318 - Division by zero in urbdrc channel 2023-10-29 10:14:56 +01:00
Tobias Frost
56d1291988 Import fix for CVE-2022-39316 - Out of bound read in zgfx decoder 2023-10-29 10:12:55 +01:00
Tobias Frost
3f665697f0 Import fix for CVE-2022-24883 - FreeRDP Server authentication might allow invalid credentials to pass. 2023-10-29 10:09:48 +01:00
Tobias Frost
a8d9578fb9 Import fix for CVE-2022-24882 - Server side NTLM does not properly check parameters. 2023-10-28 20:16:13 +02:00
Tobias Frost
14442af9ac Import fix for CVE-2021-41160 - Improper region checks in all clients allow out of bound write to memory (Closes: #1001062) 2023-10-28 18:36:39 +02:00
Tobias Frost
8f234906e9 Fix wrong number CVE changelog entry. 2023-10-07 20:03:39 +02:00
Tobias Frost
6ebfab5ec1 Prepare changelog for upload. 2023-10-07 17:31:07 +02:00
Tobias Frost
bb305bcdf7 Fix segfault in CVE-2023-39355.patch
(and use posix_memalign instead of memalign)
2023-10-07 17:08:05 +02:00
Tobias Frost
f1641af0fd Touch changelog timestamp. 2023-10-07 13:29:57 +02:00
Tobias Frost
b743b819c0 CVE-2023-40589 2023-10-07 13:29:15 +02:00
Tobias Frost
d9179e0766 CVE-2023-40569 2023-10-07 13:27:15 +02:00
Tobias Frost
24c51f4ed8 CVE-2023-40188.patch 2023-10-07 13:17:33 +02:00
Tobias Frost
f6f2bf7896 CVE-2023-40186 2023-10-07 13:11:23 +02:00
Tobias Frost
0f3fd7d339 0045-CVE-2023-40181.patch 2023-10-07 12:53:23 +02:00
Tobias Frost
d1217c6dad Apply upstream patch for CVE-2023-40567. 2023-10-07 12:53:18 +02:00
Tobias Frost
09055cabae Backport upstream patch for CVE-2023-39356. 2023-10-07 12:33:20 +02:00
Tobias Frost
ab18013d96 Backport CVE-2023-39354. 2023-10-07 12:07:10 +02:00
Tobias Frost
2dacc519e5 Backport patch for CVE-2023-39353. 2023-10-07 11:28:59 +02:00
Tobias Frost
792f6a14d1 Backport patch for CVE-2023-39352. 2023-10-07 11:10:12 +02:00
Tobias Frost
a4c483bc30 Cherry-pick upstream patch for CVE-2023-39351. 2023-10-07 10:58:09 +02:00
Tobias Frost
43cbb16760 Revisit CVE-2023-39350 after updates/clarifactions from upstream. 2023-10-07 10:51:05 +02:00
Tobias Frost
500b4499a7 Backport CVE-2023-40589.
replaced WINPR_ASSERT with plain assert, as this macro is defined only in later versions and if verbose asserting is disabled it will actually do assert() itself.
2023-10-03 11:14:37 +02:00
Tobias Frost
6ae95183f4 Backport of CVE-2023-39355
upstream is using in later version aligned memory allocation, so using memaling to simulate that.
That of course required to memset it afterwards, as upstream used calloc for the allocation before.
2023-10-03 10:57:01 +02:00
Tobias Frost
21305b53c4 Disable piuparts and blhc
piuparts is broken for buster
blhc is failing, but not going to fix that for the DLA.
2023-10-03 10:15:50 +02:00
Tobias Frost
efc916e1a4 CVE-2023-39354 2023-10-03 10:08:48 +02:00
Tobias Frost
b6e609f697 CVE-2023-39350 2023-10-03 10:07:13 +02:00
Tobias Frost
0333c99067 Enable Salsa CI 2023-10-03 09:35:54 +02:00
Tobias Frost
6e4db706a5 Debian release 2.3.0+dfsg1-2+deb11u1
-----BEGIN PGP SIGNATURE-----
 
 iQJVBAABCAA/FiEEm/uu6GwKpf+/IgeCmvRrMCV3GzEFAmInCfghHG1pa2UuZ2Fi
 cmllbEBkYXMtbmV0endlcmt0ZWFtLmRlAAoJEJr0azAldxsxnVsP/iCyxT55ot9U
 DP/mn1sY4R10wEu306RiSHYpIHdhoI5zmpwywq936DC/J7WUebZD0PZfANv5lioX
 VwoJSVXUhsvk67VTR77zFsTwU66E4mtvruh6rP0SO6ooRRbqQedVFsZAAMbugHAL
 3bMPMbJ1jklWsIui/x3ggmEQ5wy8c1kOIttn8PXmo/h4P3cOuuHDSJM1y0BpoqIs
 P7MsK3TTycobUg1sgrtrj/rKrIeqiS3NRZQ0VSiHunSCQdPYPm5CChSaVsgyAenC
 VmnU5+pLSgBYunMh7OFUQCgdBQzKnUIZ9BSxc3ybRnW5hqREpdcwMZ8Nf8oLluEw
 1FYSaqNKpfP0CkwkjWO0qPXiWIoqZIhGC1xA5SivNf2poWkmhhwLH+PXZFHCmlFc
 ba8iFrG9gt4tSM45mVbpJTHbNTHjwsQpbHB+V9zyWt5VC5zsdzsIn1Kxl8obGdvD
 JN+3oo9yTrVw4Mh5fmN52aRtmrd/QVeJKTBv8zN9L7LFi/8Bwb5P7lsqlArNOpQi
 oL1xt6Uv2nHowCteue75DKEt3Q7hxKUrZFtjTPjbuv2ZJk2TSJ27rv9RQ4dhj7hO
 RCDg2sa/AMnyrj0pK9wtaRpUrhAuKEHRfs+8n39z2aqi6CMbMM3p3P8DB2bjhpcc
 v1IXrs60cxRvsg1zhL2bhk1KCAVJrkZc
 =01RW
 -----END PGP SIGNATURE-----

Merge tag 'debian/2.3.0+dfsg1-2+deb11u1' into debian/buster to prepare a
backport for buster.

Debian release 2.3.0+dfsg1-2+deb11u1

Adapt to buster.
2023-10-03 01:16:50 +02:00
Mike Gabriel
0359d79a4b upload to bullseye (debian/2.3.0+dfsg1-2+deb11u1) 2022-03-08 08:46:53 +01:00
Mike Gabriel
6dd3e7854d debian/patches: Trivial rebase of 1001_keep-symbol-DumpThreadHandles-if-debugging-is-disabled.patch against v2.3.0. 2022-03-08 08:45:25 +01:00
Mike Gabriel
03201de47f debian/patches: Add 1001_keep-symbol-DumpThreadHandles-if-debugging-is-disabled.patch. Keep DumpThreadHandles as a symbol even if WITH_DEBUG_THREADS is OFF.
(cherry picked from commit f726052dd4)
2022-03-08 08:44:42 +01:00
Bernhard Miklautz
4db4aa6d33 debian/rules: Disable additional debug logging. (Closes: #1006683).
(cherry picked from commit a90b67e6c0)
2022-03-08 08:15:32 +01:00
Mike Gabriel
0553695929 upload to buster (debian/2.0.0~git20190204.1.2693389a+dfsg1-1+deb10u2) 2020-06-01 13:13:06 +02:00
Mike Gabriel
bdab8340a1 debian/patches: Add 0002_fix-channels-smartcard-fix-statusw-call.patch. Fix smartcard login failures. (Closes: #919281). 2020-06-01 13:05:53 +02:00
Bernhard Miklautz
163efd4c7d debian/patches: add security related patches from upstream
Back ported patches of multiple security issues were added.
Including the following CVEs:
*  CVE-2020-11521
*  CVE-2020-11522
*  CVE-2020-11523
*  CVE-2020-11524
*  CVE-2020-11525
*  CVE-2020-11526
2020-06-01 13:02:33 +02:00
Mike Gabriel
85341458bc upload to buster (debian/2.0.0~git20190204.1.2693389a+dfsg1-1+deb10u1) 2019-12-18 22:59:52 +01:00
Mike Gabriel
c6fe442da0 debian/patches: Add 0001_CVE-2019-17177.patch. Fix realloc return handling. (CVE-2019-17177). 2019-12-16 11:35:50 +01:00
51 changed files with 6134 additions and 4 deletions

10
debian/.gitlab-ci.yml vendored Normal file
View File

@ -0,0 +1,10 @@
include:
- https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/recipes/debian.yml
variables:
RELEASE: 'buster'
SALSA_CI_COMPONENTS: 'main contrib non-free'
SALSA_CI_DISABLE_REPROTEST: 1
SALSA_CI_DISABLE_LINTIAN: 1
SALSA_CI_DISABLE_BLHC: 1
SALSA_CI_DISABLE_PIUPARTS: 1

106
debian/changelog vendored
View File

@ -1,3 +1,65 @@
freerdp2 (2.3.0+dfsg1-2+deb10u5) UNRELEASED; urgency=medium
* Fix typo in CVE number in last upload. (CVE 2022-39283 instead
of 2023-29283)
-- Tobias Frost <tobi@debian.org> Fri, 17 Nov 2023 18:37:16 +0100
freerdp2 (2.3.0+dfsg1-2+deb10u4) buster-security; urgency=medium
* Non-maintainer upload by the LTS Security Team.
* Import fix for CVE-2021-41160 - Improper region checks in all clients
allow out of bound write to memory (Closes: #1001062)
* Import fix for CVE-2022-24883 - FreeRDP Server authentication might allow
invalid credentials to pass.
* Import fix for (see #1024511)
- CVE-2022-39316 - Out of bound read in zgfx decoder and
- CVE-2022-39318 - Division by zero in urbdrc channel
- CVE-2022-39319 - Missing length validation in urbdrc channel
- CVE-2022-39347 - Missing path sanitation with `drive` channel
- CVE-2022-41877 - Missing input length validation in `drive` channel
* Import fix for CVE-2022-39282 and CVE-2022-39283 (Closes: #1021659)
* Previous upload had a typo in the CVE list: It was CVE 2023-40567 not
CVE 2023-39357; fixing changelog entry.
-- Tobias Frost <tobi@debian.org> Fri, 17 Nov 2023 17:29:31 +0100
freerdp2 (2.3.0+dfsg1-2+deb10u3) buster-security; urgency=medium
* Non-maintainer for the LTS security team.
* Backport upstream version 2.3.0 from bullseye to buster.
This adresses:
CVE-2020-4030 CVE-2020-4031 CVE-2020-4032
CVE-2020-4033 CVE-2020-11017 CVE-2020-11018 CVE-2020-11019
CVE-2020-11038 CVE-2020-11039 CVE-2020-11040 CVE-2020-11041
CVE-2020-11042 CVE-2020-11043 CVE-2020-11044 CVE-2020-11045
CVE-2020-11046 CVE-2020-11047 CVE-2020-11048 CVE-2020-11049
CVE-2020-11058 CVE-2020-11085 CVE-2020-11086 CVE-2020-11087
CVE-2020-11088 CVE-2020-11089 CVE-2020-11095 CVE-2020-11096
CVE-2020-11097 CVE-2020-11098 CVE-2020-11099 CVE-2020-13396
CVE-2020-13397 CVE-2020-13398 and
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-39355 CVE-2023-39356 CVE-2023-40567
CVE-2023-40181 CVE-2023-40186 CVE-2023-40188 CVE-2023-40569
CVE-2023-40589
-- Tobias Frost <tobi@debian.org> Sat, 07 Oct 2023 17:11:57 +0200
freerdp2 (2.3.0+dfsg1-2+deb11u1) bullseye; urgency=medium
[ Bernhard Miklautz ]
* debian/rules:
+ Disable additional debug logging. (Closes: #1006683).
[ Mike Gabriel ]
* debian/patches:
+ Add 1001_keep-symbol-DumpThreadHandles-if-debugging-is-disabled.patch.
Keep DumpThreadHandles as a symbol even if WITH_DEBUG_THREADS is OFF.
-- Mike Gabriel <sunweaver@debian.org> Tue, 08 Mar 2022 08:45:48 +0100
freerdp2 (2.3.0+dfsg1-2) unstable; urgency=medium
* debian/watch:
@ -165,6 +227,50 @@ freerdp2 (2.0.0~git20190204.1.2693389a+dfsg1-2) unstable; urgency=medium
-- Mike Gabriel <sunweaver@debian.org> Mon, 16 Dec 2019 11:25:24 +0100
freerdp2 (2.0.0~git20190204.1.2693389a+dfsg1-1+deb10u2) buster; urgency=medium
[ Bernhard Miklautz ]
* debian/patches - security releated backports from upstream
* Add 0003-Fixed-6007-Boundary-checks-in-rdp_read_flow_control.patch
* Add 0004-Fixed-6009-Bounds-checks-in-autodetect_recv_bandwidt.patch
* Add 0005-Fixed-6006-bounds-checks-in-update_read_synchronize.patch
* Add 0006-Fixed-6005-Bounds-checks-in-update_read_bitmap_data.patch
* Add 0007-Fixed-6011-Bounds-check-in-rdp_read_font_capability.patch
* Add 0008-Fixed-6013-Check-new-length-is-0.patch
* Add 0009-Fix-6010-Check-length-in-read_icon_info.patch
* Add 0010-Use-substreams-to-parse-gcc_read_server_data_blocks.patch
* Add 0011-Fixed-Stream_-macros-bracing-arguments.patch
* Add 0012-Use-safe-seek-for-capability-parsing.patch
* Add 0013-Fixed-CVE-2020-11525-Out-of-bounds-read-in-bitmap_ca.patch
(CVE-2020-11525).
* Add 0014-Fixed-6012-CVE-2020-11526-Out-of-bounds-read-in-upda.patch
(CVE-2020-11526).
* Add 0015-Fix-CVE-2020-11523-clamp-invalid-rectangles-to-size-.patch
(CVE-2020-11523).
* Add 0016-Fix-CVE-2020-11524-out-of-bounds-access-in-interleav.patch
(CVE-2020-11524).
* Add 0017-Fixed-CVE-2020-11522-Limit-number-of-DELTA_RECT-to-4.patch
(CVE-2020-11522).
* Add 0018-Fixed-CVE-2020-11521-Out-of-bounds-write-in-planar-c.patch
(CVE-2020-11521).
* Add 0019-Fixed-possible-NULL-access.patch
* Add 0020-Check-for-int-overflow-in-gdi_InvalidateRegion.patch
[ Mike Gabriel ]
* debian/patches:
+ Add 0002_fix-channels-smartcard-fix-statusw-call.patch. Fix smartcard
login failures. (Closes: #919281).
-- Mike Gabriel <sunweaver@debian.org> Mon, 01 Jun 2020 13:08:46 +0200
freerdp2 (2.0.0~git20190204.1.2693389a+dfsg1-1+deb10u1) buster; urgency=medium
* debian/patches:
+ Add 0001_CVE-2019-17177.patch. Fix realloc return handling.
(CVE-2019-17177).
-- Mike Gabriel <sunweaver@debian.org> Mon, 16 Dec 2019 11:36:02 +0100
freerdp2 (2.0.0~git20190204.1.2693389a+dfsg1-1) unstable; urgency=medium
* Import Git snapshot for 2.0.0-2693389a (post ~rc4) from upstream:

7
debian/control vendored
View File

@ -6,14 +6,16 @@ Uploaders:
Mike Gabriel <sunweaver@debian.org>,
Bernhard Miklautz <bernhard.miklautz@shacknet.at>,
Build-Depends:
debhelper-compat (= 13),
cmake,
debhelper-compat (= 12),
docbook-xsl,
dpkg-dev (>= 1.16.1.1),
libasound2-dev,
libavcodec-dev,
libavutil-dev,
libcairo2-dev,
libcups2-dev,
libdbus-glib-1-dev,
libgsm1-dev,
libgstreamer1.0-dev,
libgstreamer-plugins-base1.0-dev,
@ -45,8 +47,7 @@ Build-Depends:
uuid-dev,
xmlto,
xsltproc,
Standards-Version: 4.5.1
Rules-Requires-Root: no
Standards-Version: 4.3.0
Homepage: https://www.freerdp.com/
Vcs-Browser: https://salsa.debian.org/debian-remote-team/freerdp2
Vcs-Git: https://salsa.debian.org/debian-remote-team/freerdp2.git

171
debian/patches/0001_CVE-2019-17177.patch vendored Normal file
View File

@ -0,0 +1,171 @@
From fc80ab45621bd966f70594c0b7393ec005a94007 Mon Sep 17 00:00:00 2001
From: Armin Novak <armin.novak@thincast.com>
Date: Fri, 4 Oct 2019 14:49:30 +0200
Subject: [PATCH] Fixed #5645: realloc return handling
---
client/X11/generate_argument_docbook.c | 33 +++++++++++++++++++++-----
libfreerdp/codec/region.c | 20 ++++++++++++----
winpr/libwinpr/utils/lodepng/lodepng.c | 6 ++++-
3 files changed, 48 insertions(+), 11 deletions(-)
--- a/client/X11/generate_argument_docbook.c
+++ b/client/X11/generate_argument_docbook.c
@@ -9,6 +9,7 @@
LPSTR tr_esc_str(LPCSTR arg, bool format)
{
LPSTR tmp = NULL;
+ LPSTR tmp2 = NULL;
size_t cs = 0, x, ds, len;
size_t s;
@@ -25,7 +26,12 @@
ds = s + 1;
if (s)
- tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
+ {
+ tmp2 = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
+ if (!tmp2)
+ free(tmp);
+ tmp = tmp2;
+ }
if (NULL == tmp)
{
@@ -43,7 +49,10 @@
case '<':
len = format ? 13 : 4;
ds += len - 1;
- tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
+ tmp2 = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
+ if (!tmp2)
+ free(tmp);
+ tmp = tmp2;
if (NULL == tmp)
{
@@ -64,7 +73,10 @@
case '>':
len = format ? 14 : 4;
ds += len - 1;
- tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
+ tmp2 = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
+ if (!tmp2)
+ free(tmp);
+ tmp = tmp2;
if (NULL == tmp)
{
@@ -84,7 +96,10 @@
case '\'':
ds += 5;
- tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
+ tmp2 = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
+ if (!tmp2)
+ free(tmp);
+ tmp = tmp2;
if (NULL == tmp)
{
@@ -102,7 +117,10 @@
case '"':
ds += 5;
- tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
+ tmp2 = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
+ if (!tmp2)
+ free(tmp);
+ tmp = tmp2;
if (NULL == tmp)
{
@@ -120,7 +138,10 @@
case '&':
ds += 4;
- tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
+ tmp2 = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
+ if (!tmp2)
+ free(tmp);
+ tmp = tmp2;
if (NULL == tmp)
{
--- a/libfreerdp/codec/region.c
+++ b/libfreerdp/codec/region.c
@@ -469,8 +469,12 @@
if (finalNbRects != nbRects)
{
- int allocSize = sizeof(REGION16_DATA) + (finalNbRects * sizeof(RECTANGLE_16));
- region->data = realloc(region->data, allocSize);
+ REGION16_DATA* data;
+ size_t allocSize = sizeof(REGION16_DATA) + (finalNbRects * sizeof(RECTANGLE_16));
+ data = realloc(region->data, allocSize);
+ if (!data)
+ free(region->data);
+ region->data = data;
if (!region->data)
{
@@ -487,6 +491,7 @@
BOOL region16_union_rect(REGION16* dst, const REGION16* src, const RECTANGLE_16* rect)
{
+ REGION16_DATA* data;
const RECTANGLE_16* srcExtents;
RECTANGLE_16* dstExtents;
const RECTANGLE_16* currentBand, *endSrcRect, *nextBand;
@@ -675,7 +680,10 @@
dstExtents->bottom = MAX(rect->bottom, srcExtents->bottom);
dstExtents->right = MAX(rect->right, srcExtents->right);
newItems->size = sizeof(REGION16_DATA) + (usedRects * sizeof(RECTANGLE_16));
- dst->data = realloc(newItems, newItems->size);
+ data = realloc(newItems, newItems->size);
+ if (!data)
+ free(dst->data);
+ dst->data = data;
if (!dst->data)
{
@@ -719,6 +727,7 @@
BOOL region16_intersect_rect(REGION16* dst, const REGION16* src, const RECTANGLE_16* rect)
{
+ REGION16_DATA* data;
REGION16_DATA* newItems;
const RECTANGLE_16* srcPtr, *endPtr, *srcExtents;
RECTANGLE_16* dstPtr;
@@ -791,7 +800,10 @@
if (dst->data->size)
free(dst->data);
- dst->data = realloc(newItems, newItems->size);
+ data = realloc(newItems, newItems->size);
+ if (!data)
+ free(dst->data);
+ dst->data = data;
if (!dst->data)
{
--- a/winpr/libwinpr/utils/lodepng/lodepng.c
+++ b/winpr/libwinpr/utils/lodepng/lodepng.c
@@ -840,11 +840,15 @@
static unsigned HuffmanTree_makeFromFrequencies(HuffmanTree* tree, const unsigned* frequencies,
size_t mincodes, size_t numcodes, unsigned maxbitlen)
{
+ unsigned* lengths;
unsigned error = 0;
while(!frequencies[numcodes - 1] && numcodes > mincodes) numcodes--; /*trim zeroes*/
tree->maxbitlen = maxbitlen;
tree->numcodes = (unsigned)numcodes; /*number of symbols*/
- tree->lengths = (unsigned*)realloc(tree->lengths, numcodes * sizeof(unsigned));
+ lengths = (unsigned*)realloc(tree->lengths, numcodes * sizeof(unsigned));
+ if (!lengths)
+ free(tree->lengths);
+ tree->lengths = lengths;
if(!tree->lengths) return 83; /*alloc fail*/
/*initialize all lengths to 0*/
memset(tree->lengths, 0, numcodes * sizeof(unsigned));

View File

@ -0,0 +1,46 @@
From a311075202865d22b87ec2ea8d1e32fa11868012 Mon Sep 17 00:00:00 2001
From: Bernhard Miklautz <bernhard.miklautz@thincast.com>
Date: Wed, 10 Jul 2019 18:36:34 +0200
Subject: [PATCH] fix [channels/smartcard]: fix StatusW_Call
According to 2.2.2.18 Status_Call cbAtrLen is unused an must be ignored
upon receipt.
---
channels/smartcard/client/smartcard_operations.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
--- a/channels/smartcard/client/smartcard_operations.c
+++ b/channels/smartcard/client/smartcard_operations.c
@@ -1204,15 +1204,19 @@
Status_Call* call = operation->call;
DWORD cbAtrLen;
- if (call->cbAtrLen > 32)
- call->cbAtrLen = 32;
+ /**
+ * [MS-RDPESC]
+ * According to 2.2.2.18 Status_Call cbAtrLen is unused an must be ignored upon receipt.
+ */
+ cbAtrLen = call->cbAtrLen = 32;
+
+ call->cchReaderLen;
if (call->fmszReaderNamesIsNULL)
cchReaderLen = 0;
else
cchReaderLen = SCARD_AUTOALLOCATE;
- cbAtrLen = call->cbAtrLen;
ZeroMemory(ret.pbAtr, 32);
status = ret.ReturnCode = SCardStatusW(operation->hCard,
call->fmszReaderNamesIsNULL ? NULL : (LPWSTR) &mszReaderNames,
@@ -1231,8 +1235,7 @@
ret.cBytes = cchReaderLen;
#endif
- if (call->cbAtrLen)
- ret.cbAtrLen = cbAtrLen;
+ ret.cbAtrLen = cbAtrLen;
}
smartcard_trace_status_return(smartcard, &ret, TRUE);

View File

@ -0,0 +1,81 @@
--- a/libfreerdp/core/rdp.c
+++ b/libfreerdp/core/rdp.c
@@ -110,29 +110,33 @@ void rdp_write_security_header(wStream* s, UINT16 flags)
BOOL rdp_read_share_control_header(wStream* s, UINT16* length, UINT16* type, UINT16* channel_id)
{
+ UINT16 len;
if (Stream_GetRemainingLength(s) < 2)
return FALSE;
/* Share Control Header */
- Stream_Read_UINT16(s, *length); /* totalLength */
+ Stream_Read_UINT16(s, len); /* totalLength */
+
+ *length = len;
/* If length is 0x8000 then we actually got a flow control PDU that we should ignore
http://msdn.microsoft.com/en-us/library/cc240576.aspx */
- if (*length == 0x8000)
+ if (len == 0x8000)
{
- rdp_read_flow_control_pdu(s, type);
+ if (!rdp_read_flow_control_pdu(s, type))
+ return FALSE;
*channel_id = 0;
*length = 8; /* Flow control PDU is 8 bytes */
return TRUE;
}
- if (((size_t) *length - 2) > Stream_GetRemainingLength(s))
+ if ((len < 4) || ((len - 2) > Stream_GetRemainingLength(s)))
return FALSE;
Stream_Read_UINT16(s, *type); /* pduType */
*type &= 0x0F; /* type is in the 4 least significant bits */
- if (*length > 4)
+ if (len > 4)
Stream_Read_UINT16(s, *channel_id); /* pduSource */
else
*channel_id = 0; /* Windows XP can send such short DEACTIVATE_ALL PDUs. */
@@ -1088,7 +1092,7 @@ int rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s)
}
}
-void rdp_read_flow_control_pdu(wStream* s, UINT16* type)
+BOOL rdp_read_flow_control_pdu(wStream* s, UINT16* type)
{
/*
* Read flow control PDU - documented in FlowPDU section in T.128
@@ -1098,12 +1102,17 @@ void rdp_read_flow_control_pdu(wStream* s, UINT16* type)
* Switched the order of these two fields to match this observation.
*/
UINT8 pduType;
+ if (!type)
+ return FALSE;
+ if (Stream_GetRemainingLength(s) < 6)
+ return FALSE;
Stream_Read_UINT8(s, pduType); /* pduTypeFlow */
*type = pduType;
Stream_Seek_UINT8(s); /* pad8bits */
Stream_Seek_UINT8(s); /* flowIdentifier */
Stream_Seek_UINT8(s); /* flowNumber */
Stream_Seek_UINT16(s); /* pduSource */
+ return TRUE;
}
/**
diff --git a/libfreerdp/core/rdp.h b/libfreerdp/core/rdp.h
index 9df6c0a..24d062d 100644
--- a/libfreerdp/core/rdp.h
+++ b/libfreerdp/core/rdp.h
@@ -221,7 +221,7 @@ FREERDP_LOCAL int rdp_recv_message_channel_pdu(rdpRdp* rdp, wStream* s,
FREERDP_LOCAL int rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s);
-FREERDP_LOCAL void rdp_read_flow_control_pdu(wStream* s, UINT16* type);
+FREERDP_LOCAL BOOL rdp_read_flow_control_pdu(wStream* s, UINT16* type);
FREERDP_LOCAL BOOL rdp_write_monitor_layout_pdu(wStream* s, UINT32 monitorCount,
const rdpMonitor* monitorDefArray);

View File

@ -0,0 +1,11 @@
--- a/libfreerdp/core/autodetect.c
+++ b/libfreerdp/core/autodetect.c
@@ -454,6 +454,8 @@ static BOOL autodetect_recv_bandwidth_measure_results(rdpRdp* rdp, wStream* s,
return FALSE;
WLog_VRB(AUTODETECT_TAG, "received Bandwidth Measure Results PDU");
+ if (Stream_GetRemainingLength(s) < 8)
+ return -1;
Stream_Read_UINT32(s, rdp->autodetect->bandwidthMeasureTimeDelta); /* timeDelta (4 bytes) */
Stream_Read_UINT32(s, rdp->autodetect->bandwidthMeasureByteCount); /* byteCount (4 bytes) */

View File

@ -0,0 +1,28 @@
--- a/libfreerdp/core/update.c
+++ b/libfreerdp/core/update.c
@@ -292,13 +292,13 @@ fail:
return NULL;
}
-static void update_read_synchronize(rdpUpdate* update, wStream* s)
+static BOOL update_read_synchronize(rdpUpdate* update, wStream* s)
{
- Stream_Seek_UINT16(s); /* pad2Octets (2 bytes) */
/**
* The Synchronize Update is an artifact from the
* T.128 protocol and should be ignored.
*/
+ return Stream_SafeSeek(s, 2); /* pad2Octets (2 bytes) */
}
static BOOL update_read_play_sound(wStream* s, PLAY_SOUND_UPDATE* play_sound)
@@ -676,7 +676,8 @@ BOOL update_recv(rdpUpdate* update, wStream* s)
break;
case UPDATE_TYPE_SYNCHRONIZE:
- update_read_synchronize(update, s);
+ if (!update_read_synchronize(update, s))
+ return FALSE;
rc = IFCALLRESULT(TRUE, update->Synchronize, context);
break;

View File

@ -0,0 +1,12 @@
--- a/libfreerdp/core/update.c
+++ b/libfreerdp/core/update.c
@@ -109,6 +109,9 @@ static BOOL update_read_bitmap_data(rdpUpdate* update, wStream* s,
{
if (!(bitmapData->flags & NO_BITMAP_COMPRESSION_HDR))
{
+ if (Stream_GetRemainingLength(s) < 8)
+ return FALSE;
+
Stream_Read_UINT16(s,
bitmapData->cbCompFirstRowSize); /* cbCompFirstRowSize (2 bytes) */
Stream_Read_UINT16(s,

View File

@ -0,0 +1,16 @@
--- a/libfreerdp/core/capabilities.c
+++ b/libfreerdp/core/capabilities.c
@@ -1379,10 +1379,10 @@ static BOOL rdp_print_input_capability_set(wStream* s, UINT16 length)
static BOOL rdp_read_font_capability_set(wStream* s, UINT16 length,
rdpSettings* settings)
{
- if (length > 4)
+ if (length > 5)
Stream_Seek_UINT16(s); /* fontSupportFlags (2 bytes) */
- if (length > 6)
+ if (length > 7)
Stream_Seek_UINT16(s); /* pad2Octets (2 bytes) */
return TRUE;

View File

@ -0,0 +1,11 @@
--- a/libfreerdp/core/orders.c
+++ b/libfreerdp/core/orders.c
@@ -2237,7 +2237,7 @@ static CACHE_BITMAP_V3_ORDER* update_read_cache_bitmap_v3_order(rdpUpdate* updat
Stream_Read_UINT16(s, bitmapData->height); /* height (2 bytes) */
Stream_Read_UINT32(s, new_len); /* length (4 bytes) */
- if (Stream_GetRemainingLength(s) < new_len)
+ if ((new_len == 0) || (Stream_GetRemainingLength(s) < new_len))
goto fail;
new_data = (BYTE*) realloc(bitmapData->data, new_len);

View File

@ -0,0 +1,43 @@
--- a/libfreerdp/core/window.c
+++ b/libfreerdp/core/window.c
@@ -110,9 +110,6 @@ static BOOL update_read_icon_info(wStream* s, ICON_INFO* iconInfo)
Stream_Read_UINT16(s, iconInfo->cbBitsMask); /* cbBitsMask (2 bytes) */
Stream_Read_UINT16(s, iconInfo->cbBitsColor); /* cbBitsColor (2 bytes) */
- if (Stream_GetRemainingLength(s) < iconInfo->cbBitsMask + iconInfo->cbBitsColor)
- return FALSE;
-
/* bitsMask */
newBitMask = (BYTE*) realloc(iconInfo->bitsMask, iconInfo->cbBitsMask);
@@ -124,6 +121,8 @@ static BOOL update_read_icon_info(wStream* s, ICON_INFO* iconInfo)
}
iconInfo->bitsMask = newBitMask;
+ if (Stream_GetRemainingLength(s) < iconInfo->cbBitsMask)
+ return FALSE;
Stream_Read(s, iconInfo->bitsMask, iconInfo->cbBitsMask);
/* colorTable */
@@ -158,7 +157,11 @@ static BOOL update_read_icon_info(wStream* s, ICON_INFO* iconInfo)
}
if (iconInfo->colorTable)
+ {
+ if (Stream_GetRemainingLength(s) < iconInfo->cbColorTable)
+ return FALSE;
Stream_Read(s, iconInfo->colorTable, iconInfo->cbColorTable);
+ }
/* bitsColor */
newBitMask = (BYTE*)realloc(iconInfo->bitsColor, iconInfo->cbBitsColor);
@@ -171,6 +174,8 @@ static BOOL update_read_icon_info(wStream* s, ICON_INFO* iconInfo)
}
iconInfo->bitsColor = newBitMask;
+ if (Stream_GetRemainingLength(s) < iconInfo->cbBitsColor)
+ return FALSE;
Stream_Read(s, iconInfo->bitsColor, iconInfo->cbBitsColor);
return TRUE;
}

View File

@ -0,0 +1,94 @@
--- a/libfreerdp/core/gcc.c
+++ b/libfreerdp/core/gcc.c
@@ -494,18 +494,27 @@ BOOL gcc_read_server_data_blocks(wStream* s, rdpMcs* mcs, int length)
while (offset < length)
{
- holdp = Stream_Pointer(s);
+ size_t rest;
+ wStream sub;
if (!gcc_read_user_data_header(s, &type, &blockLength))
{
WLog_ERR(TAG, "gcc_read_server_data_blocks: gcc_read_user_data_header failed");
return FALSE;
}
+ holdp = Stream_Pointer(s);
+ Stream_StaticInit(&sub, holdp, blockLength - 4);
+ if (!Stream_SafeSeek(s, blockLength - 4))
+ {
+ WLog_ERR(TAG, "gcc_read_server_data_blocks: stream too short");
+ return FALSE;
+ }
+ offset += blockLength;
switch (type)
{
case SC_CORE:
- if (!gcc_read_server_core_data(s, mcs))
+ if (!gcc_read_server_core_data(&sub, mcs))
{
WLog_ERR(TAG, "gcc_read_server_data_blocks: gcc_read_server_core_data failed");
return FALSE;
@@ -514,7 +523,7 @@ BOOL gcc_read_server_data_blocks(wStream* s, rdpMcs* mcs, int length)
break;
case SC_SECURITY:
- if (!gcc_read_server_security_data(s, mcs))
+ if (!gcc_read_server_security_data(&sub, mcs))
{
WLog_ERR(TAG,
"gcc_read_server_data_blocks: gcc_read_server_security_data failed");
@@ -524,7 +533,7 @@ BOOL gcc_read_server_data_blocks(wStream* s, rdpMcs* mcs, int length)
break;
case SC_NET:
- if (!gcc_read_server_network_data(s, mcs))
+ if (!gcc_read_server_network_data(&sub, mcs))
{
WLog_ERR(TAG,
"gcc_read_server_data_blocks: gcc_read_server_network_data failed");
@@ -534,7 +543,7 @@ BOOL gcc_read_server_data_blocks(wStream* s, rdpMcs* mcs, int length)
break;
case SC_MCS_MSGCHANNEL:
- if (!gcc_read_server_message_channel_data(s, mcs))
+ if (!gcc_read_server_message_channel_data(&sub, mcs))
{
WLog_ERR(TAG,
"gcc_read_server_data_blocks: gcc_read_server_message_channel_data failed");
@@ -544,7 +553,7 @@ BOOL gcc_read_server_data_blocks(wStream* s, rdpMcs* mcs, int length)
break;
case SC_MULTITRANSPORT:
- if (!gcc_read_server_multitransport_channel_data(s, mcs))
+ if (!gcc_read_server_multitransport_channel_data(&sub, mcs))
{
WLog_ERR(TAG,
"gcc_read_server_data_blocks: gcc_read_server_multitransport_channel_data failed");
@@ -558,8 +567,13 @@ BOOL gcc_read_server_data_blocks(wStream* s, rdpMcs* mcs, int length)
break;
}
- offset += blockLength;
- Stream_SetPointer(s, holdp + blockLength);
+ rest = Stream_GetRemainingLength(&sub);
+ if (rest > 0)
+ {
+ WLog_WARN(
+ TAG, "gcc_read_server_data_blocks: ignoring %" PRIuz " bytes with type=%" PRIu16 "",
+ rest, type);
+ }
}
return TRUE;
@@ -583,7 +597,7 @@ BOOL gcc_read_user_data_header(wStream* s, UINT16* type, UINT16* length)
Stream_Read_UINT16(s, *type); /* type */
Stream_Read_UINT16(s, *length); /* length */
- if (Stream_GetRemainingLength(s) < (size_t)(*length - 4))
+ if ((*length < 4) || (Stream_GetRemainingLength(s) < (size_t)(*length - 4)))
return FALSE;
return TRUE;

View File

@ -0,0 +1,109 @@
--- a/winpr/include/winpr/stream.h
+++ b/winpr/include/winpr/stream.h
@@ -52,7 +52,7 @@ WINPR_API BOOL Stream_EnsureCapacity(wStream* s, size_t size);
WINPR_API BOOL Stream_EnsureRemainingCapacity(wStream* s, size_t size);
WINPR_API wStream* Stream_New(BYTE* buffer, size_t size);
-WINPR_API void Stream_StaticInit(wStream *s, BYTE *buffer, size_t size);
+WINPR_API void Stream_StaticInit(wStream* s, BYTE* buffer, size_t size);
WINPR_API void Stream_Free(wStream* s, BOOL bFreeBuffer);
static INLINE void Stream_Seek(wStream* s, size_t _offset)
@@ -66,60 +66,60 @@ static INLINE void Stream_Rewind(wStream* s, size_t _offset)
}
#define _stream_read_n8(_t, _s, _v, _p) do { \
- _v = \
- (_t)(*_s->pointer); \
+ (_v) = \
+ (_t)(*(_s)->pointer); \
if (_p) Stream_Seek(_s, sizeof(_t)); } while (0)
#define _stream_read_n16_le(_t, _s, _v, _p) do { \
- _v = \
- (_t)(*_s->pointer) + \
- (_t)(((_t)(*(_s->pointer + 1))) << 8); \
+ (_v) = \
+ (_t)(*(_s)->pointer) + \
+ (_t)(((_t)(*((_s)->pointer + 1))) << 8); \
if (_p) Stream_Seek(_s, sizeof(_t)); } while (0)
#define _stream_read_n16_be(_t, _s, _v, _p) do { \
- _v = \
- (_t)(((_t)(*_s->pointer)) << 8) + \
- (_t)(*(_s->pointer + 1)); \
+ (_v) = \
+ (_t)(((_t)(*(_s)->pointer)) << 8) + \
+ (_t)(*((_s)->pointer + 1)); \
if (_p) Stream_Seek(_s, sizeof(_t)); } while (0)
#define _stream_read_n32_le(_t, _s, _v, _p) do { \
- _v = \
- (_t)(*_s->pointer) + \
- (((_t)(*(_s->pointer + 1))) << 8) + \
- (((_t)(*(_s->pointer + 2))) << 16) + \
- (((_t)(*(_s->pointer + 3))) << 24); \
+ (_v) = \
+ (_t)(*(_s)->pointer) + \
+ (((_t)(*((_s)->pointer + 1))) << 8) + \
+ (((_t)(*((_s)->pointer + 2))) << 16) + \
+ (((_t)(*((_s)->pointer + 3))) << 24); \
if (_p) Stream_Seek(_s, sizeof(_t)); } while (0)
#define _stream_read_n32_be(_t, _s, _v, _p) do { \
- _v = \
- (((_t)(*(_s->pointer))) << 24) + \
- (((_t)(*(_s->pointer + 1))) << 16) + \
- (((_t)(*(_s->pointer + 2))) << 8) + \
- (((_t)(*(_s->pointer + 3)))); \
+ (_v) = \
+ (((_t)(*((_s)->pointer))) << 24) + \
+ (((_t)(*((_s)->pointer + 1))) << 16) + \
+ (((_t)(*((_s)->pointer + 2))) << 8) + \
+ (((_t)(*((_s)->pointer + 3)))); \
if (_p) Stream_Seek(_s, sizeof(_t)); } while (0)
#define _stream_read_n64_le(_t, _s, _v, _p) do { \
- _v = \
- (_t)(*_s->pointer) + \
- (((_t)(*(_s->pointer + 1))) << 8) + \
- (((_t)(*(_s->pointer + 2))) << 16) + \
- (((_t)(*(_s->pointer + 3))) << 24) + \
- (((_t)(*(_s->pointer + 4))) << 32) + \
- (((_t)(*(_s->pointer + 5))) << 40) + \
- (((_t)(*(_s->pointer + 6))) << 48) + \
- (((_t)(*(_s->pointer + 7))) << 56); \
+ (_v) = \
+ (_t)(*(_s)->pointer) + \
+ (((_t)(*((_s)->pointer + 1))) << 8) + \
+ (((_t)(*((_s)->pointer + 2))) << 16) + \
+ (((_t)(*((_s)->pointer + 3))) << 24) + \
+ (((_t)(*((_s)->pointer + 4))) << 32) + \
+ (((_t)(*((_s)->pointer + 5))) << 40) + \
+ (((_t)(*((_s)->pointer + 6))) << 48) + \
+ (((_t)(*((_s)->pointer + 7))) << 56); \
if (_p) Stream_Seek(_s, sizeof(_t)); } while (0)
#define _stream_read_n64_be(_t, _s, _v, _p) do { \
- _v = \
- (((_t)(*(_s->pointer))) << 56) + \
- (((_t)(*(_s->pointer + 1))) << 48) + \
- (((_t)(*(_s->pointer + 2))) << 40) + \
- (((_t)(*(_s->pointer + 3))) << 32) + \
- (((_t)(*(_s->pointer + 4))) << 24) + \
- (((_t)(*(_s->pointer + 5))) << 16) + \
- (((_t)(*(_s->pointer + 6))) << 8) + \
- (((_t)(*(_s->pointer + 7)))); \
+ (_v) = \
+ (((_t)(*((_s)->pointer))) << 56) + \
+ (((_t)(*((_s)->pointer + 1))) << 48) + \
+ (((_t)(*((_s)->pointer + 2))) << 40) + \
+ (((_t)(*((_s)->pointer + 3))) << 32) + \
+ (((_t)(*((_s)->pointer + 4))) << 24) + \
+ (((_t)(*((_s)->pointer + 5))) << 16) + \
+ (((_t)(*((_s)->pointer + 6))) << 8) + \
+ (((_t)(*((_s)->pointer + 7)))); \
if (_p) Stream_Seek(_s, sizeof(_t)); } while (0)
#define Stream_Read_UINT8(_s, _v) _stream_read_n8(UINT8, _s, _v, TRUE)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,61 @@
--- a/libfreerdp/cache/bitmap.c
+++ b/libfreerdp/cache/bitmap.c
@@ -236,7 +236,7 @@ rdpBitmap* bitmap_cache_get(rdpBitmapCache* bitmapCache, UINT32 id,
{
rdpBitmap* bitmap;
- if (id > bitmapCache->maxCells)
+ if (id >= bitmapCache->maxCells)
{
WLog_ERR(TAG, "get invalid bitmap cell id: %"PRIu32"", id);
return NULL;
@@ -294,7 +294,7 @@ void bitmap_cache_register_callbacks(rdpUpdate* update)
rdpBitmapCache* bitmap_cache_new(rdpSettings* settings)
{
- int i;
+ UINT32 i;
rdpBitmapCache* bitmapCache;
bitmapCache = (rdpBitmapCache*) calloc(1, sizeof(rdpBitmapCache));
@@ -311,7 +311,7 @@ rdpBitmapCache* bitmap_cache_new(rdpSettings* settings)
if (!bitmapCache->cells)
goto fail;
- for (i = 0; i < (int) bitmapCache->maxCells; i++)
+ for (i = 0; i < bitmapCache->maxCells; i++)
{
bitmapCache->cells[i].number = settings->BitmapCacheV2CellInfo[i].numEntries;
/* allocate an extra entry for BITMAP_CACHE_WAITING_LIST_INDEX */
@@ -325,26 +325,20 @@ rdpBitmapCache* bitmap_cache_new(rdpSettings* settings)
return bitmapCache;
fail:
- if (bitmapCache->cells)
- {
- for (i = 0; i < (int) bitmapCache->maxCells; i++)
- free(bitmapCache->cells[i].entries);
- }
-
- free(bitmapCache);
+ bitmap_cache_free(bitmapCache);
return NULL;
}
void bitmap_cache_free(rdpBitmapCache* bitmapCache)
{
- int i, j;
+ UINT32 i, j;
rdpBitmap* bitmap;
if (bitmapCache)
{
- for (i = 0; i < (int) bitmapCache->maxCells; i++)
+ for (i = 0; i < bitmapCache->maxCells; i++)
{
- for (j = 0; j < (int) bitmapCache->cells[i].number + 1; j++)
+ for (j = 0; j < bitmapCache->cells[i].number + 1; j++)
{
bitmap = bitmapCache->cells[i].entries[j];
Bitmap_Free(bitmapCache->context, bitmap);

View File

@ -0,0 +1,19 @@
--- a/libfreerdp/core/orders.c
+++ b/libfreerdp/core/orders.c
@@ -3612,7 +3612,14 @@ static BOOL update_recv_secondary_order(rdpUpdate* update, wStream* s,
Stream_Read_UINT16(s, orderLength); /* orderLength (2 bytes) */
Stream_Read_UINT16(s, extraFlags); /* extraFlags (2 bytes) */
Stream_Read_UINT8(s, orderType); /* orderType (1 byte) */
- next = Stream_Pointer(s) + ((INT16) orderLength) + 7;
+ if (Stream_GetRemainingLength(s) < orderLength + 7)
+ {
+ WLog_Print(update->log, WLOG_ERROR, "Stream_GetRemainingLength(s) %" PRIuz " < %" PRIu16,
+ Stream_GetRemainingLength(s), orderLength + 7);
+ return FALSE;
+ }
+
+ next = Stream_Pointer(s) + orderLength + 7;
name = secondary_order_string(orderType);
WLog_Print(update->log, WLOG_DEBUG, "Secondary Drawing Order %s", name);

View File

@ -0,0 +1,214 @@
--- a/libfreerdp/gdi/region.c
+++ b/libfreerdp/gdi/region.c
@@ -37,6 +37,27 @@
#define TAG FREERDP_TAG("gdi.region")
+static char* gdi_rect_str(char* buffer, size_t size, const HGDI_RECT rect)
+{
+ _snprintf(buffer, size - 1,
+ "[top/left=%" PRId32 "x%" PRId32 "-bottom/right%" PRId32 "x%" PRId32 "]", rect->top,
+ rect->left, rect->bottom, rect->right);
+ if (size > 1)
+ buffer[size - 1] = '\0';
+
+ return buffer;
+}
+
+static char* gdi_regn_str(char* buffer, size_t size, const HGDI_RGN rgn)
+{
+ _snprintf(buffer, size - 1, "[%" PRId32 "x%" PRId32 "-%" PRId32 "x%" PRId32 "]", rgn->x, rgn->y,
+ rgn->w, rgn->h);
+ if (size > 1)
+ buffer[size - 1] = '\0';
+
+ return buffer;
+}
+
/**
* Create a region from rectangular coordinates.\n
* @msdn{dd183514}
@@ -50,7 +71,20 @@
HGDI_RGN gdi_CreateRectRgn(INT32 nLeftRect, INT32 nTopRect,
INT32 nRightRect, INT32 nBottomRect)
{
- HGDI_RGN hRgn = (HGDI_RGN) calloc(1, sizeof(GDI_RGN));
+ INT64 w, h;
+ HGDI_RGN hRgn;
+
+ w = nRightRect - nLeftRect + 1ll;
+ h = nBottomRect - nTopRect + 1ll;
+ if ((w < 0) || (h < 0) || (w > INT32_MAX) || (h > INT32_MAX))
+ {
+ WLog_ERR(TAG,
+ "Can not create region top/left=%" PRId32 "x%" PRId32 "-bottom/right=%" PRId32
+ "x%" PRId32,
+ nTopRect, nLeftRect, nBottomRect, nRightRect);
+ return NULL;
+ }
+ hRgn = (HGDI_RGN)calloc(1, sizeof(GDI_RGN));
if (!hRgn)
return NULL;
@@ -58,8 +92,8 @@ HGDI_RGN gdi_CreateRectRgn(INT32 nLeftRect, INT32 nTopRect,
hRgn->objectType = GDIOBJECT_REGION;
hRgn->x = nLeftRect;
hRgn->y = nTopRect;
- hRgn->w = nRightRect - nLeftRect + 1;
- hRgn->h = nBottomRect - nTopRect + 1;
+ hRgn->w = w;
+ hRgn->h = h;
hRgn->null = FALSE;
return hRgn;
}
@@ -97,10 +131,24 @@ HGDI_RECT gdi_CreateRect(INT32 xLeft, INT32 yTop,
INLINE void gdi_RectToRgn(HGDI_RECT rect, HGDI_RGN rgn)
{
+ INT64 w, h;
+ w = rect->right - rect->left + 1ll;
+ h = rect->bottom - rect->top + 1ll;
+
+ if ((w < 0) || (h < 0) || (w > INT32_MAX) || (h > INT32_MAX))
+ {
+ WLog_ERR(TAG,
+ "Can not create region top/left=%" PRId32 "x%" PRId32 "-bottom/right=%" PRId32
+ "x%" PRId32,
+ rect->top, rect->left, rect->bottom, rect->right);
+ w = 0;
+ h = 0;
+ }
+
rgn->x = rect->left;
rgn->y = rect->top;
- rgn->w = rect->right - rect->left + 1;
- rgn->h = rect->bottom - rect->top + 1;
+ rgn->w = w;
+ rgn->h = h;
}
/**
@@ -115,10 +163,24 @@ INLINE void gdi_RectToRgn(HGDI_RECT rect, HGDI_RGN rgn)
INLINE void gdi_CRectToRgn(INT32 left, INT32 top,
INT32 right, INT32 bottom, HGDI_RGN rgn)
{
+ INT64 w, h;
+ w = right - left + 1ll;
+ h = bottom - top + 1ll;
+
+ if ((w < 0) || (h < 0) || (w > INT32_MAX) || (h > INT32_MAX))
+ {
+ WLog_ERR(TAG,
+ "Can not create region top/left=%" PRId32 "x%" PRId32 "-bottom/right=%" PRId32
+ "x%" PRId32,
+ top, left, bottom, right);
+ w = 0;
+ h = 0;
+ }
+
rgn->x = left;
rgn->y = top;
- rgn->w = right - left + 1;
- rgn->h = bottom - top + 1;
+ rgn->w = w;
+ rgn->h = h;
}
/**
@@ -134,10 +196,29 @@ INLINE void gdi_RectToCRgn(const HGDI_RECT rect,
INT32* x, INT32* y,
INT32* w, INT32* h)
{
+ INT64 tmp;
*x = rect->left;
*y = rect->top;
- *w = rect->right - rect->left + 1;
- *h = rect->bottom - rect->top + 1;
+ tmp = rect->right - rect->left + 1;
+ if ((tmp < 0) || (tmp > INT32_MAX))
+ {
+ char buffer[256];
+ WLog_ERR(TAG, "[%s] rectangle invalid %s", __FUNCTION__,
+ gdi_rect_str(buffer, sizeof(buffer), rect));
+ *w = 0;
+ }
+ else
+ *w = tmp;
+ tmp = rect->bottom - rect->top + 1;
+ if ((tmp < 0) || (tmp > INT32_MAX))
+ {
+ char buffer[256];
+ WLog_ERR(TAG, "[%s] rectangle invalid %s", __FUNCTION__,
+ gdi_rect_str(buffer, sizeof(buffer), rect));
+ *h = 0;
+ }
+ else
+ *h = tmp;
}
/**
@@ -156,10 +237,24 @@ INLINE void gdi_CRectToCRgn(INT32 left, INT32 top, INT32 right,
INT32 bottom,
INT32* x, INT32* y, INT32* w, INT32* h)
{
+ INT64 wl, hl;
+ wl = right - left + 1ll;
+ hl = bottom - top + 1ll;
+
+ if ((wl < 0) || (hl < 0) || (wl > INT32_MAX) || (hl > INT32_MAX))
+ {
+ WLog_ERR(TAG,
+ "Can not create region top/left=%" PRId32 "x%" PRId32 "-bottom/right=%" PRId32
+ "x%" PRId32,
+ top, left, bottom, right);
+ w = 0;
+ h = 0;
+ }
+
*x = left;
*y = top;
- *w = right - left + 1;
- *h = bottom - top + 1;
+ *w = wl;
+ *h = hl;
}
/**
@@ -170,10 +265,21 @@ INLINE void gdi_CRectToCRgn(INT32 left, INT32 top, INT32 right,
INLINE void gdi_RgnToRect(HGDI_RGN rgn, HGDI_RECT rect)
{
+ INT64 r, b;
+ r = rgn->x + rgn->w - 1ll;
+ b = rgn->y + rgn->h - 1ll;
+
+ if ((r < INT32_MIN) || (r > INT32_MAX) || (b < INT32_MIN) || (b > INT32_MAX))
+ {
+ char buffer[256];
+ WLog_ERR(TAG, "Can not create region %s", gdi_regn_str(buffer, sizeof(buffer), rgn));
+ r = rgn->x;
+ b = rgn->y;
+ }
rect->left = rgn->x;
rect->top = rgn->y;
- rect->right = rgn->x + rgn->w - 1;
- rect->bottom = rgn->y + rgn->h - 1;
+ rect->right = r;
+ rect->bottom = b;
}
/**
@@ -225,6 +331,12 @@ INLINE void gdi_CRgnToRect(INT64 x, INT64 y, INT32 w, INT32 h,
INLINE void gdi_RgnToCRect(HGDI_RGN rgn, INT32* left, INT32* top,
INT32* right, INT32* bottom)
{
+ if ((rgn->w < 0) || (rgn->h < 0))
+ {
+ char buffer[256];
+ WLog_ERR(TAG, "Can not create region %s", gdi_regn_str(buffer, sizeof(buffer), rgn));
+ }
+
*left = rgn->x;
*top = rgn->y;
*right = rgn->x + rgn->w - 1;

View File

@ -0,0 +1,26 @@
--- a/libfreerdp/codec/include/bitmap.c
+++ b/libfreerdp/codec/include/bitmap.c
@@ -338,6 +338,9 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer,
case MEGA_MEGA_COLOR_IMAGE:
runLength = ExtractRunLength(code, pbSrc, &advance);
pbSrc = pbSrc + advance;
+ if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength))
+ return FALSE;
+
UNROLL(runLength,
{
SRCREADPIXEL(temp, pbSrc);
diff --git a/libfreerdp/codec/interleaved.c b/libfreerdp/codec/interleaved.c
index a3fe7dd..0d36e9b 100644
--- a/libfreerdp/codec/interleaved.c
+++ b/libfreerdp/codec/interleaved.c
@@ -215,7 +215,7 @@ static INLINE BOOL ensure_capacity(const BYTE* start, const BYTE* end, size_t si
{
const size_t available = (uintptr_t)end - (uintptr_t)start;
const BOOL rc = available >= size * base;
- return rc;
+ return rc && (start <= end);
}
static INLINE void write_pixel_8(BYTE* _buf, BYTE _pix)

View File

@ -0,0 +1,70 @@
--- a/libfreerdp/core/orders.c
+++ b/libfreerdp/core/orders.c
@@ -888,15 +888,19 @@ static INLINE BOOL update_write_brush(wStream* s, rdpBrush* brush,
return TRUE;
}
static INLINE BOOL update_read_delta_rects(wStream* s, DELTA_RECT* rectangles,
- UINT32 number)
+ UINT32 *nr)
{
+ UINT32 number = *nr;
UINT32 i;
BYTE flags = 0;
BYTE* zeroBits;
UINT32 zeroBitsSize;
if (number > 45)
- number = 45;
+ {
+ WLog_WARN(TAG, "Invalid number of delta rectangles %" PRIu32, number);
+ return FALSE;
+ }
zeroBitsSize = ((number + 1) / 2);
@@ -1293,7 +1297,7 @@ static BOOL update_read_multi_dstblt_order(wStream* s, const ORDER_INFO* orderIn
Stream_Read_UINT16(s, multi_dstblt->cbData);
return update_read_delta_rects(s, multi_dstblt->rectangles,
- multi_dstblt->numRectangles);
+ &multi_dstblt->numRectangles);
}
return TRUE;
@@ -1322,7 +1326,7 @@ static BOOL update_read_multi_patblt_order(wStream* s, const ORDER_INFO* orderIn
Stream_Read_UINT16(s, multi_patblt->cbData);
if (!update_read_delta_rects(s, multi_patblt->rectangles,
- multi_patblt->numRectangles))
+ &multi_patblt->numRectangles))
return FALSE;
}
@@ -1347,7 +1351,7 @@ static BOOL update_read_multi_scrblt_order(wStream* s, const ORDER_INFO* orderIn
Stream_Read_UINT16(s, multi_scrblt->cbData);
return update_read_delta_rects(s, multi_scrblt->rectangles,
- multi_scrblt->numRectangles);
+ &multi_scrblt->numRectangles);
}
return TRUE;
@@ -1401,7 +1405,7 @@ static BOOL update_read_multi_opaque_rect_order(wStream* s,
Stream_Read_UINT16(s, multi_opaque_rect->cbData);
return update_read_delta_rects(s, multi_opaque_rect->rectangles,
- multi_opaque_rect->numRectangles);
+ &multi_opaque_rect->numRectangles);
}
return TRUE;
@@ -1424,7 +1428,7 @@ static BOOL update_read_multi_draw_nine_grid_order(wStream* s,
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);
+ &multi_draw_nine_grid->nDeltaEntries);
}
return TRUE;

View File

@ -0,0 +1,77 @@
--- a/libfreerdp/codec/planar.c
+++ b/libfreerdp/codec/planar.c
@@ -42,10 +42,9 @@ static INLINE BYTE* freerdp_bitmap_planar_delta_encode_plane(
static INLINE INT32 planar_skip_plane_rle(const BYTE* pSrcData, UINT32 SrcSize,
UINT32 nWidth, UINT32 nHeight)
{
+ UINT32 used = 0;
UINT32 x, y;
BYTE controlByte;
- const BYTE* pRLE = pSrcData;
- const BYTE* pEnd = &pSrcData[SrcSize];
for (y = 0; y < nHeight; y++)
{
@@ -54,10 +53,10 @@ static INLINE INT32 planar_skip_plane_rle(const BYTE* pSrcData, UINT32 SrcSize,
int cRawBytes;
int nRunLength;
- if (pRLE >= pEnd)
+ if (used >= SrcSize)
return -1;
- controlByte = *pRLE++;
+ controlByte = pSrcData[used++];
nRunLength = PLANAR_CONTROL_BYTE_RUN_LENGTH(controlByte);
cRawBytes = PLANAR_CONTROL_BYTE_RAW_BYTES(controlByte);
@@ -72,19 +71,21 @@ static INLINE INT32 planar_skip_plane_rle(const BYTE* pSrcData, UINT32 SrcSize,
cRawBytes = 0;
}
- pRLE += cRawBytes;
+ used += cRawBytes;
x += cRawBytes;
x += nRunLength;
if (x > nWidth)
return -1;
- if (pRLE > pEnd)
+ if (used > SrcSize)
return -1;
}
}
- return (INT32)(pRLE - pSrcData);
+ if (used > INT32_MAX)
+ return -1;
+ return (INT32)used;
}
static INLINE INT32 planar_decompress_plane_rle(const BYTE* pSrcData, UINT32 SrcSize,
diff --git a/libfreerdp/core/orders.c b/libfreerdp/core/orders.c
index d004289..d4707ba 100644
--- a/libfreerdp/core/orders.c
+++ b/libfreerdp/core/orders.c
@@ -1965,6 +1965,9 @@ static CACHE_BITMAP_ORDER* update_read_cache_bitmap_order(rdpUpdate* update, wSt
}
}
+ if (cache_bitmap->bitmapLength == 0)
+ goto fail;
+
if (Stream_GetRemainingLength(s) < cache_bitmap->bitmapLength)
goto fail;
@@ -2099,6 +2102,9 @@ static CACHE_BITMAP_V2_ORDER* update_read_cache_bitmap_v2_order(rdpUpdate* updat
}
}
+ if (cache_bitmap_v2->bitmapLength == 0)
+ goto fail;
+
if (Stream_GetRemainingLength(s) < cache_bitmap_v2->bitmapLength)
goto fail;

View File

@ -0,0 +1,45 @@
--- a/libfreerdp/cache/bitmap.c
+++ b/libfreerdp/cache/bitmap.c
@@ -314,12 +314,13 @@ rdpBitmapCache* bitmap_cache_new(rdpSettings* settings)
for (i = 0; i < bitmapCache->maxCells; i++)
{
bitmapCache->cells[i].number = settings->BitmapCacheV2CellInfo[i].numEntries;
+ BITMAP_V2_CELL* cell = &bitmapCache->cells[i];
+ UINT32 nr = settings->BitmapCacheV2CellInfo[i].numEntries;
/* allocate an extra entry for BITMAP_CACHE_WAITING_LIST_INDEX */
- bitmapCache->cells[i].entries = (rdpBitmap**) calloc((
- bitmapCache->cells[i].number + 1), sizeof(rdpBitmap*));
-
- if (!bitmapCache->cells[i].entries)
+ cell->entries = (rdpBitmap**)calloc((nr + 1), sizeof(rdpBitmap*));
+ if (!cell->entries)
goto fail;
+ cell->number = nr;
}
return bitmapCache;
@@ -331,16 +332,18 @@ fail:
void bitmap_cache_free(rdpBitmapCache* bitmapCache)
{
- UINT32 i, j;
- rdpBitmap* bitmap;
-
if (bitmapCache)
{
+ UINT32 i;
for (i = 0; i < bitmapCache->maxCells; i++)
{
- for (j = 0; j < bitmapCache->cells[i].number + 1; j++)
+ UINT32 j;
+ BITMAP_V2_CELL* cell = &bitmapCache->cells[i];
+ if (!cell->entries)
+ continue;
+ for (j = 0; j < cell->number + 1; j++)
{
- bitmap = bitmapCache->cells[i].entries[j];
+ rdpBitmap* bitmap = cell->entries[j];
Bitmap_Free(bitmapCache->context, bitmap);
}

View File

@ -0,0 +1,16 @@
--- a/libfreerdp/gdi/region.c
+++ b/libfreerdp/gdi/region.c
@@ -553,9 +553,11 @@ INLINE BOOL gdi_InvalidateRegion(HGDI_DC hdc, INT32 x, INT32 y, INT32 w,
if ((hdc->hwnd->ninvalid + 1) > hdc->hwnd->count)
{
- int new_cnt;
+ size_t new_cnt;
HGDI_RGN new_rgn;
new_cnt = hdc->hwnd->count * 2;
+ if (new_cnt > UINT32_MAX)
+ return FALSE;
new_rgn = (HGDI_RGN) realloc(cinvalid, sizeof(GDI_RGN) * new_cnt);
if (!new_rgn)

View File

@ -0,0 +1,40 @@
Description: Upstream fix for CVE-2023-39350 - Global-Buffer-Overflow in ncrush_decompress
Origin: https://github.com/FreeRDP/FreeRDP/commit/7ece410ce5b5660b9191e1ccb6835158afa11822
Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-rrrv-3w42-pffh
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1051638
From 7ece410ce5b5660b9191e1ccb6835158afa11822 Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Fri, 4 Aug 2023 13:55:40 +0200
Subject: [PATCH] [codec,rfx] fix possible out of bound read
Allows malicious servers to crash FreeRDP based clients
reported by @pwn2carr
(cherry picked from commit a51952882f2eb3bbce6b69a7a4f9a54bf1dbb672)
---
libfreerdp/codec/rfx.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
--- a/libfreerdp/codec/rfx.c
+++ b/libfreerdp/codec/rfx.c
@@ -1106,8 +1106,18 @@
}
}
- Stream_StaticInit(&subStream, Stream_Pointer(s), blockLen - (6 + extraBlockLen));
- Stream_Seek(s, blockLen - (6 + extraBlockLen));
+ const size_t blockLenNoHeader = blockLen - 6;
+ if (blockLenNoHeader < extraBlockLen)
+ {
+ WLog_Print(context->priv->log, WLOG_ERROR,
+ "blockLen too small(%" PRIu32 "), must be >= 6 + %" PRIu16, blockLen,
+ extraBlockLen);
+ return FALSE;
+ }
+
+ const size_t subStreamLen = blockLenNoHeader - extraBlockLen;
+ Stream_StaticInit(&subStream, Stream_Pointer(s), subStreamLen);
+ Stream_Seek(s, subStreamLen);
switch (blockType)
{

View File

@ -0,0 +1,18 @@
Description: Upstream fix for CVE-2023-39351 - Null Pointer Dereference leading DOS in RemoteFX
Origin: https://github.com/FreeRDP/FreeRDP/commit/99e243cdbc31f66b5c917452c8fed3276e8bdcd5
Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-q9x9-cqjc-rgwq
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1051638
--- a/libfreerdp/codec/rfx.c
+++ b/libfreerdp/codec/rfx.c
@@ -1235,6 +1235,11 @@
region16_uninit(&clippingRects);
return TRUE;
}
+ else
+ {
+ rfx_message_free(context, message);
+ context->currentMessage.freeArray = TRUE;
+ }
return FALSE;
}

123
debian/patches/0038-CVE-2023-39352.patch vendored Normal file
View File

@ -0,0 +1,123 @@
Description: Upstream fix for CVE-2023-39352 - Invalid offset validation leading to Out Of Bound Write
Backport of upstream patch, redigining WINPR_ASSERT as this was introduced
in upstream codebase only.
Origin: https://github.com/FreeRDP/FreeRDP/commit/856ecaa463e963ecfebc9734423d69139e7b3916
Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-whwr-qcf2-2mvj
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1051638
From 856ecaa463e963ecfebc9734423d69139e7b3916 Mon Sep 17 00:00:00 2001
From: houchengqiu <houchengqiu@uniontech.com>
Date: Mon, 22 May 2023 16:03:54 +0800
Subject: [PATCH] [libfreerdp] add bound check in gdi_SolidFill
In Windows remote run vulnerabillities exe program, to create
Micorosoft::Windows::RDS::Graphics channel, case Remmina crash.
So, add bound check, limit the size of the requested rect, no larger than the surface data buffer.
(cherry picked from commit 6a63441e4ee8e2bf333361f5d24156a183b14ecd)
---
libfreerdp/gdi/gfx.c | 68 ++++++++++++++++++++++++++++----------------
1 file changed, 43 insertions(+), 25 deletions(-)
--- a/libfreerdp/gdi/gfx.c
+++ b/libfreerdp/gdi/gfx.c
@@ -29,6 +29,10 @@
#include <freerdp/gdi/gfx.h>
#include <freerdp/gdi/region.h>
+#include <assert.h>
+
+#define WINPR_ASSERT assert
+
#define TAG FREERDP_TAG("gdi")
static BOOL is_rect_valid(const RECTANGLE_16* rect, size_t width, size_t height)
@@ -1079,6 +1083,28 @@
return rc;
}
+static BOOL intersect_rect(const RECTANGLE_16* rect, const gdiGfxSurface* surface,
+ RECTANGLE_16* prect)
+{
+ WINPR_ASSERT(rect);
+ WINPR_ASSERT(surface);
+ WINPR_ASSERT(prect);
+
+ if (rect->left > rect->right)
+ return FALSE;
+ if (rect->left > surface->width)
+ return FALSE;
+ if (rect->top > rect->bottom)
+ return FALSE;
+ if (rect->top > surface->height)
+ return FALSE;
+ prect->left = rect->left;
+ prect->top = rect->top;
+ prect->right = MIN(rect->right, surface->width);
+ prect->bottom = MIN(rect->bottom, surface->height);
+ return TRUE;
+}
+
/**
* Function description
*
@@ -1087,40 +1113,36 @@
static UINT gdi_SolidFill(RdpgfxClientContext* context, const RDPGFX_SOLID_FILL_PDU* solidFill)
{
UINT status = ERROR_INTERNAL_ERROR;
- UINT16 index;
- UINT32 color;
- BYTE a, r, g, b;
- UINT32 nWidth, nHeight;
- RECTANGLE_16* rect;
- gdiGfxSurface* surface;
- RECTANGLE_16 invalidRect;
+ BYTE a = 0;
+ RECTANGLE_16 invalidRect = { 0 };
rdpGdi* gdi = (rdpGdi*)context->custom;
+
EnterCriticalSection(&context->mux);
- surface = (gdiGfxSurface*)context->GetSurfaceData(context, solidFill->surfaceId);
+
+ WINPR_ASSERT(context->GetSurfaceData);
+ gdiGfxSurface* surface = (gdiGfxSurface*)context->GetSurfaceData(context, solidFill->surfaceId);
if (!surface)
goto fail;
- b = solidFill->fillPixel.B;
- g = solidFill->fillPixel.G;
- r = solidFill->fillPixel.R;
- /* a = solidFill->fillPixel.XA;
- * Ignore alpha channel, this is a solid fill. */
+ const BYTE b = solidFill->fillPixel.B;
+ const BYTE g = solidFill->fillPixel.G;
+ const BYTE r = solidFill->fillPixel.R;
a = 0xFF;
- color = FreeRDPGetColor(surface->format, r, g, b, a);
+ const UINT32 color = FreeRDPGetColor(surface->format, r, g, b, a);
- for (index = 0; index < solidFill->fillRectCount; index++)
+ for (UINT16 index = 0; index < solidFill->fillRectCount; index++)
{
- rect = &(solidFill->fillRects[index]);
- nWidth = rect->right - rect->left;
- nHeight = rect->bottom - rect->top;
- invalidRect.left = rect->left;
- invalidRect.top = rect->top;
- invalidRect.right = rect->right;
- invalidRect.bottom = rect->bottom;
+ const RECTANGLE_16* rect = &(solidFill->fillRects[index]);
+
+ if (!intersect_rect(rect, surface, &invalidRect))
+ goto fail;
+
+ const UINT32 nWidth = invalidRect.right - invalidRect.left;
+ const UINT32 nHeight = invalidRect.bottom - invalidRect.top;
- if (!freerdp_image_fill(surface->data, surface->format, surface->scanline, rect->left,
- rect->top, nWidth, nHeight, color))
+ if (!freerdp_image_fill(surface->data, surface->format, surface->scanline, invalidRect.left,
+ invalidRect.top, nWidth, nHeight, color))
goto fail;
region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect);

View File

@ -0,0 +1,52 @@
Description: Upstream fix for CVE-2023-39353 - Missing offset validation leading to Out Of Bound Read
commit 1 of 2.
Origin: https://github.com/FreeRDP/FreeRDP/commit/efa0567c027239b901ccdc590b9e229e0111c68b
Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-hg53-9j9h-3c8f
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1051638
From efa0567c027239b901ccdc590b9e229e0111c68b Mon Sep 17 00:00:00 2001
From: Armin Novak <anovak@thincast.com>
Date: Sat, 5 Aug 2023 08:57:28 +0200
Subject: [PATCH] [coded,rfx] check indices are within range
reported by @pwn2carr
(cherry picked from commit 61e17f4707cee66ecaa7519073bae74ecf0a9af4)
---
libfreerdp/codec/rfx.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c
index 13d48c24f329..d7f0d8c65d25 100644
--- a/libfreerdp/codec/rfx.c
+++ b/libfreerdp/codec/rfx.c
@@ -936,6 +936,30 @@ static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa
Stream_Read_UINT8(&sub, tile->quantIdxY); /* quantIdxY (1 byte) */
Stream_Read_UINT8(&sub, tile->quantIdxCb); /* quantIdxCb (1 byte) */
Stream_Read_UINT8(&sub, tile->quantIdxCr); /* quantIdxCr (1 byte) */
+ if (tile->quantIdxY >= context->numQuant)
+ {
+ WLog_Print(context->priv->log, WLOG_ERROR,
+ "quantIdxY %" PRIu8 " >= numQuant %" PRIu8, tile->quantIdxY,
+ context->numQuant);
+ rc = FALSE;
+ break;
+ }
+ if (tile->quantIdxCb >= context->numQuant)
+ {
+ WLog_Print(context->priv->log, WLOG_ERROR,
+ "quantIdxCb %" PRIu8 " >= numQuant %" PRIu8, tile->quantIdxCb,
+ context->numQuant);
+ rc = FALSE;
+ break;
+ }
+ if (tile->quantIdxCr >= context->numQuant)
+ {
+ WLog_Print(context->priv->log, WLOG_ERROR,
+ "quantIdxCr %" PRIu8 " >= numQuant %" PRIu8, tile->quantIdxCr,
+ context->numQuant);
+ rc = FALSE;
+ break;
+
Stream_Read_UINT16(&sub, tile->xIdx); /* xIdx (2 bytes) */
Stream_Read_UINT16(&sub, tile->yIdx); /* yIdx (2 bytes) */
Stream_Read_UINT16(&sub, tile->YLen); /* YLen (2 bytes) */

View File

@ -0,0 +1,68 @@
Description: Upstream fix for CVE-2023-39353 - Missing offset validation leading to Out Of Bound Read
commit 2 of 2.
Origin: https://github.com/FreeRDP/FreeRDP/commit/9ed6d6baede27d5006e0e4c9bec8e506f695cb6a
Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-hg53-9j9h-3c8f
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1051638
From 9ed6d6baede27d5006e0e4c9bec8e506f695cb6a Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Tue, 22 Aug 2023 11:37:57 +0200
Subject: [PATCH] [codec,rfx] fix missing brace from broken backport
---
libfreerdp/codec/rfx.c | 43 ++++++++++++++++++++----------------------
1 file changed, 20 insertions(+), 23 deletions(-)
diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c
index d7f0d8c65d25..ccbc5afe44fa 100644
--- a/libfreerdp/codec/rfx.c
+++ b/libfreerdp/codec/rfx.c
@@ -937,29 +937,26 @@ static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa
Stream_Read_UINT8(&sub, tile->quantIdxCb); /* quantIdxCb (1 byte) */
Stream_Read_UINT8(&sub, tile->quantIdxCr); /* quantIdxCr (1 byte) */
if (tile->quantIdxY >= context->numQuant)
- {
- WLog_Print(context->priv->log, WLOG_ERROR,
- "quantIdxY %" PRIu8 " >= numQuant %" PRIu8, tile->quantIdxY,
- context->numQuant);
- rc = FALSE;
- break;
- }
- if (tile->quantIdxCb >= context->numQuant)
- {
- WLog_Print(context->priv->log, WLOG_ERROR,
- "quantIdxCb %" PRIu8 " >= numQuant %" PRIu8, tile->quantIdxCb,
- context->numQuant);
- rc = FALSE;
- break;
- }
- if (tile->quantIdxCr >= context->numQuant)
- {
- WLog_Print(context->priv->log, WLOG_ERROR,
- "quantIdxCr %" PRIu8 " >= numQuant %" PRIu8, tile->quantIdxCr,
- context->numQuant);
- rc = FALSE;
- break;
-
+ {
+ WLog_Print(context->priv->log, WLOG_ERROR, "quantIdxY %" PRIu8 " >= numQuant %" PRIu8,
+ tile->quantIdxY, context->numQuant);
+ rc = FALSE;
+ break;
+ }
+ else if (tile->quantIdxCb >= context->numQuant)
+ {
+ WLog_Print(context->priv->log, WLOG_ERROR, "quantIdxCb %" PRIu8 " >= numQuant %" PRIu8,
+ tile->quantIdxCb, context->numQuant);
+ rc = FALSE;
+ break;
+ }
+ else if (tile->quantIdxCr >= context->numQuant)
+ {
+ WLog_Print(context->priv->log, WLOG_ERROR, "quantIdxCr %" PRIu8 " >= numQuant %" PRIu8,
+ tile->quantIdxCr, context->numQuant);
+ rc = FALSE;
+ break;
+ }
Stream_Read_UINT16(&sub, tile->xIdx); /* xIdx (2 bytes) */
Stream_Read_UINT16(&sub, tile->yIdx); /* yIdx (2 bytes) */
Stream_Read_UINT16(&sub, tile->YLen); /* YLen (2 bytes) */

View File

@ -0,0 +1,264 @@
Description: Upstream fix for CVE-2023-39354 - Out-Of-Bounds Read in nsc_rle_decompress_data
commit 1 of 2.
Backported changes required, e.g Stream_CheckAndLogRequiredLengthWLogEx() and WPR_ASSERT substituted.
with aseert()
Origin: https://github.com/FreeRDP/FreeRDP/commit/82ac0164f330c08ddd9a6ef6f3dbf846c4b79def
Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-c3r2-pxxp-f8r6
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1051638
From 82ac0164f330c08ddd9a6ef6f3dbf846c4b79def Mon Sep 17 00:00:00 2001
From: Armin Novak <anovak@thincast.com>
Date: Sat, 5 Aug 2023 10:53:29 +0200
Subject: [PATCH] [codec,nsc] fix missing plane length check
reported by @pwn2carr
(cherry picked from commit 89cd622426b3fcac64b9203e69f9f407cc19760e)
---
libfreerdp/codec/nsc.c | 71 +++++++++++++++++++++---------------------
1 file changed, 36 insertions(+), 35 deletions(-)
--- a/libfreerdp/codec/nsc.c
+++ b/libfreerdp/codec/nsc.c
@@ -30,6 +30,9 @@
#include <winpr/crt.h>
+#include <assert.h>
+#include <winpr/stream.h>
+
#include <freerdp/codec/nsc.h>
#include <freerdp/codec/color.h>
@@ -38,6 +41,14 @@
#include "nsc_sse2.h"
+#define WINPR_ASSERT assert
+
+#if !defined(Stream_CheckAndLogRequiredLengthWLog)
+#define Stream_CheckAndLogRequiredLengthWLog(log, s, len) \
+ Stream_CheckAndLogRequiredLengthWLogEx(log, WLOG_WARN, s, len, "%s(%s:%d)", __FUNCTION__, \
+ __FILE__, __LINE__)
+#endif
+
#ifndef NSC_INIT_SIMD
#define NSC_INIT_SIMD(_nsc_context) \
do \
@@ -175,20 +186,16 @@
static BOOL nsc_rle_decompress_data(NSC_CONTEXT* context)
{
- UINT16 i;
- BYTE* rle;
- UINT32 planeSize;
- UINT32 originalSize;
-
if (!context)
return FALSE;
- rle = context->Planes;
+ BYTE* rle = context->Planes;
+ WINPR_ASSERT(rle);
- for (i = 0; i < 4; i++)
+ for (size_t i = 0; i < 4; i++)
{
- originalSize = context->OrgByteCount[i];
- planeSize = context->PlaneByteCount[i];
+ const UINT32 originalSize = context->OrgByteCount[i];
+ const UINT32 planeSize = context->PlaneByteCount[i];
if (planeSize == 0)
{
@@ -219,64 +226,63 @@
static BOOL nsc_stream_initialize(NSC_CONTEXT* context, wStream* s)
{
- int i;
-
- if (Stream_GetRemainingLength(s) < 20)
+ WINPR_ASSERT(context);
+ WINPR_ASSERT(context->priv);
+ if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 20))
return FALSE;
- for (i = 0; i < 4; i++)
+ size_t total = 0;
+ for (size_t i = 0; i < 4; i++)
+ {
Stream_Read_UINT32(s, context->PlaneByteCount[i]);
+ total += context->PlaneByteCount[i];
+ }
Stream_Read_UINT8(s, context->ColorLossLevel); /* ColorLossLevel (1 byte) */
Stream_Read_UINT8(s, context->ChromaSubsamplingLevel); /* ChromaSubsamplingLevel (1 byte) */
Stream_Seek(s, 2); /* Reserved (2 bytes) */
context->Planes = Stream_Pointer(s);
- return TRUE;
+ return Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, total);
}
static BOOL nsc_context_initialize(NSC_CONTEXT* context, wStream* s)
{
- int i;
- UINT32 length;
- UINT32 tempWidth;
- UINT32 tempHeight;
-
if (!nsc_stream_initialize(context, s))
return FALSE;
- length = context->width * context->height * 4;
+ const size_t blength = context->width * context->height * 4;
if (!context->BitmapData)
{
- context->BitmapData = calloc(1, length + 16);
+ context->BitmapData = calloc(1, blength + 16);
if (!context->BitmapData)
return FALSE;
- context->BitmapDataLength = length;
+ context->BitmapDataLength = blength;
}
- else if (length > context->BitmapDataLength)
+ else if (blength > context->BitmapDataLength)
{
void* tmp;
- tmp = realloc(context->BitmapData, length + 16);
+ tmp = realloc(context->BitmapData, blength + 16);
if (!tmp)
return FALSE;
context->BitmapData = tmp;
- context->BitmapDataLength = length;
+ context->BitmapDataLength = blength;
}
- tempWidth = ROUND_UP_TO(context->width, 8);
- tempHeight = ROUND_UP_TO(context->height, 2);
+ const UINT32 tempWidth = ROUND_UP_TO(context->width, 8);
+ const UINT32 tempHeight = ROUND_UP_TO(context->height, 2);
/* The maximum length a decoded plane can reach in all cases */
- length = tempWidth * tempHeight;
+ const size_t plength = tempWidth * tempHeight;
- if (length > context->priv->PlaneBuffersLength)
+ if (plength > context->priv->PlaneBuffersLength)
{
- for (i = 0; i < 4; i++)
+ for (size_t i = 0; i < 4; i++)
{
- void* tmp = (BYTE*)realloc(context->priv->PlaneBuffers[i], length);
+ void* tmp = (BYTE*)realloc(context->priv->PlaneBuffers[i], plength);
if (!tmp)
return FALSE;
@@ -284,13 +290,11 @@
context->priv->PlaneBuffers[i] = tmp;
}
- context->priv->PlaneBuffersLength = length;
+ context->priv->PlaneBuffersLength = plength;
}
- for (i = 0; i < 4; i++)
- {
+ for (size_t i = 0; i < 4; i++)
context->OrgByteCount[i] = context->width * context->height;
- }
if (context->ChromaSubsamplingLevel)
{
--- a/winpr/include/winpr/stream.h
+++ b/winpr/include/winpr/stream.h
@@ -27,6 +27,7 @@
#include <winpr/wtypes.h>
#include <winpr/endian.h>
#include <winpr/synch.h>
+#include <winpr/wlog.h>
#ifdef __cplusplus
extern "C"
@@ -56,6 +57,14 @@
WINPR_API void Stream_StaticInit(wStream* s, BYTE* buffer, size_t size);
WINPR_API void Stream_Free(wStream* s, BOOL bFreeBuffer);
+
+ WINPR_API BOOL Stream_CheckAndLogRequiredLengthWLogEx(wLog* log, DWORD level, wStream* s,
+ size_t nmemb, size_t size,
+ const char* fmt, ...);
+ WINPR_API BOOL Stream_CheckAndLogRequiredLengthWLogExVa(wLog* log, DWORD level, wStream* s,
+ size_t nmemb, size_t size,
+ const char* fmt, va_list args);
+
static INLINE void Stream_Seek(wStream* s, size_t _offset)
{
s->pointer += (_offset);
--- a/winpr/libwinpr/utils/stream.c
+++ b/winpr/libwinpr/utils/stream.c
@@ -26,6 +26,15 @@
#include <winpr/crt.h>
#include <winpr/stream.h>
+#include <winpr/wlog.h>
+
+#if defined(__GNUC__) || defined(__clang__)
+#define WINPR_ATTR_FORMAT_ARG(pos, args) __attribute__((__format__(__printf__, pos, args)))
+#else
+#define WINPR_ATTR_FORMAT_ARG(pos, args)
+#endif
+
+
BOOL Stream_EnsureCapacity(wStream* s, size_t size)
{
if (s->capacity < size)
@@ -132,3 +141,46 @@
free(s);
}
}
+
+BOOL Stream_CheckAndLogRequiredLengthWLogEx(wLog* log, DWORD level, wStream* s, size_t nmemb,
+ size_t size, const char* fmt, ...)
+{
+ assert(size > 0);
+ const size_t actual = Stream_GetRemainingLength(s) / size;
+
+ if (actual < nmemb)
+ {
+ va_list args;
+
+ va_start(args, fmt);
+ Stream_CheckAndLogRequiredLengthWLogExVa(log, level, s, nmemb, size, fmt, args);
+ va_end(args);
+
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+WINPR_ATTR_FORMAT_ARG(6, 0)
+BOOL Stream_CheckAndLogRequiredLengthWLogExVa(wLog* log, DWORD level, wStream* s, size_t nmemb,
+ size_t size, const char* fmt, va_list args)
+{
+ assert(size > 0);
+ const size_t actual = Stream_GetRemainingLength(s) / size;
+
+ if (actual < nmemb)
+ {
+ char prefix[1024] = { 0 };
+
+ vsnprintf(prefix, sizeof(prefix), fmt, args);
+
+ WLog_Print(log, level,
+ "[%s] invalid length, got %" PRIuz ", require at least %" PRIuz
+ " [element size=%" PRIuz "]",
+ prefix, actual, nmemb, size);
+ winpr_log_backtrace_ex(log, level, 20);
+ return FALSE;
+ }
+ return TRUE;
+}

View File

@ -0,0 +1,131 @@
Description: Upstream fix for CVE-2023-39354 - Out-Of-Bounds Read in nsc_rle_decompress_data
commit 2 of 2.
Origin: https://github.com/FreeRDP/FreeRDP/commit/9a1ee1bae5a9561f5031a7b69129f10458b62d4a
Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-c3r2-pxxp-f8r6
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1051638
From 9a1ee1bae5a9561f5031a7b69129f10458b62d4a Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Tue, 22 Aug 2023 10:48:57 +0200
Subject: [PATCH] [codec,nsc] fix input length validation
(cherry picked from commit e6bb37bea1a645610cc7e030e11fa3ec9e758dc9)
---
libfreerdp/codec/nsc.c | 32 ++++++++++++++++++++++++++++----
libfreerdp/codec/nsc_types.h | 1 +
2 files changed, 29 insertions(+), 4 deletions(-)
--- a/libfreerdp/codec/nsc.c
+++ b/libfreerdp/codec/nsc.c
@@ -122,12 +122,17 @@
return TRUE;
}
-static BOOL nsc_rle_decode(BYTE* in, BYTE* out, UINT32 outSize, UINT32 originalSize)
+static BOOL nsc_rle_decode(const BYTE* in, size_t inSize, BYTE* out, UINT32 outSize,
+ UINT32 originalSize)
{
UINT32 left = originalSize;
while (left > 4)
{
+ if (inSize < 1)
+ return FALSE;
+ inSize--;
+
const BYTE value = *in++;
UINT32 len = 0;
@@ -140,17 +145,26 @@
*out++ = value;
left--;
}
+ else if (inSize < 1)
+ return FALSE;
else if (value == *in)
{
+ inSize--;
in++;
- if (*in < 0xFF)
+ if (inSize < 1)
+ return FALSE;
+ else if (*in < 0xFF)
{
+ inSize--;
len = (UINT32)*in++;
len += 2;
}
else
{
+ if (inSize < 5)
+ return FALSE;
+ inSize -= 5;
in++;
len = ((UINT32)(*in++));
len |= ((UINT32)(*in++)) << 8U;
@@ -180,6 +194,8 @@
if ((outSize < 4) || (left < 4))
return FALSE;
+ if (inSize < 4)
+ return FALSE;
memcpy(out, in, 4);
return TRUE;
}
@@ -189,7 +205,8 @@
if (!context)
return FALSE;
- BYTE* rle = context->Planes;
+ const BYTE* rle = context->Planes;
+ size_t rleSize = context->PlanesSize;
WINPR_ASSERT(rle);
for (size_t i = 0; i < 4; i++)
@@ -197,6 +214,9 @@
const UINT32 originalSize = context->OrgByteCount[i];
const UINT32 planeSize = context->PlaneByteCount[i];
+ if (rleSize < planeSize)
+ return FALSE;
+
if (planeSize == 0)
{
if (context->priv->PlaneBuffersLength < originalSize)
@@ -206,7 +226,7 @@
}
else if (planeSize < originalSize)
{
- if (!nsc_rle_decode(rle, context->priv->PlaneBuffers[i],
+ if (!nsc_rle_decode(rle, rleSize, context->priv->PlaneBuffers[i],
context->priv->PlaneBuffersLength, originalSize))
return FALSE;
}
@@ -215,6 +235,9 @@
if (context->priv->PlaneBuffersLength < originalSize)
return FALSE;
+ if (rleSize < originalSize)
+ return FALSE;
+
CopyMemory(context->priv->PlaneBuffers[i], rle, originalSize);
}
@@ -242,6 +265,7 @@
Stream_Read_UINT8(s, context->ChromaSubsamplingLevel); /* ChromaSubsamplingLevel (1 byte) */
Stream_Seek(s, 2); /* Reserved (2 bytes) */
context->Planes = Stream_Pointer(s);
+ context->PlanesSize = total;
return Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, total);
}
--- a/libfreerdp/codec/nsc_types.h
+++ b/libfreerdp/codec/nsc_types.h
@@ -61,6 +61,7 @@
UINT32 BitmapDataLength;
BYTE* Planes;
+ size_t PlanesSize;
UINT32 PlaneByteCount[4];
UINT32 ColorLossLevel;
UINT32 ChromaSubsamplingLevel;

103
debian/patches/0041-CVE-2023-39355.patch vendored Normal file
View File

@ -0,0 +1,103 @@
Description: Upstream fix for CVE-2023-39355 - Use-After-Free in RDPGFX_CMDID_RESETGRAPHICS
Origin: https://github.com/FreeRDP/FreeRDP/commit/d6f9d33a7db0b346195b6a15b5b99944ba41beee
Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-hvwj-vmg6-2f5h
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1051638
From d6f9d33a7db0b346195b6a15b5b99944ba41beee Mon Sep 17 00:00:00 2001
From: Armin Novak <anovak@thincast.com>
Date: Sat, 5 Aug 2023 10:15:41 +0200
Subject: [PATCH] [codec,planar] fix reset
---
libfreerdp/codec/planar.c | 62 ++++++++++++++++++++++-----------------
1 file changed, 35 insertions(+), 27 deletions(-)
--- a/libfreerdp/codec/planar.c
+++ b/libfreerdp/codec/planar.c
@@ -31,6 +31,8 @@
#include <freerdp/codec/bitmap.h>
#include <freerdp/codec/planar.h>
+#include <stdlib.h>
+
#define TAG FREERDP_TAG("codec")
static INLINE UINT32 planar_invert_format(BITMAP_PLANAR_CONTEXT* planar, BOOL alpha,
@@ -847,6 +849,9 @@
{
BYTE* rleBuffer[4] = { 0 };
+ if (!planar->rlePlanesBuffer)
+ return FALSE;
+
rleBuffer[3] = planar->rlePlanesBuffer; /* AlphaPlane */
rleBuffer[0] = rleBuffer[3] + planeSize; /* LumaOrRedPlane */
rleBuffer[1] = rleBuffer[0] + planeSize; /* OrangeChromaOrGreenPlane */
@@ -1486,27 +1491,49 @@
context->maxHeight = height;
context->maxPlaneSize = context->maxWidth * context->maxHeight;
context->nTempStep = context->maxWidth * 4;
- free(context->planesBuffer);
- free(context->pTempData);
- free(context->deltaPlanesBuffer);
- free(context->rlePlanesBuffer);
- context->planesBuffer = calloc(context->maxPlaneSize, 4);
- context->pTempData = calloc(context->maxPlaneSize, 6);
- context->deltaPlanesBuffer = calloc(context->maxPlaneSize, 4);
- context->rlePlanesBuffer = calloc(context->maxPlaneSize, 4);
- if (!context->planesBuffer || !context->pTempData || !context->deltaPlanesBuffer ||
- !context->rlePlanesBuffer)
- return FALSE;
+ memset(context->planes, 0, sizeof(context->planes));
+ memset(context->rlePlanes, 0, sizeof(context->rlePlanes));
+ memset(context->deltaPlanes, 0, sizeof(context->deltaPlanes));
+
+ free(context->planesBuffer); context->planesBuffer = NULL;
+ free(context->pTempData); context->pTempData = NULL;
+ free(context->deltaPlanesBuffer); context->deltaPlanesBuffer = NULL;
+ free(context->rlePlanesBuffer); context->rlePlanesBuffer = NULL;
+
+ if (context->maxPlaneSize > 0)
+ {
+ unsigned int err = 0;
+ err = posix_memalign(&context->planesBuffer, 32, context->maxPlaneSize * 4);
+ memset(context->planesBuffer, 0, context->maxPlaneSize * 4);
+
+ err |= posix_memalign(&context->pTempData, 32, context->maxPlaneSize * 6);
+ memset(context->pTempData, 0, context->maxPlaneSize * 6);
+
+ err |= posix_memalign(&context->deltaPlanesBuffer, 32, context->maxPlaneSize * 4);
+ memset(context->deltaPlanesBuffer, 0, context->maxPlaneSize * 4);
+
+ err |= posix_memalign(&context->rlePlanesBuffer, 32, context->maxPlaneSize * 4);
+ memset(context->rlePlanesBuffer, 0, context->maxPlaneSize * 4);
+
+ if (err || !context->planesBuffer || !context->pTempData || !context->deltaPlanesBuffer ||
+ !context->rlePlanesBuffer){
+ free(context->planesBuffer); context->planesBuffer = NULL;
+ free(context->pTempData); context->pTempData = NULL;
+ free(context->deltaPlanesBuffer); context->deltaPlanesBuffer = NULL;
+ free(context->rlePlanesBuffer); context->rlePlanesBuffer = NULL;
+ return FALSE;
+ }
- context->planes[0] = &context->planesBuffer[context->maxPlaneSize * 0];
- context->planes[1] = &context->planesBuffer[context->maxPlaneSize * 1];
- context->planes[2] = &context->planesBuffer[context->maxPlaneSize * 2];
- context->planes[3] = &context->planesBuffer[context->maxPlaneSize * 3];
- context->deltaPlanes[0] = &context->deltaPlanesBuffer[context->maxPlaneSize * 0];
- context->deltaPlanes[1] = &context->deltaPlanesBuffer[context->maxPlaneSize * 1];
- context->deltaPlanes[2] = &context->deltaPlanesBuffer[context->maxPlaneSize * 2];
- context->deltaPlanes[3] = &context->deltaPlanesBuffer[context->maxPlaneSize * 3];
+ context->planes[0] = &context->planesBuffer[context->maxPlaneSize * 0];
+ context->planes[1] = &context->planesBuffer[context->maxPlaneSize * 1];
+ context->planes[2] = &context->planesBuffer[context->maxPlaneSize * 2];
+ context->planes[3] = &context->planesBuffer[context->maxPlaneSize * 3];
+ context->deltaPlanes[0] = &context->deltaPlanesBuffer[context->maxPlaneSize * 0];
+ context->deltaPlanes[1] = &context->deltaPlanesBuffer[context->maxPlaneSize * 1];
+ context->deltaPlanes[2] = &context->deltaPlanesBuffer[context->maxPlaneSize * 2];
+ context->deltaPlanes[3] = &context->deltaPlanesBuffer[context->maxPlaneSize * 3];
+ }
return TRUE;
}

View File

@ -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 <anovak@thincast.com>
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 <winpr/wtypes.h>
#include <winpr/crt.h>
+#include <assert.h>
+#define WINPR_ASSERT assert
+
#include <freerdp/api.h>
#include <freerdp/log.h>
#include <freerdp/graphics.h>
@@ -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)

View File

@ -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 <armin.novak@thincast.com>
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;

167
debian/patches/0044-CVE-2023-40567.patch vendored Normal file
View File

@ -0,0 +1,167 @@
Description: Upstream fix for CVE-2023-40567 - Out-Of-Bounds Write in clear_decompress_bands_data
Origin: https://github.com/FreeRDP/FreeRDP/commit/bacb8c016ef72aa767760b6b01d15500aee9d59a
Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-2w9f-8wg4-8jfp
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1051638
From bacb8c016ef72aa767760b6b01d15500aee9d59a Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Tue, 22 Aug 2023 14:44:57 +0200
Subject: [PATCH] [codec,clear] fix missing bounds checks
(cherry picked from commit 680619fc48f40d458c9614b47bfde61226a324aa)
---
libfreerdp/codec/clear.c | 59 +++++++++++++++++++---------------------
1 file changed, 28 insertions(+), 31 deletions(-)
diff --git a/libfreerdp/codec/clear.c b/libfreerdp/codec/clear.c
index ecf7f1ca161b..101260770ba7 100644
--- a/libfreerdp/codec/clear.c
+++ b/libfreerdp/codec/clear.c
@@ -591,13 +591,9 @@ static BOOL resize_vbar_entry(CLEAR_CONTEXT* clear, CLEAR_VBAR_ENTRY* vBarEntry)
static BOOL clear_decompress_bands_data(CLEAR_CONTEXT* clear, wStream* s, UINT32 bandsByteCount,
UINT32 nWidth, UINT32 nHeight, BYTE* pDstData,
UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst,
- UINT32 nYDst)
+ UINT32 nYDst, UINT32 nDstWidth, UINT32 nDstHeight)
{
- UINT32 i, y;
- UINT32 count;
- UINT32 suboffset;
- UINT32 nXDstRel;
- UINT32 nYDstRel;
+ UINT32 suboffset = 0;
if (Stream_GetRemainingLength(s) < bandsByteCount)
{
@@ -605,22 +601,20 @@ static BOOL clear_decompress_bands_data(CLEAR_CONTEXT* clear, wStream* s, UINT32
return FALSE;
}
- suboffset = 0;
-
while (suboffset < bandsByteCount)
{
- BYTE r, g, b;
+ BYTE cr, cg, cb;
UINT16 xStart;
UINT16 xEnd;
UINT16 yStart;
UINT16 yEnd;
UINT32 colorBkg;
UINT16 vBarHeader;
- UINT16 vBarYOn;
+ UINT16 vBarYOn = 0;
UINT16 vBarYOff;
UINT32 vBarCount;
UINT32 vBarPixelCount;
- UINT32 vBarShortPixelCount;
+ UINT32 vBarShortPixelCount = 0;
if (Stream_GetRemainingLength(s) < 11)
{
@@ -632,11 +626,11 @@ static BOOL clear_decompress_bands_data(CLEAR_CONTEXT* clear, wStream* s, UINT32
Stream_Read_UINT16(s, xEnd);
Stream_Read_UINT16(s, yStart);
Stream_Read_UINT16(s, yEnd);
- Stream_Read_UINT8(s, b);
- Stream_Read_UINT8(s, g);
- Stream_Read_UINT8(s, r);
+ Stream_Read_UINT8(s, cb);
+ Stream_Read_UINT8(s, cg);
+ Stream_Read_UINT8(s, cr);
suboffset += 11;
- colorBkg = FreeRDPGetColor(clear->format, r, g, b, 0xFF);
+ colorBkg = FreeRDPGetColor(clear->format, cr, cg, cb, 0xFF);
if (xEnd < xStart)
{
@@ -652,13 +646,13 @@ static BOOL clear_decompress_bands_data(CLEAR_CONTEXT* clear, wStream* s, UINT32
vBarCount = (xEnd - xStart) + 1;
- for (i = 0; i < vBarCount; i++)
+ for (UINT32 i = 0; i < vBarCount; i++)
{
UINT32 vBarHeight;
CLEAR_VBAR_ENTRY* vBarEntry = NULL;
- CLEAR_VBAR_ENTRY* vBarShortEntry;
+ CLEAR_VBAR_ENTRY* vBarShortEntry = NULL;
BOOL vBarUpdate = FALSE;
- const BYTE* pSrcPixel;
+ const BYTE* cpSrcPixel;
if (Stream_GetRemainingLength(s) < 2)
{
@@ -740,11 +734,11 @@ static BOOL clear_decompress_bands_data(CLEAR_CONTEXT* clear, wStream* s, UINT32
if (!resize_vbar_entry(clear, vBarShortEntry))
return FALSE;
- for (y = 0; y < vBarShortPixelCount; y++)
+ for (UINT32 y = 0; y < vBarShortPixelCount; y++)
{
- BYTE r, g, b;
+ BYTE r = 0, g = 0, b = 0;
BYTE* dstBuffer = &vBarShortEntry->pixels[y * GetBytesPerPixel(clear->format)];
- UINT32 color;
+ UINT32 color = 0;
Stream_Read_UINT8(s, b);
Stream_Read_UINT8(s, g);
Stream_Read_UINT8(s, r);
@@ -804,8 +798,8 @@ static BOOL clear_decompress_bands_data(CLEAR_CONTEXT* clear, wStream* s, UINT32
dstBuffer = vBarEntry->pixels;
/* if (y < vBarYOn), use colorBkg */
- y = 0;
- count = vBarYOn;
+ UINT32 y = 0;
+ UINT32 count = vBarYOn;
if ((y + count) > vBarPixelCount)
count = (vBarPixelCount > y) ? (vBarPixelCount - y) : 0;
@@ -868,28 +862,31 @@ static BOOL clear_decompress_bands_data(CLEAR_CONTEXT* clear, wStream* s, UINT32
return FALSE;
}
- nXDstRel = nXDst + xStart;
- nYDstRel = nYDst + yStart;
- pSrcPixel = vBarEntry->pixels;
+ const UINT32 nXDstRel = nXDst + xStart;
+ const UINT32 nYDstRel = nYDst + yStart;
+ cpSrcPixel = vBarEntry->pixels;
if (i < nWidth)
{
- count = vBarEntry->count;
+ UINT32 count = vBarEntry->count;
if (count > nHeight)
count = nHeight;
- for (y = 0; y < count; y++)
+ if (nXDstRel + i > nDstWidth)
+ return FALSE;
+
+ for (UINT32 y = 0; y < count; y++)
{
BYTE* pDstPixel8 = &pDstData[((nYDstRel + y) * nDstStep) +
((nXDstRel + i) * GetBytesPerPixel(DstFormat))];
- UINT32 color = ReadColor(pSrcPixel, clear->format);
+ UINT32 color = ReadColor(cpSrcPixel, clear->format);
color = FreeRDPConvertColor(color, clear->format, DstFormat, NULL);
if (!WriteColor(pDstPixel8, DstFormat, color))
return FALSE;
- pSrcPixel += GetBytesPerPixel(clear->format);
+ cpSrcPixel += GetBytesPerPixel(clear->format);
}
}
}
@@ -1117,7 +1114,7 @@ INT32 clear_decompress(CLEAR_CONTEXT* clear, const BYTE* pSrcData, UINT32 SrcSiz
if (bandsByteCount > 0)
{
if (!clear_decompress_bands_data(clear, s, bandsByteCount, nWidth, nHeight, pDstData,
- DstFormat, nDstStep, nXDst, nYDst))
+ DstFormat, nDstStep, nXDst, nYDst, nDstWidth, nDstHeight))
{
WLog_ERR(TAG, "clear_decompress_bands_data failed!");
goto fail;

View File

@ -0,0 +1,33 @@
Description: Upstream fix for CVE-2023-40181 - Underflow leading to Out-Of-Bound Read in zgfx_decompress_segment
Origin: https://github.com/FreeRDP/FreeRDP/commit/c23cbdc4a5756bd723223c7139654de7439fdcc0
Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-mxp4-rx7x-h2g8
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1051638
From c23cbdc4a5756bd723223c7139654de7439fdcc0 Mon Sep 17 00:00:00 2001
From: Armin Novak <armin.novak@thincast.com>
Date: Mon, 21 Aug 2023 14:30:11 +0200
Subject: [PATCH] [codec,zgfx] fix cBitsRemaining calculation
fixed out of bound read reported by @pwn2carr
(cherry picked from commit c39c82277a73332e9c1b64db98a34559f424fe20)
---
libfreerdp/codec/zgfx.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/libfreerdp/codec/zgfx.c b/libfreerdp/codec/zgfx.c
index e260aa6e28ad..841b50860711 100644
--- a/libfreerdp/codec/zgfx.c
+++ b/libfreerdp/codec/zgfx.c
@@ -259,7 +259,11 @@ static BOOL zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, wStream* stream, size_t
zgfx->pbInputCurrent = pbSegment;
zgfx->pbInputEnd = &pbSegment[cbSegment - 1];
/* NumberOfBitsToDecode = ((NumberOfBytesToDecode - 1) * 8) - ValueOfLastByte */
- zgfx->cBitsRemaining = 8 * (cbSegment - 1) - *zgfx->pbInputEnd;
+ const UINT32 bits = 8u * (cbSegment - 1u);
+ if (bits < *zgfx->pbInputEnd)
+ return FALSE;
+
+ zgfx->cBitsRemaining = bits - *zgfx->pbInputEnd;
zgfx->cBitsCurrent = 0;
zgfx->BitsCurrent = 0;

393
debian/patches/0046-CVE-2023-40186.patch vendored Normal file
View File

@ -0,0 +1,393 @@
Description: Upstream fix for CVE-2023-40186 - IntegerOverflow leading to Out-Of-Bound Write Vulnerability in gdi_CreateSurface
Origin: https://github.com/FreeRDP/FreeRDP/commit/d8a1ac342ae375644c70579c33b5cf38fb43b083
Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-hcj4-3c3r-5j3v
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1051638
From d8a1ac342ae375644c70579c33b5cf38fb43b083 Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Tue, 22 Aug 2023 09:41:28 +0200
Subject: [PATCH] [warnings] fix integer multiplications
Ensure the integer width for size arguments is 64bit in a
multiplication. Leading 64bit constant 1ull expands width, a trailing
one is ignored.
(cherry picked from commit b3f0ab2814e39e0f779343c53699e7dc6c1b1c22)
---
channels/rdpsnd/server/rdpsnd_main.c | 2 +-
client/X11/xf_gdi.c | 2 +-
client/X11/xf_gfx.c | 4 ++--
client/X11/xf_graphics.c | 4 ++--
client/X11/xf_rail.c | 4 ++--
libfreerdp/codec/clear.c | 4 ++--
libfreerdp/codec/color.c | 6 +++---
libfreerdp/codec/h264.c | 6 +++---
libfreerdp/codec/progressive.c | 2 +-
libfreerdp/gdi/bitmap.c | 2 +-
libfreerdp/gdi/gdi.c | 2 +-
libfreerdp/gdi/gfx.c | 4 ++--
libfreerdp/gdi/graphics.c | 2 +-
libfreerdp/gdi/shape.c | 2 +-
libfreerdp/gdi/video.c | 2 +-
libfreerdp/primitives/prim_copy.c | 4 ++--
libfreerdp/primitives/primitives.c | 2 +-
uwac/libuwac/uwac-window.c | 8 ++++----
winpr/libwinpr/utils/lodepng/lodepng.c | 14 +++++++-------
19 files changed, 38 insertions(+), 38 deletions(-)
--- a/channels/rdpsnd/server/rdpsnd_main.c
+++ b/channels/rdpsnd/server/rdpsnd_main.c
@@ -422,7 +422,7 @@
Stream_Seek(s, 3); /* bPad */
start = Stream_GetPosition(s);
src = context->priv->out_buffer;
- length = context->priv->out_pending_frames * context->priv->src_bytes_per_frame * 1ULL;
+ length = 1ull * context->priv->out_pending_frames * context->priv->src_bytes_per_frame;
if (!freerdp_dsp_encode(context->priv->dsp_context, context->src_format, src, length, s))
return ERROR_INTERNAL_ERROR;
--- a/client/X11/xf_gdi.c
+++ b/client/X11/xf_gdi.c
@@ -1066,7 +1066,7 @@
case RDP_CODEC_ID_NONE:
pSrcData = cmd->bmp.bitmapData;
format = gdi_get_pixel_format(cmd->bmp.bpp);
- size = cmd->bmp.width * cmd->bmp.height * GetBytesPerPixel(format) * 1ULL;
+ size = 1ull * cmd->bmp.width * cmd->bmp.height * GetBytesPerPixel(format);
if (size > cmd->bmp.bitmapDataLength)
{
WLog_ERR(TAG, "Short nocodec message: got %" PRIu32 " bytes, require %" PRIuz,
--- a/client/X11/xf_gfx.c
+++ b/client/X11/xf_gfx.c
@@ -288,7 +288,7 @@
surface->gdi.scanline = surface->gdi.width * GetBytesPerPixel(surface->gdi.format);
surface->gdi.scanline = x11_pad_scanline(surface->gdi.scanline, xfc->scanline_pad);
- size = surface->gdi.scanline * surface->gdi.height * 1ULL;
+ size = 1ull * surface->gdi.scanline * surface->gdi.height;
surface->gdi.data = (BYTE*)_aligned_malloc(size, 16);
if (!surface->gdi.data)
@@ -312,7 +312,7 @@
UINT32 bytes = GetBytesPerPixel(gdi->dstFormat);
surface->stageScanline = width * bytes;
surface->stageScanline = x11_pad_scanline(surface->stageScanline, xfc->scanline_pad);
- size = surface->stageScanline * surface->gdi.height * 1ULL;
+ size = 1ull * surface->stageScanline * surface->gdi.height;
surface->stage = (BYTE*)_aligned_malloc(size, 16);
if (!surface->stage)
--- a/client/X11/xf_graphics.c
+++ b/client/X11/xf_graphics.c
@@ -304,7 +304,7 @@
ci.height = yTargetSize;
ci.xhot = pointer->xPos * xscale;
ci.yhot = pointer->yPos * yscale;
- size = ci.height * ci.width * GetBytesPerPixel(CursorFormat) * 1ULL;
+ size = 1ull * ci.height * ci.width * GetBytesPerPixel(CursorFormat);
if (xscale != 1 || yscale != 1)
{
@@ -391,7 +391,7 @@
xpointer->nCursors = 0;
xpointer->mCursors = 0;
- size = pointer->height * pointer->width * GetBytesPerPixel(CursorFormat) * 1ULL;
+ size = 1ull * pointer->height * pointer->width * GetBytesPerPixel(CursorFormat);
if (!(xpointer->cursorPixels = (XcursorPixel*)_aligned_malloc(size, 16)))
return FALSE;
--- a/client/X11/xf_rail.c
+++ b/client/X11/xf_rail.c
@@ -532,7 +532,7 @@
cache->numCaches = settings->RemoteAppNumIconCaches;
cache->numCacheEntries = settings->RemoteAppNumIconCacheEntries;
- cache->entries = calloc(cache->numCaches * cache->numCacheEntries * 1ULL, sizeof(xfRailIcon));
+ cache->entries = calloc(1ull * cache->numCaches * cache->numCacheEntries, sizeof(xfRailIcon));
if (!cache->entries)
{
@@ -602,7 +602,7 @@
long* pixels;
int i;
int nelements;
- argbPixels = calloc(iconInfo->width * iconInfo->height * 1ULL, 4);
+ argbPixels = calloc(1ull * iconInfo->width * iconInfo->height, 4);
if (!argbPixels)
goto error;
--- a/libfreerdp/codec/clear.c
+++ b/libfreerdp/codec/clear.c
@@ -566,7 +566,7 @@
const UINT32 diffSize = (vBarEntry->count - vBarEntry->size) * bpp;
BYTE* tmp;
vBarEntry->size = vBarEntry->count;
- tmp = (BYTE*)realloc(vBarEntry->pixels, vBarEntry->count * bpp * 1ULL);
+ tmp = (BYTE*)realloc(vBarEntry->pixels, 1ull * vBarEntry->count * bpp);
if (!tmp)
{
@@ -977,7 +977,7 @@
if (glyphEntry->count > glyphEntry->size)
{
BYTE* tmp;
- tmp = realloc(glyphEntry->pixels, glyphEntry->count * bpp * 1ULL);
+ tmp = realloc(glyphEntry->pixels, 1ull * glyphEntry->count * bpp);
if (!tmp)
{
--- a/libfreerdp/codec/color.c
+++ b/libfreerdp/codec/color.c
@@ -56,7 +56,7 @@
* means of accessing individual pixels in blitting operations
*/
scanline = (width + 7) / 8;
- dstData = (BYTE*)_aligned_malloc(width * height * 1ULL, 16);
+ dstData = (BYTE*)_aligned_malloc(1ull * width * height, 16);
if (!dstData)
return NULL;
@@ -545,7 +545,7 @@
for (y = nYDst; y < nHeight; y++)
{
BYTE* pDstLine = &pDstData[y * nDstStep + nXDst * dstBytesPerPixel];
- memset(pDstLine, 0, dstBytesPerPixel * (nWidth - nXDst) * 1ULL);
+ memset(pDstLine, 0, 1ull * dstBytesPerPixel * (nWidth - nXDst));
}
switch (xorBpp)
@@ -742,7 +742,7 @@
for (y = 1; y < nHeight; y++)
{
BYTE* pDstLine = &pDstData[(y + nYDst) * nDstStep + nXDst * bpp];
- memcpy(pDstLine, pFirstDstLineXOffset, nWidth * bpp * 1ULL);
+ memcpy(pDstLine, pFirstDstLineXOffset, 1ull * nWidth * bpp);
}
return TRUE;
--- a/libfreerdp/codec/h264.c
+++ b/libfreerdp/codec/h264.c
@@ -63,9 +63,9 @@
_aligned_free(h264->pYUVData[0]);
_aligned_free(h264->pYUVData[1]);
_aligned_free(h264->pYUVData[2]);
- h264->pYUVData[0] = _aligned_malloc(h264->iStride[0] * height * 1ULL, 16);
- h264->pYUVData[1] = _aligned_malloc(h264->iStride[1] * height * 1ULL, 16);
- h264->pYUVData[2] = _aligned_malloc(h264->iStride[2] * height * 1ULL, 16);
+ h264->pYUVData[0] = _aligned_malloc(1ull * h264->iStride[0] * height, 16);
+ h264->pYUVData[1] = _aligned_malloc(1ull * h264->iStride[1] * height, 16);
+ h264->pYUVData[2] = _aligned_malloc(1ull * h264->iStride[2] * height, 16);
if (!h264->pYUVData[0] || !h264->pYUVData[1] || !h264->pYUVData[2])
return FALSE;
--- a/libfreerdp/codec/progressive.c
+++ b/libfreerdp/codec/progressive.c
@@ -411,7 +411,7 @@
tile->stride = 4 * tile->width;
{
- size_t dataLen = tile->stride * tile->height * 1ULL;
+ size_t dataLen = 1ull * tile->stride * tile->height;
tile->data = (BYTE*)_aligned_malloc(dataLen, 16);
}
--- a/libfreerdp/gdi/bitmap.c
+++ b/libfreerdp/gdi/bitmap.c
@@ -148,7 +148,7 @@
hBitmap->width = nWidth;
hBitmap->height = nHeight;
hBitmap->data =
- _aligned_malloc(nWidth * nHeight * GetBytesPerPixel(hBitmap->format) * 1ULL, 16);
+ _aligned_malloc(1ull * nWidth * nHeight * GetBytesPerPixel(hBitmap->format), 16);
hBitmap->free = _aligned_free;
if (!hBitmap->data)
--- a/libfreerdp/gdi/gdi.c
+++ b/libfreerdp/gdi/gdi.c
@@ -1057,7 +1057,7 @@
case RDP_CODEC_ID_NONE:
format = gdi_get_pixel_format(cmd->bmp.bpp);
- size = cmd->bmp.width * cmd->bmp.height * GetBytesPerPixel(format) * 1ULL;
+ size = 1ull * cmd->bmp.width * cmd->bmp.height * GetBytesPerPixel(format);
if (size > cmd->bmp.bitmapDataLength)
{
WLog_ERR(TAG, "Short nocodec message: got %" PRIu32 " bytes, require %" PRIuz,
--- a/libfreerdp/gdi/gfx.c
+++ b/libfreerdp/gdi/gfx.c
@@ -730,7 +730,7 @@
{
UINT32 x, y;
- if (Stream_GetRemainingLength(&s) < cmd->height * cmd->width * 1ULL)
+ if (Stream_GetRemainingLength(&s) < 1ull * cmd->height * cmd->width)
return ERROR_INVALID_DATA;
for (y = cmd->top; y < cmd->top + cmd->height; y++)
@@ -1029,7 +1029,7 @@
}
surface->scanline = gfx_align_scanline(surface->width * 4UL, 16);
- surface->data = (BYTE*)_aligned_malloc(surface->scanline * surface->height * 1ULL, 16);
+ surface->data = (BYTE*)_aligned_malloc(1ull * surface->scanline * surface->height, 16);
if (!surface->data)
{
--- a/libfreerdp/gdi/graphics.c
+++ b/libfreerdp/gdi/graphics.c
@@ -52,7 +52,7 @@
return NULL;
nDstStep = nWidth * GetBytesPerPixel(gdi->dstFormat);
- pDstData = _aligned_malloc(nHeight * nDstStep * 1ULL, 16);
+ pDstData = _aligned_malloc(1ull * nHeight * nDstStep, 16);
if (!pDstData)
return NULL;
--- a/libfreerdp/gdi/shape.c
+++ b/libfreerdp/gdi/shape.c
@@ -158,7 +158,7 @@
for (y = 1; y < nHeight; y++)
{
BYTE* dstp = gdi_get_bitmap_pointer(hdc, nXDest, nYDest + y);
- memcpy(dstp, srcp, nWidth * formatSize * 1ULL);
+ memcpy(dstp, srcp, 1ull * nWidth * formatSize);
}
break;
--- a/libfreerdp/gdi/video.c
+++ b/libfreerdp/gdi/video.c
@@ -66,7 +66,7 @@
ret->base.w = width;
ret->base.h = height;
ret->scanline = width * bpp;
- ret->image = _aligned_malloc(ret->scanline * height * 1ULL, 16);
+ ret->image = _aligned_malloc(1ull * ret->scanline * height, 16);
if (!ret->image)
{
--- a/libfreerdp/primitives/prim_copy.c
+++ b/libfreerdp/primitives/prim_copy.c
@@ -60,14 +60,14 @@
if (p1m <= p2m)
{
- ULONG_PTR p1mEnd = p1m + (height - 1) * p1Step * 1ULL + width * p1Size * 1ULL;
+ ULONG_PTR p1mEnd = p1m + 1ull * (height - 1) * p1Step + 1ull * width * p1Size;
if (p1mEnd > p2m)
return TRUE;
}
else
{
- ULONG_PTR p2mEnd = p2m + (height - 1) * p2Step * 1ULL + width * p2Size * 1ULL;
+ ULONG_PTR p2mEnd = p2m + 1ull * (height - 1) * p2Step + 1ull * width * p2Size;
if (p2mEnd > p1m)
return TRUE;
--- a/libfreerdp/primitives/primitives.c
+++ b/libfreerdp/primitives/primitives.c
@@ -157,7 +157,7 @@
if (!buf)
goto fail;
- winpr_RAND(buf, roi->width * roi->height * 1ULL);
+ winpr_RAND(buf, 1ull * roi->width * roi->height);
ret->steps[i] = roi->width;
}
--- a/uwac/libuwac/uwac-window.c
+++ b/uwac/libuwac/uwac-window.c
@@ -316,14 +316,14 @@
w->buffers = newBuffers;
memset(w->buffers + w->nbuffers, 0, sizeof(UwacBuffer) * nbuffers);
- fd = uwac_create_anonymous_file(allocSize * nbuffers * 1ULL);
+ fd = uwac_create_anonymous_file(1ull * allocSize * nbuffers);
if (fd < 0)
{
return UWAC_ERROR_INTERNAL;
}
- data = mmap(NULL, allocSize * nbuffers * 1ULL, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ data = mmap(NULL, 1ull * allocSize * nbuffers, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (data == MAP_FAILED)
{
@@ -335,7 +335,7 @@
if (!pool)
{
- munmap(data, allocSize * nbuffers * 1ULL);
+ munmap(data, 1ull * allocSize * nbuffers);
ret = UWAC_ERROR_NOMEMORY;
goto error_mmap;
}
@@ -756,7 +756,7 @@
if (copyContentForNextFrame)
memcpy(nextDrawingBuffer->data, pendingBuffer->data,
- window->stride * window->height * 1ULL);
+ 1ull * window->stride * window->height);
UwacSubmitBufferPtr(window, pendingBuffer);
return UWAC_SUCCESS;
--- a/winpr/libwinpr/utils/lodepng/lodepng.c
+++ b/winpr/libwinpr/utils/lodepng/lodepng.c
@@ -3814,7 +3814,7 @@
{
size_t i;
ColorTree tree;
- size_t numpixels = w * h * 1ULL;
+ size_t numpixels = 1ull * w * h;
if (lodepng_color_mode_equal(mode_out, mode_in))
{
@@ -3917,7 +3917,7 @@
unsigned error = 0;
size_t i;
ColorTree tree;
- size_t numpixels = w * h * 1ULL;
+ size_t numpixels = 1ull * w * h;
unsigned colored_done = lodepng_is_greyscale_type(mode) ? 1 : 0;
unsigned alpha_done = lodepng_can_have_alpha(mode) ? 0 : 1;
@@ -4538,7 +4538,7 @@
if (bpp < 8 && w * bpp != ((w * bpp + 7) / 8) * 8)
{
CERROR_TRY_RETURN(unfilter(in, in, w, h, bpp));
- removePaddingBits(out, in, w * bpp * 1ULL, ((w * bpp + 7ULL) / 8ULL) * 8ULL, h);
+ removePaddingBits(out, in, 1ull * w * bpp, ((w * bpp + 7ULL) / 8ULL) * 8ULL, h);
}
/*we can immediatly filter into the out buffer, no other steps needed*/
else
@@ -4564,7 +4564,7 @@
bits between the different reduced images: each reduced image still starts nicely at
a byte*/
removePaddingBits(&in[passstart[i]], &in[padded_passstart[i]],
- passw[i] * bpp * 1ULL, ((passw[i] * bpp + 7ULL) / 8ULL) * 8ULL,
+ 1ull * passw[i] * bpp, ((passw[i] * bpp + 7ULL) / 8ULL) * 8ULL,
passh[i]);
}
}
@@ -6055,7 +6055,7 @@
error = 83; /*alloc fail*/
if (!error)
{
- addPaddingBits(padded, in, ((w * bpp + 7ULL) / 8ULL) * 8ULL, w * bpp * 1ULL, h);
+ addPaddingBits(padded, in, ((w * bpp + 7ULL) / 8ULL) * 8ULL, 1ull * w * bpp, h);
error = filter(*out, padded, w, h, &info_png->color, settings);
}
free(padded);
@@ -6099,8 +6099,8 @@
if (!padded)
ERROR_BREAK(83); /*alloc fail*/
addPaddingBits(padded, &adam7[passstart[i]],
- ((passw[i] * bpp + 7ULL) / 8ULL) * 8ULL, passw[i] * bpp * 1ULL,
- passh[i] * 1ULL);
+ ((passw[i] * bpp + 7ULL) / 8ULL) * 8ULL, 1ull * passw[i] * bpp,
+ 1ull * passh[i]);
error = filter(&(*out)[filter_passstart[i]], padded, passw[i], passh[i],
&info_png->color, settings);
free(padded);

View File

@ -0,0 +1,36 @@
Description: Upstream fix for CVE-2023-40188 - Out-Of-Bounds Read in general_LumaToYUV444
Origin: https://github.com/FreeRDP/FreeRDP/commit/bdb3909a7713fb0b3d94c9676fe44d19de80eb4b
Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-9w28-wwj5-p4xq
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1051638
From bdb3909a7713fb0b3d94c9676fe44d19de80eb4b Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Tue, 22 Aug 2023 10:06:15 +0200
Subject: [PATCH] [codec,nsc] ensure integer width
ensure multiplication result is 64bit
(cherry picked from commit adb1630d623f76b314631e338559afe4d62b24fa)
---
libfreerdp/codec/nsc.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/libfreerdp/codec/nsc.c
+++ b/libfreerdp/codec/nsc.c
@@ -274,7 +274,7 @@
if (!nsc_stream_initialize(context, s))
return FALSE;
- const size_t blength = context->width * context->height * 4;
+ const size_t blength = context->width * context->height * 4ull;
if (!context->BitmapData)
{
@@ -300,7 +300,7 @@
const UINT32 tempWidth = ROUND_UP_TO(context->width, 8);
const UINT32 tempHeight = ROUND_UP_TO(context->height, 2);
/* The maximum length a decoded plane can reach in all cases */
- const size_t plength = tempWidth * tempHeight;
+ const size_t plength = 1ull * tempWidth * tempHeight;
if (plength > context->priv->PlaneBuffersLength)
{

View File

@ -0,0 +1,36 @@
Description: Upstream fix for CVE-2023-40569 - Out-Of-Bounds Write in progressive_decompress
Origin: https://github.com/FreeRDP/FreeRDP/commit/23c3daeca1598393f8c93f563f7847a4d67919f1
Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-hm8c-rcjg-c8qp
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1051638
From 23c3daeca1598393f8c93f563f7847a4d67919f1 Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Tue, 22 Aug 2023 15:05:20 +0200
Subject: [PATCH] [codec,progressive] fix missing destination checks
(cherry picked from commit ef7e0d60c207dae478952d795e74751d1516629d)
---
libfreerdp/codec/progressive.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
--- a/libfreerdp/codec/progressive.c
+++ b/libfreerdp/codec/progressive.c
@@ -2315,11 +2315,17 @@
for (j = 0; j < nbUpdateRects; j++)
{
const RECTANGLE_16* rect = &updateRects[j];
- const UINT32 nXSrc = rect->left - (nXDst + tile->x);
- const UINT32 nYSrc = rect->top - (nYDst + tile->y);
+ if (rect->left < updateRect.left)
+ goto fail;
+ const UINT32 nXSrc = rect->left - updateRect.left;
+ const UINT32 nYSrc = rect->top - updateRect.top;
const UINT32 width = rect->right - rect->left;
const UINT32 height = rect->bottom - rect->top;
+ if (rect->left + width > surface->width)
+ goto fail;
+ if (rect->top + height > surface->height)
+ goto fail;
if (!freerdp_image_copy(pDstData, DstFormat, nDstStep, rect->left, rect->top, width,
height, tile->data, progressive->format, tile->stride, nXSrc,
nYSrc, NULL, FREERDP_FLIP_NONE))

319
debian/patches/0049-CVE-2023-40589.patch vendored Normal file
View File

@ -0,0 +1,319 @@
Description: Upstream fix for CVE-2023-40569 - Global-Buffer-Overflow in ncrush_decompress
Origin: https://github.com/FreeRDP/FreeRDP/commit/c659973bb4cd65c065f2fe1a807dbc6805c684c6
Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-gc34-mw6m-g42x
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1051638
From c659973bb4cd65c065f2fe1a807dbc6805c684c6 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] [codec,ncrush] fix index checks
properly verify all offsets while decoding data.
(cherry picked from commit 880285c332a1d98334fd8fa4b06c10fba0fb6959)
---
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 3d6a216d32f4..c1d622a9c0bd 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;
}

153
debian/patches/0050-CVE-2021-41160.patch vendored Normal file
View File

@ -0,0 +1,153 @@
Description: Fix for CVE-2021-41160 - out of bound write
Origin: https://github.com/FreeRDP/FreeRDP/commit/217e0caa181fc1690cf84dd6a3ba1a4f90c02692.
Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-7c9r-6r2q-93qg
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1001062
From 217e0caa181fc1690cf84dd6a3ba1a4f90c02692 Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@users.noreply.github.com>
Date: Tue, 12 Oct 2021 12:26:22 +0200
Subject: [PATCH] Bitmap update fix (#7349)
* Added checks for bitmap width and height values
Data received from the server might have invalid values for bitmap
with or height. Abort parsing if such a value is found.
Reported by Sunglin from the Knownsec 404 team & 0103 sec team
* Added checks for glyph width & height
---
libfreerdp/core/orders.c | 14 ++++++++++++
libfreerdp/core/surface.c | 45 +++++++++++++++++++++++++++++++++++++++
libfreerdp/core/update.c | 7 ++++++
3 files changed, 66 insertions(+)
--- a/libfreerdp/core/orders.c
+++ b/libfreerdp/core/orders.c
@@ -1948,6 +1948,13 @@
!update_read_2byte_unsigned(&sub, &glyph->cy))
return FALSE;
+ if ((glyph->cx == 0) || (glyph->cy == 0))
+ {
+ WLog_ERR(TAG, "GLYPH_DATA_V2::cx=%" PRIu32 ", GLYPH_DATA_V2::cy=%" PRIu32,
+ glyph->cx, glyph->cy);
+ return FALSE;
+ }
+
glyph->cb = Stream_GetRemainingLength(&sub);
if (glyph->cb > 0)
{
@@ -2949,6 +2956,13 @@
Stream_Read_UINT16(s, create_offscreen_bitmap->cy); /* cy (2 bytes) */
deleteList = &(create_offscreen_bitmap->deleteList);
+ if ((create_offscreen_bitmap->cx == 0) || (create_offscreen_bitmap->cy == 0))
+ {
+ WLog_ERR(TAG, "Invalid OFFSCREEN_DELETE_LIST: cx=%" PRIu16 ", cy=%" PRIu16,
+ create_offscreen_bitmap->cx, create_offscreen_bitmap->cy);
+ return FALSE;
+ }
+
if (deleteListPresent)
{
UINT32 i;
--- a/libfreerdp/core/surface.c
+++ b/libfreerdp/core/surface.c
@@ -21,6 +21,8 @@
#include "config.h"
#endif
+#include <assert.h>
+
#include <freerdp/utils/pcap.h>
#include <freerdp/log.h>
@@ -29,6 +31,8 @@
#define TAG FREERDP_TAG("core.surface")
+#define WINPR_ASSERT assert
+
static BOOL update_recv_surfcmd_bitmap_header_ex(wStream* s, TS_COMPRESSED_BITMAP_HEADER_EX* header)
{
if (!s || !header)
@@ -62,6 +66,13 @@
Stream_Read_UINT16(s, bmp->height);
Stream_Read_UINT32(s, bmp->bitmapDataLength);
+ if ((bmp->width == 0) || (bmp->height == 0))
+ {
+ WLog_ERR(TAG, "invalid size value width=%" PRIu16 ", height=%" PRIu16, bmp->width,
+ bmp->height);
+ return FALSE;
+ }
+
if ((bmp->bpp < 1) || (bmp->bpp > 32))
{
WLog_ERR(TAG, "invalid bpp value %" PRIu32 "", bmp->bpp);
@@ -85,6 +96,39 @@
return TRUE;
}
+static BOOL update_recv_surfcmd_is_rect_valid(const rdpContext* context,
+ const SURFACE_BITS_COMMAND* cmd)
+{
+ WINPR_ASSERT(context);
+ WINPR_ASSERT(context->settings);
+ WINPR_ASSERT(cmd);
+
+ /* We need a rectangle with left/top being smaller than right/bottom.
+ * Also do not allow empty rectangles. */
+ if ((cmd->destTop >= cmd->destBottom) || (cmd->destLeft >= cmd->destRight))
+ {
+ WLog_WARN(TAG,
+ "Empty surface bits command rectangle: %" PRIu16 "x%" PRIu16 "-%" PRIu16
+ "x%" PRIu16,
+ cmd->destLeft, cmd->destTop, cmd->destRight, cmd->destBottom);
+ return FALSE;
+ }
+
+ /* The rectangle needs to fit into our session size */
+ if ((cmd->destRight > context->settings->DesktopWidth) ||
+ (cmd->destBottom > context->settings->DesktopHeight))
+ {
+ WLog_WARN(TAG,
+ "Invalid surface bits command rectangle: %" PRIu16 "x%" PRIu16 "-%" PRIu16
+ "x%" PRIu16 " does not fit %" PRIu32 "x%" PRIu32,
+ cmd->destLeft, cmd->destTop, cmd->destRight, cmd->destBottom,
+ context->settings->DesktopWidth, context->settings->DesktopHeight);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
static BOOL update_recv_surfcmd_surface_bits(rdpUpdate* update, wStream* s, UINT16 cmdType)
{
SURFACE_BITS_COMMAND cmd = { 0 };
@@ -98,6 +142,9 @@
Stream_Read_UINT16(s, cmd.destRight);
Stream_Read_UINT16(s, cmd.destBottom);
+ if (!update_recv_surfcmd_is_rect_valid(update->context, &cmd))
+ goto fail;
+
if (!update_recv_surfcmd_bitmap_ex(s, &cmd.bmp))
goto fail;
--- a/libfreerdp/core/update.c
+++ b/libfreerdp/core/update.c
@@ -99,6 +99,13 @@
Stream_Read_UINT16(s, bitmapData->flags);
Stream_Read_UINT16(s, bitmapData->bitmapLength);
+ if ((bitmapData->width == 0) || (bitmapData->height == 0))
+ {
+ WLog_ERR(TAG, "Invalid BITMAP_DATA: width=%" PRIu16 ", height=%" PRIu16, bitmapData->width,
+ bitmapData->height);
+ return FALSE;
+ }
+
if (bitmapData->flags & BITMAP_COMPRESSION)
{
if (!(bitmapData->flags & NO_BITMAP_COMPRESSION_HDR))

100
debian/patches/0052-CVE-2022-24883.patch vendored Normal file
View File

@ -0,0 +1,100 @@
Description: CVE-2022-24883 - FreeRDP Server authentication might allow invalid credentials to pass
Origin: https://github.com/FreeRDP/FreeRDP/commit/6f473b273a4b6f0cb6aca32b95e22fd0de88e144
Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-qxm3-v2r6-vmwf
From 6f473b273a4b6f0cb6aca32b95e22fd0de88e144 Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Fri, 22 Apr 2022 14:42:11 +0200
Subject: [PATCH] Cleaned up ntlm_fetch_ntlm_v2_hash
(cherry picked from commit 4661492e5a617199457c8074bad22f766a116cdc)
---
winpr/libwinpr/sspi/NTLM/ntlm_compute.c | 58 +++++++++++--------------
1 file changed, 25 insertions(+), 33 deletions(-)
--- a/winpr/libwinpr/sspi/NTLM/ntlm_compute.c
+++ b/winpr/libwinpr/sspi/NTLM/ntlm_compute.c
@@ -206,59 +206,48 @@
ntlm_current_time(context->Timestamp);
}
-static int ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash)
+static BOOL ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash)
{
- WINPR_SAM* sam;
- WINPR_SAM_ENTRY* entry;
+ BOOL rc = FALSE;
+ WINPR_SAM* sam = NULL;
+ WINPR_SAM_ENTRY* entry = NULL;
SSPI_CREDENTIALS* credentials = context->credentials;
sam = SamOpen(context->SamFile, TRUE);
if (!sam)
- return -1;
+ goto fail;
entry = SamLookupUserW(
- sam, (LPWSTR)credentials->identity.User, credentials->identity.UserLength * 2,
- (LPWSTR)credentials->identity.Domain, credentials->identity.DomainLength * 2);
+ sam, (LPWSTR)credentials->identity.User, credentials->identity.UserLength * sizeof(WCHAR),
+ (LPWSTR)credentials->identity.Domain, credentials->identity.DomainLength * sizeof(WCHAR));
- if (entry)
+ if (!entry)
{
-#ifdef WITH_DEBUG_NTLM
- WLog_DBG(TAG, "NTLM Hash:");
- winpr_HexDump(TAG, WLOG_DEBUG, entry->NtHash, 16);
-#endif
- NTOWFv2FromHashW(entry->NtHash, (LPWSTR)credentials->identity.User,
- credentials->identity.UserLength * 2, (LPWSTR)credentials->identity.Domain,
- credentials->identity.DomainLength * 2, (BYTE*)hash);
- SamFreeEntry(sam, entry);
- SamClose(sam);
- return 1;
+ entry = SamLookupUserW(sam, (LPWSTR)credentials->identity.User,
+ credentials->identity.UserLength * sizeof(WCHAR), NULL, 0);
}
+
+ if (!entry)
+ goto fail;
- entry = SamLookupUserW(sam, (LPWSTR)credentials->identity.User,
- credentials->identity.UserLength * 2, NULL, 0);
-
- if (entry)
- {
#ifdef WITH_DEBUG_NTLM
WLog_DBG(TAG, "NTLM Hash:");
winpr_HexDump(TAG, WLOG_DEBUG, entry->NtHash, 16);
#endif
- NTOWFv2FromHashW(entry->NtHash, (LPWSTR)credentials->identity.User,
- credentials->identity.UserLength * 2, (LPWSTR)credentials->identity.Domain,
- credentials->identity.DomainLength * 2, (BYTE*)hash);
- SamFreeEntry(sam, entry);
- SamClose(sam);
- return 1;
- }
- else
- {
- SamClose(sam);
- WLog_ERR(TAG, "Error: Could not find user in SAM database");
- return 0;
- }
+ NTOWFv2FromHashW(entry->NtHash, (LPWSTR)credentials->identity.User,
+ credentials->identity.UserLength * sizeof(WCHAR),
+ (LPWSTR)credentials->identity.Domain,
+ credentials->identity.DomainLength * sizeof(WCHAR), (BYTE*)hash);
+
+ rc = TRUE;
+
+fail:
+ SamFreeEntry(sam, entry);
SamClose(sam);
- return 1;
+ if (!rc)
+ WLog_ERR(TAG, "Error: Could not find user in SAM database");
+ return rc;
}
static int ntlm_convert_password_hash(NTLM_CONTEXT* context, BYTE* hash)

View File

@ -0,0 +1,50 @@
Description: CVE-2022-39316 - Out of bound read in zgfx decoder
Origin: https://github.com/FreeRDP/FreeRDP/commit/e865c24efc40ebc52e75979c94cdd4ee2c1495b0.patch
Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-5w4j-mrrh-jjrm
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1024511
From e865c24efc40ebc52e75979c94cdd4ee2c1495b0 Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Thu, 13 Oct 2022 09:09:28 +0200
Subject: [PATCH] Added missing length checks in zgfx_decompress_segment
(cherry picked from commit 64716b335858109d14f27b51acc4c4d71a92a816)
---
libfreerdp/codec/zgfx.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
--- a/libfreerdp/codec/zgfx.c
+++ b/libfreerdp/codec/zgfx.c
@@ -230,19 +230,19 @@
BYTE* pbSegment;
size_t cbSegment;
- if (!zgfx || !stream)
+ if (!zgfx || !stream || (segmentSize < 2))
return FALSE;
cbSegment = segmentSize - 1;
- if ((Stream_GetRemainingLength(stream) < segmentSize) || (segmentSize < 1) ||
- (segmentSize > UINT32_MAX))
+ if ((Stream_GetRemainingLength(stream) < segmentSize) || (segmentSize > UINT32_MAX))
return FALSE;
Stream_Read_UINT8(stream, flags); /* header (1 byte) */
zgfx->OutputCount = 0;
pbSegment = Stream_Pointer(stream);
- Stream_Seek(stream, cbSegment);
+ if (!Stream_SafeSeek(stream, cbSegment))
+ return FALSE;
if (!(flags & PACKET_COMPRESSED))
{
@@ -350,6 +350,9 @@
if (count > sizeof(zgfx->OutputBuffer) - zgfx->OutputCount)
return FALSE;
+ if (count > zgfx->cBitsRemaining / 8)
+ return FALSE;
+
CopyMemory(&(zgfx->OutputBuffer[zgfx->OutputCount]), zgfx->pbInputCurrent,
count);
zgfx_history_buffer_ring_write(zgfx, zgfx->pbInputCurrent, count);

View File

@ -0,0 +1,38 @@
Description: CVE-2022-39318 - Division by zero in urbdrc channel
Origin: https://github.com/FreeRDP/FreeRDP/commit/80adde17ddc4b596ed1dae0922a0c54ab3d4b8ea.patch
Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-387j-8j96-7q35
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1024511
From 80adde17ddc4b596ed1dae0922a0c54ab3d4b8ea Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Thu, 13 Oct 2022 08:27:41 +0200
Subject: [PATCH] Fixed division by zero in urbdrc
(cherry picked from commit 731f8419d04b481d7160de1f34062d630ed48765)
---
channels/urbdrc/client/libusb/libusb_udevice.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
--- a/channels/urbdrc/client/libusb/libusb_udevice.c
+++ b/channels/urbdrc/client/libusb/libusb_udevice.c
@@ -1214,12 +1214,18 @@
else
Stream_Seek(user_data->data, (NumberOfPackets * 12));
- iso_packet_size = BufferSize / NumberOfPackets;
- iso_transfer = libusb_alloc_transfer(NumberOfPackets);
+ if (NumberOfPackets > 0)
+ {
+ iso_packet_size = BufferSize / NumberOfPackets;
+ iso_transfer = libusb_alloc_transfer((int)NumberOfPackets);
+ }
if (iso_transfer == NULL)
{
- WLog_Print(urbdrc->log, WLOG_ERROR, "Error: libusb_alloc_transfer.");
+ WLog_Print(urbdrc->log, WLOG_ERROR,
+ "Error: libusb_alloc_transfer [NumberOfPackets=%" PRIu32 ", BufferSize=%" PRIu32
+ " ]",
+ NumberOfPackets, BufferSize);
async_transfer_user_data_free(user_data);
return -1;
}

View File

@ -0,0 +1,68 @@
Description: CVE-2022-39319 - Missing length validation in urbdrc channel
Origin: https://github.com/FreeRDP/FreeRDP/commit/11555828d2cf289b350baba5ad1f462f10b80b76
Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-mvxm-wfj2-5fvh
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1024511
From 11555828d2cf289b350baba5ad1f462f10b80b76 Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Thu, 13 Oct 2022 08:47:51 +0200
Subject: [PATCH] Fixed missing input buffer length check in urbdrc
(cherry picked from commit 497df00f741dd4fc89292aaef2db7368aee45d0d)
---
channels/urbdrc/client/data_transfer.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
--- a/channels/urbdrc/client/data_transfer.c
+++ b/channels/urbdrc/client/data_transfer.c
@@ -29,6 +29,10 @@
#include "urbdrc_types.h"
#include "data_transfer.h"
+#define Stream_CheckAndLogRequiredLength(tag, s, len) \
+ Stream_CheckAndLogRequiredLengthWLogEx(WLog_Get(tag), WLOG_WARN, s, len, "%s(%s:%" PRIuz ")", __FUNCTION__, \
+ __FILE__, __LINE__)
+
static void usb_process_get_port_status(IUDEVICE* pdev, wStream* out)
{
int bcdUSB = pdev->query_device_descriptor(pdev, BCD_USB);
@@ -241,6 +245,10 @@
Stream_Read_UINT32(s, OutputBufferSize);
Stream_Read_UINT32(s, RequestId);
+
+ if (OutputBufferSize > UINT32_MAX - 4)
+ return ERROR_INVALID_DATA;
+
InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
out = urb_create_iocompletion(InterfaceId, MessageId, RequestId, OutputBufferSize + 4);
@@ -720,6 +728,15 @@
Stream_Read_UINT32(s, TransferFlags); /** TransferFlags */
Stream_Read_UINT32(s, OutputBufferSize);
EndpointAddress = (PipeHandle & 0x000000ff);
+
+ if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
+ {
+ if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
+ {
+ return ERROR_INVALID_DATA;
+ }
+ }
+
/** process TS_URB_BULK_OR_INTERRUPT_TRANSFER */
return pdev->bulk_or_interrupt_transfer(pdev, callback, MessageId, RequestId, EndpointAddress,
TransferFlags, noAck, OutputBufferSize,
@@ -803,6 +820,13 @@
packetDescriptorData = Stream_Pointer(s);
Stream_Seek(s, NumberOfPackets * 12);
Stream_Read_UINT32(s, OutputBufferSize);
+
+ if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
+ {
+ if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
+ return ERROR_INVALID_DATA;
+ }
+
return pdev->isoch_transfer(
pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, StartFrame,
ErrorCount, noAck, packetDescriptorData, NumberOfPackets, OutputBufferSize,

329
debian/patches/0056-CVE-2022-39347.patch vendored Normal file
View File

@ -0,0 +1,329 @@
Description: CVE-2022-39347 - Missing path sanitation with `drive` channel
Origin: https://github.com/FreeRDP/FreeRDP/commit/027424c2c6c0991cb9c22f9511478229c9b17e5d
Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-c5xq-8v35-pffg
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1024511
From 027424c2c6c0991cb9c22f9511478229c9b17e5d Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Mon, 24 Oct 2022 10:41:55 +0200
Subject: [PATCH] Fixed path validation in drive channel
Check that canonical path is a subpath of the shared directory
(cherry picked from commit 844c94e6d0438fa7bd8ff8d5513c3f69c3018b85)
---
channels/drive/client/drive_file.c | 106 ++++++++++++++++++-----------
channels/drive/client/drive_file.h | 8 +--
channels/drive/client/drive_main.c | 8 +--
3 files changed, 73 insertions(+), 49 deletions(-)
--- a/channels/drive/client/drive_file.c
+++ b/channels/drive/client/drive_file.c
@@ -45,6 +45,45 @@
#include "drive_file.h"
+#include <assert.h>
+
+
+static int _wcsncmp(const WCHAR* string1, const WCHAR* string2, size_t count)
+{
+ assert(string1);
+ assert(string2);
+
+ for (size_t x = 0; x < count; x++)
+ {
+ const WCHAR a = string1[x];
+ const WCHAR b = string2[x];
+
+ if (a != b)
+ return (int)a - b;
+ else if ((a == '\0') || (b == '\0'))
+ return (int)a - b;
+ }
+ return 0;
+}
+
+static WCHAR* _wcsstr(const WCHAR* str, const WCHAR* strSearch)
+{
+ assert(str);
+ assert(strSearch);
+
+ if (strSearch[0] == '\0')
+ return (WCHAR*)str;
+
+ const size_t searchLen = _wcslen(strSearch);
+ while (*str)
+ {
+ if (_wcsncmp(str, strSearch, searchLen) == 0)
+ return (WCHAR*)str;
+ str++;
+ }
+ return NULL;
+}
+
#ifdef WITH_DEBUG_RDPDR
#define DEBUG_WSTR(msg, wstr) \
do \
@@ -61,10 +100,14 @@
} while (0)
#endif
-static void drive_file_fix_path(WCHAR* path)
+static BOOL drive_file_fix_path(WCHAR* path, size_t length)
{
size_t i;
- size_t length = _wcslen(path);
+
+ if ((length == 0) || (length > UINT32_MAX))
+ return FALSE;
+
+ assert(path);
for (i = 0; i < length; i++)
{
@@ -75,58 +118,82 @@
#ifdef WIN32
if ((length == 3) && (path[1] == L':') && (path[2] == L'/'))
- return;
+ return FALSE;
#else
if ((length == 1) && (path[0] == L'/'))
- return;
+ return FALSE;
#endif
if ((length > 0) && (path[length - 1] == L'/'))
path[length - 1] = L'\0';
+
+ return TRUE;
}
static WCHAR* drive_file_combine_fullpath(const WCHAR* base_path, const WCHAR* path,
- size_t PathLength)
+ size_t PathWCharLength)
{
- WCHAR* fullpath;
- size_t base_path_length;
+ BOOL ok = FALSE;
+ WCHAR* fullpath = NULL;
+ size_t length;
- if (!base_path || (!path && (PathLength > 0)))
- return NULL;
+ if (!base_path || (!path && (PathWCharLength > 0)))
+ goto fail;
- base_path_length = _wcslen(base_path) * 2;
- fullpath = (WCHAR*)calloc(1, base_path_length + PathLength + sizeof(WCHAR));
+ const size_t base_path_length = _wcsnlen(base_path, MAX_PATH);
+ length = base_path_length + PathWCharLength + 1;
+ fullpath = (WCHAR*)calloc(length, sizeof(WCHAR));
if (!fullpath)
+ goto fail;
+
+ CopyMemory(fullpath, base_path, base_path_length * sizeof(WCHAR));
+ if (path)
+ CopyMemory(&fullpath[base_path_length], path, PathWCharLength * sizeof(WCHAR));
+
+ if (!drive_file_fix_path(fullpath, length))
+ goto fail;
+
+ /* Ensure the path does not contain sequences like '..' */
+ const WCHAR dotdot[] = { '.', '.', '\0' };
+ if (_wcsstr(&fullpath[base_path_length], dotdot))
{
- WLog_ERR(TAG, "malloc failed!");
- return NULL;
+ char abuffer[MAX_PATH] = { 0 };
+ ConvertFromUnicode(CP_UTF8, 0, &fullpath[base_path_length], -1, (char**)&abuffer,
+ ARRAYSIZE(abuffer) - 1, NULL, NULL);
+
+ WLog_WARN(TAG, "[rdpdr] received invalid file path '%s' from server, aborting!",
+ &abuffer[base_path_length]);
+ goto fail;
}
- CopyMemory(fullpath, base_path, base_path_length);
- if (path)
- CopyMemory((char*)fullpath + base_path_length, path, PathLength);
- drive_file_fix_path(fullpath);
+ ok = TRUE;
+fail:
+ if (!ok)
+ {
+ free(fullpath);
+ fullpath = NULL;
+ }
return fullpath;
}
static BOOL drive_file_remove_dir(const WCHAR* path)
{
- WIN32_FIND_DATAW findFileData;
+ WIN32_FIND_DATAW findFileData = { 0 };
BOOL ret = TRUE;
- HANDLE dir;
- WCHAR* fullpath;
- WCHAR* path_slash;
- size_t base_path_length;
+ HANDLE dir = INVALID_HANDLE_VALUE;
+ WCHAR* fullpath = NULL;
+ WCHAR* path_slash = NULL;
+ size_t base_path_length = 0;
if (!path)
return FALSE;
- base_path_length = _wcslen(path) * 2;
- path_slash = (WCHAR*)calloc(1, base_path_length + sizeof(WCHAR) * 3);
+ base_path_length = _wcslen(path);
+ path_slash = (WCHAR*)calloc(base_path_length + 3, sizeof(WCHAR));
if (!path_slash)
{
@@ -134,12 +201,11 @@
return FALSE;
}
- CopyMemory(path_slash, path, base_path_length);
- path_slash[base_path_length / 2] = L'/';
- path_slash[base_path_length / 2 + 1] = L'*';
+ CopyMemory(path_slash, path, base_path_length * sizeof(WCHAR));
+ path_slash[base_path_length] = L'/';
+ path_slash[base_path_length + 1] = L'*';
DEBUG_WSTR("Search in %s", path_slash);
dir = FindFirstFileW(path_slash, &findFileData);
- path_slash[base_path_length / 2 + 1] = 0;
if (dir == INVALID_HANDLE_VALUE)
{
@@ -149,7 +215,7 @@
do
{
- size_t len = _wcslen(findFileData.cFileName);
+ const size_t len = _wcsnlen(findFileData.cFileName, ARRAYSIZE(findFileData.cFileName));
if ((len == 1 && findFileData.cFileName[0] == L'.') ||
(len == 2 && findFileData.cFileName[0] == L'.' && findFileData.cFileName[1] == L'.'))
@@ -157,7 +223,7 @@
continue;
}
- fullpath = drive_file_combine_fullpath(path_slash, findFileData.cFileName, len * 2);
+ fullpath = drive_file_combine_fullpath(path_slash, findFileData.cFileName, len);
DEBUG_WSTR("Delete %s", fullpath);
if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
@@ -333,13 +399,13 @@
return file->file_handle != INVALID_HANDLE_VALUE;
}
-DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 PathLength, UINT32 id,
- UINT32 DesiredAccess, UINT32 CreateDisposition, UINT32 CreateOptions,
- UINT32 FileAttributes, UINT32 SharedAccess)
+DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 PathWCharLength,
+ UINT32 id, UINT32 DesiredAccess, UINT32 CreateDisposition,
+ UINT32 CreateOptions, UINT32 FileAttributes, UINT32 SharedAccess)
{
DRIVE_FILE* file;
- if (!base_path || (!path && (PathLength > 0)))
+ if (!base_path || (!path && (PathWCharLength > 0)))
return NULL;
file = (DRIVE_FILE*)calloc(1, sizeof(DRIVE_FILE));
@@ -359,7 +425,7 @@
file->CreateDisposition = CreateDisposition;
file->CreateOptions = CreateOptions;
file->SharedAccess = SharedAccess;
- drive_file_set_fullpath(file, drive_file_combine_fullpath(base_path, path, PathLength));
+ drive_file_set_fullpath(file, drive_file_combine_fullpath(base_path, path, PathWCharLength));
if (!drive_file_init(file))
{
@@ -714,13 +780,10 @@
return FALSE;
fullpath = drive_file_combine_fullpath(file->basepath, (WCHAR*)Stream_Pointer(input),
- FileNameLength);
+ FileNameLength / sizeof(WCHAR));
if (!fullpath)
- {
- WLog_ERR(TAG, "drive_file_combine_fullpath failed!");
return FALSE;
- }
#ifdef _WIN32
@@ -759,7 +822,7 @@
}
BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYTE InitialQuery,
- const WCHAR* path, UINT32 PathLength, wStream* output)
+ const WCHAR* path, UINT32 PathWCharLength, wStream* output)
{
size_t length;
WCHAR* ent_path;
@@ -773,7 +836,7 @@
if (file->find_handle != INVALID_HANDLE_VALUE)
FindClose(file->find_handle);
- ent_path = drive_file_combine_fullpath(file->basepath, path, PathLength);
+ ent_path = drive_file_combine_fullpath(file->basepath, path, PathWCharLength);
/* open new search handle and retrieve the first entry */
file->find_handle = FindFirstFileW(ent_path, &file->find_data);
free(ent_path);
--- a/channels/drive/client/drive_file.h
+++ b/channels/drive/client/drive_file.h
@@ -51,9 +51,9 @@
UINT32 CreateOptions;
};
-DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 PathLength, UINT32 id,
- UINT32 DesiredAccess, UINT32 CreateDisposition, UINT32 CreateOptions,
- UINT32 FileAttributes, UINT32 SharedAccess);
+DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 PathWCharLength,
+ UINT32 id, UINT32 DesiredAccess, UINT32 CreateDisposition,
+ UINT32 CreateOptions, UINT32 FileAttributes, UINT32 SharedAccess);
BOOL drive_file_free(DRIVE_FILE* file);
BOOL drive_file_open(DRIVE_FILE* file);
@@ -64,6 +64,6 @@
BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UINT32 Length,
wStream* input);
BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYTE InitialQuery,
- const WCHAR* path, UINT32 PathLength, wStream* output);
+ const WCHAR* path, UINT32 PathWCharLength, wStream* output);
#endif /* FREERDP_CHANNEL_DRIVE_FILE_H */
--- a/channels/drive/client/drive_main.c
+++ b/channels/drive/client/drive_main.c
@@ -184,8 +184,8 @@
path = (const WCHAR*)Stream_Pointer(irp->input);
FileId = irp->devman->id_sequence++;
- file = drive_file_new(drive->path, path, PathLength, FileId, DesiredAccess, CreateDisposition,
- CreateOptions, FileAttributes, SharedAccess);
+ file = drive_file_new(drive->path, path, PathLength / sizeof(WCHAR), FileId, DesiredAccess,
+ CreateDisposition, CreateOptions, FileAttributes, SharedAccess);
if (!file)
{
@@ -636,8 +636,8 @@
irp->IoStatus = STATUS_UNSUCCESSFUL;
Stream_Write_UINT32(irp->output, 0); /* Length */
}
- else if (!drive_file_query_directory(file, FsInformationClass, InitialQuery, path, PathLength,
- irp->output))
+ else if (!drive_file_query_directory(file, FsInformationClass, InitialQuery, path,
+ PathLength / sizeof(WCHAR), irp->output))
{
irp->IoStatus = drive_map_windows_err(GetLastError());
}

View File

@ -0,0 +1,38 @@
Description: CVE-2022-41877
Origin: https://github.com/FreeRDP/FreeRDP/commit/6655841cf2a00b764f855040aecb8803cfc5eaba
Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-pmv3-wpw4-pw5h
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1024511
From 6655841cf2a00b764f855040aecb8803cfc5eaba Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Mon, 24 Oct 2022 08:45:05 +0200
Subject: [PATCH] Fixed missing stream length check in
drive_file_query_directory
(cherry picked from commit 4e4bb79795d6ac85473fb7a83e53ccf63d204b93)
---
channels/drive/client/drive_main.c | 3 +++
1 file changed, 3 insertions(+)
--- a/channels/drive/client/drive_main.c
+++ b/channels/drive/client/drive_main.c
@@ -46,6 +46,10 @@
#include "drive_file.h"
+#define Stream_CheckAndLogRequiredLength(tag, s, len) \
+ Stream_CheckAndLogRequiredLengthWLogEx(WLog_Get(tag), WLOG_WARN, s, len, "%s(%s:%" PRIuz ")", __FUNCTION__, \
+ __FILE__, __LINE__)
+
typedef struct _DRIVE_DEVICE DRIVE_DEVICE;
struct _DRIVE_DEVICE
@@ -629,6 +633,9 @@
Stream_Read_UINT32(irp->input, PathLength);
Stream_Seek(irp->input, 23); /* Padding */
path = (WCHAR*)Stream_Pointer(irp->input);
+ if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, PathLength))
+ return ERROR_INVALID_DATA;
+
file = drive_get_file_by_id(drive, irp->FileId);
if (file == NULL)

View File

@ -0,0 +1,38 @@
Description: CVE-2022-39282 - RDP client: Read of uninitialized memory with parallel port redirection
Origin: https://github.com/FreeRDP/FreeRDP/commit/60aac2abf0740dd36b62712fba91498fd6e055fe
Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-c45q-wcpg-mxjq
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1021659
From 60aac2abf0740dd36b62712fba91498fd6e055fe Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Thu, 6 Oct 2022 09:12:40 +0200
Subject: [PATCH] Fix length checks in parallel driver
The length requested was not checked against the length read from
the port.
(cherry picked from commit 094cc5a4596c299595b732effd59ee149181fd61)
---
channels/parallel/client/parallel_main.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/channels/parallel/client/parallel_main.c b/channels/parallel/client/parallel_main.c
index af3e82703a60..993605a65e23 100644
--- a/channels/parallel/client/parallel_main.c
+++ b/channels/parallel/client/parallel_main.c
@@ -159,7 +159,7 @@ static UINT parallel_process_irp_read(PARALLEL_DEVICE* parallel, IRP* irp)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(irp->input, Length);
Stream_Read_UINT64(irp->input, Offset);
- buffer = (BYTE*)malloc(Length);
+ buffer = (BYTE*)calloc(Length, sizeof(BYTE));
if (!buffer)
{
@@ -178,6 +178,7 @@ static UINT parallel_process_irp_read(PARALLEL_DEVICE* parallel, IRP* irp)
}
else
{
+ Length = status;
}
Stream_Write_UINT32(irp->output, Length);

View File

@ -0,0 +1,39 @@
Description: CVE-2022-39283 - RDP client might read out of bounds data and display it
Origin: https://github.com/FreeRDP/FreeRDP/commit/be793c3bb776c1bbda9156b427408d5a5eb00f70
Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-6cf9-3328-qrvh
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1021659
From be793c3bb776c1bbda9156b427408d5a5eb00f70 Mon Sep 17 00:00:00 2001
From: akallabeth <akallabeth@posteo.net>
Date: Thu, 6 Oct 2022 09:15:40 +0200
Subject: [PATCH] Fixed missing length check in video channel
Data received in video redirection channel was not checked for
proper length.
(cherry picked from commit eeffd1050e9284d1464b58e049b2b4d88726632b)
---
channels/video/client/video_main.c | 2 ++
1 file changed, 2 insertions(+)
--- a/channels/video/client/video_main.c
+++ b/channels/video/client/video_main.c
@@ -46,6 +46,10 @@
#include "video_main.h"
+#define Stream_CheckAndLogRequiredLength(tag, s, len) \
+ Stream_CheckAndLogRequiredLengthWLogEx(WLog_Get(tag), WLOG_WARN, s, len, "%s(%s:%" PRIuz ")", __FUNCTION__, \
+ __FILE__, __LINE__)
+
struct _VIDEO_CHANNEL_CALLBACK
{
IWTSVirtualChannelCallback iface;
@@ -930,6 +934,8 @@
Stream_Read_UINT16(s, data.PacketsInSample);
Stream_Read_UINT32(s, data.SampleNumber);
Stream_Read_UINT32(s, data.cbSample);
+ if (!Stream_CheckAndLogRequiredLength(TAG, s, data.cbSample))
+ return ERROR_INVALID_DATA;
data.pSample = Stream_Pointer(s);
/*

View File

@ -0,0 +1,38 @@
Description: Keep DumpThreadHandles as a symbol even if WITH_DEBUG_THREADS is OFF.
Author: Mike Gabriel <mike.gabriel@das-netzwerkteam.de>
Forwarded: https://github.com/FreeRDP/FreeRDP/pull/7708
--- a/winpr/libwinpr/thread/thread.c
+++ b/winpr/libwinpr/thread/thread.c
@@ -760,9 +760,9 @@
return TRUE;
}
-#if defined(WITH_DEBUG_THREADS)
VOID DumpThreadHandles(void)
{
+#if defined(WITH_DEBUG_THREADS)
char** msg;
size_t used, i;
void* stack = winpr_backtrace(20);
@@ -823,6 +823,6 @@
}
WLog_DBG(TAG, "---------------- End Dumping thread handles -------------");
-}
#endif
+}
#endif
--- a/winpr/include/winpr/thread.h
+++ b/winpr/include/winpr/thread.h
@@ -245,10 +245,7 @@
/* CommandLineToArgvA is not present in the original Windows API, WinPR always exports it */
WINPR_API LPSTR* CommandLineToArgvA(LPCSTR lpCmdLine, int* pNumArgs);
-
-#if defined(WITH_DEBUG_THREADS)
WINPR_API VOID DumpThreadHandles(void);
-#endif
#ifdef __cplusplus
}

26
debian/patches/series vendored
View File

@ -22,3 +22,29 @@
0033-Reverted-winpr_BinToHexString-argument-change.patch
0034-Fixed-6938-Remote-app-mode-clipboard-fix.patch
0035-Fixed-6989-Use-X509_STORE_set_default_paths.patch
1001_keep-symbol-DumpThreadHandles-if-debugging-is-disabled.patch
0036-CVE-2023-39350.patch
0037-CVE-2023-39351.patch
0038-CVE-2023-39352.patch
0039-CVE-2023-39353-part1.patch
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
0044-CVE-2023-40567.patch
0045-CVE-2023-40181.patch
0046-CVE-2023-40186.patch
0047-CVE-2023-40188.patch
0048-CVE-2023-40569.patch
0049-CVE-2023-40589.patch
0050-CVE-2021-41160.patch
0052-CVE-2022-24883.patch
0053-CVE-2022-39316.patch
0054-CVE-2022-39318.patch
0055-CVE-2022-39319.patch
0056-CVE-2022-39347.patch
0057-CVE-2022-41877.patch
0058-CVE-2022-39282.patch
0059-CVE-2022-39283.patch

2
debian/rules vendored
View File

@ -19,7 +19,7 @@ DEB_CMAKE_EXTRA_FLAGS = \
-DCMAKE_SKIP_RPATH=FALSE \
-DCMAKE_SKIP_INSTALL_RPATH=TRUE \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DWITH_DEBUG_ALL=ON \
-DWITH_DEBUG_ALL=OFF \
-DBUILD_TESTING=OFF \
-DWITH_CHANNELS=ON \
-DBUILTIN_CHANNELS=ON \