Skip to content

Commit

Permalink
Merge tag 'pull-fd' of git://git.kernel.org/pub/scm/linux/kernel/git/…
Browse files Browse the repository at this point in the history
…viro/vfs

Pull vfs fget updates from Al Viro:
 "fget() to fdget() conversions"

* tag 'pull-fd' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  fuse_dev_ioctl(): switch to fdget()
  cgroup_get_from_fd(): switch to fdget_raw()
  bpf: switch to fdget_raw()
  build_mount_idmapped(): switch to fdget()
  kill the last remaining user of proc_ns_fget()
  SVM-SEV: convert the rest of fget() uses to fdget() in there
  convert sgx_set_attribute() to fdget()/fdput()
  convert setns(2) to fdget()/fdput()
  • Loading branch information
Linus Torvalds committed Apr 25, 2023
2 parents 61d325d + 4a892c0 commit ef36b9a
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 113 deletions.
11 changes: 5 additions & 6 deletions arch/x86/kernel/cpu/sgx/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -892,20 +892,19 @@ static struct miscdevice sgx_dev_provision = {
int sgx_set_attribute(unsigned long *allowed_attributes,
unsigned int attribute_fd)
{
struct file *file;
struct fd f = fdget(attribute_fd);

file = fget(attribute_fd);
if (!file)
if (!f.file)
return -EINVAL;

if (file->f_op != &sgx_provision_fops) {
fput(file);
if (f.file->f_op != &sgx_provision_fops) {
fdput(f);
return -EINVAL;
}

*allowed_attributes |= SGX_ATTR_PROVISIONKEY;

fput(file);
fdput(f);
return 0;
}
EXPORT_SYMBOL_GPL(sgx_set_attribute);
Expand Down
26 changes: 14 additions & 12 deletions arch/x86/kvm/svm/sev.c
Original file line number Diff line number Diff line change
Expand Up @@ -1767,18 +1767,20 @@ int sev_vm_move_enc_context_from(struct kvm *kvm, unsigned int source_fd)
{
struct kvm_sev_info *dst_sev = &to_kvm_svm(kvm)->sev_info;
struct kvm_sev_info *src_sev, *cg_cleanup_sev;
struct file *source_kvm_file;
struct fd f = fdget(source_fd);
struct kvm *source_kvm;
bool charged = false;
int ret;

source_kvm_file = fget(source_fd);
if (!file_is_kvm(source_kvm_file)) {
if (!f.file)
return -EBADF;

if (!file_is_kvm(f.file)) {
ret = -EBADF;
goto out_fput;
}

source_kvm = source_kvm_file->private_data;
source_kvm = f.file->private_data;
ret = sev_lock_two_vms(kvm, source_kvm);
if (ret)
goto out_fput;
Expand Down Expand Up @@ -1828,8 +1830,7 @@ int sev_vm_move_enc_context_from(struct kvm *kvm, unsigned int source_fd)
out_unlock:
sev_unlock_two_vms(kvm, source_kvm);
out_fput:
if (source_kvm_file)
fput(source_kvm_file);
fdput(f);
return ret;
}

Expand Down Expand Up @@ -2046,18 +2047,20 @@ int sev_mem_enc_unregister_region(struct kvm *kvm,

int sev_vm_copy_enc_context_from(struct kvm *kvm, unsigned int source_fd)
{
struct file *source_kvm_file;
struct fd f = fdget(source_fd);
struct kvm *source_kvm;
struct kvm_sev_info *source_sev, *mirror_sev;
int ret;

source_kvm_file = fget(source_fd);
if (!file_is_kvm(source_kvm_file)) {
if (!f.file)
return -EBADF;

if (!file_is_kvm(f.file)) {
ret = -EBADF;
goto e_source_fput;
}

source_kvm = source_kvm_file->private_data;
source_kvm = f.file->private_data;
ret = sev_lock_two_vms(kvm, source_kvm);
if (ret)
goto e_source_fput;
Expand Down Expand Up @@ -2103,8 +2106,7 @@ int sev_vm_copy_enc_context_from(struct kvm *kvm, unsigned int source_fd)
e_unlock:
sev_unlock_two_vms(kvm, source_kvm);
e_source_fput:
if (source_kvm_file)
fput(source_kvm_file);
fdput(f);
return ret;
}

Expand Down
41 changes: 21 additions & 20 deletions fs/fuse/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -2257,30 +2257,31 @@ static long fuse_dev_ioctl(struct file *file, unsigned int cmd,
int res;
int oldfd;
struct fuse_dev *fud = NULL;
struct fd f;

switch (cmd) {
case FUSE_DEV_IOC_CLONE:
res = -EFAULT;
if (!get_user(oldfd, (__u32 __user *)arg)) {
struct file *old = fget(oldfd);

res = -EINVAL;
if (old) {
/*
* Check against file->f_op because CUSE
* uses the same ioctl handler.
*/
if (old->f_op == file->f_op)
fud = fuse_get_dev(old);

if (fud) {
mutex_lock(&fuse_mutex);
res = fuse_device_clone(fud->fc, file);
mutex_unlock(&fuse_mutex);
}
fput(old);
}
if (get_user(oldfd, (__u32 __user *)arg))
return -EFAULT;

f = fdget(oldfd);
if (!f.file)
return -EINVAL;

/*
* Check against file->f_op because CUSE
* uses the same ioctl handler.
*/
if (f.file->f_op == file->f_op)
fud = fuse_get_dev(f.file);

res = -EINVAL;
if (fud) {
mutex_lock(&fuse_mutex);
res = fuse_device_clone(fud->fc, file);
mutex_unlock(&fuse_mutex);
}
fdput(f);
break;
default:
res = -ENOTTY;
Expand Down
12 changes: 6 additions & 6 deletions fs/namespace.c
Original file line number Diff line number Diff line change
Expand Up @@ -4194,7 +4194,7 @@ static int build_mount_idmapped(const struct mount_attr *attr, size_t usize,
int err = 0;
struct ns_common *ns;
struct user_namespace *mnt_userns;
struct file *file;
struct fd f;

if (!((attr->attr_set | attr->attr_clr) & MOUNT_ATTR_IDMAP))
return 0;
Expand All @@ -4210,16 +4210,16 @@ static int build_mount_idmapped(const struct mount_attr *attr, size_t usize,
if (attr->userns_fd > INT_MAX)
return -EINVAL;

file = fget(attr->userns_fd);
if (!file)
f = fdget(attr->userns_fd);
if (!f.file)
return -EBADF;

if (!proc_ns_file(file)) {
if (!proc_ns_file(f.file)) {
err = -EINVAL;
goto out_fput;
}

ns = get_proc_ns(file_inode(file));
ns = get_proc_ns(file_inode(f.file));
if (ns->ops->type != CLONE_NEWUSER) {
err = -EINVAL;
goto out_fput;
Expand Down Expand Up @@ -4248,7 +4248,7 @@ static int build_mount_idmapped(const struct mount_attr *attr, size_t usize,
kattr->mnt_userns = get_user_ns(mnt_userns);

out_fput:
fput(file);
fdput(f);
return err;
}

Expand Down
18 changes: 0 additions & 18 deletions fs/nsfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -235,24 +235,6 @@ bool proc_ns_file(const struct file *file)
return file->f_op == &ns_file_operations;
}

struct file *proc_ns_fget(int fd)
{
struct file *file;

file = fget(fd);
if (!file)
return ERR_PTR(-EBADF);

if (file->f_op != &ns_file_operations)
goto out_invalid;

return file;

out_invalid:
fput(file);
return ERR_PTR(-EINVAL);
}

/**
* ns_match() - Returns true if current namespace matches dev/ino provided.
* @ns: current namespace
Expand Down
1 change: 0 additions & 1 deletion include/linux/proc_ns.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ static inline int ns_alloc_inum(struct ns_common *ns)

#define ns_free_inum(ns) proc_free_inum((ns)->inum)

extern struct file *proc_ns_fget(int fd);
#define get_proc_ns(inode) ((struct ns_common *)(inode)->i_private)
extern int ns_get_path(struct path *path, struct task_struct *task,
const struct proc_ns_operations *ns_ops);
Expand Down
38 changes: 15 additions & 23 deletions kernel/bpf/bpf_inode_storage.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,39 +84,33 @@ void bpf_inode_storage_free(struct inode *inode)
static void *bpf_fd_inode_storage_lookup_elem(struct bpf_map *map, void *key)
{
struct bpf_local_storage_data *sdata;
struct file *f;
int fd;
struct fd f = fdget_raw(*(int *)key);

fd = *(int *)key;
f = fget_raw(fd);
if (!f)
if (!f.file)
return ERR_PTR(-EBADF);

sdata = inode_storage_lookup(f->f_inode, map, true);
fput(f);
sdata = inode_storage_lookup(file_inode(f.file), map, true);
fdput(f);
return sdata ? sdata->data : NULL;
}

static int bpf_fd_inode_storage_update_elem(struct bpf_map *map, void *key,
void *value, u64 map_flags)
{
struct bpf_local_storage_data *sdata;
struct file *f;
int fd;
struct fd f = fdget_raw(*(int *)key);

fd = *(int *)key;
f = fget_raw(fd);
if (!f)
if (!f.file)
return -EBADF;
if (!inode_storage_ptr(f->f_inode)) {
fput(f);
if (!inode_storage_ptr(file_inode(f.file))) {
fdput(f);
return -EBADF;
}

sdata = bpf_local_storage_update(f->f_inode,
sdata = bpf_local_storage_update(file_inode(f.file),
(struct bpf_local_storage_map *)map,
value, map_flags, GFP_ATOMIC);
fput(f);
fdput(f);
return PTR_ERR_OR_ZERO(sdata);
}

Expand All @@ -135,16 +129,14 @@ static int inode_storage_delete(struct inode *inode, struct bpf_map *map)

static int bpf_fd_inode_storage_delete_elem(struct bpf_map *map, void *key)
{
struct file *f;
int fd, err;
struct fd f = fdget_raw(*(int *)key);
int err;

fd = *(int *)key;
f = fget_raw(fd);
if (!f)
if (!f.file)
return -EBADF;

err = inode_storage_delete(f->f_inode, map);
fput(f);
err = inode_storage_delete(file_inode(f.file), map);
fdput(f);
return err;
}

Expand Down
10 changes: 4 additions & 6 deletions kernel/cgroup/cgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -6856,14 +6856,12 @@ EXPORT_SYMBOL_GPL(cgroup_get_from_path);
struct cgroup *cgroup_v1v2_get_from_fd(int fd)
{
struct cgroup *cgrp;
struct file *f;

f = fget_raw(fd);
if (!f)
struct fd f = fdget_raw(fd);
if (!f.file)
return ERR_PTR(-EBADF);

cgrp = cgroup_v1v2_get_from_file(f);
fput(f);
cgrp = cgroup_v1v2_get_from_file(f.file);
fdput(f);
return cgrp;
}

Expand Down
17 changes: 8 additions & 9 deletions kernel/nsproxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -545,21 +545,20 @@ static void commit_nsset(struct nsset *nsset)

SYSCALL_DEFINE2(setns, int, fd, int, flags)
{
struct file *file;
struct fd f = fdget(fd);
struct ns_common *ns = NULL;
struct nsset nsset = {};
int err = 0;

file = fget(fd);
if (!file)
if (!f.file)
return -EBADF;

if (proc_ns_file(file)) {
ns = get_proc_ns(file_inode(file));
if (proc_ns_file(f.file)) {
ns = get_proc_ns(file_inode(f.file));
if (flags && (ns->ops->type != flags))
err = -EINVAL;
flags = ns->ops->type;
} else if (!IS_ERR(pidfd_pid(file))) {
} else if (!IS_ERR(pidfd_pid(f.file))) {
err = check_setns_flags(flags);
} else {
err = -EINVAL;
Expand All @@ -571,17 +570,17 @@ SYSCALL_DEFINE2(setns, int, fd, int, flags)
if (err)
goto out;

if (proc_ns_file(file))
if (proc_ns_file(f.file))
err = validate_ns(&nsset, ns);
else
err = validate_nsset(&nsset, file->private_data);
err = validate_nsset(&nsset, f.file->private_data);
if (!err) {
commit_nsset(&nsset);
perf_event_namespaces(current);
}
put_nsset(&nsset);
out:
fput(file);
fdput(f);
return err;
}

Expand Down
23 changes: 11 additions & 12 deletions net/core/net_namespace.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <linux/sched/task.h>
#include <linux/uidgid.h>
#include <linux/cookie.h>
#include <linux/proc_fs.h>

#include <net/sock.h>
#include <net/netlink.h>
Expand Down Expand Up @@ -676,21 +677,19 @@ EXPORT_SYMBOL_GPL(get_net_ns);

struct net *get_net_ns_by_fd(int fd)
{
struct file *file;
struct ns_common *ns;
struct net *net;
struct fd f = fdget(fd);
struct net *net = ERR_PTR(-EINVAL);

file = proc_ns_fget(fd);
if (IS_ERR(file))
return ERR_CAST(file);
if (!f.file)
return ERR_PTR(-EBADF);

ns = get_proc_ns(file_inode(file));
if (ns->ops == &netns_operations)
net = get_net(container_of(ns, struct net, ns));
else
net = ERR_PTR(-EINVAL);
if (proc_ns_file(f.file)) {
struct ns_common *ns = get_proc_ns(file_inode(f.file));
if (ns->ops == &netns_operations)
net = get_net(container_of(ns, struct net, ns));
}
fdput(f);

fput(file);
return net;
}
EXPORT_SYMBOL_GPL(get_net_ns_by_fd);
Expand Down

0 comments on commit ef36b9a

Please sign in to comment.