Commit 628ff7c1d8d8466a5ad8078bd0206a130f8b8a51
Committed by
Al Viro
1 parent
ed2617585f
Exists in
master
and in
4 other branches
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>
Showing 7 changed files with 17 additions and 9 deletions Side-by-side Diff
fs/anon_inodes.c
... | ... | @@ -89,11 +89,19 @@ |
89 | 89 | struct qstr this; |
90 | 90 | struct path path; |
91 | 91 | struct file *file; |
92 | + fmode_t mode; | |
92 | 93 | int error; |
93 | 94 | |
94 | 95 | if (IS_ERR(anon_inode_inode)) |
95 | 96 | return ERR_PTR(-ENODEV); |
96 | 97 | |
98 | + switch (flags & O_ACCMODE) { | |
99 | + case O_RDONLY: mode = FMODE_READ; break; | |
100 | + case O_WRONLY: mode = FMODE_WRITE; break; | |
101 | + case O_RDWR: mode = FMODE_READ | FMODE_WRITE; break; | |
102 | + default: return ERR_PTR(-EINVAL); | |
103 | + } | |
104 | + | |
97 | 105 | if (fops->owner && !try_module_get(fops->owner)) |
98 | 106 | return ERR_PTR(-ENOENT); |
99 | 107 | |
100 | 108 | |
... | ... | @@ -121,13 +129,13 @@ |
121 | 129 | d_instantiate(path.dentry, anon_inode_inode); |
122 | 130 | |
123 | 131 | error = -ENFILE; |
124 | - file = alloc_file(&path, FMODE_READ | FMODE_WRITE, fops); | |
132 | + file = alloc_file(&path, mode, fops); | |
125 | 133 | if (!file) |
126 | 134 | goto err_dput; |
127 | 135 | file->f_mapping = anon_inode_inode->i_mapping; |
128 | 136 | |
129 | 137 | file->f_pos = 0; |
130 | - file->f_flags = O_RDWR | (flags & O_NONBLOCK); | |
138 | + file->f_flags = flags & (O_ACCMODE | O_NONBLOCK); | |
131 | 139 | file->f_version = 0; |
132 | 140 | file->private_data = priv; |
133 | 141 |
fs/eventfd.c
fs/eventpoll.c
fs/signalfd.c
... | ... | @@ -236,7 +236,7 @@ |
236 | 236 | * anon_inode_getfd() will install the fd. |
237 | 237 | */ |
238 | 238 | ufd = anon_inode_getfd("[signalfd]", &signalfd_fops, ctx, |
239 | - flags & (O_CLOEXEC | O_NONBLOCK)); | |
239 | + O_RDWR | (flags & (O_CLOEXEC | O_NONBLOCK))); | |
240 | 240 | if (ufd < 0) |
241 | 241 | kfree(ctx); |
242 | 242 | } else { |
fs/timerfd.c
kernel/perf_event.c
... | ... | @@ -4724,7 +4724,7 @@ |
4724 | 4724 | if (IS_ERR(event)) |
4725 | 4725 | goto err_put_context; |
4726 | 4726 | |
4727 | - err = anon_inode_getfd("[perf_event]", &perf_fops, event, 0); | |
4727 | + err = anon_inode_getfd("[perf_event]", &perf_fops, event, O_RDWR); | |
4728 | 4728 | if (err < 0) |
4729 | 4729 | goto err_free_put_context; |
4730 | 4730 |
virt/kvm/kvm_main.c
... | ... | @@ -1177,7 +1177,7 @@ |
1177 | 1177 | */ |
1178 | 1178 | static int create_vcpu_fd(struct kvm_vcpu *vcpu) |
1179 | 1179 | { |
1180 | - return anon_inode_getfd("kvm-vcpu", &kvm_vcpu_fops, vcpu, 0); | |
1180 | + return anon_inode_getfd("kvm-vcpu", &kvm_vcpu_fops, vcpu, O_RDWR); | |
1181 | 1181 | } |
1182 | 1182 | |
1183 | 1183 | /* |
... | ... | @@ -1638,7 +1638,7 @@ |
1638 | 1638 | kvm = kvm_create_vm(); |
1639 | 1639 | if (IS_ERR(kvm)) |
1640 | 1640 | return PTR_ERR(kvm); |
1641 | - fd = anon_inode_getfd("kvm-vm", &kvm_vm_fops, kvm, 0); | |
1641 | + fd = anon_inode_getfd("kvm-vm", &kvm_vm_fops, kvm, O_RDWR); | |
1642 | 1642 | if (fd < 0) |
1643 | 1643 | kvm_put_kvm(kvm); |
1644 | 1644 |