aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorPekka Enberg <penberg@kernel.org>2010-09-14 16:21:12 -0400
committerPekka Enberg <penberg@kernel.org>2010-10-02 03:24:29 -0400
commit84c1cf62465e2fb0a692620dcfeb52323ab03d48 (patch)
tree704f4c7f7f0403aadd62be42d2e9d87abf2926fc /mm
parentdb210e70e5f191710a3b1d09f653b44885d397ea (diff)
SLUB: Fix merged slab cache names
As explained by Linus "I'm Proud to be an American" Torvalds: Looking at the merging code, I actually think it's totally buggy. If you have something like this: - load module A: create slab cache A - load module B: create slab cache B that can merge with A - unload module A - "cat /proc/slabinfo": BOOM. Oops. exactly because the name is not handled correctly, and you'll have module B holding open a slab cache that has a name pointer that points to module A that no longer exists. This patch fixes the problem by using kstrdup() to allocate dynamic memory for ->name of "struct kmem_cache" as suggested by Christoph Lameter. Acked-by: Christoph Lameter <cl@linux.com> Cc: David Rientjes <rientjes@google.com> Reported-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Pekka Enberg <penberg@kernel.org> Conflicts: mm/slub.c
Diffstat (limited to 'mm')
-rw-r--r--mm/slub.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/mm/slub.c b/mm/slub.c
index 05674aac9294..42ce17304275 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -209,6 +209,7 @@ static inline int sysfs_slab_alias(struct kmem_cache *s, const char *p)
209 { return 0; } 209 { return 0; }
210static inline void sysfs_slab_remove(struct kmem_cache *s) 210static inline void sysfs_slab_remove(struct kmem_cache *s)
211{ 211{
212 kfree(s->name);
212 kfree(s); 213 kfree(s);
213} 214}
214 215
@@ -3169,6 +3170,16 @@ void __init kmem_cache_init(void)
3169 slab_state = UP; 3170 slab_state = UP;
3170 3171
3171 /* Provide the correct kmalloc names now that the caches are up */ 3172 /* Provide the correct kmalloc names now that the caches are up */
3173 if (KMALLOC_MIN_SIZE <= 32) {
3174 kmalloc_caches[1]->name = kstrdup(kmalloc_caches[1]->name, GFP_NOWAIT);
3175 BUG_ON(!kmalloc_caches[1]->name);
3176 }
3177
3178 if (KMALLOC_MIN_SIZE <= 64) {
3179 kmalloc_caches[2]->name = kstrdup(kmalloc_caches[2]->name, GFP_NOWAIT);
3180 BUG_ON(!kmalloc_caches[2]->name);
3181 }
3182
3172 for (i = KMALLOC_SHIFT_LOW; i < SLUB_PAGE_SHIFT; i++) { 3183 for (i = KMALLOC_SHIFT_LOW; i < SLUB_PAGE_SHIFT; i++) {
3173 char *s = kasprintf(GFP_NOWAIT, "kmalloc-%d", 1 << i); 3184 char *s = kasprintf(GFP_NOWAIT, "kmalloc-%d", 1 << i);
3174 3185
@@ -3271,6 +3282,7 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size,
3271 size_t align, unsigned long flags, void (*ctor)(void *)) 3282 size_t align, unsigned long flags, void (*ctor)(void *))
3272{ 3283{
3273 struct kmem_cache *s; 3284 struct kmem_cache *s;
3285 char *n;
3274 3286
3275 if (WARN_ON(!name)) 3287 if (WARN_ON(!name))
3276 return NULL; 3288 return NULL;
@@ -3294,19 +3306,25 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size,
3294 return s; 3306 return s;
3295 } 3307 }
3296 3308
3309 n = kstrdup(name, GFP_KERNEL);
3310 if (!n)
3311 goto err;
3312
3297 s = kmalloc(kmem_size, GFP_KERNEL); 3313 s = kmalloc(kmem_size, GFP_KERNEL);
3298 if (s) { 3314 if (s) {
3299 if (kmem_cache_open(s, name, 3315 if (kmem_cache_open(s, n,
3300 size, align, flags, ctor)) { 3316 size, align, flags, ctor)) {
3301 list_add(&s->list, &slab_caches); 3317 list_add(&s->list, &slab_caches);
3302 if (sysfs_slab_add(s)) { 3318 if (sysfs_slab_add(s)) {
3303 list_del(&s->list); 3319 list_del(&s->list);
3320 kfree(n);
3304 kfree(s); 3321 kfree(s);
3305 goto err; 3322 goto err;
3306 } 3323 }
3307 up_write(&slub_lock); 3324 up_write(&slub_lock);
3308 return s; 3325 return s;
3309 } 3326 }
3327 kfree(n);
3310 kfree(s); 3328 kfree(s);
3311 } 3329 }
3312 up_write(&slub_lock); 3330 up_write(&slub_lock);
@@ -4439,6 +4457,7 @@ static void kmem_cache_release(struct kobject *kobj)
4439{ 4457{
4440 struct kmem_cache *s = to_slab(kobj); 4458 struct kmem_cache *s = to_slab(kobj);
4441 4459
4460 kfree(s->name);
4442 kfree(s); 4461 kfree(s);
4443} 4462}
4444 4463