forked from Mirrors/btrfs-progs
btrfs-progs: fsck: Fix a shallow copy which will leads to segfault.
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>master
parent
ab5984ff6c
commit
f4fac5d46e
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue