From 19452c87ab258fe06176657f8490581bebcf90e7 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 25 Aug 2010 23:12:54 -0700 Subject: [PATCH] --- yaml --- r: 210010 b: refs/heads/master c: f18194275c39835cb84563500995e0d503a32d9a h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/mm/rmap.c | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/[refs] b/[refs] index aa73ef11088e..6c515b4798da 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: d4348c678977c7093438bbbf2067c49396ae941b +refs/heads/master: f18194275c39835cb84563500995e0d503a32d9a diff --git a/trunk/mm/rmap.c b/trunk/mm/rmap.c index 87b9e8ad4509..f6f0d2dda2ea 100644 --- a/trunk/mm/rmap.c +++ b/trunk/mm/rmap.c @@ -316,7 +316,7 @@ void __init anon_vma_init(void) */ struct anon_vma *page_lock_anon_vma(struct page *page) { - struct anon_vma *anon_vma; + struct anon_vma *anon_vma, *root_anon_vma; unsigned long anon_mapping; rcu_read_lock(); @@ -327,8 +327,21 @@ struct anon_vma *page_lock_anon_vma(struct page *page) goto out; anon_vma = (struct anon_vma *) (anon_mapping - PAGE_MAPPING_ANON); - anon_vma_lock(anon_vma); - return anon_vma; + root_anon_vma = ACCESS_ONCE(anon_vma->root); + spin_lock(&root_anon_vma->lock); + + /* + * If this page is still mapped, then its anon_vma cannot have been + * freed. But if it has been unmapped, we have no security against + * the anon_vma structure being freed and reused (for another anon_vma: + * SLAB_DESTROY_BY_RCU guarantees that - so the spin_lock above cannot + * corrupt): with anon_vma_prepare() or anon_vma_fork() redirecting + * anon_vma->root before page_unlock_anon_vma() is called to unlock. + */ + if (page_mapped(page)) + return anon_vma; + + spin_unlock(&root_anon_vma->lock); out: rcu_read_unlock(); return NULL;