binderfs: rework binderfs_binder_device_create()

- switch from d_alloc_name() + d_lookup() to lookup_one_len():
  Instead of using d_alloc_name() and then doing a d_lookup() with the
  allocated dentry to find whether a device with the name we're trying to
  create already exists switch to using lookup_one_len().  The latter will
  either return the existing dentry or a new one.

- switch from kmalloc() + strscpy() to kmemdup():
  Use a more idiomatic way to copy the name for the new dentry that
  userspace gave us.

Suggested-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Christian Brauner <christian@brauner.io>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Christian Brauner 2019-01-21 11:48:05 +01:00 committed by Greg Kroah-Hartman
parent 36975fc3e5
commit 01b3f1fc56
1 changed files with 19 additions and 20 deletions

View File

@ -11,6 +11,7 @@
#include <linux/kdev_t.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/namei.h>
#include <linux/magic.h>
#include <linux/major.h>
#include <linux/miscdevice.h>
@ -106,7 +107,7 @@ bool is_binderfs_device(const struct inode *inode)
* @userp: buffer to copy information about new device for userspace to
* @req: struct binderfs_device as copied from userspace
*
* This function allocated a new binder_device and reserves a new minor
* This function allocates a new binder_device and reserves a new minor
* number for it.
* Minor numbers are limited and tracked globally in binderfs_minors. The
* function will stash a struct binder_device for the specific binder
@ -122,10 +123,10 @@ static int binderfs_binder_device_create(struct inode *ref_inode,
struct binderfs_device *req)
{
int minor, ret;
struct dentry *dentry, *dup, *root;
struct dentry *dentry, *root;
struct binder_device *device;
size_t name_len = BINDERFS_MAX_NAME + 1;
char *name = NULL;
size_t name_len;
struct inode *inode = NULL;
struct super_block *sb = ref_inode->i_sb;
struct binderfs_info *info = sb->s_fs_info;
@ -168,12 +169,13 @@ static int binderfs_binder_device_create(struct inode *ref_inode,
inode->i_uid = info->root_uid;
inode->i_gid = info->root_gid;
name = kmalloc(name_len, GFP_KERNEL);
req->name[BINDERFS_MAX_NAME] = '\0'; /* NUL-terminate */
name_len = strlen(req->name);
/* Make sure to include terminating NUL byte */
name = kmemdup(req->name, name_len + 1, GFP_KERNEL);
if (!name)
goto err;
strscpy(name, req->name, name_len);
device->binderfs_inode = inode;
device->context.binder_context_mgr_uid = INVALID_UID;
device->context.name = name;
@ -192,24 +194,21 @@ static int binderfs_binder_device_create(struct inode *ref_inode,
root = sb->s_root;
inode_lock(d_inode(root));
dentry = d_alloc_name(root, name);
if (!dentry) {
/* look it up */
dentry = lookup_one_len(name, root, name_len);
if (IS_ERR(dentry)) {
inode_unlock(d_inode(root));
ret = -ENOMEM;
ret = PTR_ERR(dentry);
goto err;
}
/* Verify that the name userspace gave us is not already in use. */
dup = d_lookup(root, &dentry->d_name);
if (dup) {
if (d_really_is_positive(dup)) {
dput(dup);
dput(dentry);
inode_unlock(d_inode(root));
ret = -EEXIST;
goto err;
}
dput(dup);
if (d_really_is_positive(dentry)) {
/* already exists */
dput(dentry);
inode_unlock(d_inode(root));
ret = -EEXIST;
goto err;
}
inode->i_private = device;