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/IARCIF 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-5.10 merged commit 6584e73a2ca62cf3b0bed42204f79f082801c3f7 ("[Huawei] mm: transplant ksm hugepage feature for kernel 5.10")] 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 21bb3e7cf3bc..b2cdbe6caa71 100644 --- a/mm/ksm.c +++ b/mm/ksm.c @@ -1922,7 +1922,6 @@ static struct 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) { @@ -1941,6 +1940,8 @@ static struct 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; }