summaryrefslogtreecommitdiff
path: root/fs/open.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-02-09 16:58:28 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2026-02-09 16:58:28 -0800
commit26c9342bb761e463774a64fb6210b4f95f5bc035 (patch)
tree486d504cf5dcfe041eba4d9d5eb468a5a7b81566 /fs/open.c
parent8a5203c630c67d578975ff237413f5e0b5000af8 (diff)
parent0787a93baa1aab9fd0cb8500105d11d3d3a58f7a (diff)
downloadlinux-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.c119
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)