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

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
...@@ -81,12 +81,29 @@ static const struct file_operations proc_fdinfo_file_operations = { ...@@ -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,35 +113,20 @@ static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags) ...@@ -96,35 +113,20 @@ 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) { task_dump_owner(task, 0, &inode->i_uid, &inode->i_gid);
struct file *file;
if (S_ISLNK(inode->i_mode)) {
rcu_read_lock(); unsigned i_mode = S_IFLNK;
file = fcheck_files(files, fd); if (f_mode & FMODE_READ)
if (file) { i_mode |= S_IRUSR | S_IXUSR;
unsigned f_mode = file->f_mode; if (f_mode & FMODE_WRITE)
i_mode |= S_IWUSR | S_IXUSR;
rcu_read_unlock(); inode->i_mode = i_mode;
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;
} }
rcu_read_unlock(); security_task_to_inode(task, inode);
put_files_struct(files); put_task_struct(task);
return 1;
} }
put_task_struct(task); put_task_struct(task);
} }
...@@ -203,11 +205,14 @@ static struct dentry *proc_lookupfd_common(struct inode *dir, ...@@ -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:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment