Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 628ff7c1 authored by Roland Dreier's avatar Roland Dreier Committed by Al Viro
Browse files

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: default avatarRoland Dreier <rolandd@cisco.com>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent ed261758
Loading
Loading
Loading
Loading
+10 −2
Original line number Diff line number Diff line
@@ -89,11 +89,19 @@ struct file *anon_inode_getfile(const char *name,
	struct qstr this;
	struct path path;
	struct file *file;
	fmode_t mode;
	int error;

	if (IS_ERR(anon_inode_inode))
		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))
		return ERR_PTR(-ENOENT);

@@ -121,13 +129,13 @@ struct file *anon_inode_getfile(const char *name,
	d_instantiate(path.dentry, anon_inode_inode);

	error = -ENFILE;
	file = alloc_file(&path, FMODE_READ | FMODE_WRITE, fops);
	file = alloc_file(&path, mode, fops);
	if (!file)
		goto err_dput;
	file->f_mapping = anon_inode_inode->i_mapping;

	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->private_data = priv;

+1 −1
Original line number Diff line number Diff line
@@ -339,7 +339,7 @@ struct file *eventfd_file_create(unsigned int count, int flags)
	ctx->flags = flags;

	file = anon_inode_getfile("[eventfd]", &eventfd_fops, ctx,
				  flags & EFD_SHARED_FCNTL_FLAGS);
				  O_RDWR | (flags & EFD_SHARED_FCNTL_FLAGS));
	if (IS_ERR(file))
		eventfd_free_ctx(ctx);

+1 −1
Original line number Diff line number Diff line
@@ -1206,7 +1206,7 @@ SYSCALL_DEFINE1(epoll_create1, int, flags)
	 * a file structure and a free file descriptor.
	 */
	error = anon_inode_getfd("[eventpoll]", &eventpoll_fops, ep,
				 flags & O_CLOEXEC);
				 O_RDWR | (flags & O_CLOEXEC));
	if (error < 0)
		ep_free(ep);

+1 −1
Original line number Diff line number Diff line
@@ -236,7 +236,7 @@ SYSCALL_DEFINE4(signalfd4, int, ufd, sigset_t __user *, user_mask,
		 * anon_inode_getfd() will install the fd.
		 */
		ufd = anon_inode_getfd("[signalfd]", &signalfd_fops, ctx,
				       flags & (O_CLOEXEC | O_NONBLOCK));
				       O_RDWR | (flags & (O_CLOEXEC | O_NONBLOCK)));
		if (ufd < 0)
			kfree(ctx);
	} else {
+1 −1
Original line number Diff line number Diff line
@@ -200,7 +200,7 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags)
	hrtimer_init(&ctx->tmr, clockid, HRTIMER_MODE_ABS);

	ufd = anon_inode_getfd("[timerfd]", &timerfd_fops, ctx,
			       flags & TFD_SHARED_FCNTL_FLAGS);
			       O_RDWR | (flags & TFD_SHARED_FCNTL_FLAGS));
	if (ufd < 0)
		kfree(ctx);

Loading