diff options
Diffstat (limited to 'fs/proc/base.c')
-rw-r--r-- | fs/proc/base.c | 63 |
1 files changed, 22 insertions, 41 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index 1c8b280146d7..57b8159f26f3 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -1799,10 +1799,15 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1799 | if (task) { | 1799 | if (task) { |
1800 | files = get_files_struct(task); | 1800 | files = get_files_struct(task); |
1801 | if (files) { | 1801 | if (files) { |
1802 | struct file *file; | ||
1802 | rcu_read_lock(); | 1803 | rcu_read_lock(); |
1803 | if (fcheck_files(files, fd)) { | 1804 | file = fcheck_files(files, fd); |
1805 | if (file) { | ||
1806 | unsigned i_mode, f_mode = file->f_mode; | ||
1807 | |||
1804 | rcu_read_unlock(); | 1808 | rcu_read_unlock(); |
1805 | put_files_struct(files); | 1809 | put_files_struct(files); |
1810 | |||
1806 | if (task_dumpable(task)) { | 1811 | if (task_dumpable(task)) { |
1807 | rcu_read_lock(); | 1812 | rcu_read_lock(); |
1808 | cred = __task_cred(task); | 1813 | cred = __task_cred(task); |
@@ -1813,7 +1818,14 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1813 | inode->i_uid = 0; | 1818 | inode->i_uid = 0; |
1814 | inode->i_gid = 0; | 1819 | inode->i_gid = 0; |
1815 | } | 1820 | } |
1816 | inode->i_mode &= ~(S_ISUID | S_ISGID); | 1821 | |
1822 | i_mode = S_IFLNK; | ||
1823 | if (f_mode & FMODE_READ) | ||
1824 | i_mode |= S_IRUSR | S_IXUSR; | ||
1825 | if (f_mode & FMODE_WRITE) | ||
1826 | i_mode |= S_IWUSR | S_IXUSR; | ||
1827 | inode->i_mode = i_mode; | ||
1828 | |||
1817 | security_task_to_inode(task, inode); | 1829 | security_task_to_inode(task, inode); |
1818 | put_task_struct(task); | 1830 | put_task_struct(task); |
1819 | return 1; | 1831 | return 1; |
@@ -1837,8 +1849,6 @@ static struct dentry *proc_fd_instantiate(struct inode *dir, | |||
1837 | struct dentry *dentry, struct task_struct *task, const void *ptr) | 1849 | struct dentry *dentry, struct task_struct *task, const void *ptr) |
1838 | { | 1850 | { |
1839 | unsigned fd = *(const unsigned *)ptr; | 1851 | unsigned fd = *(const unsigned *)ptr; |
1840 | struct file *file; | ||
1841 | struct files_struct *files; | ||
1842 | struct inode *inode; | 1852 | struct inode *inode; |
1843 | struct proc_inode *ei; | 1853 | struct proc_inode *ei; |
1844 | struct dentry *error = ERR_PTR(-ENOENT); | 1854 | struct dentry *error = ERR_PTR(-ENOENT); |
@@ -1848,25 +1858,6 @@ static struct dentry *proc_fd_instantiate(struct inode *dir, | |||
1848 | goto out; | 1858 | goto out; |
1849 | ei = PROC_I(inode); | 1859 | ei = PROC_I(inode); |
1850 | ei->fd = fd; | 1860 | ei->fd = fd; |
1851 | files = get_files_struct(task); | ||
1852 | if (!files) | ||
1853 | goto out_iput; | ||
1854 | inode->i_mode = S_IFLNK; | ||
1855 | |||
1856 | /* | ||
1857 | * We are not taking a ref to the file structure, so we must | ||
1858 | * hold ->file_lock. | ||
1859 | */ | ||
1860 | spin_lock(&files->file_lock); | ||
1861 | file = fcheck_files(files, fd); | ||
1862 | if (!file) | ||
1863 | goto out_unlock; | ||
1864 | if (file->f_mode & FMODE_READ) | ||
1865 | inode->i_mode |= S_IRUSR | S_IXUSR; | ||
1866 | if (file->f_mode & FMODE_WRITE) | ||
1867 | inode->i_mode |= S_IWUSR | S_IXUSR; | ||
1868 | spin_unlock(&files->file_lock); | ||
1869 | put_files_struct(files); | ||
1870 | 1861 | ||
1871 | inode->i_op = &proc_pid_link_inode_operations; | 1862 | inode->i_op = &proc_pid_link_inode_operations; |
1872 | inode->i_size = 64; | 1863 | inode->i_size = 64; |
@@ -1879,12 +1870,6 @@ static struct dentry *proc_fd_instantiate(struct inode *dir, | |||
1879 | 1870 | ||
1880 | out: | 1871 | out: |
1881 | return error; | 1872 | return error; |
1882 | out_unlock: | ||
1883 | spin_unlock(&files->file_lock); | ||
1884 | put_files_struct(files); | ||
1885 | out_iput: | ||
1886 | iput(inode); | ||
1887 | goto out; | ||
1888 | } | 1873 | } |
1889 | 1874 | ||
1890 | static struct dentry *proc_lookupfd_common(struct inode *dir, | 1875 | static struct dentry *proc_lookupfd_common(struct inode *dir, |
@@ -2177,16 +2162,16 @@ static struct dentry *proc_map_files_lookup(struct inode *dir, | |||
2177 | goto out; | 2162 | goto out; |
2178 | 2163 | ||
2179 | result = ERR_PTR(-EACCES); | 2164 | result = ERR_PTR(-EACCES); |
2180 | if (lock_trace(task)) | 2165 | if (!ptrace_may_access(task, PTRACE_MODE_READ)) |
2181 | goto out_put_task; | 2166 | goto out_put_task; |
2182 | 2167 | ||
2183 | result = ERR_PTR(-ENOENT); | 2168 | result = ERR_PTR(-ENOENT); |
2184 | if (dname_to_vma_addr(dentry, &vm_start, &vm_end)) | 2169 | if (dname_to_vma_addr(dentry, &vm_start, &vm_end)) |
2185 | goto out_unlock; | 2170 | goto out_put_task; |
2186 | 2171 | ||
2187 | mm = get_task_mm(task); | 2172 | mm = get_task_mm(task); |
2188 | if (!mm) | 2173 | if (!mm) |
2189 | goto out_unlock; | 2174 | goto out_put_task; |
2190 | 2175 | ||
2191 | down_read(&mm->mmap_sem); | 2176 | down_read(&mm->mmap_sem); |
2192 | vma = find_exact_vma(mm, vm_start, vm_end); | 2177 | vma = find_exact_vma(mm, vm_start, vm_end); |
@@ -2198,8 +2183,6 @@ static struct dentry *proc_map_files_lookup(struct inode *dir, | |||
2198 | out_no_vma: | 2183 | out_no_vma: |
2199 | up_read(&mm->mmap_sem); | 2184 | up_read(&mm->mmap_sem); |
2200 | mmput(mm); | 2185 | mmput(mm); |
2201 | out_unlock: | ||
2202 | unlock_trace(task); | ||
2203 | out_put_task: | 2186 | out_put_task: |
2204 | put_task_struct(task); | 2187 | put_task_struct(task); |
2205 | out: | 2188 | out: |
@@ -2233,7 +2216,7 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
2233 | goto out; | 2216 | goto out; |
2234 | 2217 | ||
2235 | ret = -EACCES; | 2218 | ret = -EACCES; |
2236 | if (lock_trace(task)) | 2219 | if (!ptrace_may_access(task, PTRACE_MODE_READ)) |
2237 | goto out_put_task; | 2220 | goto out_put_task; |
2238 | 2221 | ||
2239 | ret = 0; | 2222 | ret = 0; |
@@ -2241,12 +2224,12 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
2241 | case 0: | 2224 | case 0: |
2242 | ino = inode->i_ino; | 2225 | ino = inode->i_ino; |
2243 | if (filldir(dirent, ".", 1, 0, ino, DT_DIR) < 0) | 2226 | if (filldir(dirent, ".", 1, 0, ino, DT_DIR) < 0) |
2244 | goto out_unlock; | 2227 | goto out_put_task; |
2245 | filp->f_pos++; | 2228 | filp->f_pos++; |
2246 | case 1: | 2229 | case 1: |
2247 | ino = parent_ino(dentry); | 2230 | ino = parent_ino(dentry); |
2248 | if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0) | 2231 | if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0) |
2249 | goto out_unlock; | 2232 | goto out_put_task; |
2250 | filp->f_pos++; | 2233 | filp->f_pos++; |
2251 | default: | 2234 | default: |
2252 | { | 2235 | { |
@@ -2257,7 +2240,7 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
2257 | 2240 | ||
2258 | mm = get_task_mm(task); | 2241 | mm = get_task_mm(task); |
2259 | if (!mm) | 2242 | if (!mm) |
2260 | goto out_unlock; | 2243 | goto out_put_task; |
2261 | down_read(&mm->mmap_sem); | 2244 | down_read(&mm->mmap_sem); |
2262 | 2245 | ||
2263 | nr_files = 0; | 2246 | nr_files = 0; |
@@ -2287,7 +2270,7 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
2287 | flex_array_free(fa); | 2270 | flex_array_free(fa); |
2288 | up_read(&mm->mmap_sem); | 2271 | up_read(&mm->mmap_sem); |
2289 | mmput(mm); | 2272 | mmput(mm); |
2290 | goto out_unlock; | 2273 | goto out_put_task; |
2291 | } | 2274 | } |
2292 | for (i = 0, vma = mm->mmap, pos = 2; vma; | 2275 | for (i = 0, vma = mm->mmap, pos = 2; vma; |
2293 | vma = vma->vm_next) { | 2276 | vma = vma->vm_next) { |
@@ -2332,8 +2315,6 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
2332 | } | 2315 | } |
2333 | } | 2316 | } |
2334 | 2317 | ||
2335 | out_unlock: | ||
2336 | unlock_trace(task); | ||
2337 | out_put_task: | 2318 | out_put_task: |
2338 | put_task_struct(task); | 2319 | put_task_struct(task); |
2339 | out: | 2320 | out: |