diff options
-rw-r--r-- | fs/proc/base.c | 43 |
1 files changed, 14 insertions, 29 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index 1c8b280146d7..7d6ad98631f2 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, |