Skip to content

Commit 2420baa

Browse files
hygonitehcaster
authored andcommitted
mm/slab: Allow cache creation to proceed even if sysfs registration fails
When kobject_init_and_add() fails during cache creation, kobj->name can be leaked because SLUB does not call kobject_put(), which should be invoked per the kobject API documentation. This has a bit of historical context, though; SLUB does not call kobject_put() to avoid double-free for struct kmem_cache because 1) simply calling it would free all resources related to the cache, and 2) struct kmem_cache descriptor is always freed by cache_cache()'s error handling path, causing struct kmem_cache to be freed twice. This issue can be reproduced by creating new slab caches while applying failslab for kernfs_node_cache. This makes kobject_add_varg() succeed, but causes kobject_add_internal() to fail in kobject_init_and_add() during cache creation. Historically, this issue has attracted developers' attention several times. Each time a fix addressed either the leak or the double-free, it caused the other issue. Let's summarize a bit of history here: The leak has existed since the early days of SLUB. Commit 54b6a73 ("slub: fix leak of 'name' in sysfs_slab_add") introduced a double-free bug while fixing the leak. Commit 80da026 ("mm/slub: fix slab double-free in case of duplicate sysfs filename") re-introduced the leak while fixing the double-free error. Commit dde3c6b ("mm/slub: fix a memory leak in sysfs_slab_add()") fixed the memory leak, but it was later reverted by commit 757fed1 ("Revert "mm/slub: fix a memory leak in sysfs_slab_add()"") to avoid the double-free error. This is where we are now: we've chosen a memory leak over a double-free. To resolve this memory leak, skip creating sysfs files if it fails and continue with cache creation regardless (as suggested by Christoph). This resolves the memory leak because both the cache and the kobject remain alive on kobject_init_and_add() failure. If SLUB tries to create an alias for a cache without sysfs files, its symbolic link will not be generated. Since a slab cache might not have associated sysfs files, call kobject_del() only if such files exist. Signed-off-by: Hyeonggon Yoo <42.hyeyoo@gmail.com> Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
1 parent dbc1691 commit 2420baa

File tree

1 file changed

+18
-8
lines changed

1 file changed

+18
-8
lines changed

mm/slub.c

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6073,7 +6073,8 @@ __kmem_cache_alias(const char *name, unsigned int size, unsigned int align,
60736073
s = find_mergeable(size, align, flags, name, ctor);
60746074
if (s) {
60756075
if (sysfs_slab_alias(s, name))
6076-
return NULL;
6076+
pr_err("SLUB: Unable to add cache alias %s to sysfs\n",
6077+
name);
60776078

60786079
s->refcount++;
60796080

@@ -6155,15 +6156,18 @@ int do_kmem_cache_create(struct kmem_cache *s, const char *name,
61556156
if (!alloc_kmem_cache_cpus(s))
61566157
goto out;
61576158

6159+
err = 0;
6160+
61586161
/* Mutex is not taken during early boot */
6159-
if (slab_state <= UP) {
6160-
err = 0;
6162+
if (slab_state <= UP)
61616163
goto out;
6162-
}
61636164

6164-
err = sysfs_slab_add(s);
6165-
if (err)
6166-
goto out;
6165+
/*
6166+
* Failing to create sysfs files is not critical to SLUB functionality.
6167+
* If it fails, proceed with cache creation without these files.
6168+
*/
6169+
if (sysfs_slab_add(s))
6170+
pr_err("SLUB: Unable to add cache %s to sysfs\n", s->name);
61676171

61686172
if (s->flags & SLAB_STORE_USER)
61696173
debugfs_slab_add(s);
@@ -7233,7 +7237,8 @@ static int sysfs_slab_add(struct kmem_cache *s)
72337237

72347238
void sysfs_slab_unlink(struct kmem_cache *s)
72357239
{
7236-
kobject_del(&s->kobj);
7240+
if (s->kobj.state_in_sysfs)
7241+
kobject_del(&s->kobj);
72377242
}
72387243

72397244
void sysfs_slab_release(struct kmem_cache *s)
@@ -7262,6 +7267,11 @@ static int sysfs_slab_alias(struct kmem_cache *s, const char *name)
72627267
* If we have a leftover link then remove it.
72637268
*/
72647269
sysfs_remove_link(&slab_kset->kobj, name);
7270+
/*
7271+
* The original cache may have failed to generate sysfs file.
7272+
* In that case, sysfs_create_link() returns -ENOENT and
7273+
* symbolic link creation is skipped.
7274+
*/
72657275
return sysfs_create_link(&slab_kset->kobj, &s->kobj, name);
72667276
}
72677277

0 commit comments

Comments
 (0)