Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

proc: move fd symlink i_mode calculations into tid_fd_revalidate()

Instead of doing the i_mode calculations at proc_fd_instantiate() time,
move them into tid_fd_revalidate(), which is where the other inode state
(notably uid/gid information) is updated too.

Otherwise we'll end up with stale i_mode information if an fd is re-used
while the dentry still hangs around. Not that anything really *cares*
(symlink permissions don't really matter), but Tetsuo Handa noticed that
the owner read/write bits don't always match the state of the
readability of the file descriptor, and we _used_ to get this right a
long time ago in a galaxy far, far away.

Besides, aside from fixing an ugly detail (that has apparently been this
way since commit 61a28784028e: "proc: Remove the hard coded inode
numbers" in 2006), this removes more lines of code than it adds. And it
just makes sense to update i_mode in the same place we update i_uid/gid.

Al Viro correctly points out that we could just do the inode fill in the
inode iops ->getattr() function instead. However, that does require
somewhat slightly more invasive changes, and adds yet *another* lookup
of the file descriptor. We need to do the revalidate() for other
reasons anyway, and have the file descriptor handy, so we might as well
fill in the information at this point.

Reported-by: Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Acked-by: Eric Biederman <ebiederm@xmission.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

+14 -29
+14 -29
fs/proc/base.c
··· 1799 1799 if (task) { 1800 1800 files = get_files_struct(task); 1801 1801 if (files) { 1802 + struct file *file; 1802 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 1808 rcu_read_unlock(); 1805 1809 put_files_struct(files); 1810 + 1806 1811 if (task_dumpable(task)) { 1807 1812 rcu_read_lock(); 1808 1813 cred = __task_cred(task); ··· 1818 1813 inode->i_uid = 0; 1819 1814 inode->i_gid = 0; 1820 1815 } 1821 - inode->i_mode &= ~(S_ISUID | S_ISGID); 1816 + 1817 + i_mode = S_IFLNK; 1818 + if (f_mode & FMODE_READ) 1819 + i_mode |= S_IRUSR | S_IXUSR; 1820 + if (f_mode & FMODE_WRITE) 1821 + i_mode |= S_IWUSR | S_IXUSR; 1822 + inode->i_mode = i_mode; 1823 + 1822 1824 security_task_to_inode(task, inode); 1823 1825 put_task_struct(task); 1824 1826 return 1; ··· 1849 1837 struct dentry *dentry, struct task_struct *task, const void *ptr) 1850 1838 { 1851 1839 unsigned fd = *(const unsigned *)ptr; 1852 - struct file *file; 1853 - struct files_struct *files; 1854 1840 struct inode *inode; 1855 1841 struct proc_inode *ei; 1856 1842 struct dentry *error = ERR_PTR(-ENOENT); ··· 1858 1848 goto out; 1859 1849 ei = PROC_I(inode); 1860 1850 ei->fd = fd; 1861 - files = get_files_struct(task); 1862 - if (!files) 1863 - goto out_iput; 1864 - inode->i_mode = S_IFLNK; 1865 - 1866 - /* 1867 - * We are not taking a ref to the file structure, so we must 1868 - * hold ->file_lock. 1869 - */ 1870 - spin_lock(&files->file_lock); 1871 - file = fcheck_files(files, fd); 1872 - if (!file) 1873 - goto out_unlock; 1874 - if (file->f_mode & FMODE_READ) 1875 - inode->i_mode |= S_IRUSR | S_IXUSR; 1876 - if (file->f_mode & FMODE_WRITE) 1877 - inode->i_mode |= S_IWUSR | S_IXUSR; 1878 - spin_unlock(&files->file_lock); 1879 - put_files_struct(files); 1880 1851 1881 1852 inode->i_op = &proc_pid_link_inode_operations; 1882 1853 inode->i_size = 64; ··· 1870 1879 1871 1880 out: 1872 1881 return error; 1873 - out_unlock: 1874 - spin_unlock(&files->file_lock); 1875 - put_files_struct(files); 1876 - out_iput: 1877 - iput(inode); 1878 - goto out; 1879 1882 } 1880 1883 1881 1884 static struct dentry *proc_lookupfd_common(struct inode *dir,