diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-02-09 16:58:28 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-02-09 16:58:28 -0800 |
| commit | 26c9342bb761e463774a64fb6210b4f95f5bc035 (patch) | |
| tree | 486d504cf5dcfe041eba4d9d5eb468a5a7b81566 /fs/open.c | |
| parent | 8a5203c630c67d578975ff237413f5e0b5000af8 (diff) | |
| parent | 0787a93baa1aab9fd0cb8500105d11d3d3a58f7a (diff) | |
| download | linux-next-26c9342bb761e463774a64fb6210b4f95f5bc035.tar.gz linux-next-26c9342bb761e463774a64fb6210b4f95f5bc035.zip | |
Merge tag 'pull-filename' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs 'struct filename' updates from Al Viro:
"[Mostly] sanitize struct filename handling"
* tag 'pull-filename' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (68 commits)
sysfs(2): fs_index() argument is _not_ a pathname
alpha: switch osf_mount() to strndup_user()
ksmbd: use CLASS(filename_kernel)
mqueue: switch to CLASS(filename)
user_statfs(): switch to CLASS(filename)
statx: switch to CLASS(filename_maybe_null)
quotactl_block(): switch to CLASS(filename)
chroot(2): switch to CLASS(filename)
move_mount(2): switch to CLASS(filename_maybe_null)
namei.c: switch user pathname imports to CLASS(filename{,_flags})
namei.c: convert getname_kernel() callers to CLASS(filename_kernel)
do_f{chmod,chown,access}at(): use CLASS(filename_uflags)
do_readlinkat(): switch to CLASS(filename_flags)
do_sys_truncate(): switch to CLASS(filename)
do_utimes_path(): switch to CLASS(filename_uflags)
chdir(2): unspaghettify a bit...
do_fchownat(): unspaghettify a bit...
fspick(2): use CLASS(filename_flags)
name_to_handle_at(): use CLASS(filename_uflags)
vfs_open_tree(): use CLASS(filename_uflags)
...
Diffstat (limited to 'fs/open.c')
| -rw-r--r-- | fs/open.c | 119 |
1 files changed, 47 insertions, 72 deletions
diff --git a/fs/open.c b/fs/open.c index 74c4c1462b3e..91f1139591ab 100644 --- a/fs/open.c +++ b/fs/open.c @@ -135,15 +135,16 @@ int do_sys_truncate(const char __user *pathname, loff_t length) if (length < 0) /* sorry, but loff_t says... */ return -EINVAL; + CLASS(filename, name)(pathname); retry: - error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path); + error = filename_lookup(AT_FDCWD, name, lookup_flags, &path, NULL); if (!error) { error = vfs_truncate(&path, length); path_put(&path); - } - if (retry_estale(error, lookup_flags)) { - lookup_flags |= LOOKUP_REVAL; - goto retry; + if (retry_estale(error, lookup_flags)) { + lookup_flags |= LOOKUP_REVAL; + goto retry; + } } return error; } @@ -477,8 +478,6 @@ static int do_faccessat(int dfd, const char __user *filename, int mode, int flag if (flags & AT_SYMLINK_NOFOLLOW) lookup_flags &= ~LOOKUP_FOLLOW; - if (flags & AT_EMPTY_PATH) - lookup_flags |= LOOKUP_EMPTY; if (access_need_override_creds(flags)) { old_cred = access_override_creds(); @@ -486,8 +485,9 @@ static int do_faccessat(int dfd, const char __user *filename, int mode, int flag return -ENOMEM; } + CLASS(filename_uflags, name)(filename, flags); retry: - res = user_path_at(dfd, filename, lookup_flags, &path); + res = filename_lookup(dfd, name, lookup_flags, &path, NULL); if (res) goto out; @@ -554,24 +554,19 @@ SYSCALL_DEFINE1(chdir, const char __user *, filename) struct path path; int error; unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY; + CLASS(filename, name)(filename); retry: - error = user_path_at(AT_FDCWD, filename, lookup_flags, &path); - if (error) - goto out; - - error = path_permission(&path, MAY_EXEC | MAY_CHDIR); - if (error) - goto dput_and_out; - - set_fs_pwd(current->fs, &path); - -dput_and_out: - path_put(&path); - if (retry_estale(error, lookup_flags)) { - lookup_flags |= LOOKUP_REVAL; - goto retry; + error = filename_lookup(AT_FDCWD, name, lookup_flags, &path, NULL); + if (!error) { + error = path_permission(&path, MAY_EXEC | MAY_CHDIR); + if (!error) + set_fs_pwd(current->fs, &path); + path_put(&path); + if (retry_estale(error, lookup_flags)) { + lookup_flags |= LOOKUP_REVAL; + goto retry; + } } -out: return error; } @@ -597,10 +592,11 @@ SYSCALL_DEFINE1(chroot, const char __user *, filename) struct path path; int error; unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY; + CLASS(filename, name)(filename); retry: - error = user_path_at(AT_FDCWD, filename, lookup_flags, &path); + error = filename_lookup(AT_FDCWD, name, lookup_flags, &path, NULL); if (error) - goto out; + return error; error = path_permission(&path, MAY_EXEC | MAY_CHDIR); if (error) @@ -610,18 +606,14 @@ retry: if (!ns_capable(current_user_ns(), CAP_SYS_CHROOT)) goto dput_and_out; error = security_path_chroot(&path); - if (error) - goto dput_and_out; - - set_fs_root(current->fs, &path); - error = 0; + if (!error) + set_fs_root(current->fs, &path); dput_and_out: path_put(&path); if (retry_estale(error, lookup_flags)) { lookup_flags |= LOOKUP_REVAL; goto retry; } -out: return error; } @@ -685,11 +677,9 @@ static int do_fchmodat(int dfd, const char __user *filename, umode_t mode, return -EINVAL; lookup_flags = (flags & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW; - if (flags & AT_EMPTY_PATH) - lookup_flags |= LOOKUP_EMPTY; - + CLASS(filename_uflags, name)(filename, flags); retry: - error = user_path_at(dfd, filename, lookup_flags, &path); + error = filename_lookup(dfd, name, lookup_flags, &path, NULL); if (!error) { error = chmod_common(&path, mode); path_put(&path); @@ -800,31 +790,28 @@ int do_fchownat(int dfd, const char __user *filename, uid_t user, gid_t group, int flag) { struct path path; - int error = -EINVAL; + int error; int lookup_flags; if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0) - goto out; + return -EINVAL; lookup_flags = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW; - if (flag & AT_EMPTY_PATH) - lookup_flags |= LOOKUP_EMPTY; + CLASS(filename_uflags, name)(filename, flag); retry: - error = user_path_at(dfd, filename, lookup_flags, &path); - if (error) - goto out; - error = mnt_want_write(path.mnt); - if (error) - goto out_release; - error = chown_common(&path, user, group); - mnt_drop_write(path.mnt); -out_release: - path_put(&path); - if (retry_estale(error, lookup_flags)) { - lookup_flags |= LOOKUP_REVAL; - goto retry; + error = filename_lookup(dfd, name, lookup_flags, &path, NULL); + if (!error) { + error = mnt_want_write(path.mnt); + if (!error) { + error = chown_common(&path, user, group); + mnt_drop_write(path.mnt); + } + path_put(&path); + if (retry_estale(error, lookup_flags)) { + lookup_flags |= LOOKUP_REVAL; + goto retry; + } } -out: return error; } @@ -1334,7 +1321,7 @@ struct file *file_open_name(struct filename *name, int flags, umode_t mode) int err = build_open_flags(&how, &op); if (err) return ERR_PTR(err); - return do_filp_open(AT_FDCWD, name, &op); + return do_file_open(AT_FDCWD, name, &op); } /** @@ -1350,14 +1337,8 @@ struct file *file_open_name(struct filename *name, int flags, umode_t mode) */ struct file *filp_open(const char *filename, int flags, umode_t mode) { - struct filename *name = getname_kernel(filename); - struct file *file = ERR_CAST(name); - - if (!IS_ERR(name)) { - file = file_open_name(name, flags, mode); - putname(name); - } - return file; + CLASS(filename_kernel, name)(filename); + return file_open_name(name, flags, mode); } EXPORT_SYMBOL(filp_open); @@ -1377,18 +1358,12 @@ static int do_sys_openat2(int dfd, const char __user *filename, struct open_how *how) { struct open_flags op; - struct filename *tmp __free(putname) = NULL; - int err; - - err = build_open_flags(how, &op); + int err = build_open_flags(how, &op); if (unlikely(err)) return err; - tmp = getname(filename); - if (IS_ERR(tmp)) - return PTR_ERR(tmp); - - return FD_ADD(how->flags, do_filp_open(dfd, tmp, &op)); + CLASS(filename, name)(filename); + return FD_ADD(how->flags, do_file_open(dfd, name, &op)); } int do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode) |
