mirror of
https://github.com/kdave/btrfs-progs
synced 2025-02-26 15:01:03 +00:00
btrfs-progs: check: do not dereference tree_refs as data_refs
In a filesystem corrupted by a faulty memory module, btrfsck would get very confused attempting to access backrefs that weren't data backrefs as if they were. Besides invoking undefined behavior for accessing potentially-uninitialized data past the end of objects, or with dynamic types unrelated with the static types held in the corresponding memory, it used offsets and lengths from such fields that did not correspond to anything in the filesystem proper. Moving the test for full backrefs and checking that they're data backrefs earlier avoided the crash I was running into, but that was not enough to make the filesystem complete a successful repair. Signed-off-by: Alexandre Oliva <oliva@gnu.org> Signed-off-by: David Sterba <dsterba@suse.cz>
This commit is contained in:
parent
ca1e04597a
commit
12adc878ae
19
cmds-check.c
19
cmds-check.c
@ -4911,15 +4911,17 @@ static int verify_backrefs(struct btrfs_trans_handle *trans,
|
||||
return 0;
|
||||
|
||||
list_for_each_entry(back, &rec->backrefs, list) {
|
||||
if (back->full_backref || !back->is_data)
|
||||
continue;
|
||||
|
||||
dback = (struct data_backref *)back;
|
||||
|
||||
/*
|
||||
* We only pay attention to backrefs that we found a real
|
||||
* backref for.
|
||||
*/
|
||||
if (dback->found_ref == 0)
|
||||
continue;
|
||||
if (back->full_backref)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* For now we only catch when the bytes don't match, not the
|
||||
@ -5035,6 +5037,9 @@ static int verify_backrefs(struct btrfs_trans_handle *trans,
|
||||
* references and fix up the ones that don't match.
|
||||
*/
|
||||
list_for_each_entry(back, &rec->backrefs, list) {
|
||||
if (back->full_backref || !back->is_data)
|
||||
continue;
|
||||
|
||||
dback = (struct data_backref *)back;
|
||||
|
||||
/*
|
||||
@ -5043,8 +5048,6 @@ static int verify_backrefs(struct btrfs_trans_handle *trans,
|
||||
*/
|
||||
if (dback->found_ref == 0)
|
||||
continue;
|
||||
if (back->full_backref)
|
||||
continue;
|
||||
|
||||
if (dback->bytes == best->bytes &&
|
||||
dback->disk_bytenr == best->bytenr)
|
||||
@ -5264,14 +5267,16 @@ static int find_possible_backrefs(struct btrfs_trans_handle *trans,
|
||||
int ret;
|
||||
|
||||
list_for_each_entry(back, &rec->backrefs, list) {
|
||||
/* Don't care about full backrefs (poor unloved backrefs) */
|
||||
if (back->full_backref || !back->is_data)
|
||||
continue;
|
||||
|
||||
dback = (struct data_backref *)back;
|
||||
|
||||
/* We found this one, we don't need to do a lookup */
|
||||
if (dback->found_ref)
|
||||
continue;
|
||||
/* Don't care about full backrefs (poor unloved backrefs) */
|
||||
if (back->full_backref)
|
||||
continue;
|
||||
|
||||
key.objectid = dback->root;
|
||||
key.type = BTRFS_ROOT_ITEM_KEY;
|
||||
key.offset = (u64)-1;
|
||||
|
Loading…
Reference in New Issue
Block a user