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]] -=-=-=-=-=-=-=-=-=-=-=-
