From 707c62352909a9be2453ae073e160de59d2d4a1f Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 15 Jun 2018 15:20:42 -0700 Subject: configfs: use kvasprintf() instead of open-coding it Signed-off-by: Bart Van Assche Signed-off-by: Christoph Hellwig --- fs/configfs/item.c | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/fs/configfs/item.c b/fs/configfs/item.c index 88f266efc09b..99d491cd01f9 100644 --- a/fs/configfs/item.c +++ b/fs/configfs/item.c @@ -64,7 +64,6 @@ static void config_item_init(struct config_item *item) */ int config_item_set_name(struct config_item *item, const char *fmt, ...) { - int error = 0; int limit = CONFIGFS_ITEM_NAME_LEN; int need; va_list args; @@ -79,25 +78,11 @@ int config_item_set_name(struct config_item *item, const char *fmt, ...) if (need < limit) name = item->ci_namebuf; else { - /* - * Need more space? Allocate it and try again - */ - limit = need + 1; - name = kmalloc(limit, GFP_KERNEL); - if (!name) { - error = -ENOMEM; - goto Done; - } va_start(args, fmt); - need = vsnprintf(name, limit, fmt, args); + name = kvasprintf(GFP_KERNEL, fmt, args); va_end(args); - - /* Still? Give up. */ - if (need >= limit) { - kfree(name); - error = -EFAULT; - goto Done; - } + if (!name) + return -EFAULT; } /* Free the old name, if necessary. */ @@ -106,8 +91,7 @@ int config_item_set_name(struct config_item *item, const char *fmt, ...) /* Now, set the new name */ item->ci_name = name; - Done: - return error; + return 0; } EXPORT_SYMBOL(config_item_set_name); -- cgit v1.2.3-59-g8ed1b From 1823342a1f2b47a4e6f5667f67cd28ab6bc4d6cd Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sun, 1 Jul 2018 13:56:54 -0700 Subject: configfs: replace strncpy with memcpy gcc 8.1.0 complains: fs/configfs/symlink.c:67:3: warning: 'strncpy' output truncated before terminating nul copying as many bytes from a string as its length fs/configfs/symlink.c: In function 'configfs_get_link': fs/configfs/symlink.c:63:13: note: length computed here Using strncpy() is indeed less than perfect since the length of data to be copied has already been determined with strlen(). Replace strncpy() with memcpy() to address the warning and optimize the code a little. Signed-off-by: Guenter Roeck Signed-off-by: Christoph Hellwig --- fs/configfs/symlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c index 78ffc2699993..a5c54af861f7 100644 --- a/fs/configfs/symlink.c +++ b/fs/configfs/symlink.c @@ -64,7 +64,7 @@ static void fill_item_path(struct config_item * item, char * buffer, int length) /* back up enough to print this bus id with '/' */ length -= cur; - strncpy(buffer + length,config_item_name(p),cur); + memcpy(buffer + length, config_item_name(p), cur); *(buffer + --length) = '/'; } } -- cgit v1.2.3-59-g8ed1b From cc57c07343bd071cdf1915a91a24ab7d40c9b590 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Sun, 15 Jul 2018 18:16:17 -0500 Subject: configfs: fix registered group removal This patch fixes a bug where configfs_register_group had added a group in a tree, and userspace has done a rmdir on a dir somewhere above that group and we hit a kernel crash. The problem is configfs_rmdir will detach everything under it and unlink groups on the default_groups list. It will not unlink groups added with configfs_register_group so when configfs_unregister_group is called to drop its references to the group/items we crash when we try to access the freed dentrys. The patch just adds a check for if a rmdir has been done above us and if so just does the unlink part of unregistration. Sorry if you are getting this multiple times. I thouhgt I sent this to some of you and lkml, but I do not see it. Signed-off-by: Mike Christie Cc: Christoph Hellwig Cc: Joel Becker Signed-off-by: Christoph Hellwig --- fs/configfs/dir.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 577cff24707b..39843fa7e11b 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c @@ -1777,6 +1777,16 @@ void configfs_unregister_group(struct config_group *group) struct dentry *dentry = group->cg_item.ci_dentry; struct dentry *parent = group->cg_item.ci_parent->ci_dentry; + mutex_lock(&subsys->su_mutex); + if (!group->cg_item.ci_parent->ci_group) { + /* + * The parent has already been unlinked and detached + * due to a rmdir. + */ + goto unlink_group; + } + mutex_unlock(&subsys->su_mutex); + inode_lock_nested(d_inode(parent), I_MUTEX_PARENT); spin_lock(&configfs_dirent_lock); configfs_detach_prep(dentry, NULL); @@ -1791,6 +1801,7 @@ void configfs_unregister_group(struct config_group *group) dput(dentry); mutex_lock(&subsys->su_mutex); +unlink_group: unlink_group(group); mutex_unlock(&subsys->su_mutex); } -- cgit v1.2.3-59-g8ed1b