In 0ee50b47532a ("namei: change filename_parentat() calling conventions"), filename_parentat() was made to always put the struct filename before returning, and kern_path_locked() was migrated to this calling convention. However, kern_path_locked() uses the "last" parameter to lookup and potentially create a new dentry. The last parameter contains the last component of the path and points within the filename, which was recently freed at the end of filename_parentat(). Thus, when kern_path_locked() calls __lookup_hash(), it is using the filename after it has already been freed. To avoid this, switch back to __filename_parentat() and place a putname at the end of the function, once all uses are completed. Fixes: 0ee50b47532a ("namei: change filename_parentat() calling conventions") Reported-by: syzbot+fb0d60a179096e8c2731@xxxxxxxxxxxxxxxxxxxxxxxxx Signed-off-by: Stephen Brennan <stephen.s.brennan@xxxxxxxxxx> --- fs/namei.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index d049d3972695..a0122f0016a3 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2551,17 +2551,22 @@ static int filename_parentat(int dfd, struct filename *name, /* does lookup, returns the object with parent locked */ struct dentry *kern_path_locked(const char *name, struct path *path) { + struct filename *filename; struct dentry *d; struct qstr last; int type, error; - error = filename_parentat(AT_FDCWD, getname_kernel(name), 0, path, + filename = getname_kernel(name); + error = __filename_parentat(AT_FDCWD, filename, 0, path, &last, &type); - if (error) - return ERR_PTR(error); + if (error) { + d = ERR_PTR(error); + goto out; + } if (unlikely(type != LAST_NORM)) { path_put(path); - return ERR_PTR(-EINVAL); + d = ERR_PTR(-EINVAL); + goto out; } inode_lock_nested(path->dentry->d_inode, I_MUTEX_PARENT); d = __lookup_hash(&last, path->dentry, 0); @@ -2569,6 +2574,8 @@ struct dentry *kern_path_locked(const char *name, struct path *path) inode_unlock(path->dentry->d_inode); path_put(path); } +out: + putname(filename); return d; } -- 2.30.2