From: Chengming Zhou chengming.zhou@linux.dev
mainline inclusion from mainline-v6.10-rc1 commit 90e823498881fb8a91d83e9a8eed87c8c3ff2176 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IARBRI CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
The commit 2c653d0ee2ae ("ksm: introduce ksm_max_page_sharing per page deduplication limit") introduced a possible failure case in the stable_tree_insert(), where we may free the new allocated stable_node_dup if we fail to prepare the missing chain node.
Then that kfolio return and unlock with a freed stable_node set... And any MM activities can come in to access kfolio->mapping, so UAF.
Fix it by moving folio_set_stable_node() to the end after stable_node is inserted successfully.
Link: https://lkml.kernel.org/r/20240513-b4-ksm-stable-node-uaf-v1-1-f687de76f452@... Fixes: 2c653d0ee2ae ("ksm: introduce ksm_max_page_sharing per page deduplication limit") Signed-off-by: Chengming Zhou chengming.zhou@linux.dev Acked-by: David Hildenbrand david@redhat.com Cc: Andrea Arcangeli aarcange@redhat.com Cc: Hugh Dickins hughd@google.com Cc: Stefan Roesch shr@devkernel.io Signed-off-by: Andrew Morton akpm@linux-foundation.org
Conflicts: mm/ksm.c [OLK-6.6 didn't merge mainline inclusion commit 79899cce33e0887c06d41e767aa543aaaaef48e2("mm/ksm: convert chain series funcs and replace get_ksm_page")] Signed-off-by: Kaixiong Yu yukaixiong@huawei.com --- mm/ksm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/mm/ksm.c b/mm/ksm.c index c828630985c0..7d5c76746712 100644 --- a/mm/ksm.c +++ b/mm/ksm.c @@ -1965,7 +1965,6 @@ static struct ksm_stable_node *stable_tree_insert(struct page *kpage)
INIT_HLIST_HEAD(&stable_node_dup->hlist); stable_node_dup->kpfn = kpfn; - set_page_stable_node(kpage, stable_node_dup); stable_node_dup->rmap_hlist_len = 0; DO_NUMA(stable_node_dup->nid = nid); if (!need_chain) { @@ -1984,6 +1983,8 @@ static struct ksm_stable_node *stable_tree_insert(struct page *kpage) stable_node_chain_add_dup(stable_node_dup, stable_node); }
+ set_page_stable_node(kpage, stable_node_dup); + return stable_node_dup; }