From: Ashishkumar Parmar <[email protected]>

Pick the upstream backport [1] for CVE-2026-43618 as mentioned in [2],
where compressed-token decoding could overflow the token index.

[1] 
https://github.com/RsyncProject/rsync/commit/901041dddc9a343ed51f8e2cd3992aed3ae0180c
[2] https://www.cve.org/CVERecord?id=CVE-2026-43618

Signed-off-by: Ashishkumar Parmar <[email protected]>
---
 .../rsync/files/CVE-2026-43618.patch          | 252 ++++++++++++++++++
 meta/recipes-devtools/rsync/rsync_3.2.7.bb    |   1 +
 2 files changed, 253 insertions(+)
 create mode 100644 meta/recipes-devtools/rsync/files/CVE-2026-43618.patch

diff --git a/meta/recipes-devtools/rsync/files/CVE-2026-43618.patch 
b/meta/recipes-devtools/rsync/files/CVE-2026-43618.patch
new file mode 100644
index 0000000000..ed07491b50
--- /dev/null
+++ b/meta/recipes-devtools/rsync/files/CVE-2026-43618.patch
@@ -0,0 +1,252 @@
+From b45912207aed17451adcda954b8bd6689714d2ed Mon Sep 17 00:00:00 2001
+From: Andrew Tridgell <[email protected]>
+Date: Wed, 29 Apr 2026 11:10:59 +1000
+Subject: [PATCH] token: harden compressed-token decoding against integer
+ overflow
+
+The receiver's three compressed-token decoders --
+recv_deflated_token (zlib), recv_zstd_token, and
+recv_compressed_token (lz4) -- accumulated rx_token (a 32-bit
+signed counter) without overflow checking. A malicious sender
+could craft a compressed-token stream that walked rx_token past
+INT32_MAX, with careful manipulation leaking process memory
+contents to the wire (environment variables, passwords, heap
+pointers, library pointers -- significantly weakening ASLR
+and facilitating further exploitation).
+
+Cap rx_token at MAX_TOKEN_INDEX = 0x7ffffffe. Fold the
+bookkeeping into recv_compressed_token_num() and
+recv_compressed_token_run() shared by all three decoders. Reject
+negative or out-of-range token values explicitly. Also cap the
+simple_recv_token literal-block length at the source: any
+wire-supplied length > CHUNK_SIZE is ill-formed (the matching
+simple_send_token never writes a chunk larger than CHUNK_SIZE),
+so reject before looping on attacker-controlled bytes.
+
+Reach: an authenticated daemon connection with compression
+enabled (the default for protocols >= 30 when both peers
+advertise it). Disabling compression on the daemon
+("refuse options = compress" in rsyncd.conf) is the available
+workaround.
+
+Reporter: Omar Elsayed (seks99x).
+
+Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
+
+CVE: CVE-2026-43618
+Upstream-Status: Backport 
[https://github.com/RsyncProject/rsync/commit/901041dddc9a343ed51f8e2cd3992aed3ae0180c]
+
+Backport Changes:
+- Resolved context conflict against existing Scarthgap token
+  hardening by keeping the upstream
+  recv_compressed_token_num() helper call.
+- The upstream deletion hunks for the old inline
+  rx_token < 0 checks were absent or already different
+  in Scarthgap token.c. The backport keeps the
+  helper-based validation and omits those no-op
+  context deletions.
+
+(cherry picked from commit 901041dddc9a343ed51f8e2cd3992aed3ae0180c)
+Signed-off-by: Ashishkumar Parmar <[email protected]>
+---
+ receiver.c |  11 +++++-
+ token.c    | 102 ++++++++++++++++++++++++++++++-----------------------
+ 2 files changed, 67 insertions(+), 46 deletions(-)
+
+diff --git a/receiver.c b/receiver.c
+index 8f5b51dd..63e5cedb 100644
+--- a/receiver.c
++++ b/receiver.c
+@@ -318,7 +318,12 @@ static int receive_data(int f_in, char *fname_r, int 
fd_r, OFF_T size_r,
+               }
+       }
+ 
+-      while ((i = recv_token(f_in, &data)) != 0) {
++      while (1) {
++              data = NULL;
++              i = recv_token(f_in, &data);
++              if (i == 0)
++                      break;
++
+               if (INFO_GTE(PROGRESS, 1))
+                       show_progress(offset, total_size);
+ 
+@@ -326,6 +331,10 @@ static int receive_data(int f_in, char *fname_r, int 
fd_r, OFF_T size_r,
+                       maybe_send_keepalive(time(NULL), MSK_ALLOW_FLUSH | 
MSK_ACTIVE_RECEIVER);
+ 
+               if (i > 0) {
++                      if (!data) {
++                              rprintf(FERROR, "Invalid literal token with no 
data [%s]\n", who_am_i());
++                              exit_cleanup(RERR_PROTOCOL);
++                      }
+                       if (DEBUG_GTE(DELTASUM, 3)) {
+                               rprintf(FINFO,"data recv %d at %s\n",
+                                       i, big_num(offset));
+diff --git a/token.c b/token.c
+index c108b3af..02dabd8d 100644
+--- a/token.c
++++ b/token.c
+@@ -291,6 +291,14 @@ static int32 simple_recv_token(int f, char **data)
+               int32 i = read_int(f);
+               if (i <= 0)
+                       return i;
++              /* simple_send_token caps each literal chunk at CHUNK_SIZE;
++               * reject anything larger so a hostile peer cannot drive the
++               * read_buf below past our static CHUNK_SIZE buffer. */
++              if (i > CHUNK_SIZE) {
++                      rprintf(FERROR, "invalid uncompressed token length %ld 
[%s]\n",
++                              (long)i, who_am_i());
++                      exit_cleanup(RERR_PROTOCOL);
++              }
+               residue = i;
+       }
+ 
+@@ -493,9 +501,52 @@ static char *cbuf;
+ static char *dbuf;
+ 
+ /* for decoding runs of tokens */
++#define MAX_TOKEN_INDEX ((int32)0x7ffffffe)
++
+ static int32 rx_token;
+ static int32 rx_run;
+ 
++static NORETURN void invalid_compressed_token(void)
++{
++      rprintf(FERROR, "invalid token number in compressed stream\n");
++      exit_cleanup(RERR_PROTOCOL);
++}
++
++static int32 recv_compressed_token_num(int f, int32 flag)
++{
++      if (flag & TOKEN_REL) {
++              int32 incr = flag & 0x3f;
++              if (rx_token > MAX_TOKEN_INDEX - incr)
++                      invalid_compressed_token();
++              rx_token += incr;
++              flag >>= 6;
++      } else {
++              rx_token = read_int(f);
++              if (rx_token < 0 || rx_token > MAX_TOKEN_INDEX)
++                      invalid_compressed_token();
++      }
++
++      if (flag & 1) {
++              rx_run = read_byte(f);
++              rx_run += read_byte(f) << 8;
++              if (rx_run <= 0 || rx_token > MAX_TOKEN_INDEX - rx_run)
++                      invalid_compressed_token();
++              recv_state = r_running;
++      }
++
++      return -1 - rx_token;
++}
++
++static int32 recv_compressed_token_run(void)
++{
++      if (rx_run <= 0 || rx_token >= MAX_TOKEN_INDEX)
++              invalid_compressed_token();
++      ++rx_token;
++      if (--rx_run == 0)
++              recv_state = r_idle;
++      return -1 - rx_token;
++}
++
+ /* Receive a deflated token and inflate it */
+ static int32 recv_deflated_token(int f, char **data)
+ {
+@@ -586,17 +637,7 @@ static int32 recv_deflated_token(int f, char **data)
+                       }
+ 
+                       /* here we have a token of some kind */
+-                      if (flag & TOKEN_REL) {
+-                              rx_token += flag & 0x3f;
+-                              flag >>= 6;
+-                      } else
+-                              rx_token = read_int(f);
+-                      if (flag & 1) {
+-                              rx_run = read_byte(f);
+-                              rx_run += read_byte(f) << 8;
+-                              recv_state = r_running;
+-                      }
+-                      return -1 - rx_token;
++                      return recv_compressed_token_num(f, flag);
+ 
+               case r_inflating:
+                       rx_strm.next_out = (Bytef *)dbuf;
+@@ -616,10 +657,7 @@ static int32 recv_deflated_token(int f, char **data)
+                       break;
+ 
+               case r_running:
+-                      ++rx_token;
+-                      if (--rx_run == 0)
+-                              recv_state = r_idle;
+-                      return -1 - rx_token;
++                      return recv_compressed_token_run();
+               }
+       }
+ }
+@@ -828,17 +866,7 @@ static int32 recv_zstd_token(int f, char **data)
+                               return 0;
+                       }
+                       /* here we have a token of some kind */
+-                      if (flag & TOKEN_REL) {
+-                              rx_token += flag & 0x3f;
+-                              flag >>= 6;
+-                      } else
+-                              rx_token = read_int(f);
+-                      if (flag & 1) {
+-                              rx_run = read_byte(f);
+-                              rx_run += read_byte(f) << 8;
+-                              recv_state = r_running;
+-                      }
+-                      return -1 - rx_token;
++                      return recv_compressed_token_num(f, flag);
+ 
+               case r_inflated: /* zstd doesn't get into this state */
+                       break;
+@@ -869,10 +897,7 @@ static int32 recv_zstd_token(int f, char **data)
+                       break;
+ 
+               case r_running:
+-                      ++rx_token;
+-                      if (--rx_run == 0)
+-                              recv_state = r_idle;
+-                      return -1 - rx_token;
++                      return recv_compressed_token_run();
+               }
+       }
+ }
+@@ -992,17 +1017,7 @@ static int32 recv_compressed_token(int f, char **data)
+                       }
+ 
+                       /* here we have a token of some kind */
+-                      if (flag & TOKEN_REL) {
+-                              rx_token += flag & 0x3f;
+-                              flag >>= 6;
+-                      } else
+-                              rx_token = read_int(f);
+-                      if (flag & 1) {
+-                              rx_run = read_byte(f);
+-                              rx_run += read_byte(f) << 8;
+-                              recv_state = r_running;
+-                      }
+-                      return -1 - rx_token;
++                      return recv_compressed_token_num(f, flag);
+ 
+               case r_inflating:
+                       avail_out = LZ4_decompress_safe(next_in, dbuf, 
avail_in, size);
+@@ -1018,10 +1033,7 @@ static int32 recv_compressed_token(int f, char **data)
+                       break;
+ 
+               case r_running:
+-                      ++rx_token;
+-                      if (--rx_run == 0)
+-                              recv_state = r_idle;
+-                      return -1 - rx_token;
++                      return recv_compressed_token_run();
+               }
+       }
+ }
+-- 
+2.35.6
+
diff --git a/meta/recipes-devtools/rsync/rsync_3.2.7.bb 
b/meta/recipes-devtools/rsync/rsync_3.2.7.bb
index 7dd4f7c471..e232abafc3 100644
--- a/meta/recipes-devtools/rsync/rsync_3.2.7.bb
+++ b/meta/recipes-devtools/rsync/rsync_3.2.7.bb
@@ -38,6 +38,7 @@ SRC_URI = 
"https://download.samba.org/pub/${BPN}/src/${BP}.tar.gz \
            file://CVE-2026-43619_p2.patch \
            file://CVE-2026-43619_p3.patch \
            file://CVE-2026-43619_p4.patch \
+           file://CVE-2026-43618.patch \
            "
 SRC_URI[sha256sum] = 
"4e7d9d3f6ed10878c58c5fb724a67dacf4b6aac7340b13e488fb2dc41346f2bb"
 
-- 
2.44.1

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#238605): 
https://lists.openembedded.org/g/openembedded-core/message/238605
Mute This Topic: https://lists.openembedded.org/mt/119772225/21656
Group Owner: [email protected]
Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub 
[[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-

  • ... Ashishkumar Parmar X (asparmar - E INFOCHIPS PRIVATE LIMITED at Cisco) via lists.openembedded.org
    • ... Ashishkumar Parmar X (asparmar - E INFOCHIPS PRIVATE LIMITED at Cisco) via lists.openembedded.org
    • ... Ashishkumar Parmar X (asparmar - E INFOCHIPS PRIVATE LIMITED at Cisco) via lists.openembedded.org
    • ... Ashishkumar Parmar X (asparmar - E INFOCHIPS PRIVATE LIMITED at Cisco) via lists.openembedded.org
    • ... Ashishkumar Parmar X (asparmar - E INFOCHIPS PRIVATE LIMITED at Cisco) via lists.openembedded.org
    • ... Ashishkumar Parmar X (asparmar - E INFOCHIPS PRIVATE LIMITED at Cisco) via lists.openembedded.org

Reply via email to