^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* Filesystem access-by-fd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2017 Red Hat, Inc. All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Written by David Howells (dhowells@redhat.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/fs_context.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/fs_parser.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/syscalls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/security.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/anon_inodes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/namei.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <uapi/linux/mount.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "mount.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * Allow the user to read back any error, warning or informational messages.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static ssize_t fscontext_read(struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) char __user *_buf, size_t len, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct fs_context *fc = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct fc_log *log = fc->log.log;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) unsigned int logsize = ARRAY_SIZE(log->buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) ssize_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) char *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) bool need_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) int index, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) ret = mutex_lock_interruptible(&fc->uapi_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (log->head == log->tail) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) mutex_unlock(&fc->uapi_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return -ENODATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) index = log->tail & (logsize - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) p = log->buffer[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) need_free = log->need_free & (1 << index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) log->buffer[index] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) log->need_free &= ~(1 << index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) log->tail++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) mutex_unlock(&fc->uapi_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) ret = -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) n = strlen(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (n > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) goto err_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) ret = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (copy_to_user(_buf, p, n) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) goto err_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) ret = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) err_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (need_free)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) kfree(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static int fscontext_release(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct fs_context *fc = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (fc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) file->private_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) put_fs_context(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) const struct file_operations fscontext_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) .read = fscontext_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) .release = fscontext_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) .llseek = no_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * Attach a filesystem context to a file and an fd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static int fscontext_create_fd(struct fs_context *fc, unsigned int o_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) int fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) fd = anon_inode_getfd("[fscontext]", &fscontext_fops, fc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) O_RDWR | o_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (fd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) put_fs_context(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static int fscontext_alloc_log(struct fs_context *fc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) fc->log.log = kzalloc(sizeof(*fc->log.log), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (!fc->log.log)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) refcount_set(&fc->log.log->usage, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) fc->log.log->owner = fc->fs_type->owner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * Open a filesystem by name so that it can be configured for mounting.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * We are allowed to specify a container in which the filesystem will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * opened, thereby indicating which namespaces will be used (notably, which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * network namespace will be used for network filesystems).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) SYSCALL_DEFINE2(fsopen, const char __user *, _fs_name, unsigned int, flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct file_system_type *fs_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct fs_context *fc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) const char *fs_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (!ns_capable(current->nsproxy->mnt_ns->user_ns, CAP_SYS_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (flags & ~FSOPEN_CLOEXEC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) fs_name = strndup_user(_fs_name, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (IS_ERR(fs_name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return PTR_ERR(fs_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) fs_type = get_fs_type(fs_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) kfree(fs_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (!fs_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) fc = fs_context_for_mount(fs_type, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) put_filesystem(fs_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (IS_ERR(fc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return PTR_ERR(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) fc->phase = FS_CONTEXT_CREATE_PARAMS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) ret = fscontext_alloc_log(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) goto err_fc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return fscontext_create_fd(fc, flags & FSOPEN_CLOEXEC ? O_CLOEXEC : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) err_fc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) put_fs_context(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * Pick a superblock into a context for reconfiguration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) SYSCALL_DEFINE3(fspick, int, dfd, const char __user *, path, unsigned int, flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct fs_context *fc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) struct path target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) unsigned int lookup_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (!ns_capable(current->nsproxy->mnt_ns->user_ns, CAP_SYS_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if ((flags & ~(FSPICK_CLOEXEC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) FSPICK_SYMLINK_NOFOLLOW |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) FSPICK_NO_AUTOMOUNT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) FSPICK_EMPTY_PATH)) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) lookup_flags = LOOKUP_FOLLOW | LOOKUP_AUTOMOUNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (flags & FSPICK_SYMLINK_NOFOLLOW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) lookup_flags &= ~LOOKUP_FOLLOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (flags & FSPICK_NO_AUTOMOUNT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) lookup_flags &= ~LOOKUP_AUTOMOUNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (flags & FSPICK_EMPTY_PATH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) lookup_flags |= LOOKUP_EMPTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) ret = user_path_at(dfd, path, lookup_flags, &target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (target.mnt->mnt_root != target.dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) goto err_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) fc = fs_context_for_reconfigure(target.dentry, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (IS_ERR(fc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) ret = PTR_ERR(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) goto err_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) fc->phase = FS_CONTEXT_RECONF_PARAMS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) ret = fscontext_alloc_log(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) goto err_fc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) path_put(&target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return fscontext_create_fd(fc, flags & FSPICK_CLOEXEC ? O_CLOEXEC : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) err_fc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) put_fs_context(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) err_path:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) path_put(&target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * Check the state and apply the configuration. Note that this function is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * allowed to 'steal' the value by setting param->xxx to NULL before returning.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) static int vfs_fsconfig_locked(struct fs_context *fc, int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) struct fs_parameter *param)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) struct super_block *sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) ret = finish_clean_context(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) case FSCONFIG_CMD_CREATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (fc->phase != FS_CONTEXT_CREATE_PARAMS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (!mount_capable(fc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) fc->phase = FS_CONTEXT_CREATING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) ret = vfs_get_tree(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) sb = fc->root->d_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) ret = security_sb_kern_mount(sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (unlikely(ret)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) fc_drop_locked(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) up_write(&sb->s_umount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) fc->phase = FS_CONTEXT_AWAITING_MOUNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) case FSCONFIG_CMD_RECONFIGURE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (fc->phase != FS_CONTEXT_RECONF_PARAMS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) fc->phase = FS_CONTEXT_RECONFIGURING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) sb = fc->root->d_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (!ns_capable(sb->s_user_ns, CAP_SYS_ADMIN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) ret = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) down_write(&sb->s_umount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) ret = reconfigure_super(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) up_write(&sb->s_umount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) vfs_clean_context(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (fc->phase != FS_CONTEXT_CREATE_PARAMS &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) fc->phase != FS_CONTEXT_RECONF_PARAMS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) return vfs_parse_fs_param(fc, param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) fc->phase = FS_CONTEXT_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * sys_fsconfig - Set parameters and trigger actions on a context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) * @fd: The filesystem context to act upon
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * @cmd: The action to take
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * @_key: Where appropriate, the parameter key to set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) * @_value: Where appropriate, the parameter value to set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) * @aux: Additional information for the value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) * This system call is used to set parameters on a context, including
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) * superblock settings, data source and security labelling.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) * Actions include triggering the creation of a superblock and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) * reconfiguration of the superblock attached to the specified context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * When setting a parameter, @cmd indicates the type of value being proposed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) * and @_key indicates the parameter to be altered.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) * @_value and @aux are used to specify the value, should a value be required:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) * (*) fsconfig_set_flag: No value is specified. The parameter must be boolean
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * in nature. The key may be prefixed with "no" to invert the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * setting. @_value must be NULL and @aux must be 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) * (*) fsconfig_set_string: A string value is specified. The parameter can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) * expecting boolean, integer, string or take a path. A conversion to an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) * appropriate type will be attempted (which may include looking up as a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * path). @_value points to a NUL-terminated string and @aux must be 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) * (*) fsconfig_set_binary: A binary blob is specified. @_value points to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * blob and @aux indicates its size. The parameter must be expecting a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * blob.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * (*) fsconfig_set_path: A non-empty path is specified. The parameter must be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) * expecting a path object. @_value points to a NUL-terminated string that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) * is the path and @aux is a file descriptor at which to start a relative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * lookup or AT_FDCWD.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) * (*) fsconfig_set_path_empty: As fsconfig_set_path, but with AT_EMPTY_PATH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) * implied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) * (*) fsconfig_set_fd: An open file descriptor is specified. @_value must be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) * NULL and @aux indicates the file descriptor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) SYSCALL_DEFINE5(fsconfig,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) int, fd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) unsigned int, cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) const char __user *, _key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) const void __user *, _value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) int, aux)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) struct fs_context *fc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) struct fd f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) int lookup_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) struct fs_parameter param = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) .type = fs_value_is_undefined,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (fd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) case FSCONFIG_SET_FLAG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (!_key || _value || aux)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) case FSCONFIG_SET_STRING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) if (!_key || !_value || aux)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) case FSCONFIG_SET_BINARY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (!_key || !_value || aux <= 0 || aux > 1024 * 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) case FSCONFIG_SET_PATH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) case FSCONFIG_SET_PATH_EMPTY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (!_key || !_value || (aux != AT_FDCWD && aux < 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) case FSCONFIG_SET_FD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (!_key || _value || aux < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) case FSCONFIG_CMD_CREATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) case FSCONFIG_CMD_RECONFIGURE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (_key || _value || aux)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) f = fdget(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (!f.file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) return -EBADF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (f.file->f_op != &fscontext_fops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) goto out_f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) fc = f.file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (fc->ops == &legacy_fs_context_ops) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) case FSCONFIG_SET_BINARY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) case FSCONFIG_SET_PATH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) case FSCONFIG_SET_PATH_EMPTY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) case FSCONFIG_SET_FD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) ret = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) goto out_f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (_key) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) param.key = strndup_user(_key, 256);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (IS_ERR(param.key)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) ret = PTR_ERR(param.key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) goto out_f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) case FSCONFIG_SET_FLAG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) param.type = fs_value_is_flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) case FSCONFIG_SET_STRING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) param.type = fs_value_is_string;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) param.string = strndup_user(_value, 256);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (IS_ERR(param.string)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) ret = PTR_ERR(param.string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) goto out_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) param.size = strlen(param.string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) case FSCONFIG_SET_BINARY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) param.type = fs_value_is_blob;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) param.size = aux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) param.blob = memdup_user_nul(_value, aux);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (IS_ERR(param.blob)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) ret = PTR_ERR(param.blob);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) goto out_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) case FSCONFIG_SET_PATH_EMPTY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) lookup_flags = LOOKUP_EMPTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) case FSCONFIG_SET_PATH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) param.type = fs_value_is_filename;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) param.name = getname_flags(_value, lookup_flags, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (IS_ERR(param.name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) ret = PTR_ERR(param.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) goto out_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) param.dirfd = aux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) param.size = strlen(param.name->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) case FSCONFIG_SET_FD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) param.type = fs_value_is_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) ret = -EBADF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) param.file = fget(aux);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (!param.file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) goto out_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) ret = mutex_lock_interruptible(&fc->uapi_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (ret == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) ret = vfs_fsconfig_locked(fc, cmd, ¶m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) mutex_unlock(&fc->uapi_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) /* Clean up the our record of any value that we obtained from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) * userspace. Note that the value may have been stolen by the LSM or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) * filesystem, in which case the value pointer will have been cleared.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) case FSCONFIG_SET_STRING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) case FSCONFIG_SET_BINARY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) kfree(param.string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) case FSCONFIG_SET_PATH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) case FSCONFIG_SET_PATH_EMPTY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (param.name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) putname(param.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) case FSCONFIG_SET_FD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (param.file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) fput(param.file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) out_key:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) kfree(param.key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) out_f:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) fdput(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) }