>From 602fa952feeeb0a2cd4a4bca92f4659529f01454 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A1draig=20Brady?= Date: Mon, 28 Mar 2011 19:22:21 +0100 Subject: [PATCH] copy: protect against overlapping extents * src/extent-scan.c (extent_scan_read): Add a more stringent check for OFF_T overflow, to ensure subsequent code is immune. Detect overlapping extents and fail. If this happens in the initial fiemap scan, we'll revert to a standard copy, or otherwise we'll fail with a diagnostic. * src/copy.c (extent_copy): Add an assert to protect against generating an invalid hole_size with overlapping extents. We can remove this when extent_scan_read() is modified to read all extents, thus encapsulating all extent checking and merging within that function. --- src/copy.c | 3 +++ src/extent-scan.c | 11 ++++++++++- 2 files changed, 13 insertions(+), 1 deletions(-) diff --git a/src/copy.c b/src/copy.c index a672fd3..7c1b3c6 100644 --- a/src/copy.c +++ b/src/copy.c @@ -350,6 +350,9 @@ extent_copy (int src_fd, int dest_fd, char *buf, size_t buf_size, ext_len = 0; } + /* TODO: remove this if extent_scan_read() reads all extents. */ + assert (ext_start > last_ext_start + last_ext_len); + hole_size = ext_start - last_ext_start - last_ext_len; wrote_hole_at_eof = false; diff --git a/src/extent-scan.c b/src/extent-scan.c index b9520b7..b1919ec 100644 --- a/src/extent-scan.c +++ b/src/extent-scan.c @@ -90,7 +90,7 @@ extent_scan_read (struct extent_scan *scan) for (i = 0; i < scan->ei_count; i++) { - assert (fm_extents[i].fe_logical <= OFF_T_MAX); + assert (fm_extents[i].fe_logical <= OFF_T_MAX - fm_extents[i].fe_length); if (si && last_ei->ext_flags == (fm_extents[i].fe_flags & ~FIEMAP_EXTENT_LAST) @@ -102,6 +102,15 @@ extent_scan_read (struct extent_scan *scan) /* Copy flags in case different. */ last_ei->ext_flags = fm_extents[i].fe_flags; } + else if (last_ei->ext_logical + last_ei->ext_length + > fm_extents[i].fe_logical) + { + /* BTRFS before 2.6.38 could return + overlapping extents for sparse files. */ + if (scan->scan_start == 0) + scan->initial_scan_failed = true; + return false; + } else { last_ei = scan->ext_info + si; -- 1.7.4