All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] fs: buffer: Check to avoid NULL pointer dereference of returned buffer_head for a private page
@ 2019-08-14 15:09 Monthero Ronald
  2019-08-14 16:02 ` Greg KH
  2019-08-18  4:31 ` Al Viro
  0 siblings, 2 replies; 6+ messages in thread
From: Monthero Ronald @ 2019-08-14 15:09 UTC (permalink / raw)
  To: viro; +Cc: stable, Monthero Ronald

The patch checks for this condition of NULL pointer for the buffer_head returned from page_buffers()
and also a check placed within the list traversal loop for next buffer_head structs.

crash scenario:
The buffer_head returned from page_buffers() is not checked in block_invalidatepage_range function.
The struct buffer_head* pointer returned by page_buffers(page) was 0x0, although this page had its
private flag PG_private bit set and was expected to have buffer_head structs attached.The NULL pointer
buffer_head was dereferenced in block_invalidatepage_range function at bh->b_size, where bh returned by
page_buffers(page) was 0x0.

The stack frames were  truncate_inode_page() => do_invalidatepage_range() => xfs_vm_invalidatepage() =>
          [exception RIP: block_invalidatepage_range+132]

The inode for truncate in this case was valid and had  proper inode.i_state = 0x20 - FREEING and had
a valid mapped address space to xfs. And the struct page in context of block_invalidatepage_range()
had its page flag PG_private set but the page.private was 0x0. So page_buffers(page) returned 0x0
and hence the crash.
This patch performs NULL pointer check for returned buffer_head. Applies to 3.16 and later kernels.

Signed-off-by: Monthero Ronald <rhmcruiser@gmail.com>
---
 fs/buffer.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/fs/buffer.c b/fs/buffer.c
index eba6e4f..fa80cf4 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1541,6 +1541,7 @@ void block_invalidatepage(struct page *page, unsigned int offset,
 	BUG_ON(stop > PAGE_CACHE_SIZE || stop < length);
 
 	head = page_buffers(page);
+	BUG_ON(!head);
 	bh = head;
 	do {
 		unsigned int next_off = curr_off + bh->b_size;
@@ -1559,6 +1560,7 @@ void block_invalidatepage(struct page *page, unsigned int offset,
 			discard_buffer(bh);
 		curr_off = next_off;
 		bh = next;
+		BUG_ON(!bh);
 	} while (bh != head);
 
 	/*
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2019-08-18  5:10 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-08-14 15:09 [PATCH] fs: buffer: Check to avoid NULL pointer dereference of returned buffer_head for a private page Monthero Ronald
2019-08-14 16:02 ` Greg KH
2019-08-18  4:27   ` Ron Enfield
2019-08-18  5:10     ` Greg KH
2019-08-18  4:31 ` Al Viro
2019-08-18  4:57   ` Ron Enfield

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.