diff options
author | KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> | 2012-10-08 19:29:19 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-09 03:22:22 -0400 |
commit | 63f74ca21f1fad36d075e063f06dcc6d39fe86b2 (patch) | |
tree | 44ba87965b18f77fbb464d891ef07b2eca8304d4 /mm/mempolicy.c | |
parent | b22d127a39ddd10d93deee3d96e643657ad53a49 (diff) |
mempolicy: fix refcount leak in mpol_set_shared_policy()
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>
Diffstat (limited to 'mm/mempolicy.c')
-rw-r--r-- | mm/mempolicy.c | 15 |
1 files changed, 9 insertions, 6 deletions
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index b2f12ecc1b34..1763418f1ada 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c | |||
@@ -2157,12 +2157,17 @@ mpol_shared_policy_lookup(struct shared_policy *sp, unsigned long idx) | |||
2157 | return pol; | 2157 | return pol; |
2158 | } | 2158 | } |
2159 | 2159 | ||
2160 | static void sp_free(struct sp_node *n) | ||
2161 | { | ||
2162 | mpol_put(n->policy); | ||
2163 | kmem_cache_free(sn_cache, n); | ||
2164 | } | ||
2165 | |||
2160 | static void sp_delete(struct shared_policy *sp, struct sp_node *n) | 2166 | static void sp_delete(struct shared_policy *sp, struct sp_node *n) |
2161 | { | 2167 | { |
2162 | pr_debug("deleting %lx-l%lx\n", n->start, n->end); | 2168 | pr_debug("deleting %lx-l%lx\n", n->start, n->end); |
2163 | rb_erase(&n->nd, &sp->root); | 2169 | rb_erase(&n->nd, &sp->root); |
2164 | mpol_put(n->policy); | 2170 | sp_free(n); |
2165 | kmem_cache_free(sn_cache, n); | ||
2166 | } | 2171 | } |
2167 | 2172 | ||
2168 | static struct sp_node *sp_alloc(unsigned long start, unsigned long end, | 2173 | static struct sp_node *sp_alloc(unsigned long start, unsigned long end, |
@@ -2301,7 +2306,7 @@ int mpol_set_shared_policy(struct shared_policy *info, | |||
2301 | } | 2306 | } |
2302 | err = shared_policy_replace(info, vma->vm_pgoff, vma->vm_pgoff+sz, new); | 2307 | err = shared_policy_replace(info, vma->vm_pgoff, vma->vm_pgoff+sz, new); |
2303 | if (err && new) | 2308 | if (err && new) |
2304 | kmem_cache_free(sn_cache, new); | 2309 | sp_free(new); |
2305 | return err; | 2310 | return err; |
2306 | } | 2311 | } |
2307 | 2312 | ||
@@ -2318,9 +2323,7 @@ void mpol_free_shared_policy(struct shared_policy *p) | |||
2318 | while (next) { | 2323 | while (next) { |
2319 | n = rb_entry(next, struct sp_node, nd); | 2324 | n = rb_entry(next, struct sp_node, nd); |
2320 | next = rb_next(&n->nd); | 2325 | next = rb_next(&n->nd); |
2321 | rb_erase(&n->nd, &p->root); | 2326 | sp_delete(p, n); |
2322 | mpol_put(n->policy); | ||
2323 | kmem_cache_free(sn_cache, n); | ||
2324 | } | 2327 | } |
2325 | mutex_unlock(&p->mutex); | 2328 | mutex_unlock(&p->mutex); |
2326 | } | 2329 | } |