From fd138f8678808717635a145832c1b13320ce6cd2 Mon Sep 17 00:00:00 2001 From: Qu Wenruo Date: Tue, 27 Dec 2022 13:25:12 +0800 Subject: [PATCH] btrfs-progs: fix the wrong timestamp and UUID check for root items [BUG] Since commit d729048be6ef ("btrfs-progs: stop using btrfs_root_item_v0"), "btrfs subvolume list" not longer correctly report UUID nor timestamp, while older (btrfs-progs v6.0.2) still works correct: v6.0.2: # btrfs subv list -u /mnt/btrfs/ ID 256 gen 12 top level 5 uuid ed4af580-d512-2644-b392-2a71aaeeb99e path subv1 ID 257 gen 13 top level 5 uuid a22ccba7-0a0a-a94f-af4b-5116ab58bb61 path subv2 v6.1: # ./btrfs subv list -u /mnt/btrfs/ ID 256 gen 12 top level 5 uuid - path subv1 ID 257 gen 13 top level 5 uuid - path subv2 [CAUSE] Commit d729048be6ef ("btrfs-progs: stop using btrfs_root_item_v0") removed old btrfs_root_item_v0, but incorrectly changed the check for v0 root item. Now we will treat v0 root items as latest root items, causing possible out-of-bound access. while treat current root items as older v0 root items, ignoring the UUID nor timestamp. [FIX] Fix the bug by using correct checks, and add extra comments on the branches. Issue: #562 Fixes: d729048be6ef ("btrfs-progs: stop using btrfs_root_item_v0") Signed-off-by: Qu Wenruo --- cmds/subvolume-list.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/cmds/subvolume-list.c b/cmds/subvolume-list.c index 6d5ef509a..7cdb0402b 100644 --- a/cmds/subvolume-list.c +++ b/cmds/subvolume-list.c @@ -870,14 +870,21 @@ static int list_subvol_search(int fd, struct rb_root *root_lookup) ri = (struct btrfs_root_item *)(args.buf + off); gen = btrfs_root_generation(ri); flags = btrfs_root_flags(ri); - if(sh.len < - sizeof(struct btrfs_root_item)) { + if(sh.len >= sizeof(struct btrfs_root_item)) { + /* + * The new full btrfs_root_item with + * timestamp and UUID. + */ otime = btrfs_stack_timespec_sec(&ri->otime); ogen = btrfs_root_otransid(ri); memcpy(uuid, ri->uuid, BTRFS_UUID_SIZE); memcpy(puuid, ri->parent_uuid, BTRFS_UUID_SIZE); memcpy(ruuid, ri->received_uuid, BTRFS_UUID_SIZE); } else { + /* + * The old v0 root item, which doesn't + * has timestamp nor UUID. + */ otime = 0; ogen = 0; memset(uuid, 0, BTRFS_UUID_SIZE);