From 69eef72ecb248ccb902232f0ea8dd4ccfa4d5504 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 22 Jun 2026 09:16:41 +1000 Subject: [PATCH] hlink/main: guard the F_SUM checksum-slot lifetime hlink.c must confirm S_ISREG before quick_check_ok(FT_REG,...) reads F_SUM, and start_server() must set sender_keeps_checksum when a daemon sender runs -c with a %C log format so make_file() allocates SUM_EXTRA_CNT. Without these, F_SUM() reads past the pool slot and (for %C) hex-encodes adjacent heap into the transfer log. Co-authored-by: Greg Kroah-Hartman --- hlink.c | 9 ++++++++- main.c | 11 +++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/hlink.c b/hlink.c index b3d1974d..dc95c42e 100644 --- a/hlink.c +++ b/hlink.c @@ -420,7 +420,14 @@ int hard_link_check(struct file_struct *file, int ndx, char *fname, } break; } - if (!quick_check_ok(FT_REG, cmpbuf, file, &alt_sx.st)) + /* Content-based basis match only applies to regular + * files: for a hard-linked symlink/device/special the + * exact-inode check above is the only meaningful test, + * and quick_check_ok(FT_REG, ...) would read F_SUM() + * on a file_struct that has no SUM_EXTRA_CNT space + * (recv_file_entry only allocates it for S_ISREG). */ + if (!S_ISREG(file->mode) + || !quick_check_ok(FT_REG, cmpbuf, file, &alt_sx.st)) continue; statret = 1; if (unchanged_attrs(cmpbuf, file, &alt_sx)) diff --git a/main.c b/main.c index 0ce222b3..9a13b96a 100644 --- a/main.c +++ b/main.c @@ -1292,6 +1292,17 @@ void start_server(int f_in, int f_out, int argc, char *argv[]) if (am_sender) { keep_dirlinks = 0; /* Must be disabled on the sender. */ + + /* Mirror client_run()'s sender_keeps_checksum check: a daemon- + * as-sender with -c and a `log format` containing %C will read + * F_SUM(file) in log_formatted(), so make_file() must allocate + * SUM_EXTRA_CNT. Without this, F_SUM() reads past the pool slot + * and hex-encodes adjacent heap into the transfer log. */ + if (always_checksum + && (log_format_has(stdout_format, 'C') + || log_format_has(logfile_format, 'C'))) + sender_keeps_checksum = 1; + if (need_messages_from_generator) io_start_multiplex_in(f_in); else