diff mbox

[2/5] proc_lookupfd_common(): don't bother with instantiate unless the file is open

Message ID 20180526000410.10804-2-viro@ZenIV.linux.org.uk (mailing list archive)
State New, archived
Headers show

Commit Message

Al Viro May 26, 2018, 12:04 a.m. UTC
From: Al Viro <viro@zeniv.linux.org.uk>

... and take the "check if file is open, pick ->f_mode" into a helper;
tid_fd_revalidate() can use it.

The next patch will get rid of tid_fd_revalidate() calls in instantiate
callbacks.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 fs/proc/fd.c | 63 ++++++++++++++++++++++++++++++++----------------------------
 1 file changed, 34 insertions(+), 29 deletions(-)
diff mbox

Patch

diff --git a/fs/proc/fd.c b/fs/proc/fd.c
index 6b80cd1e419a..d38845ecc408 100644
--- a/fs/proc/fd.c
+++ b/fs/proc/fd.c
@@ -81,12 +81,29 @@  static const struct file_operations proc_fdinfo_file_operations = {
 	.release	= single_release,
 };
 
+static bool tid_fd_mode(struct task_struct *task, unsigned fd, fmode_t *mode)
+{
+	struct files_struct *files = get_files_struct(task);
+	struct file *file;
+
+	if (!files)
+		return false;
+
+	rcu_read_lock();
+	file = fcheck_files(files, fd);
+	if (file)
+		*mode = file->f_mode;
+	rcu_read_unlock();
+	put_files_struct(files);
+	return !!file;
+}
+
 static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags)
 {
-	struct files_struct *files;
 	struct task_struct *task;
 	struct inode *inode;
 	unsigned int fd;
+	fmode_t f_mode;
 
 	if (flags & LOOKUP_RCU)
 		return -ECHILD;
@@ -96,35 +113,20 @@  static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags)
 	fd = proc_fd(inode);
 
 	if (task) {
-		files = get_files_struct(task);
-		if (files) {
-			struct file *file;
-
-			rcu_read_lock();
-			file = fcheck_files(files, fd);
-			if (file) {
-				unsigned f_mode = file->f_mode;
-
-				rcu_read_unlock();
-				put_files_struct(files);
-
-				task_dump_owner(task, 0, &inode->i_uid, &inode->i_gid);
-
-				if (S_ISLNK(inode->i_mode)) {
-					unsigned i_mode = S_IFLNK;
-					if (f_mode & FMODE_READ)
-						i_mode |= S_IRUSR | S_IXUSR;
-					if (f_mode & FMODE_WRITE)
-						i_mode |= S_IWUSR | S_IXUSR;
-					inode->i_mode = i_mode;
-				}
-
-				security_task_to_inode(task, inode);
-				put_task_struct(task);
-				return 1;
+		if (tid_fd_mode(task, fd, &f_mode)) {
+			task_dump_owner(task, 0, &inode->i_uid, &inode->i_gid);
+
+			if (S_ISLNK(inode->i_mode)) {
+				unsigned i_mode = S_IFLNK;
+				if (f_mode & FMODE_READ)
+					i_mode |= S_IRUSR | S_IXUSR;
+				if (f_mode & FMODE_WRITE)
+					i_mode |= S_IWUSR | S_IXUSR;
+				inode->i_mode = i_mode;
 			}
-			rcu_read_unlock();
-			put_files_struct(files);
+			security_task_to_inode(task, inode);
+			put_task_struct(task);
+			return 1;
 		}
 		put_task_struct(task);
 	}
@@ -203,11 +205,14 @@  static struct dentry *proc_lookupfd_common(struct inode *dir,
 	struct task_struct *task = get_proc_task(dir);
 	int result = -ENOENT;
 	unsigned fd = name_to_int(&dentry->d_name);
+	fmode_t f_mode;
 
 	if (!task)
 		goto out_no_task;
 	if (fd == ~0U)
 		goto out;
+	if (!tid_fd_mode(task, fd, &f_mode))
+		goto out;
 
 	result = instantiate(dir, dentry, task, (void *)(unsigned long)fd);
 out: