mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
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)
...
This commit is contained in:
@@ -1340,3 +1340,14 @@ The ->setlease() file_operation must now be explicitly set in order to provide
|
||||
support for leases. When set to NULL, the kernel will now return -EINVAL to
|
||||
attempts to set a lease. Filesystems that wish to use the kernel-internal lease
|
||||
implementation should set it to generic_setlease().
|
||||
|
||||
---
|
||||
|
||||
**mandatory**
|
||||
|
||||
fs/namei.c primitives that consume filesystem references (do_renameat2(),
|
||||
do_linkat(), do_symlinkat(), do_mkdirat(), do_mknodat(), do_unlinkat()
|
||||
and do_rmdir()) are gone; they are replaced with non-consuming analogues
|
||||
(filename_renameat2(), etc.)
|
||||
Callers are adjusted - responsibility for dropping the filenames belongs
|
||||
to them now.
|
||||
|
||||
+11
-23
@@ -454,42 +454,30 @@ static int
|
||||
osf_ufs_mount(const char __user *dirname,
|
||||
struct ufs_args __user *args, int flags)
|
||||
{
|
||||
int retval;
|
||||
struct cdfs_args tmp;
|
||||
struct filename *devname;
|
||||
struct ufs_args tmp;
|
||||
char *devname __free(kfree) = NULL;
|
||||
|
||||
retval = -EFAULT;
|
||||
if (copy_from_user(&tmp, args, sizeof(tmp)))
|
||||
goto out;
|
||||
devname = getname(tmp.devname);
|
||||
retval = PTR_ERR(devname);
|
||||
return -EFAULT;
|
||||
devname = strndup_user(tmp.devname, PATH_MAX);
|
||||
if (IS_ERR(devname))
|
||||
goto out;
|
||||
retval = do_mount(devname->name, dirname, "ext2", flags, NULL);
|
||||
putname(devname);
|
||||
out:
|
||||
return retval;
|
||||
return PTR_ERR(devname);
|
||||
return do_mount(devname, dirname, "ext2", flags, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
osf_cdfs_mount(const char __user *dirname,
|
||||
struct cdfs_args __user *args, int flags)
|
||||
{
|
||||
int retval;
|
||||
struct cdfs_args tmp;
|
||||
struct filename *devname;
|
||||
char *devname __free(kfree) = NULL;
|
||||
|
||||
retval = -EFAULT;
|
||||
if (copy_from_user(&tmp, args, sizeof(tmp)))
|
||||
goto out;
|
||||
devname = getname(tmp.devname);
|
||||
retval = PTR_ERR(devname);
|
||||
return -EFAULT;
|
||||
devname = strndup_user(tmp.devname, PATH_MAX);
|
||||
if (IS_ERR(devname))
|
||||
goto out;
|
||||
retval = do_mount(devname->name, dirname, "iso9660", flags, NULL);
|
||||
putname(devname);
|
||||
out:
|
||||
return retval;
|
||||
return PTR_ERR(devname);
|
||||
return do_mount(devname, dirname, "iso9660", flags, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
+2
-1
@@ -895,11 +895,12 @@ static bool coredump_file(struct core_name *cn, struct coredump_params *cprm,
|
||||
* privs and don't want to unlink another user's coredump.
|
||||
*/
|
||||
if (!coredump_force_suid_safe(cprm)) {
|
||||
CLASS(filename_kernel, name)(cn->corename);
|
||||
/*
|
||||
* If it doesn't exist, that's fine. If there's some
|
||||
* other problem, we'll catch it at the filp_open().
|
||||
*/
|
||||
do_unlinkat(AT_FDCWD, getname_kernel(cn->corename));
|
||||
filename_unlinkat(AT_FDCWD, name);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+1
-7
@@ -3297,10 +3297,6 @@ static void __init dcache_init(void)
|
||||
runtime_const_init(ptr, dentry_hashtable);
|
||||
}
|
||||
|
||||
/* SLAB cache for __getname() consumers */
|
||||
struct kmem_cache *names_cachep __ro_after_init;
|
||||
EXPORT_SYMBOL(names_cachep);
|
||||
|
||||
void __init vfs_caches_init_early(void)
|
||||
{
|
||||
int i;
|
||||
@@ -3314,9 +3310,7 @@ void __init vfs_caches_init_early(void)
|
||||
|
||||
void __init vfs_caches_init(void)
|
||||
{
|
||||
names_cachep = kmem_cache_create_usercopy("names_cache", PATH_MAX, 0,
|
||||
SLAB_HWCACHE_ALIGN|SLAB_PANIC, 0, PATH_MAX, NULL);
|
||||
|
||||
filename_init();
|
||||
dcache_init();
|
||||
inode_init();
|
||||
files_init();
|
||||
|
||||
@@ -777,10 +777,8 @@ static struct file *do_open_execat(int fd, struct filename *name, int flags)
|
||||
return ERR_PTR(-EINVAL);
|
||||
if (flags & AT_SYMLINK_NOFOLLOW)
|
||||
open_exec_flags.lookup_flags &= ~LOOKUP_FOLLOW;
|
||||
if (flags & AT_EMPTY_PATH)
|
||||
open_exec_flags.lookup_flags |= LOOKUP_EMPTY;
|
||||
|
||||
file = do_filp_open(fd, name, &open_exec_flags);
|
||||
file = do_file_open(fd, name, &open_exec_flags);
|
||||
if (IS_ERR(file))
|
||||
return file;
|
||||
|
||||
@@ -815,14 +813,8 @@ static struct file *do_open_execat(int fd, struct filename *name, int flags)
|
||||
*/
|
||||
struct file *open_exec(const char *name)
|
||||
{
|
||||
struct filename *filename = getname_kernel(name);
|
||||
struct file *f = ERR_CAST(filename);
|
||||
|
||||
if (!IS_ERR(filename)) {
|
||||
f = do_open_execat(AT_FDCWD, filename, 0);
|
||||
putname(filename);
|
||||
}
|
||||
return f;
|
||||
CLASS(filename_kernel, filename)(name);
|
||||
return do_open_execat(AT_FDCWD, filename, 0);
|
||||
}
|
||||
EXPORT_SYMBOL(open_exec);
|
||||
|
||||
@@ -1471,6 +1463,9 @@ out_free:
|
||||
return ERR_PTR(retval);
|
||||
}
|
||||
|
||||
DEFINE_CLASS(bprm, struct linux_binprm *, if (!IS_ERR(_T)) free_bprm(_T),
|
||||
alloc_bprm(fd, name, flags), int fd, struct filename *name, int flags)
|
||||
|
||||
int bprm_change_interp(const char *interp, struct linux_binprm *bprm)
|
||||
{
|
||||
/* If a binfmt changed the interp, free it first. */
|
||||
@@ -1785,12 +1780,8 @@ static int do_execveat_common(int fd, struct filename *filename,
|
||||
struct user_arg_ptr envp,
|
||||
int flags)
|
||||
{
|
||||
struct linux_binprm *bprm;
|
||||
int retval;
|
||||
|
||||
if (IS_ERR(filename))
|
||||
return PTR_ERR(filename);
|
||||
|
||||
/*
|
||||
* We move the actual failure in case of RLIMIT_NPROC excess from
|
||||
* set*uid() to execve() because too many poorly written programs
|
||||
@@ -1798,47 +1789,43 @@ static int do_execveat_common(int fd, struct filename *filename,
|
||||
* whether NPROC limit is still exceeded.
|
||||
*/
|
||||
if ((current->flags & PF_NPROC_EXCEEDED) &&
|
||||
is_rlimit_overlimit(current_ucounts(), UCOUNT_RLIMIT_NPROC, rlimit(RLIMIT_NPROC))) {
|
||||
retval = -EAGAIN;
|
||||
goto out_ret;
|
||||
}
|
||||
is_rlimit_overlimit(current_ucounts(), UCOUNT_RLIMIT_NPROC, rlimit(RLIMIT_NPROC)))
|
||||
return -EAGAIN;
|
||||
|
||||
/* We're below the limit (still or again), so we don't want to make
|
||||
* further execve() calls fail. */
|
||||
current->flags &= ~PF_NPROC_EXCEEDED;
|
||||
|
||||
bprm = alloc_bprm(fd, filename, flags);
|
||||
if (IS_ERR(bprm)) {
|
||||
retval = PTR_ERR(bprm);
|
||||
goto out_ret;
|
||||
}
|
||||
CLASS(bprm, bprm)(fd, filename, flags);
|
||||
if (IS_ERR(bprm))
|
||||
return PTR_ERR(bprm);
|
||||
|
||||
retval = count(argv, MAX_ARG_STRINGS);
|
||||
if (retval < 0)
|
||||
goto out_free;
|
||||
return retval;
|
||||
bprm->argc = retval;
|
||||
|
||||
retval = count(envp, MAX_ARG_STRINGS);
|
||||
if (retval < 0)
|
||||
goto out_free;
|
||||
return retval;
|
||||
bprm->envc = retval;
|
||||
|
||||
retval = bprm_stack_limits(bprm);
|
||||
if (retval < 0)
|
||||
goto out_free;
|
||||
return retval;
|
||||
|
||||
retval = copy_string_kernel(bprm->filename, bprm);
|
||||
if (retval < 0)
|
||||
goto out_free;
|
||||
return retval;
|
||||
bprm->exec = bprm->p;
|
||||
|
||||
retval = copy_strings(bprm->envc, envp, bprm);
|
||||
if (retval < 0)
|
||||
goto out_free;
|
||||
return retval;
|
||||
|
||||
retval = copy_strings(bprm->argc, argv, bprm);
|
||||
if (retval < 0)
|
||||
goto out_free;
|
||||
return retval;
|
||||
|
||||
/*
|
||||
* When argv is empty, add an empty string ("") as argv[0] to
|
||||
@@ -1849,134 +1836,62 @@ static int do_execveat_common(int fd, struct filename *filename,
|
||||
if (bprm->argc == 0) {
|
||||
retval = copy_string_kernel("", bprm);
|
||||
if (retval < 0)
|
||||
goto out_free;
|
||||
return retval;
|
||||
bprm->argc = 1;
|
||||
|
||||
pr_warn_once("process '%s' launched '%s' with NULL argv: empty string added\n",
|
||||
current->comm, bprm->filename);
|
||||
}
|
||||
|
||||
retval = bprm_execve(bprm);
|
||||
out_free:
|
||||
free_bprm(bprm);
|
||||
|
||||
out_ret:
|
||||
putname(filename);
|
||||
return retval;
|
||||
return bprm_execve(bprm);
|
||||
}
|
||||
|
||||
int kernel_execve(const char *kernel_filename,
|
||||
const char *const *argv, const char *const *envp)
|
||||
{
|
||||
struct filename *filename;
|
||||
struct linux_binprm *bprm;
|
||||
int fd = AT_FDCWD;
|
||||
int retval;
|
||||
|
||||
/* It is non-sense for kernel threads to call execve */
|
||||
if (WARN_ON_ONCE(current->flags & PF_KTHREAD))
|
||||
return -EINVAL;
|
||||
|
||||
filename = getname_kernel(kernel_filename);
|
||||
if (IS_ERR(filename))
|
||||
return PTR_ERR(filename);
|
||||
|
||||
bprm = alloc_bprm(fd, filename, 0);
|
||||
if (IS_ERR(bprm)) {
|
||||
retval = PTR_ERR(bprm);
|
||||
goto out_ret;
|
||||
}
|
||||
CLASS(filename_kernel, filename)(kernel_filename);
|
||||
CLASS(bprm, bprm)(AT_FDCWD, filename, 0);
|
||||
if (IS_ERR(bprm))
|
||||
return PTR_ERR(bprm);
|
||||
|
||||
retval = count_strings_kernel(argv);
|
||||
if (WARN_ON_ONCE(retval == 0))
|
||||
retval = -EINVAL;
|
||||
return -EINVAL;
|
||||
if (retval < 0)
|
||||
goto out_free;
|
||||
return retval;
|
||||
bprm->argc = retval;
|
||||
|
||||
retval = count_strings_kernel(envp);
|
||||
if (retval < 0)
|
||||
goto out_free;
|
||||
return retval;
|
||||
bprm->envc = retval;
|
||||
|
||||
retval = bprm_stack_limits(bprm);
|
||||
if (retval < 0)
|
||||
goto out_free;
|
||||
return retval;
|
||||
|
||||
retval = copy_string_kernel(bprm->filename, bprm);
|
||||
if (retval < 0)
|
||||
goto out_free;
|
||||
return retval;
|
||||
bprm->exec = bprm->p;
|
||||
|
||||
retval = copy_strings_kernel(bprm->envc, envp, bprm);
|
||||
if (retval < 0)
|
||||
goto out_free;
|
||||
return retval;
|
||||
|
||||
retval = copy_strings_kernel(bprm->argc, argv, bprm);
|
||||
if (retval < 0)
|
||||
goto out_free;
|
||||
return retval;
|
||||
|
||||
retval = bprm_execve(bprm);
|
||||
out_free:
|
||||
free_bprm(bprm);
|
||||
out_ret:
|
||||
putname(filename);
|
||||
return retval;
|
||||
return bprm_execve(bprm);
|
||||
}
|
||||
|
||||
static int do_execve(struct filename *filename,
|
||||
const char __user *const __user *__argv,
|
||||
const char __user *const __user *__envp)
|
||||
{
|
||||
struct user_arg_ptr argv = { .ptr.native = __argv };
|
||||
struct user_arg_ptr envp = { .ptr.native = __envp };
|
||||
return do_execveat_common(AT_FDCWD, filename, argv, envp, 0);
|
||||
}
|
||||
|
||||
static int do_execveat(int fd, struct filename *filename,
|
||||
const char __user *const __user *__argv,
|
||||
const char __user *const __user *__envp,
|
||||
int flags)
|
||||
{
|
||||
struct user_arg_ptr argv = { .ptr.native = __argv };
|
||||
struct user_arg_ptr envp = { .ptr.native = __envp };
|
||||
|
||||
return do_execveat_common(fd, filename, argv, envp, flags);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static int compat_do_execve(struct filename *filename,
|
||||
const compat_uptr_t __user *__argv,
|
||||
const compat_uptr_t __user *__envp)
|
||||
{
|
||||
struct user_arg_ptr argv = {
|
||||
.is_compat = true,
|
||||
.ptr.compat = __argv,
|
||||
};
|
||||
struct user_arg_ptr envp = {
|
||||
.is_compat = true,
|
||||
.ptr.compat = __envp,
|
||||
};
|
||||
return do_execveat_common(AT_FDCWD, filename, argv, envp, 0);
|
||||
}
|
||||
|
||||
static int compat_do_execveat(int fd, struct filename *filename,
|
||||
const compat_uptr_t __user *__argv,
|
||||
const compat_uptr_t __user *__envp,
|
||||
int flags)
|
||||
{
|
||||
struct user_arg_ptr argv = {
|
||||
.is_compat = true,
|
||||
.ptr.compat = __argv,
|
||||
};
|
||||
struct user_arg_ptr envp = {
|
||||
.is_compat = true,
|
||||
.ptr.compat = __envp,
|
||||
};
|
||||
return do_execveat_common(fd, filename, argv, envp, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
void set_binfmt(struct linux_binfmt *new)
|
||||
{
|
||||
struct mm_struct *mm = current->mm;
|
||||
@@ -2001,12 +1916,19 @@ void set_dumpable(struct mm_struct *mm, int value)
|
||||
__mm_flags_set_mask_dumpable(mm, value);
|
||||
}
|
||||
|
||||
static inline struct user_arg_ptr native_arg(const char __user *const __user *p)
|
||||
{
|
||||
return (struct user_arg_ptr){.ptr.native = p};
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE3(execve,
|
||||
const char __user *, filename,
|
||||
const char __user *const __user *, argv,
|
||||
const char __user *const __user *, envp)
|
||||
{
|
||||
return do_execve(getname(filename), argv, envp);
|
||||
CLASS(filename, name)(filename);
|
||||
return do_execveat_common(AT_FDCWD, name,
|
||||
native_arg(argv), native_arg(envp), 0);
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE5(execveat,
|
||||
@@ -2015,17 +1937,25 @@ SYSCALL_DEFINE5(execveat,
|
||||
const char __user *const __user *, envp,
|
||||
int, flags)
|
||||
{
|
||||
return do_execveat(fd,
|
||||
getname_uflags(filename, flags),
|
||||
argv, envp, flags);
|
||||
CLASS(filename_uflags, name)(filename, flags);
|
||||
return do_execveat_common(fd, name,
|
||||
native_arg(argv), native_arg(envp), flags);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
||||
static inline struct user_arg_ptr compat_arg(const compat_uptr_t __user *p)
|
||||
{
|
||||
return (struct user_arg_ptr){.is_compat = true, .ptr.compat = p};
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE3(execve, const char __user *, filename,
|
||||
const compat_uptr_t __user *, argv,
|
||||
const compat_uptr_t __user *, envp)
|
||||
{
|
||||
return compat_do_execve(getname(filename), argv, envp);
|
||||
CLASS(filename, name)(filename);
|
||||
return do_execveat_common(AT_FDCWD, name,
|
||||
compat_arg(argv), compat_arg(envp), 0);
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE5(execveat, int, fd,
|
||||
@@ -2034,9 +1964,9 @@ COMPAT_SYSCALL_DEFINE5(execveat, int, fd,
|
||||
const compat_uptr_t __user *, envp,
|
||||
int, flags)
|
||||
{
|
||||
return compat_do_execveat(fd,
|
||||
getname_uflags(filename, flags),
|
||||
argv, envp, flags);
|
||||
CLASS(filename_uflags, name)(filename, flags);
|
||||
return do_execveat_common(fd, name,
|
||||
compat_arg(argv), compat_arg(envp), flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+2
-3
@@ -157,9 +157,8 @@ SYSCALL_DEFINE5(name_to_handle_at, int, dfd, const char __user *, name,
|
||||
fh_flags |= EXPORT_FH_CONNECTABLE;
|
||||
|
||||
lookup_flags = (flag & AT_SYMLINK_FOLLOW) ? LOOKUP_FOLLOW : 0;
|
||||
if (flag & AT_EMPTY_PATH)
|
||||
lookup_flags |= LOOKUP_EMPTY;
|
||||
err = user_path_at(dfd, name, lookup_flags, &path);
|
||||
CLASS(filename_uflags, filename)(name, flag);
|
||||
err = filename_lookup(dfd, filename, lookup_flags, &path, NULL);
|
||||
if (!err) {
|
||||
err = do_sys_name_to_handle(&path, handle, mnt_id,
|
||||
flag & AT_HANDLE_MNT_ID_UNIQUE,
|
||||
|
||||
+2
-10
@@ -374,7 +374,6 @@ SYSCALL_DEFINE5(file_getattr, int, dfd, const char __user *, filename,
|
||||
unsigned int, at_flags)
|
||||
{
|
||||
struct path filepath __free(path_put) = {};
|
||||
struct filename *name __free(putname) = NULL;
|
||||
unsigned int lookup_flags = 0;
|
||||
struct file_attr fattr;
|
||||
struct file_kattr fa;
|
||||
@@ -395,10 +394,7 @@ SYSCALL_DEFINE5(file_getattr, int, dfd, const char __user *, filename,
|
||||
if (usize < FILE_ATTR_SIZE_VER0)
|
||||
return -EINVAL;
|
||||
|
||||
name = getname_maybe_null(filename, at_flags);
|
||||
if (IS_ERR(name))
|
||||
return PTR_ERR(name);
|
||||
|
||||
CLASS(filename_maybe_null, name)(filename, at_flags);
|
||||
if (!name && dfd >= 0) {
|
||||
CLASS(fd, f)(dfd);
|
||||
if (fd_empty(f))
|
||||
@@ -431,7 +427,6 @@ SYSCALL_DEFINE5(file_setattr, int, dfd, const char __user *, filename,
|
||||
unsigned int, at_flags)
|
||||
{
|
||||
struct path filepath __free(path_put) = {};
|
||||
struct filename *name __free(putname) = NULL;
|
||||
unsigned int lookup_flags = 0;
|
||||
struct file_attr fattr;
|
||||
struct file_kattr fa;
|
||||
@@ -461,10 +456,7 @@ SYSCALL_DEFINE5(file_setattr, int, dfd, const char __user *, filename,
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
name = getname_maybe_null(filename, at_flags);
|
||||
if (IS_ERR(name))
|
||||
return PTR_ERR(name);
|
||||
|
||||
CLASS(filename_maybe_null, name)(filename, at_flags);
|
||||
if (!name && dfd >= 0) {
|
||||
CLASS(fd, f)(dfd);
|
||||
if (fd_empty(f))
|
||||
|
||||
+3
-6
@@ -132,24 +132,21 @@ EXPORT_SYMBOL(unregister_filesystem);
|
||||
static int fs_index(const char __user * __name)
|
||||
{
|
||||
struct file_system_type * tmp;
|
||||
struct filename *name;
|
||||
char *name __free(kfree) = strndup_user(__name, PATH_MAX);
|
||||
int err, index;
|
||||
|
||||
name = getname(__name);
|
||||
err = PTR_ERR(name);
|
||||
if (IS_ERR(name))
|
||||
return err;
|
||||
return PTR_ERR(name);
|
||||
|
||||
err = -EINVAL;
|
||||
read_lock(&file_systems_lock);
|
||||
for (tmp=file_systems, index=0 ; tmp ; tmp=tmp->next, index++) {
|
||||
if (strcmp(tmp->name, name->name) == 0) {
|
||||
if (strcmp(tmp->name, name) == 0) {
|
||||
err = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
read_unlock(&file_systems_lock);
|
||||
putname(name);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -181,9 +181,9 @@ SYSCALL_DEFINE3(fspick, int, dfd, const char __user *, path, unsigned int, flags
|
||||
lookup_flags &= ~LOOKUP_FOLLOW;
|
||||
if (flags & FSPICK_NO_AUTOMOUNT)
|
||||
lookup_flags &= ~LOOKUP_AUTOMOUNT;
|
||||
if (flags & FSPICK_EMPTY_PATH)
|
||||
lookup_flags |= LOOKUP_EMPTY;
|
||||
ret = user_path_at(dfd, path, lookup_flags, &target);
|
||||
CLASS(filename_flags, filename)(path,
|
||||
(flags & FSPICK_EMPTY_PATH) ? LOOKUP_EMPTY : 0);
|
||||
ret = filename_lookup(dfd, filename, lookup_flags, &target, NULL);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
|
||||
@@ -157,110 +157,40 @@ int __init init_stat(const char *filename, struct kstat *stat, int flags)
|
||||
|
||||
int __init init_mknod(const char *filename, umode_t mode, unsigned int dev)
|
||||
{
|
||||
struct dentry *dentry;
|
||||
struct path path;
|
||||
int error;
|
||||
|
||||
if (S_ISFIFO(mode) || S_ISSOCK(mode))
|
||||
dev = 0;
|
||||
else if (!(S_ISBLK(mode) || S_ISCHR(mode)))
|
||||
return -EINVAL;
|
||||
|
||||
dentry = start_creating_path(AT_FDCWD, filename, &path, 0);
|
||||
if (IS_ERR(dentry))
|
||||
return PTR_ERR(dentry);
|
||||
|
||||
mode = mode_strip_umask(d_inode(path.dentry), mode);
|
||||
error = security_path_mknod(&path, dentry, mode, dev);
|
||||
if (!error)
|
||||
error = vfs_mknod(mnt_idmap(path.mnt), path.dentry->d_inode,
|
||||
dentry, mode, new_decode_dev(dev), NULL);
|
||||
end_creating_path(&path, dentry);
|
||||
return error;
|
||||
CLASS(filename_kernel, name)(filename);
|
||||
return filename_mknodat(AT_FDCWD, name, mode, dev);
|
||||
}
|
||||
|
||||
int __init init_link(const char *oldname, const char *newname)
|
||||
{
|
||||
struct dentry *new_dentry;
|
||||
struct path old_path, new_path;
|
||||
struct mnt_idmap *idmap;
|
||||
int error;
|
||||
|
||||
error = kern_path(oldname, 0, &old_path);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
new_dentry = start_creating_path(AT_FDCWD, newname, &new_path, 0);
|
||||
error = PTR_ERR(new_dentry);
|
||||
if (IS_ERR(new_dentry))
|
||||
goto out;
|
||||
|
||||
error = -EXDEV;
|
||||
if (old_path.mnt != new_path.mnt)
|
||||
goto out_dput;
|
||||
idmap = mnt_idmap(new_path.mnt);
|
||||
error = may_linkat(idmap, &old_path);
|
||||
if (unlikely(error))
|
||||
goto out_dput;
|
||||
error = security_path_link(old_path.dentry, &new_path, new_dentry);
|
||||
if (error)
|
||||
goto out_dput;
|
||||
error = vfs_link(old_path.dentry, idmap, new_path.dentry->d_inode,
|
||||
new_dentry, NULL);
|
||||
out_dput:
|
||||
end_creating_path(&new_path, new_dentry);
|
||||
out:
|
||||
path_put(&old_path);
|
||||
return error;
|
||||
CLASS(filename_kernel, old)(oldname);
|
||||
CLASS(filename_kernel, new)(newname);
|
||||
return filename_linkat(AT_FDCWD, old, AT_FDCWD, new, 0);
|
||||
}
|
||||
|
||||
int __init init_symlink(const char *oldname, const char *newname)
|
||||
{
|
||||
struct dentry *dentry;
|
||||
struct path path;
|
||||
int error;
|
||||
|
||||
dentry = start_creating_path(AT_FDCWD, newname, &path, 0);
|
||||
if (IS_ERR(dentry))
|
||||
return PTR_ERR(dentry);
|
||||
error = security_path_symlink(&path, dentry, oldname);
|
||||
if (!error)
|
||||
error = vfs_symlink(mnt_idmap(path.mnt), path.dentry->d_inode,
|
||||
dentry, oldname, NULL);
|
||||
end_creating_path(&path, dentry);
|
||||
return error;
|
||||
CLASS(filename_kernel, old)(oldname);
|
||||
CLASS(filename_kernel, new)(newname);
|
||||
return filename_symlinkat(old, AT_FDCWD, new);
|
||||
}
|
||||
|
||||
int __init init_unlink(const char *pathname)
|
||||
{
|
||||
return do_unlinkat(AT_FDCWD, getname_kernel(pathname));
|
||||
CLASS(filename_kernel, name)(pathname);
|
||||
return filename_unlinkat(AT_FDCWD, name);
|
||||
}
|
||||
|
||||
int __init init_mkdir(const char *pathname, umode_t mode)
|
||||
{
|
||||
struct dentry *dentry;
|
||||
struct path path;
|
||||
int error;
|
||||
|
||||
dentry = start_creating_path(AT_FDCWD, pathname, &path,
|
||||
LOOKUP_DIRECTORY);
|
||||
if (IS_ERR(dentry))
|
||||
return PTR_ERR(dentry);
|
||||
mode = mode_strip_umask(d_inode(path.dentry), mode);
|
||||
error = security_path_mkdir(&path, dentry, mode);
|
||||
if (!error) {
|
||||
dentry = vfs_mkdir(mnt_idmap(path.mnt), path.dentry->d_inode,
|
||||
dentry, mode, NULL);
|
||||
if (IS_ERR(dentry))
|
||||
error = PTR_ERR(dentry);
|
||||
}
|
||||
end_creating_path(&path, dentry);
|
||||
return error;
|
||||
CLASS(filename_kernel, name)(pathname);
|
||||
return filename_mkdirat(AT_FDCWD, name, mode);
|
||||
}
|
||||
|
||||
int __init init_rmdir(const char *pathname)
|
||||
{
|
||||
return do_rmdir(AT_FDCWD, getname_kernel(pathname));
|
||||
CLASS(filename_kernel, name)(pathname);
|
||||
return filename_rmdir(AT_FDCWD, name);
|
||||
}
|
||||
|
||||
int __init init_utimes(char *filename, struct timespec64 *ts)
|
||||
|
||||
+10
-7
@@ -53,14 +53,15 @@ extern int finish_clean_context(struct fs_context *fc);
|
||||
*/
|
||||
extern int filename_lookup(int dfd, struct filename *name, unsigned flags,
|
||||
struct path *path, const struct path *root);
|
||||
int do_rmdir(int dfd, struct filename *name);
|
||||
int do_unlinkat(int dfd, struct filename *name);
|
||||
int filename_rmdir(int dfd, struct filename *name);
|
||||
int filename_unlinkat(int dfd, struct filename *name);
|
||||
int may_linkat(struct mnt_idmap *idmap, const struct path *link);
|
||||
int do_renameat2(int olddfd, struct filename *oldname, int newdfd,
|
||||
int filename_renameat2(int olddfd, struct filename *oldname, int newdfd,
|
||||
struct filename *newname, unsigned int flags);
|
||||
int do_mkdirat(int dfd, struct filename *name, umode_t mode);
|
||||
int do_symlinkat(struct filename *from, int newdfd, struct filename *to);
|
||||
int do_linkat(int olddfd, struct filename *old, int newdfd,
|
||||
int filename_mkdirat(int dfd, struct filename *name, umode_t mode);
|
||||
int filename_mknodat(int dfd, struct filename *name, umode_t mode, unsigned int dev);
|
||||
int filename_symlinkat(struct filename *from, int newdfd, struct filename *to);
|
||||
int filename_linkat(int olddfd, struct filename *old, int newdfd,
|
||||
struct filename *new, int flags);
|
||||
int vfs_tmpfile(struct mnt_idmap *idmap,
|
||||
const struct path *parentpath,
|
||||
@@ -70,6 +71,8 @@ struct dentry *start_dirop(struct dentry *parent, struct qstr *name,
|
||||
unsigned int lookup_flags);
|
||||
int lookup_noperm_common(struct qstr *qname, struct dentry *base);
|
||||
|
||||
void __init filename_init(void);
|
||||
|
||||
/*
|
||||
* namespace.c
|
||||
*/
|
||||
@@ -187,7 +190,7 @@ struct open_flags {
|
||||
int intent;
|
||||
int lookup_flags;
|
||||
};
|
||||
extern struct file *do_filp_open(int dfd, struct filename *pathname,
|
||||
extern struct file *do_file_open(int dfd, struct filename *pathname,
|
||||
const struct open_flags *op);
|
||||
extern struct file *do_file_open_root(const struct path *,
|
||||
const char *, const struct open_flags *);
|
||||
|
||||
+222
-200
File diff suppressed because it is too large
Load Diff
+6
-16
@@ -3195,8 +3195,6 @@ static struct file *vfs_open_tree(int dfd, const char __user *filename, unsigned
|
||||
lookup_flags &= ~LOOKUP_AUTOMOUNT;
|
||||
if (flags & AT_SYMLINK_NOFOLLOW)
|
||||
lookup_flags &= ~LOOKUP_FOLLOW;
|
||||
if (flags & AT_EMPTY_PATH)
|
||||
lookup_flags |= LOOKUP_EMPTY;
|
||||
|
||||
/*
|
||||
* If we create a new mount namespace with the cloned mount tree we
|
||||
@@ -3210,7 +3208,8 @@ static struct file *vfs_open_tree(int dfd, const char __user *filename, unsigned
|
||||
if ((flags & OPEN_TREE_CLONE) && !may_mount())
|
||||
return ERR_PTR(-EPERM);
|
||||
|
||||
ret = user_path_at(dfd, filename, lookup_flags, &path);
|
||||
CLASS(filename_uflags, name)(filename, flags);
|
||||
ret = filename_lookup(dfd, name, lookup_flags, &path, NULL);
|
||||
if (unlikely(ret))
|
||||
return ERR_PTR(ret);
|
||||
|
||||
@@ -4528,8 +4527,6 @@ SYSCALL_DEFINE5(move_mount,
|
||||
{
|
||||
struct path to_path __free(path_put) = {};
|
||||
struct path from_path __free(path_put) = {};
|
||||
struct filename *to_name __free(putname) = NULL;
|
||||
struct filename *from_name __free(putname) = NULL;
|
||||
unsigned int lflags, uflags;
|
||||
enum mnt_tree_flags_t mflags = 0;
|
||||
int ret = 0;
|
||||
@@ -4551,10 +4548,7 @@ SYSCALL_DEFINE5(move_mount,
|
||||
if (flags & MOVE_MOUNT_T_EMPTY_PATH)
|
||||
uflags = AT_EMPTY_PATH;
|
||||
|
||||
to_name = getname_maybe_null(to_pathname, uflags);
|
||||
if (IS_ERR(to_name))
|
||||
return PTR_ERR(to_name);
|
||||
|
||||
CLASS(filename_maybe_null,to_name)(to_pathname, uflags);
|
||||
if (!to_name && to_dfd >= 0) {
|
||||
CLASS(fd_raw, f_to)(to_dfd);
|
||||
if (fd_empty(f_to))
|
||||
@@ -4577,10 +4571,7 @@ SYSCALL_DEFINE5(move_mount,
|
||||
if (flags & MOVE_MOUNT_F_EMPTY_PATH)
|
||||
uflags = AT_EMPTY_PATH;
|
||||
|
||||
from_name = getname_maybe_null(from_pathname, uflags);
|
||||
if (IS_ERR(from_name))
|
||||
return PTR_ERR(from_name);
|
||||
|
||||
CLASS(filename_maybe_null,from_name)(from_pathname, uflags);
|
||||
if (!from_name && from_dfd >= 0) {
|
||||
CLASS(fd_raw, f_from)(from_dfd);
|
||||
if (fd_empty(f_from))
|
||||
@@ -5116,8 +5107,6 @@ SYSCALL_DEFINE5(mount_setattr, int, dfd, const char __user *, path,
|
||||
lookup_flags &= ~LOOKUP_AUTOMOUNT;
|
||||
if (flags & AT_SYMLINK_NOFOLLOW)
|
||||
lookup_flags &= ~LOOKUP_FOLLOW;
|
||||
if (flags & AT_EMPTY_PATH)
|
||||
lookup_flags |= LOOKUP_EMPTY;
|
||||
|
||||
kattr = (struct mount_kattr) {
|
||||
.lookup_flags = lookup_flags,
|
||||
@@ -5130,7 +5119,8 @@ SYSCALL_DEFINE5(mount_setattr, int, dfd, const char __user *, path,
|
||||
if (err <= 0)
|
||||
return err;
|
||||
|
||||
err = user_path_at(dfd, path, kattr.lookup_flags, &target);
|
||||
CLASS(filename_uflags, name)(path, flags);
|
||||
err = filename_lookup(dfd, name, kattr.lookup_flags, &target, NULL);
|
||||
if (!err) {
|
||||
err = do_mount_setattr(&target, &kattr);
|
||||
path_put(&target);
|
||||
|
||||
+2
-3
@@ -424,8 +424,7 @@ static int ntfs_readdir(struct file *file, struct dir_context *ctx)
|
||||
if (!dir_emit_dots(file, ctx))
|
||||
return 0;
|
||||
|
||||
/* Allocate PATH_MAX bytes. */
|
||||
name = __getname();
|
||||
name = kmalloc(PATH_MAX, GFP_KERNEL);
|
||||
if (!name)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -503,7 +502,7 @@ static int ntfs_readdir(struct file *file, struct dir_context *ctx)
|
||||
|
||||
out:
|
||||
|
||||
__putname(name);
|
||||
kfree(name);
|
||||
put_indx_node(node);
|
||||
|
||||
if (err == 1) {
|
||||
|
||||
+2
-2
@@ -2627,7 +2627,7 @@ int ntfs_set_label(struct ntfs_sb_info *sbi, u8 *label, int len)
|
||||
u32 uni_bytes;
|
||||
struct ntfs_inode *ni = sbi->volume.ni;
|
||||
/* Allocate PATH_MAX bytes. */
|
||||
struct cpu_str *uni = __getname();
|
||||
struct cpu_str *uni = kmalloc(PATH_MAX, GFP_KERNEL);
|
||||
|
||||
if (!uni)
|
||||
return -ENOMEM;
|
||||
@@ -2671,6 +2671,6 @@ unlock_out:
|
||||
err = _ni_write_inode(&ni->vfs_inode, 0);
|
||||
|
||||
out:
|
||||
__putname(uni);
|
||||
kfree(uni);
|
||||
return err;
|
||||
}
|
||||
|
||||
+6
-7
@@ -1281,7 +1281,7 @@ int ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
|
||||
fa |= FILE_ATTRIBUTE_READONLY;
|
||||
|
||||
/* Allocate PATH_MAX bytes. */
|
||||
new_de = kmem_cache_zalloc(names_cachep, GFP_KERNEL);
|
||||
new_de = kzalloc(PATH_MAX, GFP_KERNEL);
|
||||
if (!new_de) {
|
||||
err = -ENOMEM;
|
||||
goto out1;
|
||||
@@ -1702,7 +1702,7 @@ out3:
|
||||
ntfs_mark_rec_free(sbi, ino, false);
|
||||
|
||||
out2:
|
||||
__putname(new_de);
|
||||
kfree(new_de);
|
||||
kfree(rp);
|
||||
|
||||
out1:
|
||||
@@ -1723,7 +1723,7 @@ int ntfs_link_inode(struct inode *inode, struct dentry *dentry)
|
||||
struct NTFS_DE *de;
|
||||
|
||||
/* Allocate PATH_MAX bytes. */
|
||||
de = kmem_cache_zalloc(names_cachep, GFP_KERNEL);
|
||||
de = kzalloc(PATH_MAX, GFP_KERNEL);
|
||||
if (!de)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -1737,7 +1737,7 @@ int ntfs_link_inode(struct inode *inode, struct dentry *dentry)
|
||||
|
||||
err = ni_add_name(ntfs_i(d_inode(dentry->d_parent)), ni, de);
|
||||
out:
|
||||
__putname(de);
|
||||
kfree(de);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1760,8 +1760,7 @@ int ntfs_unlink_inode(struct inode *dir, const struct dentry *dentry)
|
||||
if (ntfs_is_meta_file(sbi, ni->mi.rno))
|
||||
return -EINVAL;
|
||||
|
||||
/* Allocate PATH_MAX bytes. */
|
||||
de = kmem_cache_zalloc(names_cachep, GFP_KERNEL);
|
||||
de = kzalloc(PATH_MAX, GFP_KERNEL);
|
||||
if (!de)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -1797,7 +1796,7 @@ int ntfs_unlink_inode(struct inode *dir, const struct dentry *dentry)
|
||||
|
||||
out:
|
||||
ni_unlock(ni);
|
||||
__putname(de);
|
||||
kfree(de);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
+8
-9
@@ -68,7 +68,7 @@ static struct dentry *ntfs_lookup(struct inode *dir, struct dentry *dentry,
|
||||
u32 flags)
|
||||
{
|
||||
struct ntfs_inode *ni = ntfs_i(dir);
|
||||
struct cpu_str *uni = __getname();
|
||||
struct cpu_str *uni = kmalloc(PATH_MAX, GFP_KERNEL);
|
||||
struct inode *inode;
|
||||
int err;
|
||||
|
||||
@@ -85,7 +85,7 @@ static struct dentry *ntfs_lookup(struct inode *dir, struct dentry *dentry,
|
||||
inode = dir_search_u(dir, uni, NULL);
|
||||
ni_unlock(ni);
|
||||
}
|
||||
__putname(uni);
|
||||
kfree(uni);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -303,8 +303,7 @@ static int ntfs_rename(struct mnt_idmap *idmap, struct inode *dir,
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Allocate PATH_MAX bytes. */
|
||||
de = __getname();
|
||||
de = kmalloc(PATH_MAX, GFP_KERNEL);
|
||||
if (!de)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -349,7 +348,7 @@ static int ntfs_rename(struct mnt_idmap *idmap, struct inode *dir,
|
||||
ni_unlock(ni);
|
||||
ni_unlock(dir_ni);
|
||||
out:
|
||||
__putname(de);
|
||||
kfree(de);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -407,7 +406,7 @@ static int ntfs_d_hash(const struct dentry *dentry, struct qstr *name)
|
||||
/*
|
||||
* Try slow way with current upcase table
|
||||
*/
|
||||
uni = kmem_cache_alloc(names_cachep, GFP_NOWAIT);
|
||||
uni = kmalloc(PATH_MAX, GFP_NOWAIT);
|
||||
if (!uni)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -429,7 +428,7 @@ static int ntfs_d_hash(const struct dentry *dentry, struct qstr *name)
|
||||
err = 0;
|
||||
|
||||
out:
|
||||
kmem_cache_free(names_cachep, uni);
|
||||
kfree(uni);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -468,7 +467,7 @@ static int ntfs_d_compare(const struct dentry *dentry, unsigned int len1,
|
||||
* Try slow way with current upcase table
|
||||
*/
|
||||
sbi = dentry->d_sb->s_fs_info;
|
||||
uni1 = __getname();
|
||||
uni1 = kmalloc(PATH_MAX, GFP_NOWAIT);
|
||||
if (!uni1)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -498,7 +497,7 @@ static int ntfs_d_compare(const struct dentry *dentry, unsigned int len1,
|
||||
ret = !ntfs_cmp_names_cpu(uni1, uni2, sbi->upcase, false) ? 0 : 1;
|
||||
|
||||
out:
|
||||
__putname(uni1);
|
||||
kfree(uni1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
+2
-3
@@ -556,8 +556,7 @@ struct posix_acl *ntfs_get_acl(struct mnt_idmap *idmap, struct dentry *dentry,
|
||||
if (unlikely(is_bad_ni(ni)))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
/* Allocate PATH_MAX bytes. */
|
||||
buf = __getname();
|
||||
buf = kmalloc(PATH_MAX, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
@@ -588,7 +587,7 @@ struct posix_acl *ntfs_get_acl(struct mnt_idmap *idmap, struct dentry *dentry,
|
||||
if (!IS_ERR(acl))
|
||||
set_cached_acl(inode, type, acl);
|
||||
|
||||
__putname(buf);
|
||||
kfree(buf);
|
||||
|
||||
return acl;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
+1
-2
@@ -867,7 +867,7 @@ static struct super_block *quotactl_block(const char __user *special, int cmd)
|
||||
{
|
||||
#ifdef CONFIG_BLOCK
|
||||
struct super_block *sb;
|
||||
struct filename *tmp = getname(special);
|
||||
CLASS(filename, tmp)(special);
|
||||
bool excl = false, thawed = false;
|
||||
int error;
|
||||
dev_t dev;
|
||||
@@ -875,7 +875,6 @@ static struct super_block *quotactl_block(const char __user *special, int cmd)
|
||||
if (IS_ERR(tmp))
|
||||
return ERR_CAST(tmp);
|
||||
error = lookup_bdev(tmp->name, &dev);
|
||||
putname(tmp);
|
||||
if (error)
|
||||
return ERR_PTR(error);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user