Version in base suite: 0.10.1-3.1+deb13u1 Base version: xrdp_0.10.1-3.1+deb13u1 Target version: xrdp_0.10.1-3.1+deb13u2 Base file: /srv/ftp-master.debian.org/ftp/pool/main/x/xrdp/xrdp_0.10.1-3.1+deb13u1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/x/xrdp/xrdp_0.10.1-3.1+deb13u2.dsc changelog | 30 ++++ patches/CVE-2026-32105-1.patch | 132 +++++++++++++++++++ patches/CVE-2026-32105-2.patch | 46 ++++++ patches/CVE-2026-32105-3.patch | 150 ++++++++++++++++++++++ patches/CVE-2026-32105-5.patch | 31 ++++ patches/CVE-2026-32107.patch | 271 +++++++++++++++++++++++++++++++++++++++ patches/CVE-2026-32623.patch | 162 +++++++++++++++++++++++ patches/CVE-2026-32624.patch | 43 ++++++ patches/CVE-2026-33145.patch | 43 ++++++ patches/CVE-2026-33516.patch | 53 +++++++ patches/CVE-2026-33689.patch | 23 +++ patches/CVE-2026-35512.patch | 69 ++++++++++ patches/CVE-2026-41252-1.patch | 47 ++++++ patches/CVE-2026-41252-2.patch | 52 +++++++ patches/CVE-2026-41521.patch | 80 +++++++++++ patches/CVE-2026-42218.patch | 84 ++++++++++++ patches/CVE-2026-44178.patch | 124 ++++++++++++++++++ patches/CVE-2026-44978.patch | 42 ++++++ patches/CVE-2026-54538.patch | 54 +++++++ patches/CVE-2026-55238.patch | 278 +++++++++++++++++++++++++++++++++++++++++ patches/CVE-2026-55639.patch | 23 +++ patches/CVE-2026-55645.patch | 23 +++ patches/series | 21 +++ 23 files changed, 1881 insertions(+) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmp2wz1p49m/xrdp_0.10.1-3.1+deb13u1.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmp2wz1p49m/xrdp_0.10.1-3.1+deb13u2.dsc: no acceptable signature found diff -Nru xrdp-0.10.1/debian/changelog xrdp-0.10.1/debian/changelog --- xrdp-0.10.1/debian/changelog 2026-02-03 06:09:05.000000000 +0000 +++ xrdp-0.10.1/debian/changelog 2026-08-13 08:44:56.000000000 +0000 @@ -1,3 +1,33 @@ +xrdp (0.10.1-3.1+deb13u2) trixie-security; urgency=high + + * Non-maintainer upload. + * CVE-CVE-2026-32105: modify encrypted traffic in transit without + detection (Closes: #1134339) + * CVE-2026-32107: improper privilege management allow attacker to + escalate privileges to root and execute arbitrary code. + * CVE-2026-32623: heap-based buffer overflow vulnerability + * CVE-2026-32624: heap-based buffer overflow vulnerability + * CVE-2026-33145: authenticated remote user to execute arbitrary + commands + * CVE-2026-33516: out-of-bounds read vulnerability + * CVE-2026-33689: out-of-bounds read vulnerability + * CVE-2026-35512: a heap-based buffer overflow + * CVE-2026-41252: missing bounds check in xrdp, which allows a + heap-based buffer overflow + * CVE-2026-41521: nteger overflow vulnerability + * CVE-2026-42218: a timing side-channel vulnerability in the login + interface + * CVE-2026-44178: heap-based buffer overflow vulnerability + * CVE-2026-44978: heap out-of-bounds read vulnerability + * CVE-2026-54538: sending a specially crafted packet that forces the + process into an infinite, CPU-bound loop + * CVE-2026-55238: Denial of Service + * CVE-2026-55639: exploit by specially crafted RDP malformed data + and read out-of-bound data block. + * CVE-2026-55645: out-of-bounds memory reads + + -- Abhijith PA Thu, 13 Aug 2026 14:14:56 +0530 + xrdp (0.10.1-3.1+deb13u1) trixie-security; urgency=high * Non-maintainer upload by the Security Team. diff -Nru xrdp-0.10.1/debian/patches/CVE-2026-32105-1.patch xrdp-0.10.1/debian/patches/CVE-2026-32105-1.patch --- xrdp-0.10.1/debian/patches/CVE-2026-32105-1.patch 1970-01-01 00:00:00.000000000 +0000 +++ xrdp-0.10.1/debian/patches/CVE-2026-32105-1.patch 2026-08-13 08:44:56.000000000 +0000 @@ -0,0 +1,132 @@ +From 5e8f889f3994fe04f3a9984c53b26c00ff81f7ea Mon Sep 17 00:00:00 2001 +From: matt335672 <30179339+matt335672@users.noreply.github.com> +Date: Tue, 10 Mar 2026 18:03:39 +0000 +Subject: [PATCH] security: Check HMAC on FIPS fastpath input + +CVE-2026-32105: Add a check that the HMAC signature supplied with a +FIPS fastpath input PDU matches the calculated signature. + +(cherry picked from commit 2a411f752591c0293a7698a452f00a46ef6c09bf) +--- + libxrdp/xrdp_sec.c | 87 +++++++++++++++++++++++++++++----------------- + 1 file changed, 56 insertions(+), 31 deletions(-) + +--- a/libxrdp/xrdp_sec.c ++++ b/libxrdp/xrdp_sec.c +@@ -1073,6 +1073,54 @@ xrdp_sec_hash_48(char *out, char *in, ch + } + + /*****************************************************************************/ ++/* Output a uint32 into a buffer (little-endian) */ ++static void ++buf_out_uint32(char *buffer, int value) ++{ ++ buffer[0] = (value) & 0xff; ++ buffer[1] = (value >> 8) & 0xff; ++ buffer[2] = (value >> 16) & 0xff; ++ buffer[3] = (value >> 24) & 0xff; ++} ++ ++/*****************************************************************************/ ++/* Generate a MAC hash (5.2.3.1), using SHA1 for outgoing data */ ++static void ++xrdp_sec_fips_sign(struct xrdp_sec *self, char *out, int out_len, ++ char *data, int data_len) ++{ ++ char buf[20]; ++ char lenhdr[4]; ++ ++ buf_out_uint32(lenhdr, self->encrypt_use_count); ++ ssl_hmac_sha1_init(self->sign_fips_info, self->fips_sign_key, 20); ++ ssl_hmac_transform(self->sign_fips_info, data, data_len); ++ ssl_hmac_transform(self->sign_fips_info, lenhdr, 4); ++ ssl_hmac_complete(self->sign_fips_info, buf, 20); ++ g_memcpy(out, buf, out_len); ++} ++ ++/*****************************************************************************/ ++/* Check a FIPS hash is valid */ ++static int ++xrdp_sec_fips_check_sig(struct xrdp_sec *self, const char *sig, int sig_len, ++ char *data, int data_len) ++{ ++ char buf[20]; ++ char lenhdr[4]; ++ ++ // Account for the decrypt operation which has just happened when ++ // creating the HMAC ++ buf_out_uint32(lenhdr, self->decrypt_use_count - 1); ++ ssl_hmac_sha1_init(self->sign_fips_info, self->fips_sign_key, 20); ++ ssl_hmac_transform(self->sign_fips_info, data, data_len); ++ ssl_hmac_transform(self->sign_fips_info, lenhdr, 4); ++ ssl_hmac_complete(self->sign_fips_info, buf, 20); ++ ++ return memcmp(buf, sig, sig_len) == 0; ++} ++ ++/*****************************************************************************/ + static void + xrdp_sec_hash_16(char *out, char *in, char *salt1, char *salt2) + { +@@ -1224,6 +1272,7 @@ xrdp_sec_recv_fastpath(struct xrdp_sec * + int ver; + int len; + int pad; ++ const char *data_signature; + + #ifndef USE_DEVEL_LOGGING + /* TODO: remove UNUSED_VAR once the `ver` variable is used for more than +@@ -1259,11 +1308,15 @@ xrdp_sec_recv_fastpath(struct xrdp_sec * + } + + /* remainder of TS_FP_INPUT_PDU */ +- in_uint8s(s, 8); /* dataSignature (8 bytes), skip for now */ +- LOG_DEVEL(LOG_LEVEL_TRACE, "CRYPT_LEVEL_FIPS - data len %d", +- (int)(s->end - s->p)); ++ in_uint8p(s, data_signature, 8); + xrdp_sec_fips_decrypt(self, s->p, (int)(s->end - s->p)); + s->end -= pad; ++ if (!xrdp_sec_fips_check_sig(self, data_signature, 8, ++ s->p, (int)(s->end - s->p))) ++ { ++ LOG(LOG_LEVEL_ERROR, "MAC checksum error for FP-FIPS PDU"); ++ return 1; ++ } + } + else + { +@@ -1456,34 +1509,6 @@ xrdp_sec_recv(struct xrdp_sec *self, str + } + + /*****************************************************************************/ +-/* Output a uint32 into a buffer (little-endian) */ +-static void +-buf_out_uint32(char *buffer, int value) +-{ +- buffer[0] = (value) & 0xff; +- buffer[1] = (value >> 8) & 0xff; +- buffer[2] = (value >> 16) & 0xff; +- buffer[3] = (value >> 24) & 0xff; +-} +- +-/*****************************************************************************/ +-/* Generate a MAC hash (5.2.3.1), using a combination of SHA1 and MD5 */ +-static void +-xrdp_sec_fips_sign(struct xrdp_sec *self, char *out, int out_len, +- char *data, int data_len) +-{ +- char buf[20]; +- char lenhdr[4]; +- +- buf_out_uint32(lenhdr, self->encrypt_use_count); +- ssl_hmac_sha1_init(self->sign_fips_info, self->fips_sign_key, 20); +- ssl_hmac_transform(self->sign_fips_info, data, data_len); +- ssl_hmac_transform(self->sign_fips_info, lenhdr, 4); +- ssl_hmac_complete(self->sign_fips_info, buf, 20); +- g_memcpy(out, buf, out_len); +-} +- +-/*****************************************************************************/ + /* Generate a MAC hash (5.2.3.1), using a combination of SHA1 and MD5 */ + static void + xrdp_sec_sign(struct xrdp_sec *self, char *out, int out_len, diff -Nru xrdp-0.10.1/debian/patches/CVE-2026-32105-2.patch xrdp-0.10.1/debian/patches/CVE-2026-32105-2.patch --- xrdp-0.10.1/debian/patches/CVE-2026-32105-2.patch 1970-01-01 00:00:00.000000000 +0000 +++ xrdp-0.10.1/debian/patches/CVE-2026-32105-2.patch 2026-08-13 08:44:56.000000000 +0000 @@ -0,0 +1,46 @@ +From a0b6151770f9343d0c7b8e31e3896466e8061676 Mon Sep 17 00:00:00 2001 +From: matt335672 <30179339+matt335672@users.noreply.github.com> +Date: Tue, 10 Mar 2026 18:24:40 +0000 +Subject: [PATCH] security: Check HMAC on FIPS slowpath input + +CVE-2026-32105: Add a check that the HMAC signature supplied with a +FIPS slowpath input PDU matches the calculated signature. + +(cherry picked from commit 0d8cf57e9d12393bd452a2b6cb1af0e38887d8a2) +--- + libxrdp/xrdp_sec.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +--- a/libxrdp/xrdp_sec.c ++++ b/libxrdp/xrdp_sec.c +@@ -1364,7 +1364,7 @@ xrdp_sec_recv(struct xrdp_sec *self, str + int len; + int ver; + int pad; +- ++ const char *data_signature; + + if (xrdp_mcs_recv(self->mcs_layer, s, chan) != 0) + { +@@ -1408,7 +1408,7 @@ xrdp_sec_recv(struct xrdp_sec *self, str + in_uint16_le(s, len); /* length */ + in_uint8(s, ver); /* version */ + in_uint8(s, pad); /* padlen */ +- in_uint8s(s, 8); /* signature(8) */ ++ in_uint8p(s, data_signature, 8); + LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [MS-RDPBCGR] TS_SECURITY_HEADER2 " + "length %d, version %d, padlen %d, dataSignature (ignored)", + len, ver, pad); +@@ -1426,6 +1426,12 @@ xrdp_sec_recv(struct xrdp_sec *self, str + } + xrdp_sec_fips_decrypt(self, s->p, (int)(s->end - s->p)); + s->end -= pad; ++ if (!xrdp_sec_fips_check_sig(self, data_signature, 8, ++ s->p, (int)(s->end - s->p))) ++ { ++ LOG(LOG_LEVEL_ERROR, "MAC checksum error for FIPS PDU"); ++ return 1; ++ } + } + else if (self->crypt_level > CRYPT_LEVEL_NONE) + { diff -Nru xrdp-0.10.1/debian/patches/CVE-2026-32105-3.patch xrdp-0.10.1/debian/patches/CVE-2026-32105-3.patch --- xrdp-0.10.1/debian/patches/CVE-2026-32105-3.patch 1970-01-01 00:00:00.000000000 +0000 +++ xrdp-0.10.1/debian/patches/CVE-2026-32105-3.patch 2026-08-13 08:44:56.000000000 +0000 @@ -0,0 +1,150 @@ +From 1cdfc764ac57133e4a0561697161b17383f5a06e Mon Sep 17 00:00:00 2001 +From: matt335672 <30179339+matt335672@users.noreply.github.com> +Date: Tue, 10 Mar 2026 20:33:15 +0000 +Subject: [PATCH] security: Check HMAC on non-FIPS slowpath input + +CVE-2026-32105: Add a check that the HMAC signature supplied with a +non-FIPS slowpath input PDU matches the calculated signature. + +(cherry picked from commit 759104912c64b33b2442ed788c1806e36d028db0) +--- + libxrdp/xrdp_sec.c | 104 +++++++++++++++++++++++++++++++-------------- + 1 file changed, 71 insertions(+), 33 deletions(-) + +--- a/libxrdp/xrdp_sec.c ++++ b/libxrdp/xrdp_sec.c +@@ -1101,7 +1101,10 @@ xrdp_sec_fips_sign(struct xrdp_sec *self + } + + /*****************************************************************************/ +-/* Check a FIPS hash is valid */ ++/* Check a FIPS hash is valid ++ * ++ * Result is boolean (i.e. != 0 is OK) ++ * */ + static int + xrdp_sec_fips_check_sig(struct xrdp_sec *self, const char *sig, int sig_len, + char *data, int data_len) +@@ -1121,6 +1124,66 @@ xrdp_sec_fips_check_sig(struct xrdp_sec + } + + /*****************************************************************************/ ++/* Generate a MAC hash (5.3.6.1), using a combination of SHA1 and MD5 ++ * ++ * Salted MAC is not currently supported */ ++static void ++xrdp_sec_sign(struct xrdp_sec *self, char *out, int out_len, ++ char *data, int data_len) ++{ ++ char shasig[20]; ++ char md5sig[16]; ++ char lenhdr[4]; ++ void *sha1_info; ++ void *md5_info; ++ ++ buf_out_uint32(lenhdr, data_len); ++ sha1_info = ssl_sha1_info_create(); ++ md5_info = ssl_md5_info_create(); ++ ssl_sha1_clear(sha1_info); ++ ssl_sha1_transform(sha1_info, self->sign_key, self->rc4_key_len); ++ ssl_sha1_transform(sha1_info, (char *)g_pad_54, 40); ++ ssl_sha1_transform(sha1_info, lenhdr, 4); ++ ssl_sha1_transform(sha1_info, data, data_len); ++ ssl_sha1_complete(sha1_info, shasig); ++ ssl_md5_clear(md5_info); ++ ssl_md5_transform(md5_info, self->sign_key, self->rc4_key_len); ++ ssl_md5_transform(md5_info, (char *)g_pad_92, 48); ++ ssl_md5_transform(md5_info, shasig, 20); ++ ssl_md5_complete(md5_info, md5sig); ++ g_memcpy(out, md5sig, out_len); ++ ssl_sha1_info_delete(sha1_info); ++ ssl_md5_info_delete(md5_info); ++} ++ ++/*****************************************************************************/ ++/* Check a non-FIPS hash is valid ++ * ++ * Salted MAC is not currently supported ++ * ++ * Result is boolean (i.e. != 0 is OK) */ ++static int ++xrdp_sec_check_sig(struct xrdp_sec *self, const char *sig, int sig_len, ++ char *data, int data_len) ++{ ++ char computed[8]; ++ int rv = 0; ++ if (sig_len > (int)sizeof(computed)) ++ { ++ LOG(LOG_LEVEL_ERROR, ++ "xrdp_sec_check_sig() Buffer overflow (got %d expected %d)", ++ sig_len, (int)sizeof(computed)); ++ } ++ else ++ { ++ xrdp_sec_sign(self, computed, sig_len, data, data_len); ++ rv = (memcmp(computed, sig, sig_len) == 0); ++ } ++ ++ return rv; ++} ++ ++/*****************************************************************************/ + static void + xrdp_sec_hash_16(char *out, char *in, char *salt1, char *salt2) + { +@@ -1440,10 +1503,16 @@ xrdp_sec_recv(struct xrdp_sec *self, str + return 1; + } + /* TS_SECURITY_HEADER1 */ +- in_uint8s(s, 8); /* signature(8) */ ++ in_uint8p(s, data_signature, 8); + LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [MS-RDPBCGR] TS_SECURITY_HEADER1 " + "dataSignature (ignored)"); + xrdp_sec_decrypt(self, s->p, (int)(s->end - s->p)); ++ if (!xrdp_sec_check_sig(self, data_signature, 8, ++ s->p, (int)(s->end - s->p))) ++ { ++ LOG(LOG_LEVEL_ERROR, "MAC checksum error for non-FIPS PDU"); ++ return 1; ++ } + } + } + +@@ -1515,37 +1584,6 @@ xrdp_sec_recv(struct xrdp_sec *self, str + } + + /*****************************************************************************/ +-/* Generate a MAC hash (5.2.3.1), using a combination of SHA1 and MD5 */ +-static void +-xrdp_sec_sign(struct xrdp_sec *self, char *out, int out_len, +- char *data, int data_len) +-{ +- char shasig[20]; +- char md5sig[16]; +- char lenhdr[4]; +- void *sha1_info; +- void *md5_info; +- +- buf_out_uint32(lenhdr, data_len); +- sha1_info = ssl_sha1_info_create(); +- md5_info = ssl_md5_info_create(); +- ssl_sha1_clear(sha1_info); +- ssl_sha1_transform(sha1_info, self->sign_key, self->rc4_key_len); +- ssl_sha1_transform(sha1_info, (char *)g_pad_54, 40); +- ssl_sha1_transform(sha1_info, lenhdr, 4); +- ssl_sha1_transform(sha1_info, data, data_len); +- ssl_sha1_complete(sha1_info, shasig); +- ssl_md5_clear(md5_info); +- ssl_md5_transform(md5_info, self->sign_key, self->rc4_key_len); +- ssl_md5_transform(md5_info, (char *)g_pad_92, 48); +- ssl_md5_transform(md5_info, shasig, 20); +- ssl_md5_complete(md5_info, md5sig); +- g_memcpy(out, md5sig, out_len); +- ssl_sha1_info_delete(sha1_info); +- ssl_md5_info_delete(md5_info); +-} +- +-/*****************************************************************************/ + /* returns error */ + int + xrdp_sec_send(struct xrdp_sec *self, struct stream *s, int chan) diff -Nru xrdp-0.10.1/debian/patches/CVE-2026-32105-5.patch xrdp-0.10.1/debian/patches/CVE-2026-32105-5.patch --- xrdp-0.10.1/debian/patches/CVE-2026-32105-5.patch 1970-01-01 00:00:00.000000000 +0000 +++ xrdp-0.10.1/debian/patches/CVE-2026-32105-5.patch 2026-08-13 08:44:56.000000000 +0000 @@ -0,0 +1,31 @@ +From 391aaf92f9f944a612b8187552c9a49dcf3a60a5 Mon Sep 17 00:00:00 2001 +From: matt335672 <30179339+matt335672@users.noreply.github.com> +Date: Tue, 10 Mar 2026 20:38:50 +0000 +Subject: [PATCH] security: Check HMAC on non-FIPS fastpath input + +CVE-2026-32105: Add a check that the HMAC signature supplied with a +non-FIPS fastpath input PDU matches the calculated signature. + +(cherry picked from commit 187d22cef89e8d60091d52e4abf64b82c49d57ee) +--- + libxrdp/xrdp_sec.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/libxrdp/xrdp_sec.c ++++ b/libxrdp/xrdp_sec.c +@@ -1389,8 +1389,14 @@ xrdp_sec_recv_fastpath(struct xrdp_sec * + return 1; + } + /* remainder of TS_FP_INPUT_PDU */ +- in_uint8s(s, 8); /* dataSignature (8 bytes), skip for now */ ++ in_uint8p(s, data_signature, 8); + xrdp_sec_decrypt(self, s->p, (int)(s->end - s->p)); ++ if (!xrdp_sec_check_sig(self, data_signature, 8, ++ s->p, (int)(s->end - s->p))) ++ { ++ LOG(LOG_LEVEL_ERROR, "MAC checksum error for FP-non-FIPS PDU"); ++ return 1; ++ } + } + } + diff -Nru xrdp-0.10.1/debian/patches/CVE-2026-32107.patch xrdp-0.10.1/debian/patches/CVE-2026-32107.patch --- xrdp-0.10.1/debian/patches/CVE-2026-32107.patch 1970-01-01 00:00:00.000000000 +0000 +++ xrdp-0.10.1/debian/patches/CVE-2026-32107.patch 2026-08-13 08:44:56.000000000 +0000 @@ -0,0 +1,271 @@ +Description: CVE-2026-32107 +Author: Abhijith PA + +Origin: https://github.com/neutrinolabs/xrdp/commit/68b5ae9e2e3b3e040fe2174aa5fc652f0c5c67d1 +Forwarded: not-needed +Last-Update: 2026-08-17 + +--- a/sesman/sesexec/env.c ++++ b/sesman/sesexec/env.c +@@ -91,7 +91,7 @@ env_check_password_file(const char *file + + /******************************************************************************/ + /* its the responsibility of the caller to free passwd_file */ +-int ++void + env_set_user(int uid, char **passwd_file, int display, + const struct list *env_names, const struct list *env_values) + { +@@ -114,64 +114,71 @@ env_set_user(int uid, char **passwd_file + error = g_getuser_info_by_uid(uid, &pw_username, &pw_gid, &pw_shell, + &pw_dir, 0); + +- if (error == 0) ++ if (error != 0) + { +- g_rm_temp_dir(); +- g_clearenv(); ++ LOG(LOG_LEVEL_ALWAYS, ++ "fatal error getting user info for uid %d: %s", uid, ++ g_get_strerror()); ++ goto fatal; ++ } ++ g_rm_temp_dir(); ++ g_clearenv(); + #ifdef HAVE_SETUSERCONTEXT +- error = g_set_allusercontext(uid); ++ if (g_set_allusercontext(uid) != 0) ++ { ++ LOG(LOG_LEVEL_ALWAYS, ++ "fatal error setting allusercontext for uid %d: %s", ++ uid, g_get_strerror()); ++ goto fatal; ++ } + #else + /* Set some of the things setusercontext() handles on other + * systems */ + +- /* Primary group. Note that secondary groups should already +- * have been set, if we're not using setusercontext() */ +- error = g_setgid(pw_gid); +- +- if (error == 0) +- { +- error = g_setuid(uid); +- } +- +- if (error == 0) +- { +- g_setenv("PATH", "/sbin:/bin:/usr/bin:/usr/local/bin", 1); +- } ++ /* GID/UID. Note that secondary groups should already ++ * have been set, if we're not using setusercontext() */ ++ if (g_setgid(pw_gid) != 0 || g_setuid(uid) != 0) ++ { ++ LOG(LOG_LEVEL_ALWAYS, ++ "fatal error getting setting uid:gid to %d:%d - %s", ++ uid, pw_gid, g_get_strerror()); ++ goto fatal; ++ } ++ g_setenv("PATH", "/sbin:/bin:/usr/bin:/usr/local/bin", 1); + #endif +- if (error == 0) +- { +- g_setenv("SHELL", pw_shell, 1); +- g_setenv("USER", pw_username, 1); +- g_setenv("LOGNAME", pw_username, 1); +- g_snprintf(text, sizeof(text), "%d", uid); +- g_setenv("UID", text, 1); +- g_setenv("HOME", pw_dir, 1); +- g_set_current_dir(pw_dir); +- g_snprintf(text, sizeof(text), ":%d.0", display); +- g_setenv("DISPLAY", text, 1); +- // Use our PID as the XRDP_SESSION value +- g_snprintf(text, sizeof(text), "%d", g_pid); +- g_setenv("XRDP_SESSION", text, 1); +- /* XRDP_SOCKET_PATH should be set here. It's used by +- * xorgxrdp and the pulseaudio plugin */ +- g_snprintf(text, sizeof(text), XRDP_SOCKET_PATH, uid); +- g_setenv("XRDP_SOCKET_PATH", text, 1); +- /* pulse sink socket */ +- g_snprintf(text, sizeof(text), CHANSRV_PORT_OUT_BASE_STR, display); +- g_setenv("XRDP_PULSE_SINK_SOCKET", text, 1); +- /* pulse source socket */ +- g_snprintf(text, sizeof(text), CHANSRV_PORT_IN_BASE_STR, display); +- g_setenv("XRDP_PULSE_SOURCE_SOCKET", text, 1); +- if ((env_names != 0) && (env_values != 0) && +- (env_names->count == env_values->count)) +- { +- for (index = 0; index < env_names->count; index++) ++ ++ g_setenv("SHELL", pw_shell, 1); ++ g_setenv("USER", pw_username, 1); ++ g_setenv("LOGNAME", pw_username, 1); ++ g_snprintf(text, sizeof(text), "%d", uid); ++ g_setenv("UID", text, 1); ++ g_setenv("HOME", pw_dir, 1); ++ g_set_current_dir(pw_dir); ++ g_snprintf(text, sizeof(text), ":%d.0", display); ++ g_setenv("DISPLAY", text, 1); ++ // Use our PID as the XRDP_SESSION value ++ g_snprintf(text, sizeof(text), "%d", g_pid); ++ g_setenv("XRDP_SESSION", text, 1); ++ /* XRDP_SOCKET_PATH should be set here. It's used by ++ * xorgxrdp and the pulseaudio plugin */ ++ g_snprintf(text, sizeof(text), XRDP_SOCKET_PATH, uid); ++ g_setenv("XRDP_SOCKET_PATH", text, 1); ++ /* pulse sink socket */ ++ g_snprintf(text, sizeof(text), CHANSRV_PORT_OUT_BASE_STR, display); ++ g_setenv("XRDP_PULSE_SINK_SOCKET", text, 1); ++ /* pulse source socket */ ++ g_snprintf(text, sizeof(text), CHANSRV_PORT_IN_BASE_STR, display); ++ g_setenv("XRDP_PULSE_SOURCE_SOCKET", text, 1); ++ if ((env_names != 0) && (env_values != 0) && ++ (env_names->count == env_values->count)) ++ { ++ for (index = 0; index < env_names->count; index++) + { + name = (char *) list_get_item(env_names, index), + value = (char *) list_get_item(env_values, index), + g_setenv(name, value, 1); + } +- } ++ } + g_gethostname(hostname, 255); + hostname[255] = 0; + if (passwd_file != 0) +@@ -194,63 +201,66 @@ env_set_user(int uid, char **passwd_file + pw_dir, pw_username, hostname, display); + ++len; // Allow for terminator + +- *passwd_file = (char *) g_malloc(len, 1); +- if (*passwd_file != NULL) +- { +- /* Try legacy names first, remove if found */ +- g_snprintf(*passwd_file, len, +- "%s/.vnc/sesman_%s_passwd:%d", +- pw_dir, pw_username, display); +- if (g_file_exist(*passwd_file)) +- { +- LOG(LOG_LEVEL_WARNING, "Removing old " +- "password file %s", *passwd_file); +- g_file_delete(*passwd_file); +- } +- g_snprintf(*passwd_file, len, +- "%s/.vnc/sesman_%s_passwd", +- pw_dir, pw_username); +- if (g_file_exist(*passwd_file)) +- { +- LOG(LOG_LEVEL_WARNING, "Removing insecure " +- "password file %s", *passwd_file); +- g_file_delete(*passwd_file); +- } +- g_snprintf(*passwd_file, len, +- "%s/.vnc/sesman_passwd-%s@%s:%d", +- pw_dir, pw_username, hostname, display); +- } +- } +- else ++ *passwd_file = (char *) g_malloc(len, 1); ++ if (*passwd_file != NULL) ++ { ++ /* Try legacy names first, remove if found */ ++ g_snprintf(*passwd_file, len, ++ "%s/.vnc/sesman_%s_passwd:%d", ++ pw_dir, pw_username, display); ++ if (g_file_exist(*passwd_file)) + { +- /* we use auth_file_path as requested */ +- len = g_snprintf(NULL, 0, g_cfg->auth_file_path, pw_username); + +- ++len; // Allow for terminator +- *passwd_file = (char *) g_malloc(len, 1); +- if (*passwd_file != NULL) +- { +- g_snprintf(*passwd_file, len, +- g_cfg->auth_file_path, pw_username); +- } ++ LOG(LOG_LEVEL_WARNING, "Removing old " ++ "password file %s", *passwd_file); ++ g_file_delete(*passwd_file); + } + +- if (*passwd_file != NULL) ++ g_snprintf(*passwd_file, len, ++ "%s/.vnc/sesman_%s_passwd", ++ pw_dir, pw_username); ++ ++ if (g_file_exist(*passwd_file)) + { +- LOG_DEVEL(LOG_LEVEL_DEBUG, "pass file: %s", *passwd_file); ++ LOG(LOG_LEVEL_WARNING, "Removing insecure " ++ "password file %s", *passwd_file); ++ g_file_delete(*passwd_file); + } ++ g_snprintf(*passwd_file, len, ++ "%s/.vnc/sesman_passwd-%s@%s:%d", ++ pw_dir, pw_username, hostname, display); + } + +- g_free(pw_username); +- g_free(pw_dir); +- g_free(pw_shell); ++ } ++ else ++ { ++ /* we use auth_file_path as requested */ ++ len = g_snprintf(NULL, 0, g_cfg->auth_file_path, pw_username); ++ ++len; // Allow for terminator ++ *passwd_file = (char *) g_malloc(len, 1); ++ if (*passwd_file != NULL) ++ { ++ g_snprintf(*passwd_file, len, ++ g_cfg->auth_file_path, pw_username); ++ } + } +- } +- else +- { +- LOG(LOG_LEVEL_ERROR, +- "error getting user info for uid %d", uid); +- } + +- return error; ++ if (*passwd_file != NULL) ++ { ++ LOG_DEVEL(LOG_LEVEL_DEBUG, "pass file: %s", *passwd_file); ++ } ++ ++ } ++ g_free(pw_username); ++ g_free(pw_dir); ++ g_free(pw_shell); ++ ++ ++ return; ++ ++fatal: ++ g_free(pw_username); ++ g_free(pw_dir); ++ g_free(pw_shell); ++ g_exit(1); + } +--- a/sesman/sesexec/env.h ++++ b/sesman/sesexec/env.h +@@ -46,10 +46,14 @@ env_check_password_file(const char *file + * @param uid user ID + * @param passwd_file VNC password file + * @param display The session display +- * @return 0 on success, g_getuser_info() error codes on error ++ * @param env_names List of session environment variables to set ++ * @param env_values List of session environment values to set ++ * ++ * On error, the calling process exits, to prevent privilege ++ * escalations. + * + */ +-int ++void + env_set_user(int uid, char **passwd_file, int display, + const struct list *env_names, const struct list *env_values); + diff -Nru xrdp-0.10.1/debian/patches/CVE-2026-32623.patch xrdp-0.10.1/debian/patches/CVE-2026-32623.patch --- xrdp-0.10.1/debian/patches/CVE-2026-32623.patch 1970-01-01 00:00:00.000000000 +0000 +++ xrdp-0.10.1/debian/patches/CVE-2026-32623.patch 2026-08-13 08:44:56.000000000 +0000 @@ -0,0 +1,162 @@ +From b6b610f5f7bba56fcd355bb2131adffd2ba19e5a Mon Sep 17 00:00:00 2001 +From: matt335672 <30179339+matt335672@users.noreply.github.com> +Date: Mon, 9 Mar 2026 14:20:35 +0000 +Subject: [PATCH] CVE-2026-32623: vulns in neutrinordp fragment reassembly + +This PR addresses potential buffer overflows in fragment reassembly in +the neutrinordp shim by adding length and status checks. + +(cherry picked from commit 3f0f7df6ffc639092b872600ac263db3af6bd643) +--- + neutrinordp/xrdp-neutrinordp.c | 109 +++++++++++++++++++++++++++++---- + 1 file changed, 96 insertions(+), 13 deletions(-) + +diff --git a/neutrinordp/xrdp-neutrinordp.c b/neutrinordp/xrdp-neutrinordp.c +index e320a6f87c..57a67ace13 100644 +--- a/neutrinordp/xrdp-neutrinordp.c ++++ b/neutrinordp/xrdp-neutrinordp.c +@@ -481,7 +481,6 @@ lxrdp_event(struct mod *mod, int msg, long param1, long param2, + size = (int)param2; + data = (char *)param3; + total_size = (int)param4; +- + LOG_DEVEL(LOG_LEVEL_DEBUG, "lxrdp_event: client to server ,chanid= %d flags= %d", chanid, flags); + + if ((chanid < 0) || (chanid >= mod->inst->settings->num_channels)) +@@ -490,40 +489,124 @@ lxrdp_event(struct mod *mod, int msg, long param1, long param2, + break; + } + ++ if (size < 0 || total_size < 0) ++ { ++ LOG(LOG_LEVEL_ERROR, "Bad WM_CHANNEL_DATA received"); ++ g_free(mod->chan_buf); ++ mod->chan_buf = NULL; ++ mod->chan_buf_bytes = 0; ++ mod->chan_buf_valid = 0; ++ break; ++ } ++ + lchid = mod->inst->settings->channels[chanid].channel_id; + + switch (flags & 3) + { + case 3: +- mod->inst->SendChannelData(mod->inst, lchid, (tui8 *)data, total_size); ++ if (mod->chan_buf != NULL) ++ { ++ // This shouldn't happen. Lose the fragments we have ++ LOG(LOG_LEVEL_WARNING, ++ "WM_CHANNEL_DATA - unexpected full chunk received"); ++ g_free(mod->chan_buf); ++ mod->chan_buf = NULL; ++ mod->chan_buf_bytes = 0; ++ mod->chan_buf_valid = 0; ++ } ++ if (size != total_size) ++ { ++ LOG(LOG_LEVEL_ERROR, ++ "WM_CHANNEL_DATA - inconsistent full chunk size"); ++ } ++ else ++ { ++ mod->inst->SendChannelData(mod->inst, lchid, (tui8 *)data, total_size); ++ } + break; + + case 2: + /* end */ +- g_memcpy(mod->chan_buf + mod->chan_buf_valid, data, size); +- mod->chan_buf_valid += size; +- mod->inst->SendChannelData(mod->inst, lchid, (tui8 *)(mod->chan_buf), +- total_size); ++ if (size != (mod->chan_buf_bytes - mod->chan_buf_valid)) ++ { ++ LOG(LOG_LEVEL_ERROR, ++ "WM_CHANNEL_DATA - bad end fragment size." ++ " Was %d s/b %d", ++ size, mod->chan_buf_bytes - mod->chan_buf_valid); ++ } ++ else ++ { ++ g_memcpy(mod->chan_buf + mod->chan_buf_valid, data, size); ++ mod->chan_buf_valid += size; ++ mod->inst->SendChannelData(mod->inst, lchid, (tui8 *)(mod->chan_buf), ++ total_size); ++ } + g_free(mod->chan_buf); +- mod->chan_buf = 0; ++ mod->chan_buf = NULL; + mod->chan_buf_bytes = 0; + mod->chan_buf_valid = 0; + break; + + case 1: + /* start */ ++ if (mod->chan_buf != NULL) ++ { ++ // This shouldn't happen ++ LOG(LOG_LEVEL_WARNING, ++ "WM_CHANNEL_DATA - unexpected start chunk received"); ++ } + g_free(mod->chan_buf); +- mod->chan_buf = (char *)g_malloc(total_size, 0); +- mod->chan_buf_bytes = total_size; ++ mod->chan_buf = NULL; ++ mod->chan_buf_bytes = 0; + mod->chan_buf_valid = 0; +- g_memcpy(mod->chan_buf + mod->chan_buf_valid, data, size); +- mod->chan_buf_valid += size; ++ if (size > total_size) ++ { ++ LOG(LOG_LEVEL_ERROR, ++ "WM_CHANNEL_DATA - bad start fragment size"); ++ } ++ else ++ { ++ if (total_size == 0) ++ { ++ // Nothing in the specification disallows this, ++ // but it seems pathological ++ mod->chan_buf = (char *)g_malloc(1, 0); ++ } ++ else ++ { ++ mod->chan_buf = (char *)g_malloc(total_size, 0); ++ } ++ if (mod->chan_buf == NULL) ++ { ++ LOG(LOG_LEVEL_ERROR, ++ "WM_CHANNEL_DATA - can't allocate %d bytes", ++ total_size); ++ } ++ else ++ { ++ mod->chan_buf_bytes = total_size; ++ g_memcpy(mod->chan_buf, data, size); ++ mod->chan_buf_valid += size; ++ } ++ } + break; + + default: + /* middle */ +- g_memcpy(mod->chan_buf + mod->chan_buf_valid, data, size); +- mod->chan_buf_valid += size; ++ if (size > (mod->chan_buf_bytes - mod->chan_buf_valid)) ++ { ++ LOG(LOG_LEVEL_ERROR, ++ "WM_CHANNEL_DATA - oversized middle fragment"); ++ g_free(mod->chan_buf); ++ mod->chan_buf = NULL; ++ mod->chan_buf_bytes = 0; ++ mod->chan_buf_valid = 0; ++ } ++ else ++ { ++ g_memcpy(mod->chan_buf + mod->chan_buf_valid, data, size); ++ mod->chan_buf_valid += size; ++ } + break; + } + diff -Nru xrdp-0.10.1/debian/patches/CVE-2026-32624.patch xrdp-0.10.1/debian/patches/CVE-2026-32624.patch --- xrdp-0.10.1/debian/patches/CVE-2026-32624.patch 1970-01-01 00:00:00.000000000 +0000 +++ xrdp-0.10.1/debian/patches/CVE-2026-32624.patch 2026-08-13 08:44:56.000000000 +0000 @@ -0,0 +1,43 @@ +From 4594d4ed9198f5fa6c1f2eb03fac96110a4e0ebb Mon Sep 17 00:00:00 2001 +From: matt335672 <30179339+matt335672@users.noreply.github.com> +Date: Fri, 6 Mar 2026 11:03:48 +0000 +Subject: [PATCH] CVE-2026-32624: buffer overflow if domain sep used + +Check the username buffer is not overflowed if the domain separator +feature is used. + +(cherry picked from commit f1a2bec41560ccc420931d94f07a18c31141c069) +--- + libxrdp/xrdp_sec.c | 21 +++++++++++++++++---- + 1 file changed, 17 insertions(+), 4 deletions(-) + +--- a/libxrdp/xrdp_sec.c ++++ b/libxrdp/xrdp_sec.c +@@ -861,10 +861,23 @@ xrdp_sec_process_logon_info(struct xrdp_ + if (self->rdp_layer->client_info.domain_user_separator[0] != '\0' + && self->rdp_layer->client_info.domain[0] != '\0') + { +- LOG(LOG_LEVEL_DEBUG, "Client supplied domain with user name. Overwriting user name with user name parsed from domain."); +- int size = sizeof(self->rdp_layer->client_info.username); +- g_strncat(self->rdp_layer->client_info.username, self->rdp_layer->client_info.domain_user_separator, size - 1 - g_strlen(self->rdp_layer->client_info.domain_user_separator)); +- g_strncat(self->rdp_layer->client_info.username, self->rdp_layer->client_info.domain, size - 1 - g_strlen(self->rdp_layer->client_info.domain)); ++ // Check the composite string is not too long ++ unsigned int size = ++ g_strlen(self->rdp_layer->client_info.username) + ++ g_strlen(self->rdp_layer->client_info.domain_user_separator) + ++ g_strlen(self->rdp_layer->client_info.domain); ++ ++ if (size >= sizeof(self->rdp_layer->client_info.username)) ++ { ++ LOG(LOG_LEVEL_ERROR, "Username/domain is too long"); ++ return 1; ++ } ++ LOG(LOG_LEVEL_DEBUG, "Client supplied domain with user name." ++ " Overwriting user name with user name parsed from domain."); ++ g_strcat(self->rdp_layer->client_info.username, ++ self->rdp_layer->client_info.domain_user_separator); ++ g_strcat(self->rdp_layer->client_info.username, ++ self->rdp_layer->client_info.domain); + } + + if (ts_info_utf16_in(s, len_program, self->rdp_layer->client_info.program, sizeof(self->rdp_layer->client_info.program)) != 0) diff -Nru xrdp-0.10.1/debian/patches/CVE-2026-33145.patch xrdp-0.10.1/debian/patches/CVE-2026-33145.patch --- xrdp-0.10.1/debian/patches/CVE-2026-33145.patch 1970-01-01 00:00:00.000000000 +0000 +++ xrdp-0.10.1/debian/patches/CVE-2026-33145.patch 2026-08-13 08:44:56.000000000 +0000 @@ -0,0 +1,43 @@ +Description: CVE-2026-33145 +Author: Abhijith PA +Bug-Debian: https://bugs.debian.org/1134339 +Origin: https://github.com/neutrinolabs/xrdp/commit/4174e61f38e5ebf79dade7b30634e998311e573f.patch +Forwarded: not-needed +Last-Update: 2026-08-24 + +--- xrdp-0.10.1.orig/docs/man/sesman.ini.5.in ++++ xrdp-0.10.1/docs/man/sesman.ini.5.in +@@ -301,7 +301,8 @@ if the group specified in \fBTerminalSer + + .TP + \fBAllowAlternateShell\fR=\fI[true|false]\fR +-If set to \fB0\fR, \fBfalse\fR or \fBno\fR, prevent usage of alternate shells by users. ++Set to \fB1\fR, \fBtrue\fR or \fByes\fR, to allow alternate shells to ++be specified by users. + + .TP + \fBXorgNoNewPrivileges\fR=\fI[true|false]\fR +--- xrdp-0.10.1.orig/sesman/libsesman/sesman_config.c ++++ xrdp-0.10.1/sesman/libsesman/sesman_config.c +@@ -309,7 +309,7 @@ config_read_security(int file, struct co + sc->login_retry = 3; + sc->restrict_outbound_clipboard = 0; + sc->restrict_inbound_clipboard = 0; +- sc->allow_alternate_shell = 1; ++ sc->allow_alternate_shell = 0; + sc->xorg_no_new_privileges = 1; + sc->ts_users = g_strdup(""); + sc->ts_admins = g_strdup(""); +--- xrdp-0.10.1.orig/sesman/sesman.ini ++++ xrdp-0.10.1/sesman/sesman.ini +@@ -37,8 +37,8 @@ RestrictOutboundClipboard=none + ; false: an alias of none + ; yes: an alias of all + RestrictInboundClipboard=none +-; Set to 'no' to prevent users from logging in with alternate shells +-#AllowAlternateShell=true ++; Set to 'yes' to allow users to log in with alternate shells ++#AllowAlternateShell=no + ; On Linux systems, the Xorg X11 server is normally invoked using + ; no_new_privs to avoid problems if the executable is suid. This may, + ; however, interfere with the use of security modules such as AppArmor. diff -Nru xrdp-0.10.1/debian/patches/CVE-2026-33516.patch xrdp-0.10.1/debian/patches/CVE-2026-33516.patch --- xrdp-0.10.1/debian/patches/CVE-2026-33516.patch 1970-01-01 00:00:00.000000000 +0000 +++ xrdp-0.10.1/debian/patches/CVE-2026-33516.patch 2026-08-13 08:44:56.000000000 +0000 @@ -0,0 +1,53 @@ +From d2a8802c3124c103cd0c40aba661602420d01a73 Mon Sep 17 00:00:00 2001 +From: matt335672 <30179339+matt335672@users.noreply.github.com> +Date: Thu, 2 Apr 2026 11:23:42 +0100 +Subject: [PATCH] CVE-2026-33516 : Address potential OOB read + +The codec list processing code contains a potential out-of-bounds +read, as the length check comes after the data is read. + +(cherry picked from commit 6831249bed8785c9f6cbbdf0dcddaad597705832) +--- + libxrdp/xrdp_caps.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/libxrdp/xrdp_caps.c b/libxrdp/xrdp_caps.c +index c304add3fb..b3382bdef7 100644 +--- a/libxrdp/xrdp_caps.c ++++ b/libxrdp/xrdp_caps.c +@@ -578,26 +578,27 @@ xrdp_caps_process_codecs(struct xrdp_rdp *self, struct stream *s, int len) + { + codec_guid = s->p; + +- g_memcpy(guid.g, s->p, GUID_SIZE); +- guid_to_str(&guid, codec_guid_str); +- +- if (len < 16 + 1 + 2) ++ if (len < GUID_SIZE + 1 + 2) + { +- LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_codecs: error"); ++ LOG(LOG_LEVEL_ERROR, "Short codec data received"); + return 1; + } +- in_uint8s(s, 16); ++ ++ in_uint8a(s, guid.g, GUID_SIZE); + in_uint8(s, codec_id); + in_uint16_le(s, codec_properties_length); +- len -= 16 + 1 + 2; ++ len -= GUID_SIZE + 1 + 2; ++ + if (len < codec_properties_length) + { +- LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_codecs: error"); ++ LOG(LOG_LEVEL_ERROR, "Short codec properties"); + return 1; + } + len -= codec_properties_length; + next_guid = s->p + codec_properties_length; + ++ guid_to_str(&guid, codec_guid_str); ++ + if (g_memcmp(codec_guid, XR_CODEC_GUID_NSCODEC, 16) == 0) + { + LOG(LOG_LEVEL_INFO, "xrdp_caps_process_codecs: NSCodec(%s), codec id [%d], properties len [%d]", diff -Nru xrdp-0.10.1/debian/patches/CVE-2026-33689.patch xrdp-0.10.1/debian/patches/CVE-2026-33689.patch --- xrdp-0.10.1/debian/patches/CVE-2026-33689.patch 1970-01-01 00:00:00.000000000 +0000 +++ xrdp-0.10.1/debian/patches/CVE-2026-33689.patch 2026-08-13 08:44:56.000000000 +0000 @@ -0,0 +1,23 @@ +From d1323f9bb0caebdb9ca46627579954c25599ed25 Mon Sep 17 00:00:00 2001 +From: matt335672 <30179339+matt335672@users.noreply.github.com> +Date: Mon, 23 Mar 2026 13:42:50 +0000 +Subject: [PATCH] CVE-2026-33689: Fix length check on channel open + +A check for at least two bytes remaining in a buffer should be 4 bytes. + +(cherry picked from commit 3c131a9f5e2bd01fff4f5912c324ffad0fc71ab6) +--- + xrdp/xrdp_mm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/xrdp/xrdp_mm.c ++++ b/xrdp/xrdp_mm.c +@@ -2242,7 +2242,7 @@ xrdp_mm_trans_process_drdynvc_channel_op + char name[1024 + 1]; + struct xrdp_drdynvc_procs procs; + +- if (!s_check_rem(s, 2)) ++ if (!s_check_rem(s, 4)) + { + return 1; + } diff -Nru xrdp-0.10.1/debian/patches/CVE-2026-35512.patch xrdp-0.10.1/debian/patches/CVE-2026-35512.patch --- xrdp-0.10.1/debian/patches/CVE-2026-35512.patch 1970-01-01 00:00:00.000000000 +0000 +++ xrdp-0.10.1/debian/patches/CVE-2026-35512.patch 2026-08-13 08:44:56.000000000 +0000 @@ -0,0 +1,69 @@ +From 8c407ce3ed690100fd9fd259c506f526ab74ee5f Mon Sep 17 00:00:00 2001 +From: matt335672 <30179339+matt335672@users.noreply.github.com> +Date: Wed, 1 Apr 2026 10:49:51 +0100 +Subject: [PATCH] CVE-2026-35512: Heap overflow in dynvc processing + +Length checking for the EGFX dynamic virtual channel is inadequate, +allowing for heap overflows to be forced by a malicious client before +authentication. + +(cherry picked from commit 41a4af0a362724f4e7899dc98ac388b2d7e09df4) +--- + libxrdp/xrdp_channel.c | 11 ++++++++++- + xrdp/xrdp_egfx.c | 9 ++++++--- + 2 files changed, 16 insertions(+), 4 deletions(-) + +--- a/libxrdp/xrdp_channel.c ++++ b/libxrdp/xrdp_channel.c +@@ -468,6 +468,15 @@ drdynvc_process_data_first(struct xrdp_c + "ChannelId %d, Length %d, Data (omitted from the log)", + chan_id, total_bytes); + ++ // See [MS-RDPBCGR] 2.2.3 ++ if (total_bytes < 1590 || bytes > total_bytes) ++ { ++ LOG(LOG_LEVEL_ERROR, ++ "Badly formed DYNVC_DATA_FIRST PDU received on dynamic channel %d", ++ chan_id); ++ return 1; ++ } ++ + session = self->sec_layer->rdp_layer->session; + if (chan_id > 255) + { +@@ -513,7 +522,7 @@ drdynvc_process_data(struct xrdp_channel + session = self->sec_layer->rdp_layer->session; + if (chan_id > 255) + { +- LOG(LOG_LEVEL_ERROR, "Received message for an invalid " ++ LOG(LOG_LEVEL_ERROR, "Received DYNVC_DATA PDU for an invalid " + "channel id. channel id %d", chan_id); + return 1; + } +--- a/xrdp/xrdp_egfx.c ++++ b/xrdp/xrdp_egfx.c +@@ -973,10 +973,12 @@ xrdp_egfx_data_first(intptr_t id, int ch + egfx = process->wm->mm->egfx; + if (egfx->s != NULL) + { +- LOG(LOG_LEVEL_DEBUG, "xrdp_egfx_data_first: Error!" +- " Stream is not working on initial data received!"); ++ LOG(LOG_LEVEL_ERROR, "DYNVC_DATA_FIRST PDU received while" ++ " another stream is active on channel %d", chan_id); ++ return 1; + } + make_stream(egfx->s); ++ // Caller has checked total_bytes is >= 0 and bytes is < total_bytes + init_stream(egfx->s, total_bytes); + out_uint8a(egfx->s, data, bytes); + return 0; +@@ -1031,7 +1033,8 @@ xrdp_egfx_data(intptr_t id, int chan_id, + } + if (!s_check_rem_out(egfx->s, bytes)) + { +- LOG(LOG_LEVEL_DEBUG, "xrdp_egfx_data: error"); ++ LOG(LOG_LEVEL_ERROR, "DYNVC_DATA PDU data overflow on channel %d", ++ chan_id); + return 1; + } + out_uint8a(egfx->s, data, bytes); diff -Nru xrdp-0.10.1/debian/patches/CVE-2026-41252-1.patch xrdp-0.10.1/debian/patches/CVE-2026-41252-1.patch --- xrdp-0.10.1/debian/patches/CVE-2026-41252-1.patch 1970-01-01 00:00:00.000000000 +0000 +++ xrdp-0.10.1/debian/patches/CVE-2026-41252-1.patch 2026-08-13 08:44:56.000000000 +0000 @@ -0,0 +1,47 @@ +From a64b788f24d8f5c133b75cee2f920b1258e3fb09 Mon Sep 17 00:00:00 2001 +From: matt335672 <30179339+matt335672@users.noreply.github.com> +Date: Wed, 15 Apr 2026 10:50:10 +0100 +Subject: [PATCH] CVE-2026-41252: lib_palette_update Heap Buffer Overflow + +(cherry picked from commit 9834a58ca65018d09b04ed7550dfa71aecb09b10) +--- + vnc/vnc.c | 7 +++++++ + vnc/vnc.h | 4 +++- + 2 files changed, 10 insertions(+), 1 deletion(-) + +--- a/vnc/vnc.c ++++ b/vnc/vnc.c +@@ -1439,6 +1439,13 @@ lib_palette_update(struct vnc *v) + in_uint8s(s, 1); + in_uint16_be(s, first_color); + in_uint16_be(s, num_colors); ++ if ((first_color + num_colors) > VNC_PALETTE_SIZE) ++ { ++ LOG(LOG_LEVEL_ERROR, "lib_palette_update: palette overflow"); ++ free_stream(s); ++ return 1; ++ } ++ + init_stream(s, 8192); + error = trans_force_read_s(v->trans, s, num_colors * 6); + } +--- a/vnc/vnc.h ++++ b/vnc/vnc.h +@@ -73,6 +73,8 @@ struct source_info; + /* Defined in vnc_clip.c */ + struct vnc_clipboard_data; + ++#define VNC_PALETTE_SIZE 256 ++ + /* Defined in xrdp_client_info.h */ + struct monitor_info; + +@@ -162,7 +164,7 @@ struct vnc + int server_bpp; + char mod_name[256]; + int mod_mouse_state; +- int palette[256]; ++ int palette[VNC_PALETTE_SIZE]; + int vnc_desktop; + char username[256]; + char password[256]; diff -Nru xrdp-0.10.1/debian/patches/CVE-2026-41252-2.patch xrdp-0.10.1/debian/patches/CVE-2026-41252-2.patch --- xrdp-0.10.1/debian/patches/CVE-2026-41252-2.patch 1970-01-01 00:00:00.000000000 +0000 +++ xrdp-0.10.1/debian/patches/CVE-2026-41252-2.patch 2026-08-13 08:44:56.000000000 +0000 @@ -0,0 +1,52 @@ +Description: CVE-2026-41252 +Author: Abhijith PA + +Origin: https://github.com/neutrinolabs/xrdp/commit/b07b78f1.patch +Forwarded: not-needed +Last-Update: 2026-08-24 + +--- xrdp-0.10.1.orig/xrdp/xrdp.ini ++++ xrdp-0.10.1/xrdp/xrdp.ini +@@ -263,18 +263,31 @@ port=-1 + #chansrvport=DISPLAY(0) + + ; Generic VNC Proxy +-; Tailor this to specific hosts and VNC instances by specifying an ip ++; To use this, remove the '#-#' prefix from the lines below. Tailor ++; the section to specific hosts and VNC instances by specifying an ip + ; and port and setting a suitable name. +-[vnc-any] +-name=vnc-any +-lib=libvnc.so +-ip=ask +-port=ask5900 +-username=na +-password=ask +-#pamusername=asksame +-#pampassword=asksame +-#delay_ms=2000 ++; This can be used with no customisations in test environments, but ++; should always be locked down to specific hosts and/or ports in ++; production. ++#-#[vnc-any] ++#-#name=vnc-any ++#-#lib=libvnc.@lib_extension@ ++#-#ip=ask ++#-#port=ask5900 ++#-#username=na ++#-#password=ask ++#-##pamusername=asksame ++#-##pampassword=asksame ++#-##delay_ms=2000 ++#-#; Use one of these to connect to a chansrv instance created outside of sesman ++#-#; (e.g. as part of an x11vnc console session). Replace 'n' with the ++#-#; display number of the session, and (if applicable) 'u' with the numeric ++#-#; UID of the session. ++#-#; ++#-#; If 'username' or 'pamusername' is set, you probably don't need to use ++#-#; the two parameter variant with 'u'. ++#-##chansrvport=DISPLAY(n) ++#-##chansrvport=DISPLAY(n,u) + + ; Generic RDP proxy using NeutrinoRDP + ; Tailor this to specific hosts by specifying an ip and port and setting diff -Nru xrdp-0.10.1/debian/patches/CVE-2026-41521.patch xrdp-0.10.1/debian/patches/CVE-2026-41521.patch --- xrdp-0.10.1/debian/patches/CVE-2026-41521.patch 1970-01-01 00:00:00.000000000 +0000 +++ xrdp-0.10.1/debian/patches/CVE-2026-41521.patch 2026-08-13 08:44:56.000000000 +0000 @@ -0,0 +1,80 @@ +From 1179d6b737b59024e70a0b223652656947a3047c Mon Sep 17 00:00:00 2001 +From: matt335672 <30179339+matt335672@users.noreply.github.com> +Date: Wed, 15 Apr 2026 11:35:39 +0100 +Subject: [PATCH] CVE-2026-41521: [V0.10] lib_framebuffer_update int overflow + +An integer overflow can lead to possible heap info leak and ASLR +bypass. + +(cherry picked from commit 2a94fc967465b7b569056d1607d9a98e14291515) +--- + vnc/vnc.c | 35 +++++++++++++++++++++++++++++++---- + 1 file changed, 31 insertions(+), 4 deletions(-) + +--- a/vnc/vnc.c ++++ b/vnc/vnc.c +@@ -30,6 +30,8 @@ + #include + #endif + ++#include ++ + #include "vnc.h" + #include "vnc_clip.h" + #include "rfb.h" +@@ -918,6 +920,21 @@ skip_encoding(struct vnc *v, int x, int + } + + /**************************************************************************//** ++ * Checks the size parameters from a framebuffer update are sane ++ * @param cx Width of update ++ * @param cy height of update ++ * @return 0 if the proposed sizes could result in overflow ++ * ++ * [MS-RDPBCGR] allows for a max desktop size of 32766 x 32766. ++ * Each pixel needs up to 4 bytes ++ */ ++static int ++framebuffer_update_size_ok(int cx, int cy) ++{ ++ return (cx <= 32766 && cy <= 32766 && (cx * cy) <= (INT_MAX / 4)); ++} ++ ++/**************************************************************************//** + * Parses an entire framebuffer update message from the wire, and returns the + * first matching ExtendedDesktopSize encoding if found. + * +@@ -975,9 +992,15 @@ find_matching_extended_rect(struct vnc * + in_uint16_be(s, cy); + in_uint32_be(s, encoding); + +- if (encoding == RFB_ENC_EXTENDED_DESKTOP_SIZE && +- !found && +- match(x, y, cx, cy)) ++ if (!framebuffer_update_size_ok(cx, cy)) ++ { ++ LOG(LOG_LEVEL_ERROR, ++ "find_matching_extended_rect: Frame buffer too large"); ++ error = 1; ++ } ++ else if (encoding == RFB_ENC_EXTENDED_DESKTOP_SIZE && ++ !found && ++ match(x, y, cx, cy)) + { + LOG(LOG_LEVEL_DEBUG, + "VNC matched ExtendedDesktopSize rectangle " +@@ -1291,7 +1314,13 @@ lib_framebuffer_update(struct vnc *v) + in_uint16_be(s, cy); + in_uint32_be(s, encoding); + +- if (encoding == RFB_ENC_RAW) ++ if (!framebuffer_update_size_ok(cx, cy)) ++ { ++ LOG(LOG_LEVEL_ERROR, ++ "lib_framebuffer_update: Frame buffer too large"); ++ error = 1; ++ } ++ else if (encoding == RFB_ENC_RAW) + { + need_size = cx * cy * get_bytes_per_pixel(v->server_bpp); + init_stream(pixel_s, need_size); diff -Nru xrdp-0.10.1/debian/patches/CVE-2026-42218.patch xrdp-0.10.1/debian/patches/CVE-2026-42218.patch --- xrdp-0.10.1/debian/patches/CVE-2026-42218.patch 1970-01-01 00:00:00.000000000 +0000 +++ xrdp-0.10.1/debian/patches/CVE-2026-42218.patch 2026-08-13 08:44:56.000000000 +0000 @@ -0,0 +1,84 @@ +From 13bbb975d49c7e2e328322c3ea052c9d01d53092 Mon Sep 17 00:00:00 2001 +From: matt335672 <30179339+matt335672@users.noreply.github.com> +Date: Mon, 27 Apr 2026 10:19:57 +0100 +Subject: [PATCH] CVE-2026-42218: Ensure auth fails take a fixed time + +Implement a constant time for password-based authentication failure. + +(cherry picked from commit 07479384a694153a96ec1acbfe7af425d1d4a322) +--- + sesman/sesexec/login_info.c | 28 +++++++++++++++++++++++++++- + 1 file changed, 27 insertions(+), 1 deletion(-) + +--- a/sesman/sesexec/login_info.c ++++ b/sesman/sesexec/login_info.c +@@ -41,6 +41,17 @@ + #include "sesexec.h" + #include "string_calls.h" + ++// Sys login fails all take a fixed time before returning. This ++// prevents an attacker using timing differences to determine ++// information about the users on the system (CVE-2026-42218) ++// ++// Note that some systems may provide an upper time bound for ++// a login failure that is higher than this. For example, the Linux ++// PAM stack default sys login fail time is around 2000 milli-seconds. ++// Consequently, it is important the auth stack is always called, even ++// if it has been determined that this is unnecessary. ++#define FAILED_LOGIN_CONSTANT_TIME 600 // milli-seconds ++ + /******************************************************************************/ + /** + * Logs an authentication failure message +@@ -72,7 +83,6 @@ log_authfail_message(const char *usernam + * @return Status for the operation + * + * @post If E_SCP_LOGIN_OK is returned, g_login_info is filled in +- * + */ + static enum scp_login_status + authenticate_and_authorize_connection(const char *supplied_username, +@@ -84,6 +94,7 @@ authenticate_and_authorize_connection(co + char *username; // From reverse-looking up the UID + enum scp_login_status status; + struct auth_info *auth_info; ++ int start_time = g_time3(); + + if (g_getuser_info_by_name(supplied_username, + &uid, NULL, NULL, NULL, NULL) != 0) +@@ -93,6 +104,11 @@ authenticate_and_authorize_connection(co + supplied_username); + log_authfail_message(supplied_username, ip_addr); + status = E_SCP_LOGIN_NOT_AUTHENTICATED; ++ ++ /* Call the auth stack anyway. On some systems (e.g. linux-pam), ++ * a fixed delay is built in to the stack for an unsuccessful ++ * login, and this delay may exceed FAILED_LOGIN_CONSTANT_TIME */ ++ auth_end(auth_userpass(supplied_username, password, ip_addr, NULL)); + } + else if (g_getuser_info_by_uid(uid, + &username, +@@ -100,6 +116,7 @@ authenticate_and_authorize_connection(co + { + LOG(LOG_LEVEL_ERROR, "Can't reverse lookup UID %d", uid); + status = E_SCP_LOGIN_NOT_AUTHENTICATED; ++ auth_end(auth_userpass(supplied_username, password, ip_addr, NULL)); + } + else + { +@@ -179,6 +196,15 @@ authenticate_and_authorize_connection(co + + g_free(username); + } ++ ++ if (status != E_SCP_LOGIN_OK) ++ { ++ int elapsed_ms = g_time3() - start_time; ++ if (elapsed_ms > 0 && elapsed_ms < FAILED_LOGIN_CONSTANT_TIME) ++ { ++ g_sleep(FAILED_LOGIN_CONSTANT_TIME - elapsed_ms); ++ } ++ } + return status; + } + diff -Nru xrdp-0.10.1/debian/patches/CVE-2026-44178.patch xrdp-0.10.1/debian/patches/CVE-2026-44178.patch --- xrdp-0.10.1/debian/patches/CVE-2026-44178.patch 1970-01-01 00:00:00.000000000 +0000 +++ xrdp-0.10.1/debian/patches/CVE-2026-44178.patch 2026-08-13 08:44:56.000000000 +0000 @@ -0,0 +1,124 @@ +From 43dc9c3b71e5e46733d70ec0239c482ee264cd9f Mon Sep 17 00:00:00 2001 +From: matt335672 <30179339+matt335672@users.noreply.github.com> +Date: Mon, 20 Apr 2026 13:15:17 +0100 +Subject: [PATCH] CVE-2026-44178: Heap overflow in xrdp->chansrv msgs + +Some xrdp -> chansrv messages allocate a fixed-size buffer which +can be overflowed by a malicious RDP client. + +(cherry picked from commit 679faa64bc05a3959fcac888f36a768fad7dcce1) +--- + xrdp/xrdp_mm.c | 65 ++++++++++++++++++++++++++++---------------------- + 1 file changed, 36 insertions(+), 29 deletions(-) + +--- a/xrdp/xrdp_mm.c ++++ b/xrdp/xrdp_mm.c +@@ -2178,16 +2178,19 @@ xrdp_mm_drdynvc_data_first(intptr_t id, + + pro = (struct xrdp_process *) id; + wm = pro->wm; ++ // Size of PDU sent to chansrv ++ int pdu_size = 8 + 8 + 4 + 4 + 4 + bytes; ++ + trans = wm->mm->chan_trans; +- s = trans_get_out_s(trans, 8192); ++ s = trans_get_out_s(trans, pdu_size); + if (s == NULL) + { + return 1; + } + out_uint32_le(s, 0); /* version */ +- out_uint32_le(s, 8 + 8 + 4 + 4 + 4 + bytes); ++ out_uint32_le(s, pdu_size); + out_uint32_le(s, 17); /* msg id */ +- out_uint32_le(s, 8 + 4 + 4 + 4 + bytes); ++ out_uint32_le(s, pdu_size - 8); + chansrv_chan_id = wm->mm->xr2cr_cid_map[chan_id]; + out_uint32_le(s, chansrv_chan_id); + out_uint32_le(s, bytes); +@@ -2210,16 +2213,19 @@ xrdp_mm_drdynvc_data(intptr_t id, int ch + + pro = (struct xrdp_process *) id; + wm = pro->wm; ++ // Size of PDU sent to chansrv ++ int pdu_size = 8 + 8 + 4 + 4 + bytes; ++ + trans = wm->mm->chan_trans; +- s = trans_get_out_s(trans, 8192); ++ s = trans_get_out_s(trans, pdu_size); + if (s == NULL) + { + return 1; + } + out_uint32_le(s, 0); /* version */ +- out_uint32_le(s, 8 + 8 + 4 + 4 + bytes); ++ out_uint32_le(s, pdu_size); + out_uint32_le(s, 19); /* msg id */ +- out_uint32_le(s, 8 + 4 + 4 + bytes); ++ out_uint32_le(s, pdu_size - 8); + chansrv_chan_id = wm->mm->xr2cr_cid_map[chan_id]; + out_uint32_le(s, chansrv_chan_id); + out_uint32_le(s, bytes); +@@ -2615,38 +2621,39 @@ int + xrdp_mm_process_channel_data(struct xrdp_mm *self, tbus param1, tbus param2, + tbus param3, tbus param4) + { +- struct stream *s; +- int rv; +- int length; +- int total_length; +- int flags; +- int id; +- char *data; +- +- rv = 0; ++ int rv = 0; + + if ((self->chan_trans != 0) && self->chan_trans->status == TRANS_STATUS_UP) + { +- s = trans_get_out_s(self->chan_trans, 8192); ++ int id = LOWORD(param1); ++ int flags = HIWORD(param1); ++ int length = param2; ++ const char *data = (const char *)param3; ++ int total_length = param4; + +- if (s != 0) ++ // Check passed-in lengths ++ if (length > 65535) + { +- id = LOWORD(param1); +- flags = HIWORD(param1); +- length = param2; +- data = (char *)param3; +- total_length = param4; ++ LOG(LOG_LEVEL_ERROR, "xrdp_mm_process_channel_data(): length overflow"); ++ return 1; ++ } + +- if (total_length < length) +- { +- LOG(LOG_LEVEL_WARNING, "WARNING in xrdp_mm_process_channel_data(): total_len < length"); +- total_length = length; +- } ++ if (total_length < length) ++ { ++ LOG(LOG_LEVEL_ERROR, "xrdp_mm_process_channel_data(): total_len < length"); ++ return 1; ++ } ++ ++ // Size of PDU sent to chansrv ++ int pdu_size = 8 + 8 + 2 + 2 + 2 + 4 + length; + ++ struct stream *s = trans_get_out_s(self->chan_trans, pdu_size); ++ if (s != 0) ++ { + out_uint32_le(s, 0); /* version */ +- out_uint32_le(s, 8 + 8 + 2 + 2 + 2 + 4 + length); ++ out_uint32_le(s, pdu_size); + out_uint32_le(s, 5); /* msg id */ +- out_uint32_le(s, 8 + 2 + 2 + 2 + 4 + length); ++ out_uint32_le(s, pdu_size - 8); + out_uint16_le(s, id); + out_uint16_le(s, flags); + out_uint16_le(s, length); diff -Nru xrdp-0.10.1/debian/patches/CVE-2026-44978.patch xrdp-0.10.1/debian/patches/CVE-2026-44978.patch --- xrdp-0.10.1/debian/patches/CVE-2026-44978.patch 1970-01-01 00:00:00.000000000 +0000 +++ xrdp-0.10.1/debian/patches/CVE-2026-44978.patch 2026-08-13 08:44:56.000000000 +0000 @@ -0,0 +1,42 @@ +From d308e77c3d115b6528e6cf9df0861838f31606ab Mon Sep 17 00:00:00 2001 +From: matt335672 <30179339+matt335672@users.noreply.github.com> +Date: Wed, 6 May 2026 11:40:08 +0100 +Subject: [PATCH] CVE-2026-44978: Check FIPS PDU padding value before use + +(cherry picked from commit e42951868bcd2da2088da58fa20b31c1e2268c06 +--- + libxrdp/xrdp_sec.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/libxrdp/xrdp_sec.c ++++ b/libxrdp/xrdp_sec.c +@@ -1385,7 +1385,14 @@ xrdp_sec_recv_fastpath(struct xrdp_sec * + + /* remainder of TS_FP_INPUT_PDU */ + in_uint8p(s, data_signature, 8); ++ // Decrypt the packet, and subtract the padding length, ++ // after checking the validity + xrdp_sec_fips_decrypt(self, s->p, (int)(s->end - s->p)); ++ if (pad > 7 || pad > (int)(s->end - s->p)) ++ { ++ LOG(LOG_LEVEL_ERROR, "Bad padding for TS_FP_FIPS_INFO PDU"); ++ return 1; ++ } + s->end -= pad; + if (!xrdp_sec_fips_check_sig(self, data_signature, 8, + s->p, (int)(s->end - s->p))) +@@ -1506,7 +1513,14 @@ xrdp_sec_recv(struct xrdp_sec *self, str + "has unexpected version. Expected 1, actual %d", ver); + return 1; + } ++ // Decrypt the packet, and subtract the padding length, ++ // after checking the validity + xrdp_sec_fips_decrypt(self, s->p, (int)(s->end - s->p)); ++ if (pad > 7 || pad > (int)(s->end - s->p)) ++ { ++ LOG(LOG_LEVEL_ERROR, "Bad padding for TS_SECURITY_HEADER2 PDU"); ++ return 1; ++ } + s->end -= pad; + if (!xrdp_sec_fips_check_sig(self, data_signature, 8, + s->p, (int)(s->end - s->p))) diff -Nru xrdp-0.10.1/debian/patches/CVE-2026-54538.patch xrdp-0.10.1/debian/patches/CVE-2026-54538.patch --- xrdp-0.10.1/debian/patches/CVE-2026-54538.patch 1970-01-01 00:00:00.000000000 +0000 +++ xrdp-0.10.1/debian/patches/CVE-2026-54538.patch 2026-08-13 08:44:56.000000000 +0000 @@ -0,0 +1,54 @@ +From 9a610fc2f297613790bc91086b183ca81d06e6f5 Mon Sep 17 00:00:00 2001 +From: matt335672 <30179339+matt335672@users.noreply.github.com> +Date: Mon, 15 Jun 2026 11:52:25 +0100 +Subject: [PATCH] CVE-2026-54538: Pre-auth infinite loop in + TS_SHARECONTROLHEADER + +(cherry picked from commit 2394084bf46a8716ceeb66d1feccb65055d707dd) +--- + libxrdp/xrdp_rdp.c | 31 +++++++++++++++++-------------- + 1 file changed, 17 insertions(+), 14 deletions(-) + +--- a/libxrdp/xrdp_rdp.c ++++ b/libxrdp/xrdp_rdp.c +@@ -535,23 +535,26 @@ xrdp_rdp_recv(struct xrdp_rdp *self, str + { + s->next_packet = 0; + *code = 0; +- LOG(LOG_LEVEL_ERROR, "xrdp_rdp_recv: out code 0 (skip data) " +- "bad RDP packet"); +- return 0; ++ LOG(LOG_LEVEL_ERROR, "xrdp_rdp_recv: out code 0 bad RDP packet"); ++ return 1; + } +- else ++ in_uint16_le(s, len); /* totalLength */ ++ in_uint16_le(s, pdu_code); /* pduType */ ++ in_uint8s(s, 2); /* pduSource */ ++ // Length must be at least the size of TS_SHARECONTROLHEADER, and ++ // cannot fall beyond the end of the PDU ++ if (len < 6 || !s_check_rem(s, len - 6)) + { +- in_uint16_le(s, len); /* totalLength */ +- in_uint16_le(s, pdu_code); /* pduType */ +- *code = pdu_code & 0xf; +- in_uint8s(s, 2); /* pduSource */ +- s->next_packet += len; +- LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [MS-RDPBCGR] TS_SHARECONTROLHEADER " +- "totalLength %d, pduType.type %s (%d), pduType.PDUVersion %d, " +- "pduSource (ignored)", len, PDUTYPE_TO_STR(*code), *code, +- ((pdu_code & 0xfff0) >> 4)); +- return 0; ++ LOG(LOG_LEVEL_ERROR, "bad TS_SHARECONTROLHEADER length 0x%04X", len); ++ return 1; + } ++ *code = pdu_code & 0xf; ++ s->next_packet += len; ++ LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [MS-RDPBCGR] TS_SHARECONTROLHEADER " ++ "totalLength %d, pduType.type %s (%d), pduType.PDUVersion %d, " ++ "pduSource (ignored)", len, PDUTYPE_TO_STR(*code), *code, ++ ((pdu_code & 0xfff0) >> 4)); ++ return 0; + } + + /*****************************************************************************/ diff -Nru xrdp-0.10.1/debian/patches/CVE-2026-55238.patch xrdp-0.10.1/debian/patches/CVE-2026-55238.patch --- xrdp-0.10.1/debian/patches/CVE-2026-55238.patch 1970-01-01 00:00:00.000000000 +0000 +++ xrdp-0.10.1/debian/patches/CVE-2026-55238.patch 2026-08-13 08:44:56.000000000 +0000 @@ -0,0 +1,278 @@ +From 1d7477b5a5db0cfef482ce43a7752df9feaf67a4 Mon Sep 17 00:00:00 2001 +From: matt335672 <30179339+matt335672@users.noreply.github.com> +Date: Thu, 11 Jun 2026 16:32:06 +0100 +Subject: [PATCH] CVE-2026-55238: Possible OOB reads in capability processing + +Add missing per-capability length checks in the RDP Confirm Active PDU +parser, and abort the parser if a buffer length violation is discovered. + +(cherry picked from commit 4aa8bdf1eac3aab7e166393913019edf9616008c) +--- + libxrdp/xrdp_caps.c | 132 ++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 108 insertions(+), 24 deletions(-) + +diff --git a/libxrdp/xrdp_caps.c b/libxrdp/xrdp_caps.c +index b3382bdef7..f33c144e4a 100644 +--- a/libxrdp/xrdp_caps.c ++++ b/libxrdp/xrdp_caps.c +@@ -415,6 +415,11 @@ xrdp_caps_process_input(struct xrdp_rdp *self, struct stream *s, + int inputFlags; + int client_does_fastpath_input; + ++ if (len < 2) ++ { ++ LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_input: missing data"); ++ return 1; ++ } + in_uint16_le(s, inputFlags); + client_does_fastpath_input = (inputFlags & INPUT_FLAG_FASTPATH_INPUT) || + (inputFlags & INPUT_FLAG_FASTPATH_INPUT2); +@@ -668,6 +673,11 @@ xrdp_caps_process_multifragmentupdate(struct xrdp_rdp *self, struct stream *s, + { + int MaxRequestSize; + ++ if (len < 4) ++ { ++ LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_multifragmentupdate: missing data"); ++ return 1; ++ } + in_uint32_le(s, MaxRequestSize); + if (self->client_info.use_fast_path & 1) + { +@@ -683,6 +693,11 @@ xrdp_caps_process_largepointer(struct xrdp_rdp *self, struct stream *s, + { + int largePointerSupportFlags; + ++ if (len < 2) ++ { ++ LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_largepointer: missing data"); ++ return 1; ++ } + in_uint16_le(s, largePointerSupportFlags); + self->client_info.large_pointer_support_flags = largePointerSupportFlags; + return 0; +@@ -692,16 +707,25 @@ xrdp_caps_process_largepointer(struct xrdp_rdp *self, struct stream *s, + static int + xrdp_caps_process_frame_ack(struct xrdp_rdp *self, struct stream *s, int len) + { ++ int max_count; + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_process_frame_ack:"); ++ if (len < 4) ++ { ++ LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_frame_ack: missing data"); ++ return 1; ++ } + self->client_info.use_frame_acks = 1; +- in_uint32_le(s, self->client_info.max_unacknowledged_frame_count); +- if (self->client_info.max_unacknowledged_frame_count < 0) ++ in_uint32_le(s, max_count); ++ if (max_count < 0) + { +- LOG(LOG_LEVEL_WARNING, " invalid max_unacknowledged_frame_count value (%d), setting to 0", +- self->client_info.max_unacknowledged_frame_count); +- self->client_info.max_unacknowledged_frame_count = 0; ++ LOG(LOG_LEVEL_WARNING, ++ " invalid max_unacknowledged_frame_count value (%d), setting to 0", ++ max_count); ++ max_count = 0; + } +- LOG_DEVEL(LOG_LEVEL_TRACE, " max_unacknowledged_frame_count %d", self->client_info.max_unacknowledged_frame_count); ++ LOG_DEVEL(LOG_LEVEL_TRACE, ++ " max_unacknowledged_frame_count %d", max_count); ++ self->client_info.max_unacknowledged_frame_count = max_count; + return 0; + } + +@@ -715,6 +739,12 @@ xrdp_caps_process_surface_cmds(struct xrdp_rdp *self, struct stream *s, int len) + logging in debug mode */ + UNUSED_VAR(cmdFlags); + #endif ++ // Check the data is there, whether or not we are logging it ++ if (len < 8) ++ { ++ LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_surface_cmds: missing data"); ++ return 1; ++ } + + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_process_surface_cmds:"); + in_uint32_le(s, cmdFlags); +@@ -802,22 +832,34 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s) + case CAPSTYPE_GENERAL: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_GENERAL"); +- xrdp_caps_process_general(self, s, len); ++ if (xrdp_caps_process_general(self, s, len) != 0) ++ { ++ return 1; ++ } + break; + case CAPSTYPE_BITMAP: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_BITMAP"); +- xrdp_caps_process_bitmap(self, s, len); ++ if (xrdp_caps_process_bitmap(self, s, len) != 0) ++ { ++ return 1; ++ } + break; + case CAPSTYPE_ORDER: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_ORDER"); +- xrdp_caps_process_order(self, s, len); ++ if (xrdp_caps_process_order(self, s, len) != 0) ++ { ++ return 1; ++ } + break; + case CAPSTYPE_BITMAPCACHE: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_BITMAPCACHE"); +- xrdp_caps_process_bmpcache(self, s, len); ++ if (xrdp_caps_process_bmpcache(self, s, len) != 0) ++ { ++ return 1; ++ } + break; + case CAPSTYPE_CONTROL: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " +@@ -826,7 +868,10 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s) + case 6: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = 6"); +- xrdp_caps_process_cache_v3_codec_id(self, s, len); ++ if (xrdp_caps_process_cache_v3_codec_id(self, s, len) != 0) ++ { ++ return 1; ++ } + break; + case CAPSTYPE_ACTIVATION: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " +@@ -835,7 +880,10 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s) + case CAPSTYPE_POINTER: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_POINTER"); +- xrdp_caps_process_pointer(self, s, len); ++ if (xrdp_caps_process_pointer(self, s, len) != 0) ++ { ++ return 1; ++ } + break; + case CAPSTYPE_SHARE: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " +@@ -852,7 +900,10 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s) + case CAPSTYPE_INPUT: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_INPUT"); +- xrdp_caps_process_input(self, s, len); ++ if (xrdp_caps_process_input(self, s, len) != 0) ++ { ++ return 1; ++ } + break; + case CAPSTYPE_FONT: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " +@@ -861,22 +912,34 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s) + case CAPSTYPE_BRUSH: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_BRUSH"); +- xrdp_caps_process_brushcache(self, s, len); ++ if (xrdp_caps_process_brushcache(self, s, len) != 0) ++ { ++ return 1; ++ } + break; + case CAPSTYPE_GLYPHCACHE: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_GLYPHCACHE"); +- xrdp_caps_process_glyphcache(self, s, len); ++ if (xrdp_caps_process_glyphcache(self, s, len) != 0) ++ { ++ return 1; ++ } + break; + case CAPSTYPE_OFFSCREENCACHE: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_OFFSCREENCACHE"); +- xrdp_caps_process_offscreen_bmpcache(self, s, len); ++ if (xrdp_caps_process_offscreen_bmpcache(self, s, len) != 0) ++ { ++ return 1; ++ } + break; + case CAPSTYPE_BITMAPCACHE_REV2: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_BITMAPCACHE_REV2"); +- xrdp_caps_process_bmpcache2(self, s, len); ++ if (xrdp_caps_process_bmpcache2(self, s, len) != 0) ++ { ++ return 1; ++ } + break; + case CAPSTYPE_VIRTUALCHANNEL: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " +@@ -893,37 +956,58 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s) + case CAPSTYPE_RAIL: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_RAIL"); +- xrdp_caps_process_rail(self, s, len); ++ if (xrdp_caps_process_rail(self, s, len) != 0) ++ { ++ return 1; ++ } + break; + case CAPSTYPE_WINDOW: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_WINDOW"); +- xrdp_caps_process_window(self, s, len); ++ if (xrdp_caps_process_window(self, s, len) != 0) ++ { ++ return 1; ++ } + break; + case CAPSSETTYPE_MULTIFRAGMENTUPDATE: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSSETTYPE_MULTIFRAGMENTUPDATE"); +- xrdp_caps_process_multifragmentupdate(self, s, len); ++ if (xrdp_caps_process_multifragmentupdate(self, s, len) != 0) ++ { ++ return 1; ++ } + break; + case CAPSETTYPE_LARGE_POINTER: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSETTYPE_LARGE_POINTER"); +- xrdp_caps_process_largepointer(self, s, len); ++ if (xrdp_caps_process_largepointer(self, s, len) != 0) ++ { ++ return 1; ++ } + break; + case CAPSETTYPE_SURFACE_COMMANDS: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSETTYPE_SURFACE_COMMANDS"); +- xrdp_caps_process_surface_cmds(self, s, len); ++ if (xrdp_caps_process_surface_cmds(self, s, len) != 0) ++ { ++ return 1; ++ } + break; + case CAPSSETTYPE_BITMAP_CODECS: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSSETTYPE_BITMAP_CODECS"); +- xrdp_caps_process_codecs(self, s, len); ++ if (xrdp_caps_process_codecs(self, s, len) != 0) ++ { ++ return 1; ++ } + break; + case CAPSTYPE_FRAME_ACKNOWLEDGE: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_FRAME_ACKNOWLEDGE"); +- xrdp_caps_process_frame_ack(self, s, len); ++ if (xrdp_caps_process_frame_ack(self, s, len) != 0) ++ { ++ return 1; ++ } + break; + default: + LOG(LOG_LEVEL_WARNING, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " diff -Nru xrdp-0.10.1/debian/patches/CVE-2026-55639.patch xrdp-0.10.1/debian/patches/CVE-2026-55639.patch --- xrdp-0.10.1/debian/patches/CVE-2026-55639.patch 1970-01-01 00:00:00.000000000 +0000 +++ xrdp-0.10.1/debian/patches/CVE-2026-55639.patch 2026-08-13 08:44:56.000000000 +0000 @@ -0,0 +1,23 @@ +From 5d72302e1b777ae879f202678f5c1fd4c9b15fbf Mon Sep 17 00:00:00 2001 +From: matt335672 <30179339+matt335672@users.noreply.github.com> +Date: Mon, 15 Jun 2026 10:36:24 +0100 +Subject: [PATCH] CVE-2026-55639: OOB read in GCC Conference Create Request + +(cherry picked from commit 9d16ec4e756b332e0e4cedea342890bca70a7042) +--- + libxrdp/xrdp_sec.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/libxrdp/xrdp_sec.c ++++ b/libxrdp/xrdp_sec.c +@@ -2098,6 +2098,10 @@ xrdp_sec_process_mcs_data_CS_SECURITY(st + int crypt_method; + int found; + ++ if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPBCGR] CS_SECURITY")) ++ { ++ return 1; ++ } + in_uint32_le(s, crypt_method); + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_SEC " + "encryptionMethods 0x%8.8x, extEncryptionMethods (ignored)", diff -Nru xrdp-0.10.1/debian/patches/CVE-2026-55645.patch xrdp-0.10.1/debian/patches/CVE-2026-55645.patch --- xrdp-0.10.1/debian/patches/CVE-2026-55645.patch 1970-01-01 00:00:00.000000000 +0000 +++ xrdp-0.10.1/debian/patches/CVE-2026-55645.patch 2026-08-13 08:44:56.000000000 +0000 @@ -0,0 +1,23 @@ +From 6f1eda171517ec92ce05c0d98a427956dde6ab1f Mon Sep 17 00:00:00 2001 +From: matt335672 <30179339+matt335672@users.noreply.github.com> +Date: Mon, 15 Jun 2026 11:23:08 +0100 +Subject: [PATCH] CVE-2026-55645: OOB read in Client Control PDU processing + +(cherry picked from commit b1edb60c1de4cbf2119f3a79358df32d5a1d2db0) +--- + libxrdp/xrdp_rdp.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/libxrdp/xrdp_rdp.c ++++ b/libxrdp/xrdp_rdp.c +@@ -1153,6 +1153,10 @@ xrdp_rdp_process_data_control(struct xrd + { + int action; + ++ if (!s_check_rem_and_log(s, 8, "Parsing [MS-RDPBCGR] TS_CONTROL_PDU")) ++ { ++ return 1; ++ } + in_uint16_le(s, action); + in_uint8s(s, 2); /* user id */ + in_uint8s(s, 4); /* control id */ diff -Nru xrdp-0.10.1/debian/patches/series xrdp-0.10.1/debian/patches/series --- xrdp-0.10.1/debian/patches/series 2026-02-03 06:08:48.000000000 +0000 +++ xrdp-0.10.1/debian/patches/series 2026-08-13 08:44:56.000000000 +0000 @@ -9,3 +9,24 @@ #fix-environment.diff #cherry-pick-dvorak-pr-3112 CVE-2025-68670-Buffer-overflow-parsing-domain.patch +CVE-2026-32105-1.patch +CVE-2026-32105-2.patch +CVE-2026-32105-3.patch +CVE-2026-32105-5.patch +CVE-2026-32107.patch +CVE-2026-32623.patch +CVE-2026-32624.patch +CVE-2026-33145.patch +CVE-2026-33516.patch +CVE-2026-33689.patch +CVE-2026-35512.patch +CVE-2026-41252-1.patch +CVE-2026-41252-2.patch +CVE-2026-41521.patch +CVE-2026-42218.patch +CVE-2026-44178.patch +CVE-2026-44978.patch +CVE-2026-54538.patch +CVE-2026-55238.patch +CVE-2026-55639.patch +CVE-2026-55645.patch