diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2018-05-02 22:42:22 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2018-05-22 14:28:04 -0400 |
commit | 1ae9bd8b7e4912b238a14adc7c559a7ecbb9c062 (patch) | |
tree | 118b9f6c708060ea5286d46a879b5efd5c3a4ef7 | |
parent | 1bbc55131e59bd099fdc568d3aa0b42634dbd188 (diff) |
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: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/proc/fd.c | 63 |
1 files changed, 34 insertions, 29 deletions
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 = { | |||
81 | .release = single_release, | 81 | .release = single_release, |
82 | }; | 82 | }; |
83 | 83 | ||
84 | static bool tid_fd_mode(struct task_struct *task, unsigned fd, fmode_t *mode) | ||
85 | { | ||
86 | struct files_struct *files = get_files_struct(task); | ||
87 | struct file *file; | ||
88 | |||
89 | if (!files) | ||
90 | return false; | ||
91 | |||
92 | rcu_read_lock(); | ||
93 | file = fcheck_files(files, fd); | ||
94 | if (file) | ||
95 | *mode = file->f_mode; | ||
96 | rcu_read_unlock(); | ||
97 | put_files_struct(files); | ||
98 | return !!file; | ||
99 | } | ||
100 | |||
84 | static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags) | 101 | static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags) |
85 | { | 102 | { |
86 | struct files_struct *files; | ||
87 | struct task_struct *task; | 103 | struct task_struct *task; |
88 | struct inode *inode; | 104 | struct inode *inode; |
89 | unsigned int fd; | 105 | unsigned int fd; |
106 | fmode_t f_mode; | ||
90 | 107 | ||
91 | if (flags & LOOKUP_RCU) | 108 | if (flags & LOOKUP_RCU) |
92 | return -ECHILD; | 109 | return -ECHILD; |
@@ -96,35 +113,20 @@ static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags) | |||
96 | fd = proc_fd(inode); | 113 | fd = proc_fd(inode); |
97 | 114 | ||
98 | if (task) { | 115 | if (task) { |
99 | files = get_files_struct(task); | 116 | if (tid_fd_mode(task, fd, &f_mode)) { |
100 | if (files) { | 117 | task_dump_owner(task, 0, &inode->i_uid, &inode->i_gid); |
101 | struct file *file; | 118 | |
102 | 119 | if (S_ISLNK(inode->i_mode)) { | |
103 | rcu_read_lock(); | 120 | unsigned i_mode = S_IFLNK; |
104 | file = fcheck_files(files, fd); | 121 | if (f_mode & FMODE_READ) |
105 | if (file) { | 122 | i_mode |= S_IRUSR | S_IXUSR; |
106 | unsigned f_mode = file->f_mode; | 123 | if (f_mode & FMODE_WRITE) |
107 | 124 | i_mode |= S_IWUSR | S_IXUSR; | |
108 | rcu_read_unlock(); | 125 | inode->i_mode = i_mode; |
109 | put_files_struct(files); | ||
110 | |||
111 | task_dump_owner(task, 0, &inode->i_uid, &inode->i_gid); | ||
112 | |||
113 | if (S_ISLNK(inode->i_mode)) { | ||
114 | unsigned i_mode = S_IFLNK; | ||
115 | if (f_mode & FMODE_READ) | ||
116 | i_mode |= S_IRUSR | S_IXUSR; | ||
117 | if (f_mode & FMODE_WRITE) | ||
118 | i_mode |= S_IWUSR | S_IXUSR; | ||
119 | inode->i_mode = i_mode; | ||
120 | } | ||
121 | |||
122 | security_task_to_inode(task, inode); | ||
123 | put_task_struct(task); | ||
124 | return 1; | ||
125 | } | 126 | } |
126 | rcu_read_unlock(); | 127 | security_task_to_inode(task, inode); |
127 | put_files_struct(files); | 128 | put_task_struct(task); |
129 | return 1; | ||
128 | } | 130 | } |
129 | put_task_struct(task); | 131 | put_task_struct(task); |
130 | } | 132 | } |
@@ -203,11 +205,14 @@ static struct dentry *proc_lookupfd_common(struct inode *dir, | |||
203 | struct task_struct *task = get_proc_task(dir); | 205 | struct task_struct *task = get_proc_task(dir); |
204 | int result = -ENOENT; | 206 | int result = -ENOENT; |
205 | unsigned fd = name_to_int(&dentry->d_name); | 207 | unsigned fd = name_to_int(&dentry->d_name); |
208 | fmode_t f_mode; | ||
206 | 209 | ||
207 | if (!task) | 210 | if (!task) |
208 | goto out_no_task; | 211 | goto out_no_task; |
209 | if (fd == ~0U) | 212 | if (fd == ~0U) |
210 | goto out; | 213 | goto out; |
214 | if (!tid_fd_mode(task, fd, &f_mode)) | ||
215 | goto out; | ||
211 | 216 | ||
212 | result = instantiate(dir, dentry, task, (void *)(unsigned long)fd); | 217 | result = instantiate(dir, dentry, task, (void *)(unsigned long)fd); |
213 | out: | 218 | out: |