diff --git a/0014-btrfs-progs-image-fix-the-bug-that-filename-sanitiza.patch b/0014-btrfs-progs-image-fix-the-bug-that-filename-sanitiza.patch new file mode 100644 index 0000000000000000000000000000000000000000..bd0f108ff3ea4de6f1a8f9947832ec9957638954 --- /dev/null +++ b/0014-btrfs-progs-image-fix-the-bug-that-filename-sanitiza.patch @@ -0,0 +1,138 @@ +From a2c6c5933368b573b6509b0104b1b3da916a2ee1 Mon Sep 17 00:00:00 2001 +From: Qu Wenruo +Date: Mon, 8 Jul 2024 13:33:54 +0930 +Subject: [PATCH] btrfs-progs: image: fix the bug that filename sanitization + not working +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[BUG] +There is a bug report that image dump taken by "btrfs-image -s" doesn't +really sanitize the filenames: + + # truncates -s 1G source.raw + # mkfs.btrfs -f source.raw + # mount source.raw $mnt + # touch $mnt/top_secret_filename + # touch $mnt/secret_filename + # umount $mnt + # btrfs-image -s source.raw dump.img + # string dump.img | grep filename + top_secret_filename + secret_filename + top_secret_filename + secret_filename + top_secret_filename + +[CAUSE] +Using above image to store the fs, and we got the following result in fs +tree: + + item 0 key (256 INODE_ITEM 0) itemoff 16123 itemsize 160 + generation 3 transid 7 size 68 nbytes 16384 + block group 0 mode 40755 links 1 uid 0 gid 0 rdev 0 + sequence 2 flags 0x0(none) + item 1 key (256 INODE_REF 256) itemoff 16111 itemsize 12 + index 0 namelen 2 name: .. + item 2 key (256 DIR_ITEM 439756795) itemoff 16062 itemsize 49 + location key (257 INODE_ITEM 0) type FILE + transid 7 data_len 0 name_len 19 + name: top_secret_filename + item 3 key (256 DIR_ITEM 693462946) itemoff 16017 itemsize 45 + location key (258 INODE_ITEM 0) type FILE + transid 7 data_len 0 name_len 15 + name: secret_filename + item 4 key (256 DIR_INDEX 2) itemoff 15968 itemsize 49 + location key (257 INODE_ITEM 0) type FILE + transid 7 data_len 0 name_len 19 + name: top_secret_filename + item 5 key (256 DIR_INDEX 3) itemoff 15923 itemsize 45 + location key (258 INODE_ITEM 0) type FILE + transid 7 data_len 0 name_len 15 + name: secret_filename + item 6 key (257 INODE_ITEM 0) itemoff 15763 itemsize 160 + generation 7 transid 7 size 0 nbytes 0 + block group 0 mode 100644 links 1 uid 0 gid 0 rdev 0 + sequence 1 flags 0x0(none) + item 7 key (257 INODE_REF 256) itemoff 15734 itemsize 29 + index 2 namelen 19 name: top_secret_filename + item 8 key (258 INODE_ITEM 0) itemoff 15574 itemsize 160 + generation 7 transid 7 size 0 nbytes 0 + block group 0 mode 100644 links 1 uid 0 gid 0 rdev 0 + sequence 1 flags 0x0(none) + item 9 key (258 INODE_REF 256) itemoff 15549 itemsize 25 + index 3 namelen 15 name: 1���'�gc*&R + +The result shows, only the last INODE_REF got sanitized, all the +remaining are not touched at all. + +This is caused by how we sanitize the filenames: + + copy_buffer() + |- memcpy(dst, src->data, src->len); + | This means we copy the whole eb into our buffer already. + | + |- zero_items() + |- sanitize_name() + |- eb = alloc_dummy_eb(); + |- memcpy(eb->data, src->data, src->len); + | This means we generate a dummy eb with the same contents of + | the source eb. + | + |- sanitize_dir_item(); + | We override the dir item of the given item (specified by the + | slot number) inside our dummy eb. + | + |- memcpy(dst, eb->data, eb->lem); + +The last one copy the dummy eb into our buffer, with only the slot +corrupted. + +But when the whole work flow hits the next slot, we only corrupt the +next slot, but still copy the whole dummy eb back to buffer. + +This means the previous slot would be overwritten by the old unsanitized +data. + +Resulting only the last slot is corrupted. + +[FIX] +Fix the bug by only copying back the corrupted item to the buffer. +So that other slots won't be overwritten by unsanitized data. + +Reported-by: Andrea Gelmini +Signed-off-by: Qu Wenruo +--- + image/sanitize.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/image/sanitize.c b/image/sanitize.c +index 084da22..ef4f6e5 100644 +--- a/image/sanitize.c ++++ b/image/sanitize.c +@@ -449,6 +449,8 @@ void sanitize_name(enum sanitize_mode sanitize, struct rb_root *name_tree, + int slot) + { + struct extent_buffer *eb; ++ u32 item_ptr_off = btrfs_item_ptr_offset(src, slot); ++ u32 item_ptr_size = btrfs_item_size(src, slot); + + eb = alloc_dummy_eb(src->start, src->len); + if (!eb) { +@@ -476,7 +478,11 @@ void sanitize_name(enum sanitize_mode sanitize, struct rb_root *name_tree, + break; + } + +- memcpy(dst, eb->data, eb->len); ++ /* ++ * Only overwrite the sanitized part, or we can overwrite previous ++ * sanitized value with the old values from @src. ++ */ ++ memcpy(dst + item_ptr_off, eb->data + item_ptr_off, item_ptr_size); + free(eb); + } + +-- +2.43.0 + diff --git a/btrfs-progs.spec b/btrfs-progs.spec index 00b81c9d8707fd278a73494d395027451affe930..cc58ed91164d97dd9806bcbbca7748a2674050c5 100644 --- a/btrfs-progs.spec +++ b/btrfs-progs.spec @@ -1,6 +1,6 @@ Name: btrfs-progs Version: 6.6.3 -Release: 13 +Release: 14 Summary: btrfs userspace programs License: GPLv2 and GPL+ and LGPL-2.1+ and GPL-3.0+ and LGPL-2.1 and MIT URL: https://btrfs.wiki.kernel.org/index.php/Main_Page @@ -19,6 +19,7 @@ Patch0010: 0010-btrfs-progs-fix-the-conflicting-super-block-flags.patch Patch0011: 0011-btrfs-progs-convert-for-ext2-fix-possible-tree-check.patch Patch0012: 0012-btrfs-progs-convert-insert-a-dummy-inode-item-before.patch Patch0013: 0013-btrfs-progs-corrupt-block-fix-memory-leak-in-debug_c.patch +Patch0014: 0014-btrfs-progs-image-fix-the-bug-that-filename-sanitiza.patch BuildRequires: python3-devel >= 3.4 BuildRequires: libacl-devel, e2fsprogs-devel, libblkid-devel, libuuid-devel, zlib-devel, libzstd-devel, lzo-devel, systemd-devel @@ -84,6 +85,9 @@ make mandir=%{_mandir} bindir=%{_sbindir} libdir=%{_libdir} incdir=%{_includedir %{_mandir}/man8/*.gz %changelog +* Tue Sep 10 2024 liuh - 6.6.3-14 +- btrfs-progs: image: fix the bug that filename sanitization not working + * Fri Sep 6 2024 cenhuilin - 6.6.3-13 - btrfs-progs: corrupt-block: fix memory leak in debug_corrupt_sector()