Commit 628ff7c1d8d8466a5ad8078bd0206a130f8b8a51

Authored by Roland Dreier
Committed by Al Viro
1 parent ed2617585f

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

... ... @@ -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  
... ... @@ -339,7 +339,7 @@
339 339 ctx->flags = flags;
340 340  
341 341 file = anon_inode_getfile("[eventfd]", &eventfd_fops, ctx,
342   - flags & EFD_SHARED_FCNTL_FLAGS);
  342 + O_RDWR | (flags & EFD_SHARED_FCNTL_FLAGS));
343 343 if (IS_ERR(file))
344 344 eventfd_free_ctx(ctx);
345 345  
... ... @@ -1206,7 +1206,7 @@
1206 1206 * a file structure and a free file descriptor.
1207 1207 */
1208 1208 error = anon_inode_getfd("[eventpoll]", &eventpoll_fops, ep,
1209   - flags & O_CLOEXEC);
  1209 + O_RDWR | (flags & O_CLOEXEC));
1210 1210 if (error < 0)
1211 1211 ep_free(ep);
1212 1212  
... ... @@ -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 {
... ... @@ -200,7 +200,7 @@
200 200 hrtimer_init(&ctx->tmr, clockid, HRTIMER_MODE_ABS);
201 201  
202 202 ufd = anon_inode_getfd("[timerfd]", &timerfd_fops, ctx,
203   - flags & TFD_SHARED_FCNTL_FLAGS);
  203 + O_RDWR | (flags & TFD_SHARED_FCNTL_FLAGS));
204 204 if (ufd < 0)
205 205 kfree(ctx);
206 206  
... ... @@ -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  
... ... @@ -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