Skip to content

Commit 2026559

Browse files
konisakpm00
authored andcommitted
nilfs2: fix null-ptr-deref in block_dirty_buffer tracepoint
When using the "block:block_dirty_buffer" tracepoint, mark_buffer_dirty() may cause a NULL pointer dereference, or a general protection fault when KASAN is enabled. This happens because, since the tracepoint was added in mark_buffer_dirty(), it references the dev_t member bh->b_bdev->bd_dev regardless of whether the buffer head has a pointer to a block_device structure. In the current implementation, nilfs_grab_buffer(), which grabs a buffer to read (or create) a block of metadata, including b-tree node blocks, does not set the block device, but instead does so only if the buffer is not in the "uptodate" state for each of its caller block reading functions. However, if the uptodate flag is set on a folio/page, and the buffer heads are detached from it by try_to_free_buffers(), and new buffer heads are then attached by create_empty_buffers(), the uptodate flag may be restored to each buffer without the block device being set to bh->b_bdev, and mark_buffer_dirty() may be called later in that state, resulting in the bug mentioned above. Fix this issue by making nilfs_grab_buffer() always set the block device of the super block structure to the buffer head, regardless of the state of the buffer's uptodate flag. Link: https://lkml.kernel.org/r/[email protected] Fixes: 5305cb8 ("block: add block_{touch|dirty}_buffer tracepoint") Signed-off-by: Ryusuke Konishi <[email protected]> Cc: Tejun Heo <[email protected]> Cc: Ubisectech Sirius <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent cd45e96 commit 2026559

File tree

4 files changed

+2
-6
lines changed

4 files changed

+2
-6
lines changed

fs/nilfs2/btnode.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ nilfs_btnode_create_block(struct address_space *btnc, __u64 blocknr)
6868
goto failed;
6969
}
7070
memset(bh->b_data, 0, i_blocksize(inode));
71-
bh->b_bdev = inode->i_sb->s_bdev;
7271
bh->b_blocknr = blocknr;
7372
set_buffer_mapped(bh);
7473
set_buffer_uptodate(bh);
@@ -133,7 +132,6 @@ int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr,
133132
goto found;
134133
}
135134
set_buffer_mapped(bh);
136-
bh->b_bdev = inode->i_sb->s_bdev;
137135
bh->b_blocknr = pblocknr; /* set block address for read */
138136
bh->b_end_io = end_buffer_read_sync;
139137
get_bh(bh);

fs/nilfs2/gcinode.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,8 @@ int nilfs_gccache_submit_read_data(struct inode *inode, sector_t blkoff,
8383
goto out;
8484
}
8585

86-
if (!buffer_mapped(bh)) {
87-
bh->b_bdev = inode->i_sb->s_bdev;
86+
if (!buffer_mapped(bh))
8887
set_buffer_mapped(bh);
89-
}
9088
bh->b_blocknr = pbn;
9189
bh->b_end_io = end_buffer_read_sync;
9290
get_bh(bh);

fs/nilfs2/mdt.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ static int nilfs_mdt_create_block(struct inode *inode, unsigned long block,
8989
if (buffer_uptodate(bh))
9090
goto failed_bh;
9191

92-
bh->b_bdev = sb->s_bdev;
9392
err = nilfs_mdt_insert_new_block(inode, block, bh, init_block);
9493
if (likely(!err)) {
9594
get_bh(bh);

fs/nilfs2/page.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ struct buffer_head *nilfs_grab_buffer(struct inode *inode,
6363
folio_put(folio);
6464
return NULL;
6565
}
66+
bh->b_bdev = inode->i_sb->s_bdev;
6667
return bh;
6768
}
6869

0 commit comments

Comments
 (0)