| From 63f74ca21f1fad36d075e063f06dcc6d39fe86b2 Mon Sep 17 00:00:00 2001 |
| From: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> |
| Date: Mon, 8 Oct 2012 16:29:19 -0700 |
| Subject: mempolicy: fix refcount leak in mpol_set_shared_policy() |
| |
| From: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> |
| |
| commit 63f74ca21f1fad36d075e063f06dcc6d39fe86b2 upstream. |
| |
| When shared_policy_replace() fails to allocate new->policy is not freed |
| correctly by mpol_set_shared_policy(). The problem is that shared |
| mempolicy code directly call kmem_cache_free() in multiple places where |
| it is easy to make a mistake. |
| |
| This patch creates an sp_free wrapper function and uses it. The bug was |
| introduced pre-git age (IOW, before 2.6.12-rc2). |
| |
| [mgorman@suse.de: Editted changelog] |
| Signed-off-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> |
| Signed-off-by: Mel Gorman <mgorman@suse.de> |
| Reviewed-by: Christoph Lameter <cl@linux.com> |
| Cc: Josh Boyer <jwboyer@gmail.com> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| mm/mempolicy.c | 15 +++++++++------ |
| 1 file changed, 9 insertions(+), 6 deletions(-) |
| |
| --- a/mm/mempolicy.c |
| +++ b/mm/mempolicy.c |
| @@ -2095,12 +2095,17 @@ mpol_shared_policy_lookup(struct shared_ |
| return pol; |
| } |
| |
| +static void sp_free(struct sp_node *n) |
| +{ |
| + mpol_put(n->policy); |
| + kmem_cache_free(sn_cache, n); |
| +} |
| + |
| static void sp_delete(struct shared_policy *sp, struct sp_node *n) |
| { |
| pr_debug("deleting %lx-l%lx\n", n->start, n->end); |
| rb_erase(&n->nd, &sp->root); |
| - mpol_put(n->policy); |
| - kmem_cache_free(sn_cache, n); |
| + sp_free(n); |
| } |
| |
| static struct sp_node *sp_alloc(unsigned long start, unsigned long end, |
| @@ -2239,7 +2244,7 @@ int mpol_set_shared_policy(struct shared |
| } |
| err = shared_policy_replace(info, vma->vm_pgoff, vma->vm_pgoff+sz, new); |
| if (err && new) |
| - kmem_cache_free(sn_cache, new); |
| + sp_free(new); |
| return err; |
| } |
| |
| @@ -2256,9 +2261,7 @@ void mpol_free_shared_policy(struct shar |
| while (next) { |
| n = rb_entry(next, struct sp_node, nd); |
| next = rb_next(&n->nd); |
| - rb_erase(&n->nd, &p->root); |
| - mpol_put(n->policy); |
| - kmem_cache_free(sn_cache, n); |
| + sp_delete(p, n); |
| } |
| mutex_unlock(&p->mutex); |
| } |