btrfs-progs: fsck: Fix a shallow copy which will leads to segfault.
authorQu Wenruo <quwenruo@cn.fujitsu.com>
Tue, 5 May 2015 02:20:19 +0000 (10:20 +0800)
committerDavid Sterba <dsterba@suse.cz>
Thu, 14 May 2015 13:41:06 +0000 (15:41 +0200)
In copy_inode_rec(), a shallow copy happens on rec->holes rb_root.
So for shared inode case, new rec->holes still points to old rb_root,
and when the old inode record is freed, the new inode_rec->holes will
points to garbage and cause segfault when we try to free new
inode_rec->holes.

Fix it by calling copy_file_extent_holes() to do deep copy.

Reported-by: Eric Sandeen <sandeen@redhat.com>
Reported-by: Filipe David Manana <fdmanana@gmail.com>
Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
cmds-check.c

index 60ef48e391825d9b80e892e46108423db1fce541..db121b1c6433e8ca49594052bb0c36ac4b0cc51a 100644 (file)
@@ -516,12 +516,14 @@ static struct inode_record *clone_inode_rec(struct inode_record *orig_rec)
        struct orphan_data_extent *src_orphan;
        struct orphan_data_extent *dst_orphan;
        size_t size;
+       int ret;
 
        rec = malloc(sizeof(*rec));
        memcpy(rec, orig_rec, sizeof(*rec));
        rec->refs = 1;
        INIT_LIST_HEAD(&rec->backrefs);
        INIT_LIST_HEAD(&rec->orphan_extents);
+       rec->holes = RB_ROOT;
 
        list_for_each_entry(orig, &orig_rec->backrefs, list) {
                size = sizeof(*orig) + orig->namelen + 1;
@@ -536,6 +538,9 @@ static struct inode_record *clone_inode_rec(struct inode_record *orig_rec)
                memcpy(dst_orphan, src_orphan, sizeof(*src_orphan));
                list_add_tail(&dst_orphan->list, &rec->orphan_extents);
        }
+       ret = copy_file_extent_holes(&rec->holes, &orig_rec->holes);
+       BUG_ON(ret < 0);
+
        return rec;
 }