diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2011-11-22 10:02:02 -0500 |
---|---|---|
committer | Pekka Enberg <penberg@kernel.org> | 2011-11-24 01:44:19 -0500 |
commit | bc6697d8a506dedf09e8e9974ffa3a316183e608 (patch) | |
tree | b54d3d45349fb8a00ce8a086da55a1ebf3394646 /mm | |
parent | 42d623a8cd08eb93ab221d22cee5a62618895bbf (diff) |
slub: avoid potential NULL dereference or corruption
show_slab_objects() can trigger NULL dereferences or memory corruption.
Another cpu can change its c->page to NULL or c->node to NUMA_NO_NODE
while we use them.
Use ACCESS_ONCE(c->page) and ACCESS_ONCE(c->node) to make sure this
cannot happen.
Acked-by: Christoph Lameter <cl@linux.com>
Acked-by: David Rientjes <rientjes@google.com>
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/slub.c | 21 |
1 files changed, 11 insertions, 10 deletions
@@ -4444,30 +4444,31 @@ static ssize_t show_slab_objects(struct kmem_cache *s, | |||
4444 | 4444 | ||
4445 | for_each_possible_cpu(cpu) { | 4445 | for_each_possible_cpu(cpu) { |
4446 | struct kmem_cache_cpu *c = per_cpu_ptr(s->cpu_slab, cpu); | 4446 | struct kmem_cache_cpu *c = per_cpu_ptr(s->cpu_slab, cpu); |
4447 | int node = ACCESS_ONCE(c->node); | ||
4447 | struct page *page; | 4448 | struct page *page; |
4448 | 4449 | ||
4449 | if (!c || c->node < 0) | 4450 | if (node < 0) |
4450 | continue; | 4451 | continue; |
4451 | 4452 | page = ACCESS_ONCE(c->page); | |
4452 | if (c->page) { | 4453 | if (page) { |
4453 | if (flags & SO_TOTAL) | 4454 | if (flags & SO_TOTAL) |
4454 | x = c->page->objects; | 4455 | x = page->objects; |
4455 | else if (flags & SO_OBJECTS) | 4456 | else if (flags & SO_OBJECTS) |
4456 | x = c->page->inuse; | 4457 | x = page->inuse; |
4457 | else | 4458 | else |
4458 | x = 1; | 4459 | x = 1; |
4459 | 4460 | ||
4460 | total += x; | 4461 | total += x; |
4461 | nodes[c->node] += x; | 4462 | nodes[node] += x; |
4462 | } | 4463 | } |
4463 | page = c->partial; | 4464 | page = c->partial; |
4464 | 4465 | ||
4465 | if (page) { | 4466 | if (page) { |
4466 | x = page->pobjects; | 4467 | x = page->pobjects; |
4467 | total += x; | 4468 | total += x; |
4468 | nodes[c->node] += x; | 4469 | nodes[node] += x; |
4469 | } | 4470 | } |
4470 | per_cpu[c->node]++; | 4471 | per_cpu[node]++; |
4471 | } | 4472 | } |
4472 | } | 4473 | } |
4473 | 4474 | ||