mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-02 15:18:19 +00:00
XArray: Disallow sibling entries of nodes
[ Upstream commit63b1898fff
] There is a race between xas_split() and xas_load() which can result in the wrong page being returned, and thus data corruption. Fortunately, it's hard to hit (syzbot took three months to find it) and often guarded with VM_BUG_ON(). The anatomy of this race is: thread A thread B order-9 page is stored at index 0x200 lookup of page at index 0x274 page split starts load of sibling entry at offset 9 stores nodes at offsets 8-15 load of entry at offset 8 The entry at offset 8 turns out to be a node, and so we descend into it, and load the page at index 0x234 instead of 0x274. This is hard to fix on the split side; we could replace the entire node that contains the order-9 page instead of replacing the eight entries. Fixing it on the lookup side is easier; just disallow sibling entries that point to nodes. This cannot ever be a useful thing as the descent would not know the correct offset to use within the new node. The test suite continues to pass, but I have not added a new test for this bug. Reported-by: syzbot+cf4cf13056f85dec2c40@syzkaller.appspotmail.com Tested-by: syzbot+cf4cf13056f85dec2c40@syzkaller.appspotmail.com Fixes:6b24ca4a1a
("mm: Use multi-index entries in the page cache") Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
3b63a41f9e
commit
825b95bd8f
1 changed files with 2 additions and 0 deletions
|
@ -207,6 +207,8 @@ static void *xas_descend(struct xa_state *xas, struct xa_node *node)
|
|||
if (xa_is_sibling(entry)) {
|
||||
offset = xa_to_sibling(entry);
|
||||
entry = xa_entry(xas->xa, node, offset);
|
||||
if (node->shift && xa_is_node(entry))
|
||||
entry = XA_RETRY_ENTRY;
|
||||
}
|
||||
|
||||
xas->xa_offset = offset;
|
||||
|
|
Loading…
Reference in a new issue