anonfd: Allow making anon files read-only
It seems a couple places such as arch/ia64/kernel/perfmon.c and drivers/infiniband/core/uverbs_main.c could use anon_inode_getfile() instead of a private pseudo-fs + alloc_file(), if only there were a way to get a read-only file. So provide this by having anon_inode_getfile() create a read-only file if we pass O_RDONLY in flags. Signed-off-by: Roland Dreier <rolandd@cisco.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Родитель
ed2617585f
Коммит
628ff7c1d8
|
@ -89,11 +89,19 @@ struct file *anon_inode_getfile(const char *name,
|
||||||
struct qstr this;
|
struct qstr this;
|
||||||
struct path path;
|
struct path path;
|
||||||
struct file *file;
|
struct file *file;
|
||||||
|
fmode_t mode;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if (IS_ERR(anon_inode_inode))
|
if (IS_ERR(anon_inode_inode))
|
||||||
return ERR_PTR(-ENODEV);
|
return ERR_PTR(-ENODEV);
|
||||||
|
|
||||||
|
switch (flags & O_ACCMODE) {
|
||||||
|
case O_RDONLY: mode = FMODE_READ; break;
|
||||||
|
case O_WRONLY: mode = FMODE_WRITE; break;
|
||||||
|
case O_RDWR: mode = FMODE_READ | FMODE_WRITE; break;
|
||||||
|
default: return ERR_PTR(-EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
if (fops->owner && !try_module_get(fops->owner))
|
if (fops->owner && !try_module_get(fops->owner))
|
||||||
return ERR_PTR(-ENOENT);
|
return ERR_PTR(-ENOENT);
|
||||||
|
|
||||||
|
@ -121,13 +129,13 @@ struct file *anon_inode_getfile(const char *name,
|
||||||
d_instantiate(path.dentry, anon_inode_inode);
|
d_instantiate(path.dentry, anon_inode_inode);
|
||||||
|
|
||||||
error = -ENFILE;
|
error = -ENFILE;
|
||||||
file = alloc_file(&path, FMODE_READ | FMODE_WRITE, fops);
|
file = alloc_file(&path, mode, fops);
|
||||||
if (!file)
|
if (!file)
|
||||||
goto err_dput;
|
goto err_dput;
|
||||||
file->f_mapping = anon_inode_inode->i_mapping;
|
file->f_mapping = anon_inode_inode->i_mapping;
|
||||||
|
|
||||||
file->f_pos = 0;
|
file->f_pos = 0;
|
||||||
file->f_flags = O_RDWR | (flags & O_NONBLOCK);
|
file->f_flags = flags & (O_ACCMODE | O_NONBLOCK);
|
||||||
file->f_version = 0;
|
file->f_version = 0;
|
||||||
file->private_data = priv;
|
file->private_data = priv;
|
||||||
|
|
||||||
|
|
|
@ -339,7 +339,7 @@ struct file *eventfd_file_create(unsigned int count, int flags)
|
||||||
ctx->flags = flags;
|
ctx->flags = flags;
|
||||||
|
|
||||||
file = anon_inode_getfile("[eventfd]", &eventfd_fops, ctx,
|
file = anon_inode_getfile("[eventfd]", &eventfd_fops, ctx,
|
||||||
flags & EFD_SHARED_FCNTL_FLAGS);
|
O_RDWR | (flags & EFD_SHARED_FCNTL_FLAGS));
|
||||||
if (IS_ERR(file))
|
if (IS_ERR(file))
|
||||||
eventfd_free_ctx(ctx);
|
eventfd_free_ctx(ctx);
|
||||||
|
|
||||||
|
|
|
@ -1206,7 +1206,7 @@ SYSCALL_DEFINE1(epoll_create1, int, flags)
|
||||||
* a file structure and a free file descriptor.
|
* a file structure and a free file descriptor.
|
||||||
*/
|
*/
|
||||||
error = anon_inode_getfd("[eventpoll]", &eventpoll_fops, ep,
|
error = anon_inode_getfd("[eventpoll]", &eventpoll_fops, ep,
|
||||||
flags & O_CLOEXEC);
|
O_RDWR | (flags & O_CLOEXEC));
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
ep_free(ep);
|
ep_free(ep);
|
||||||
|
|
||||||
|
|
|
@ -236,7 +236,7 @@ SYSCALL_DEFINE4(signalfd4, int, ufd, sigset_t __user *, user_mask,
|
||||||
* anon_inode_getfd() will install the fd.
|
* anon_inode_getfd() will install the fd.
|
||||||
*/
|
*/
|
||||||
ufd = anon_inode_getfd("[signalfd]", &signalfd_fops, ctx,
|
ufd = anon_inode_getfd("[signalfd]", &signalfd_fops, ctx,
|
||||||
flags & (O_CLOEXEC | O_NONBLOCK));
|
O_RDWR | (flags & (O_CLOEXEC | O_NONBLOCK)));
|
||||||
if (ufd < 0)
|
if (ufd < 0)
|
||||||
kfree(ctx);
|
kfree(ctx);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -200,7 +200,7 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags)
|
||||||
hrtimer_init(&ctx->tmr, clockid, HRTIMER_MODE_ABS);
|
hrtimer_init(&ctx->tmr, clockid, HRTIMER_MODE_ABS);
|
||||||
|
|
||||||
ufd = anon_inode_getfd("[timerfd]", &timerfd_fops, ctx,
|
ufd = anon_inode_getfd("[timerfd]", &timerfd_fops, ctx,
|
||||||
flags & TFD_SHARED_FCNTL_FLAGS);
|
O_RDWR | (flags & TFD_SHARED_FCNTL_FLAGS));
|
||||||
if (ufd < 0)
|
if (ufd < 0)
|
||||||
kfree(ctx);
|
kfree(ctx);
|
||||||
|
|
||||||
|
|
|
@ -4724,7 +4724,7 @@ SYSCALL_DEFINE5(perf_event_open,
|
||||||
if (IS_ERR(event))
|
if (IS_ERR(event))
|
||||||
goto err_put_context;
|
goto err_put_context;
|
||||||
|
|
||||||
err = anon_inode_getfd("[perf_event]", &perf_fops, event, 0);
|
err = anon_inode_getfd("[perf_event]", &perf_fops, event, O_RDWR);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto err_free_put_context;
|
goto err_free_put_context;
|
||||||
|
|
||||||
|
|
|
@ -1177,7 +1177,7 @@ static struct file_operations kvm_vcpu_fops = {
|
||||||
*/
|
*/
|
||||||
static int create_vcpu_fd(struct kvm_vcpu *vcpu)
|
static int create_vcpu_fd(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
return anon_inode_getfd("kvm-vcpu", &kvm_vcpu_fops, vcpu, 0);
|
return anon_inode_getfd("kvm-vcpu", &kvm_vcpu_fops, vcpu, O_RDWR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1638,7 +1638,7 @@ static int kvm_dev_ioctl_create_vm(void)
|
||||||
kvm = kvm_create_vm();
|
kvm = kvm_create_vm();
|
||||||
if (IS_ERR(kvm))
|
if (IS_ERR(kvm))
|
||||||
return PTR_ERR(kvm);
|
return PTR_ERR(kvm);
|
||||||
fd = anon_inode_getfd("kvm-vm", &kvm_vm_fops, kvm, 0);
|
fd = anon_inode_getfd("kvm-vm", &kvm_vm_fops, kvm, O_RDWR);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
kvm_put_kvm(kvm);
|
kvm_put_kvm(kvm);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче