Skip to content

Commit a681b7c

Browse files
committed
fs: ensure that *path_locked*() helpers leave passed path pristine
The functions currently leaving dangling pointers in the passed-in path leading to hard to debug bugs in the long run. Ensure that the path is left in pristine state just like we do in e.g., path_parentat() and other helpers. Link: https://lore.kernel.org/20250414-rennt-wimmeln-f186c3a780f1@brauner Signed-off-by: Christian Brauner <brauner@kernel.org>
1 parent c86b300 commit a681b7c

File tree

1 file changed

+18
-16
lines changed

1 file changed

+18
-16
lines changed

fs/namei.c

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2752,46 +2752,48 @@ static int filename_parentat(int dfd, struct filename *name,
27522752
/* does lookup, returns the object with parent locked */
27532753
static struct dentry *__kern_path_locked(int dfd, struct filename *name, struct path *path)
27542754
{
2755+
struct path parent_path __free(path_put) = {};
27552756
struct dentry *d;
27562757
struct qstr last;
27572758
int type, error;
27582759

2759-
error = filename_parentat(dfd, name, 0, path, &last, &type);
2760+
error = filename_parentat(dfd, name, 0, &parent_path, &last, &type);
27602761
if (error)
27612762
return ERR_PTR(error);
2762-
if (unlikely(type != LAST_NORM)) {
2763-
path_put(path);
2763+
if (unlikely(type != LAST_NORM))
27642764
return ERR_PTR(-EINVAL);
2765-
}
2766-
inode_lock_nested(path->dentry->d_inode, I_MUTEX_PARENT);
2767-
d = lookup_one_qstr_excl(&last, path->dentry, 0);
2765+
inode_lock_nested(parent_path.dentry->d_inode, I_MUTEX_PARENT);
2766+
d = lookup_one_qstr_excl(&last, parent_path.dentry, 0);
27682767
if (IS_ERR(d)) {
2769-
inode_unlock(path->dentry->d_inode);
2770-
path_put(path);
2768+
inode_unlock(parent_path.dentry->d_inode);
2769+
return d;
27712770
}
2771+
path->dentry = no_free_ptr(parent_path.dentry);
2772+
path->mnt = no_free_ptr(parent_path.mnt);
27722773
return d;
27732774
}
27742775

27752776
struct dentry *kern_path_locked_negative(const char *name, struct path *path)
27762777
{
2778+
struct path parent_path __free(path_put) = {};
27772779
struct filename *filename __free(putname) = getname_kernel(name);
27782780
struct dentry *d;
27792781
struct qstr last;
27802782
int type, error;
27812783

2782-
error = filename_parentat(AT_FDCWD, filename, 0, path, &last, &type);
2784+
error = filename_parentat(AT_FDCWD, filename, 0, &parent_path, &last, &type);
27832785
if (error)
27842786
return ERR_PTR(error);
2785-
if (unlikely(type != LAST_NORM)) {
2786-
path_put(path);
2787+
if (unlikely(type != LAST_NORM))
27872788
return ERR_PTR(-EINVAL);
2788-
}
2789-
inode_lock_nested(path->dentry->d_inode, I_MUTEX_PARENT);
2790-
d = lookup_one_qstr_excl_raw(&last, path->dentry, 0);
2789+
inode_lock_nested(parent_path.dentry->d_inode, I_MUTEX_PARENT);
2790+
d = lookup_one_qstr_excl_raw(&last, parent_path.dentry, 0);
27912791
if (IS_ERR(d)) {
2792-
inode_unlock(path->dentry->d_inode);
2793-
path_put(path);
2792+
inode_unlock(parent_path.dentry->d_inode);
2793+
return d;
27942794
}
2795+
path->dentry = no_free_ptr(parent_path.dentry);
2796+
path->mnt = no_free_ptr(parent_path.mnt);
27952797
return d;
27962798
}
27972799

0 commit comments

Comments
 (0)