Commit Graph
131 Commits
Author SHA1 Message Date
Stuart Inglis bc2faf8275 match: bound the hash_search() chain walk (issue #217)
hash_search() walks the entire hash-table chain for the current rolling
checksum at every byte offset of the source file. Disk and VM images
contain large runs of identical blocks, so a single weak checksum
(get_checksum1) can collide thousands of times and pile every one of
those blocks onto one chain. When the sender then rolls across a region
whose weak checksum keeps landing on that chain without ever producing a
strong-checksum match, it re-walks the whole chain for every byte, giving
O(file_size * chain_length) behaviour. The result is rsync sitting at
100% CPU for hours with no apparent progress -- the long-standing "rsync
hangs on large files" reports.

Cap the number of same-weak-checksum candidates examined per offset at
MAX_CHAIN_LEN. Once the cap is hit we treat the offset as a non-match and
roll forward a byte; any block skipped this way is simply sent as literal
data, so the transferred result is always correct -- only the transfer
size is marginally affected. This is purely a sender-side search limit:
it changes no checksum, emitted byte, or protocol field, so a capped
sender interoperates with an unmodified receiver and vice versa.

On a synthetic 40000-block basis sharing one weak checksum, syncing a
60KB source dropped from ~18.4s to ~0.7s; the unbounded cost grows with
the square of the file size.

testsuite/hashsearch-chain_test.py reproduces the pathology with a tiny
basis of weak-checksum-colliding decoy blocks and asserts, via the
existing false_alarms counter (--debug=deltasum1), that the per-hash-hit
chain walk stays bounded. The assertion is exact and machine-independent
rather than timing-based.
2026-07-20 14:51:18 +10:00
Andrew Tridgell 9491aafdac match: clamp peer-supplied s->flength to local len in append mode
In daemon-as-sender mode, send_files() leaves mbuf NULL for an empty local file
(st.st_size == 0). receive_sums() then derives s->flength from the peer's
sum_head (count * blength), so a hostile client that sends a non-empty sum_head
against that empty file drives the append_mode==2 verify loop into
map_ptr(NULL, ...), dereferencing the NULL map. The diminished-file guard
compares against F_LENGTH(file) (the daemon's own flist size, also 0), not the
peer-supplied flength, so it does not catch this.

Clamp s->flength to len before the verify loop -- we cannot checksum bytes we do
not have, and last_match must not run past len for the trailing matched() flush.

(cherry picked from commit 43f43c92d3414f340029ddf7ddc316dc4d4e3e7b)
2026-06-15 17:15:28 +10:00
Andrew Tridgell 8c1d0d3820 match: re-check .len == l before substituting want_i in hash_search
The check_want_i adjacent-match optimisation substitutes i = want_i after
verifying sum1 and sum2, but -- unlike the main chain loop and the aligned_i
path -- did not re-check s->sums[want_i].len == l. A hostile peer acting as the
generator against a daemon-as-sender can set s2length=0 (read_sum_head only
enforces >= 0, so the sum2 memcmp is a no-op) and craft count=2, blength=len+1,
remainder=len with both sum1 set to the file's rolling checksum. The chain head
(.len=remainder=len) passes the l==.len gate; want_i=0 (.len=blength=len+1) is
then substituted unchecked. After matched(), offset advances to len, k =
MIN(blength, len-offset) = 0, map_ptr(...,0) returns NULL, and the rolling-
checksum trim dereferences map[0] -- a remote unauthenticated SEGV of the
per-connection daemon child against any module serving a non-empty regular file.

Add the missing length re-check, matching the chain loop and aligned_i path.

(cherry picked from commit aad82d77aae098c8d8529f69614a0ffcbfbbb5d3)
2026-06-15 17:15:28 +10:00
Andrew Tridgell 589b0691e5 prevent information leak off the stack
prevent leak of uninitialised stack data in hash_search
2025-01-15 05:30:32 +11:00
Wayne Davison 0902b52f66 Some checksum buffer fixes.
- Put sum2_array into sum_struct to hold an array of sum2 checksums
  that are each xfer_sum_len bytes.
- Remove sum2 buf from sum_buf.
- Add macro sum2_at() to access each sum2 array element.
- Throw an error if a sums header has an s2length larger than
  xfer_sum_len.
2024-10-29 23:06:34 -07:00
Wayne Davison 9a06b2edb0 Preparing for release of 3.3.0pre1 [buildall] 2023-04-29 09:01:43 -07:00
Wayne Davison 0f599d3641 Fix overflow of sum2 buffer for sha1 rolling checksums.
Fixed #353.
2023-04-22 08:49:50 -07:00
Wayne Davison ed4b3448be Preparing for release of 3.2.7pre1 2022-09-30 12:36:21 -07:00
Wayne Davison 7e2711bb2b Improve various things in the checksum code
- Size flist checksum data to hold the active size, not the max.
- Add a negotiated hash method to the daemon auth code.
- Use EVP for all openssl digests. This makes it easy to add more
  openssl digest methods and avoids deprecation warnings.
- Support a way to re-enable deprecated digests via openssl conf
  file and allow a default file to be configured.
- Supply a simple openssl-rsync.cnf file to enable legacy digests.
2022-09-10 11:39:37 -07:00
Wayne Davison 11eb67eec9 Some memory allocation improvements
- All the memory-allocation macros now auto-check for failure and exit
   with a failure message that incudes the caller's file and lineno
   info.  This includes strdup().

 - Added the `--max-alloc=SIZE` option to be able to override the memory
   allocator's sanity-check limit.  It defaults to 1G (as before).
   Fixes bugzilla bug 12769.
2020-06-25 20:54:21 -07:00
Wayne Davison e63ff70eae Some indentation fixes. 2020-06-13 19:15:02 -07:00
Wayne Davison 3e2e4b5a33 Tweak the copyright year. 2019-03-16 09:15:49 -07:00
Wayne Davison 473108ae6e Tweak copyright date. 2018-01-14 19:55:07 -08:00
Wayne Davison 416e719bea More archaic-checksum improvements. This makes the len vars clearer
and ensures that only the flist code gets the 2-byte digest len.
2017-11-07 14:01:13 -08:00
Wayne Davison a5a7d3a297 Add --checksum-choice option to choose the checksum algorithms. 2016-05-01 17:06:54 -07:00
Wayne Davison 453914e35b Update the copyright year. 2015-08-08 12:47:03 -07:00
Wayne Davison dfa5b49110 Bump the year to 2014. 2014-01-26 09:29:15 -08:00
Wayne Davison de94193353 Remove bypassed checksums in --inplace to improve speed.
When checking a checksum that refers to a part of an --inplace file that
has been overwritten w/o getting SUMFLG_SAME_OFFSET set, we remove the
checksum from the list.  This will speed up files that have a lot of
identical checksum blocks (e.g. sequences of zeros) that we can't use
due to them not getting marked as being the same.  Patch provided by
Michael Chapman.
2013-08-03 09:59:38 -07:00
Wayne Davison 7e1a9c4d79 Update copyright year. 2013-01-19 11:05:53 -08:00
Wayne Davison 813d5a25e3 Fix a potential crash when trying to find a better block match. 2011-04-22 16:06:06 -07:00
Wayne Davison 4b4bcbe674 Optimize finding the sum that matches our --inplace position. 2011-01-16 17:35:50 -08:00
Wayne Davison 3f26945cb1 Include backup in map_ptr() to avoid backing up when reading. 2011-01-15 11:16:49 -08:00
Wayne Davison 580cffdec9 Sender realigns chunks with generator during an --inplace copy
when sending a sequence of zeros.
2011-01-14 21:32:15 -08:00
Wayne Davison 58a1c1a218 Make sure an alternate --inplace sum has the right length
and add missing break in --inplace same-offset loop.
2011-01-14 15:37:48 -08:00
Wayne Davison 8484ddd3d1 A couple comment tweaks. 2010-11-20 09:30:35 -08:00
Wayne Davison 51b2ff03b3 Optimize --inplace chunck search to avoid a non-aligned search. 2010-11-12 09:07:58 -08:00
Wayne Davison b3bf9b9df9 Update the copyright year. 2009-01-03 10:57:14 -08:00
Wayne Davison 5dd14f0c33 Split up the ifuncs.h file into 3 .h files. 2008-09-01 19:11:36 -07:00
Wayne Davison adc2476fa2 Output numbers in 3-digit groups by default (e.g. 1,234,567).
Also improved the human-readable output functions, including
adding the ability to output negative numbers.
2008-09-01 13:27:11 -07:00
Wayne Davison 5a18b34de3 Changed the chksum debug flag to deltasum. 2008-07-20 20:02:09 -07:00
Wayne Davison 886df221c1 Added a '%C' (MD5 checksum) flag for the output/logfile formatting. 2008-07-19 22:50:28 -07:00
Wayne Davison 6d56efa6ea Changed human_num() to big_num() with an extra arg so that it can
be used in place of all %.0f output idioms.
2008-07-17 07:37:31 -07:00
Wayne Davison 951e826b75 Added the --info=FLAGS an --debug=FLAGS options, which allows
fine-grained output control (in addition to the coarse -v).
2008-07-13 20:51:08 -07:00
Wayne Davison d3d07a5e86 Include 2008 in the copyright years. 2008-03-01 12:01:41 -08:00
Wayne Davison a2c770dc21 Switching over to a dynamic hash method for really large files.
This code has been reported to be better for large files than the
file-chunking code that was included in pre3.
2007-11-28 00:39:02 -08:00
Wayne Davison 5851ac2dfe Fixed a problem with build_hash_table() getting called too
often when overwriting a shorter file.
2007-10-27 04:41:18 +00:00
Wayne Davison 4c17cdcb64 Chunk a really large file to avoid sender-side hash-table
overload.
2007-10-26 22:11:19 +00:00
Wayne Davison 936fa865e1 Handle the new --append and --append-verify options. 2007-09-01 16:38:00 +00:00
Wayne Davison 8e41b68e8f Tweaking the license text a bit more. 2007-07-10 13:55:49 +00:00
Wayne Davison 4fd842f98d Switching to GPL 3. 2007-07-07 05:33:14 +00:00
Wayne Davison a0456b9c46 Protocol 30 now uses MD5 checksums instead of MD4. 2007-03-18 06:00:53 +00:00
Wayne Davison ba2133d6ad Further modifications to the copyright comment section. 2007-02-04 14:54:58 +00:00
Wayne Davison edb977215b Only append_mode > 0 now indicates option is enabled. 2006-12-28 07:54:07 +00:00
Wayne Davison 264042760b Use an explicit cast when a value gets stored in a smaller var. 2006-11-21 08:35:58 +00:00
Wayne Davison e7c67065c0 Updated the FSF's address to an even newer one. 2006-04-25 23:51:12 +00:00
Wayne Davison 0f78b81511 - Updated the address for the FSF in the opening comment.
- Standardized the format of the opening comment, including adding a
  brief description of what's in the file for those that lacked it.
- Added some missing copyright lines.
- Some minor whitespace tweaks (in a few of the files).
2006-04-25 20:23:34 +00:00
Wayne Davison 34f961bbf3 Got the order of s1 and s2 right in the debug output. 2006-02-28 21:48:15 +00:00
Wayne Davison 48cce779a2 Decided to drop the dynamically sized hash table for now. This was
due to timing tests showing that the per-byte modulus calculation
slowed down regular sized files.  Kept the other improvements
because they lessened our memory use and actually sped up the code.
2006-02-28 21:20:08 +00:00
Wayne Davison 6820753732 Renamed sum_table -> hash_table. 2006-02-28 07:32:48 +00:00
Wayne Davison fbbe9a016d Changed the name of GETTAG() to SUM2HASH(). 2006-02-28 01:00:03 +00:00