On Mon, Aug 20, 2012 at 07:51:10PM +0000, Christoph Lameter wrote: > On Mon, 20 Aug 2012, Mel Gorman wrote: > > > diff --git a/mm/mempolicy.c b/mm/mempolicy.c > > index 45f9825..82e872f 100644 > > --- a/mm/mempolicy.c > > +++ b/mm/mempolicy.c > > @@ -1545,15 +1545,28 @@ struct mempolicy *get_vma_policy(struct task_struct *task, > > struct vm_area_struct *vma, unsigned long addr) > > { > > struct mempolicy *pol = task->mempolicy; > > + int got_ref; > > New variable. Need to set it to zero? > Not needed at all, I was meant to get rid of it. Ben had pointed out this exact problem with the initialisation. > > > > if (vma) { > > if (vma->vm_ops && vma->vm_ops->get_policy) { > > struct mempolicy *vpol = vma->vm_ops->get_policy(vma, > > addr); > > - if (vpol) > > + if (vpol) { > > pol = vpol; > > - } else if (vma->vm_policy) > > + got_ref = 1; > > Set the new variable. But it was not initialzed before. So now its 1 or > undefined? > It's not even needed because the next block is the code that originally cared about the value of got_ref. > > + } > > + } else if (vma->vm_policy) { > > pol = vma->vm_policy; > > + > > + /* > > + * shmem_alloc_page() passes MPOL_F_SHARED policy with > > + * a pseudo vma whose vma->vm_ops=NULL. Take a reference > > + * count on these policies which will be dropped by > > + * mpol_cond_put() later > > + */ > > + if (mpol_needs_cond_ref(pol)) > > + mpol_get(pol); > > + } > > } > > if (!pol) > > pol = &default_policy; > > > > I do not see any use of got_ref. Can we get rid of the variable? > Yes, here is a correct version of the patch. Thanks Christoph. ---8<--- mempolicy: fix a memory corruption by refcount imbalance in alloc_pages_vma() [cc9a6c87: cpuset: mm: reduce large amounts of memory barrier related damage v3] introduced a potential memory corruption. shmem_alloc_page() uses a pseudo vma and it has one significant unique combination, vma->vm_ops=NULL and vma->policy->flags & MPOL_F_SHARED. get_vma_policy() does NOT increase a policy ref when vma->vm_ops=NULL and mpol_cond_put() DOES decrease a policy ref when a policy has MPOL_F_SHARED. Therefore, when a cpuset update race occurs, alloc_pages_vma() falls in 'goto retry_cpuset' path, decrements the reference count and frees the policy prematurely. Signed-off-by: KOSAKI Motohiro <kosaki.motohiro@xxxxxxxxxxxxxx> Signed-off-by: Mel Gorman <mgorman@xxxxxxx> --- mm/mempolicy.c | 12 +++++++++++- 1 files changed, 11 insertions(+), 1 deletions(-) diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 45f9825..9842ef5 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -1552,8 +1552,18 @@ struct mempolicy *get_vma_policy(struct task_struct *task, addr); if (vpol) pol = vpol; - } else if (vma->vm_policy) + } else if (vma->vm_policy) { pol = vma->vm_policy; + + /* + * shmem_alloc_page() passes MPOL_F_SHARED policy with + * a pseudo vma whose vma->vm_ops=NULL. Take a reference + * count on these policies which will be dropped by + * mpol_cond_put() later + */ + if (mpol_needs_cond_ref(pol)) + mpol_get(pol); + } } if (!pol) pol = &default_policy; -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@xxxxxxxxx. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"dont@xxxxxxxxx"> email@xxxxxxxxx </a>