diff options
author | Linus Torvalds | 2021-09-12 10:43:51 -0700 |
---|---|---|
committer | Linus Torvalds | 2021-09-12 10:43:51 -0700 |
commit | fdfc346302a7b63e3d5b9168be74bb12b1975999 (patch) | |
tree | 4c31a7d643c04aba5e2099b6968bd147709a36c5 | |
parent | 8d4a0b5d0813c990637fa9f3c9bea5dab1fedb8f (diff) | |
parent | ea47ab111669b187808b3080602788dec26cb9bc (diff) |
Merge branch 'misc.namei' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull namei updates from Al Viro:
"Clearing fallout from mkdirat in io_uring series. The fix in the
kern_path_locked() patch plus associated cleanups"
* 'misc.namei' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
putname(): IS_ERR_OR_NULL() is wrong here
namei: Standardize callers of filename_create()
namei: Standardize callers of filename_lookup()
rename __filename_parentat() to filename_parentat()
namei: Fix use after free in kern_path_locked
-rw-r--r-- | fs/fs_parser.c | 1 | ||||
-rw-r--r-- | fs/namei.c | 116 |
2 files changed, 58 insertions, 59 deletions
diff --git a/fs/fs_parser.c b/fs/fs_parser.c index 980d44fd3a36..3df07c0e32b3 100644 --- a/fs/fs_parser.c +++ b/fs/fs_parser.c @@ -165,7 +165,6 @@ int fs_lookup_param(struct fs_context *fc, return invalf(fc, "%s: not usable as path", param->key); } - f->refcnt++; /* filename_lookup() drops our ref. */ ret = filename_lookup(param->dirfd, f, flags, _path, NULL); if (ret < 0) { errorf(fc, "%s: Lookup failure for '%s'", param->key, f->name); diff --git a/fs/namei.c b/fs/namei.c index 95a881e0552b..1946d9667790 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -255,7 +255,7 @@ getname_kernel(const char * filename) void putname(struct filename *name) { - if (IS_ERR_OR_NULL(name)) + if (IS_ERR(name)) return; BUG_ON(name->refcnt <= 0); @@ -2467,7 +2467,7 @@ static int path_lookupat(struct nameidata *nd, unsigned flags, struct path *path return err; } -static int __filename_lookup(int dfd, struct filename *name, unsigned flags, +int filename_lookup(int dfd, struct filename *name, unsigned flags, struct path *path, struct path *root) { int retval; @@ -2488,15 +2488,6 @@ static int __filename_lookup(int dfd, struct filename *name, unsigned flags, return retval; } -int filename_lookup(int dfd, struct filename *name, unsigned flags, - struct path *path, struct path *root) -{ - int retval = __filename_lookup(dfd, name, flags, path, root); - - putname(name); - return retval; -} - /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */ static int path_parentat(struct nameidata *nd, unsigned flags, struct path *parent) @@ -2514,9 +2505,10 @@ static int path_parentat(struct nameidata *nd, unsigned flags, return err; } -static int __filename_parentat(int dfd, struct filename *name, - unsigned int flags, struct path *parent, - struct qstr *last, int *type) +/* Note: this does not consume "name" */ +static int filename_parentat(int dfd, struct filename *name, + unsigned int flags, struct path *parent, + struct qstr *last, int *type) { int retval; struct nameidata nd; @@ -2538,25 +2530,14 @@ static int __filename_parentat(int dfd, struct filename *name, return retval; } -static int filename_parentat(int dfd, struct filename *name, - unsigned int flags, struct path *parent, - struct qstr *last, int *type) -{ - int retval = __filename_parentat(dfd, name, flags, parent, last, type); - - putname(name); - return retval; -} - /* does lookup, returns the object with parent locked */ -struct dentry *kern_path_locked(const char *name, struct path *path) +static struct dentry *__kern_path_locked(struct filename *name, struct path *path) { struct dentry *d; struct qstr last; int type, error; - error = filename_parentat(AT_FDCWD, getname_kernel(name), 0, path, - &last, &type); + error = filename_parentat(AT_FDCWD, name, 0, path, &last, &type); if (error) return ERR_PTR(error); if (unlikely(type != LAST_NORM)) { @@ -2572,10 +2553,23 @@ struct dentry *kern_path_locked(const char *name, struct path *path) return d; } +struct dentry *kern_path_locked(const char *name, struct path *path) +{ + struct filename *filename = getname_kernel(name); + struct dentry *res = __kern_path_locked(filename, path); + + putname(filename); + return res; +} + int kern_path(const char *name, unsigned int flags, struct path *path) { - return filename_lookup(AT_FDCWD, getname_kernel(name), - flags, path, NULL); + struct filename *filename = getname_kernel(name); + int ret = filename_lookup(AT_FDCWD, filename, flags, path, NULL); + + putname(filename); + return ret; + } EXPORT_SYMBOL(kern_path); @@ -2591,10 +2585,15 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt, const char *name, unsigned int flags, struct path *path) { + struct filename *filename; struct path root = {.mnt = mnt, .dentry = dentry}; + int ret; + + filename = getname_kernel(name); /* the first argument of filename_lookup() is ignored with root */ - return filename_lookup(AT_FDCWD, getname_kernel(name), - flags , path, &root); + ret = filename_lookup(AT_FDCWD, filename, flags, path, &root); + putname(filename); + return ret; } EXPORT_SYMBOL(vfs_path_lookup); @@ -2798,8 +2797,11 @@ int path_pts(struct path *path) int user_path_at_empty(int dfd, const char __user *name, unsigned flags, struct path *path, int *empty) { - return filename_lookup(dfd, getname_flags(name, flags, empty), - flags, path, NULL); + struct filename *filename = getname_flags(name, flags, empty); + int ret = filename_lookup(dfd, filename, flags, path, NULL); + + putname(filename); + return ret; } EXPORT_SYMBOL(user_path_at_empty); @@ -3618,8 +3620,8 @@ struct file *do_file_open_root(const struct path *root, return file; } -static struct dentry *__filename_create(int dfd, struct filename *name, - struct path *path, unsigned int lookup_flags) +static struct dentry *filename_create(int dfd, struct filename *name, + struct path *path, unsigned int lookup_flags) { struct dentry *dentry = ERR_PTR(-EEXIST); struct qstr last; @@ -3634,7 +3636,7 @@ static struct dentry *__filename_create(int dfd, struct filename *name, */ lookup_flags &= LOOKUP_REVAL; - error = __filename_parentat(dfd, name, lookup_flags, path, &last, &type); + error = filename_parentat(dfd, name, lookup_flags, path, &last, &type); if (error) return ERR_PTR(error); @@ -3687,21 +3689,15 @@ out: return dentry; } -static inline struct dentry *filename_create(int dfd, struct filename *name, +struct dentry *kern_path_create(int dfd, const char *pathname, struct path *path, unsigned int lookup_flags) { - struct dentry *res = __filename_create(dfd, name, path, lookup_flags); + struct filename *filename = getname_kernel(pathname); + struct dentry *res = filename_create(dfd, filename, path, lookup_flags); - putname(name); + putname(filename); return res; } - -struct dentry *kern_path_create(int dfd, const char *pathname, - struct path *path, unsigned int lookup_flags) -{ - return filename_create(dfd, getname_kernel(pathname), - path, lookup_flags); -} EXPORT_SYMBOL(kern_path_create); void done_path_create(struct path *path, struct dentry *dentry) @@ -3716,7 +3712,11 @@ EXPORT_SYMBOL(done_path_create); inline struct dentry *user_path_create(int dfd, const char __user *pathname, struct path *path, unsigned int lookup_flags) { - return filename_create(dfd, getname(pathname), path, lookup_flags); + struct filename *filename = getname(pathname); + struct dentry *res = filename_create(dfd, filename, path, lookup_flags); + + putname(filename); + return res; } EXPORT_SYMBOL(user_path_create); @@ -3797,7 +3797,7 @@ static int do_mknodat(int dfd, struct filename *name, umode_t mode, if (error) goto out1; retry: - dentry = __filename_create(dfd, name, &path, lookup_flags); + dentry = filename_create(dfd, name, &path, lookup_flags); error = PTR_ERR(dentry); if (IS_ERR(dentry)) goto out1; @@ -3897,7 +3897,7 @@ int do_mkdirat(int dfd, struct filename *name, umode_t mode) unsigned int lookup_flags = LOOKUP_DIRECTORY; retry: - dentry = __filename_create(dfd, name, &path, lookup_flags); + dentry = filename_create(dfd, name, &path, lookup_flags); error = PTR_ERR(dentry); if (IS_ERR(dentry)) goto out_putname; @@ -3996,7 +3996,7 @@ int do_rmdir(int dfd, struct filename *name) int type; unsigned int lookup_flags = 0; retry: - error = __filename_parentat(dfd, name, lookup_flags, &path, &last, &type); + error = filename_parentat(dfd, name, lookup_flags, &path, &last, &type); if (error) goto exit1; @@ -4137,7 +4137,7 @@ int do_unlinkat(int dfd, struct filename *name) struct inode *delegated_inode = NULL; unsigned int lookup_flags = 0; retry: - error = __filename_parentat(dfd, name, lookup_flags, &path, &last, &type); + error = filename_parentat(dfd, name, lookup_flags, &path, &last, &type); if (error) goto exit1; @@ -4266,7 +4266,7 @@ int do_symlinkat(struct filename *from, int newdfd, struct filename *to) goto out_putnames; } retry: - dentry = __filename_create(newdfd, to, &path, lookup_flags); + dentry = filename_create(newdfd, to, &path, lookup_flags); error = PTR_ERR(dentry); if (IS_ERR(dentry)) goto out_putnames; @@ -4426,11 +4426,11 @@ int do_linkat(int olddfd, struct filename *old, int newdfd, if (flags & AT_SYMLINK_FOLLOW) how |= LOOKUP_FOLLOW; retry: - error = __filename_lookup(olddfd, old, how, &old_path, NULL); + error = filename_lookup(olddfd, old, how, &old_path, NULL); if (error) goto out_putnames; - new_dentry = __filename_create(newdfd, new, &new_path, + new_dentry = filename_create(newdfd, new, &new_path, (how & LOOKUP_REVAL)); error = PTR_ERR(new_dentry); if (IS_ERR(new_dentry)) @@ -4689,13 +4689,13 @@ int do_renameat2(int olddfd, struct filename *from, int newdfd, target_flags = 0; retry: - error = __filename_parentat(olddfd, from, lookup_flags, &old_path, - &old_last, &old_type); + error = filename_parentat(olddfd, from, lookup_flags, &old_path, + &old_last, &old_type); if (error) goto put_names; - error = __filename_parentat(newdfd, to, lookup_flags, &new_path, &new_last, - &new_type); + error = filename_parentat(newdfd, to, lookup_flags, &new_path, &new_last, + &new_type); if (error) goto exit1; |