Skip to content

Commit

Permalink
nilfs2: fix data corruption in dsync block recovery for small block s…
Browse files Browse the repository at this point in the history
…izes

The helper function nilfs_recovery_copy_block() of
nilfs_recovery_dsync_blocks(), which recovers data from logs created by
data sync writes during a mount after an unclean shutdown, incorrectly
calculates the on-page offset when copying repair data to the file's page
cache.  In environments where the block size is smaller than the page
size, this flaw can cause data corruption and leak uninitialized memory
bytes during the recovery process.

Fix these issues by correcting this byte offset calculation on the page.

Link: https://lkml.kernel.org/r/20240124121936.10575-1-konishi.ryusuke@gmail.com
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
Tested-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
  • Loading branch information
konis authored and akpm00 committed Jan 29, 2024
1 parent 16214e2 commit 6dfd7b0
Showing 1 changed file with 4 additions and 3 deletions.
7 changes: 4 additions & 3 deletions fs/nilfs2/recovery.c
Original file line number Diff line number Diff line change
Expand Up @@ -472,17 +472,18 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,

static int nilfs_recovery_copy_block(struct the_nilfs *nilfs,
struct nilfs_recovery_block *rb,
struct page *page)
loff_t pos, struct page *page)
{
struct buffer_head *bh_org;
size_t from = pos & ~PAGE_MASK;
void *kaddr;

bh_org = __bread(nilfs->ns_bdev, rb->blocknr, nilfs->ns_blocksize);
if (unlikely(!bh_org))
return -EIO;

kaddr = kmap_atomic(page);
memcpy(kaddr + bh_offset(bh_org), bh_org->b_data, bh_org->b_size);
memcpy(kaddr + from, bh_org->b_data, bh_org->b_size);
kunmap_atomic(kaddr);
brelse(bh_org);
return 0;
Expand Down Expand Up @@ -521,7 +522,7 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
goto failed_inode;
}

err = nilfs_recovery_copy_block(nilfs, rb, page);
err = nilfs_recovery_copy_block(nilfs, rb, pos, page);
if (unlikely(err))
goto failed_page;

Expand Down

0 comments on commit 6dfd7b0

Please sign in to comment.