Skip to content

Commit

Permalink
reiserfs: check directory items on read from disk
Browse files Browse the repository at this point in the history
While verifying the leaf item that we read from the disk, reiserfs
doesn't check the directory items, this could cause a crash when we
read a directory item from the disk that has an invalid deh_location.

This patch adds a check to the directory items read from the disk that
does a bounds check on deh_location for the directory entries. Any
directory entry header with a directory entry offset greater than the
item length is considered invalid.

Link: https://lore.kernel.org/r/20210709152929.766363-1-chouhan.shreyansh630@gmail.com
Reported-by: syzbot+c31a48e6702ccb3d64c9@syzkaller.appspotmail.com
Signed-off-by: Shreyansh Chouhan <chouhan.shreyansh630@gmail.com>
Signed-off-by: Jan Kara <jack@suse.cz>
  • Loading branch information
Shreyansh Chouhan authored and Jan Kara committed Jul 16, 2021
1 parent 728d392 commit 13d2575
Showing 1 changed file with 26 additions and 5 deletions.
31 changes: 26 additions & 5 deletions fs/reiserfs/stree.c
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,24 @@ void pathrelse(struct treepath *search_path)
search_path->path_length = ILLEGAL_PATH_ELEMENT_OFFSET;
}

static int has_valid_deh_location(struct buffer_head *bh, struct item_head *ih)
{
struct reiserfs_de_head *deh;
int i;

deh = B_I_DEH(bh, ih);
for (i = 0; i < ih_entry_count(ih); i++) {
if (deh_location(&deh[i]) > ih_item_len(ih)) {
reiserfs_warning(NULL, "reiserfs-5094",
"directory entry location seems wrong %h",
&deh[i]);
return 0;
}
}

return 1;
}

static int is_leaf(char *buf, int blocksize, struct buffer_head *bh)
{
struct block_head *blkh;
Expand Down Expand Up @@ -454,11 +472,14 @@ static int is_leaf(char *buf, int blocksize, struct buffer_head *bh)
"(second one): %h", ih);
return 0;
}
if (is_direntry_le_ih(ih) && (ih_item_len(ih) < (ih_entry_count(ih) * IH_SIZE))) {
reiserfs_warning(NULL, "reiserfs-5093",
"item entry count seems wrong %h",
ih);
return 0;
if (is_direntry_le_ih(ih)) {
if (ih_item_len(ih) < (ih_entry_count(ih) * IH_SIZE)) {
reiserfs_warning(NULL, "reiserfs-5093",
"item entry count seems wrong %h",
ih);
return 0;
}
return has_valid_deh_location(bh, ih);
}
prev_location = ih_location(ih);
}
Expand Down

0 comments on commit 13d2575

Please sign in to comment.