Commit 1ae9bd8b authored by Al Viro's avatar Al Viro
Browse files

proc_lookupfd_common(): don't bother with instantiate unless the file is open



... 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: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 1bbc5513
Loading
Loading
Loading
Loading
+34 −29
Original line number Original line Diff line number Diff line
@@ -81,12 +81,29 @@ static const struct file_operations proc_fdinfo_file_operations = {
	.release	= single_release,
	.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)
static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags)
{
{
	struct files_struct *files;
	struct task_struct *task;
	struct task_struct *task;
	struct inode *inode;
	struct inode *inode;
	unsigned int fd;
	unsigned int fd;
	fmode_t f_mode;


	if (flags & LOOKUP_RCU)
	if (flags & LOOKUP_RCU)
		return -ECHILD;
		return -ECHILD;
@@ -96,18 +113,7 @@ static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags)
	fd = proc_fd(inode);
	fd = proc_fd(inode);


	if (task) {
	if (task) {
		files = get_files_struct(task);
		if (tid_fd_mode(task, fd, &f_mode)) {
		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);
			task_dump_owner(task, 0, &inode->i_uid, &inode->i_gid);


			if (S_ISLNK(inode->i_mode)) {
			if (S_ISLNK(inode->i_mode)) {
@@ -118,14 +124,10 @@ static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags)
					i_mode |= S_IWUSR | S_IXUSR;
					i_mode |= S_IWUSR | S_IXUSR;
				inode->i_mode = i_mode;
				inode->i_mode = i_mode;
			}
			}

			security_task_to_inode(task, inode);
			security_task_to_inode(task, inode);
			put_task_struct(task);
			put_task_struct(task);
			return 1;
			return 1;
		}
		}
			rcu_read_unlock();
			put_files_struct(files);
		}
		put_task_struct(task);
		put_task_struct(task);
	}
	}
	return 0;
	return 0;
@@ -203,11 +205,14 @@ static struct dentry *proc_lookupfd_common(struct inode *dir,
	struct task_struct *task = get_proc_task(dir);
	struct task_struct *task = get_proc_task(dir);
	int result = -ENOENT;
	int result = -ENOENT;
	unsigned fd = name_to_int(&dentry->d_name);
	unsigned fd = name_to_int(&dentry->d_name);
	fmode_t f_mode;


	if (!task)
	if (!task)
		goto out_no_task;
		goto out_no_task;
	if (fd == ~0U)
	if (fd == ~0U)
		goto out;
		goto out;
	if (!tid_fd_mode(task, fd, &f_mode))
		goto out;


	result = instantiate(dir, dentry, task, (void *)(unsigned long)fd);
	result = instantiate(dir, dentry, task, (void *)(unsigned long)fd);
out:
out: