aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
authorCalvin Owens <calvinowens@fb.com>2015-09-09 18:35:54 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-09-10 16:29:01 -0400
commitbdb4d100afe9818aebd1d98ced575c5ef143456c (patch)
tree154a6d4360aac40ccb8ea815e464b4a3f9d6aab4 /fs/proc
parentd3691d2c6d3e72624c987bbef6f322631bbb2d5d (diff)
procfs: always expose /proc/<pid>/map_files/ and make it readable
Currently, /proc/<pid>/map_files/ is restricted to CAP_SYS_ADMIN, and is only exposed if CONFIG_CHECKPOINT_RESTORE is set. Each mapped file region gets a symlink in /proc/<pid>/map_files/ corresponding to the virtual address range at which it is mapped. The symlinks work like the symlinks in /proc/<pid>/fd/, so you can follow them to the backing file even if that backing file has been unlinked. Currently, files which are mapped, unlinked, and closed are impossible to stat() from userspace. Exposing /proc/<pid>/map_files/ closes this functionality "hole". Not being able to stat() such files makes noticing and explicitly accounting for the space they use on the filesystem impossible. You can work around this by summing up the space used by every file in the filesystem and subtracting that total from what statfs() tells you, but that obviously isn't great, and it becomes unworkable once your filesystem becomes large enough. This patch moves map_files/ out from behind CONFIG_CHECKPOINT_RESTORE, and adjusts the permissions enforced on it as follows: * proc_map_files_lookup() * proc_map_files_readdir() * map_files_d_revalidate() Remove the CAP_SYS_ADMIN restriction, leaving only the current restriction requiring PTRACE_MODE_READ. The information made available to userspace by these three functions is already available in /proc/PID/maps with MODE_READ, so I don't see any reason to limit them any further (see below for more detail). * proc_map_files_follow_link() This stub has been added, and requires that the user have CAP_SYS_ADMIN in order to follow the links in map_files/, since there was concern on LKML both about the potential for bypassing permissions on ancestor directories in the path to files pointed to, and about what happens with more exotic memory mappings created by some drivers (ie dma-buf). In older versions of this patch, I changed every permission check in the four functions above to enforce MODE_ATTACH instead of MODE_READ. This was an oversight on my part, and after revisiting the discussion it seems that nobody was concerned about anything outside of what is made possible by ->follow_link(). So in this version, I've left the checks for PTRACE_MODE_READ as-is. [akpm@linux-foundation.org: catch up with concurrent proc_pid_follow_link() changes] Signed-off-by: Calvin Owens <calvinowens@fb.com> Reviewed-by: Kees Cook <keescook@chromium.org> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Cyrill Gorcunov <gorcunov@openvz.org> Cc: Joe Perches <joe@perches.com> Cc: Kirill A. Shutemov <kirill@shutemov.name> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/base.c43
1 files changed, 24 insertions, 19 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index aa50d1ac28fc..60c71b10eaee 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1836,8 +1836,6 @@ end_instantiate:
1836 return dir_emit(ctx, name, len, 1, DT_UNKNOWN); 1836 return dir_emit(ctx, name, len, 1, DT_UNKNOWN);
1837} 1837}
1838 1838
1839#ifdef CONFIG_CHECKPOINT_RESTORE
1840
1841/* 1839/*
1842 * dname_to_vma_addr - maps a dentry name into two unsigned longs 1840 * dname_to_vma_addr - maps a dentry name into two unsigned longs
1843 * which represent vma start and end addresses. 1841 * which represent vma start and end addresses.
@@ -1864,11 +1862,6 @@ static int map_files_d_revalidate(struct dentry *dentry, unsigned int flags)
1864 if (flags & LOOKUP_RCU) 1862 if (flags & LOOKUP_RCU)
1865 return -ECHILD; 1863 return -ECHILD;
1866 1864
1867 if (!capable(CAP_SYS_ADMIN)) {
1868 status = -EPERM;
1869 goto out_notask;
1870 }
1871
1872 inode = d_inode(dentry); 1865 inode = d_inode(dentry);
1873 task = get_proc_task(inode); 1866 task = get_proc_task(inode);
1874 if (!task) 1867 if (!task)
@@ -1957,6 +1950,29 @@ struct map_files_info {
1957 unsigned char name[4*sizeof(long)+2]; /* max: %lx-%lx\0 */ 1950 unsigned char name[4*sizeof(long)+2]; /* max: %lx-%lx\0 */
1958}; 1951};
1959 1952
1953/*
1954 * Only allow CAP_SYS_ADMIN to follow the links, due to concerns about how the
1955 * symlinks may be used to bypass permissions on ancestor directories in the
1956 * path to the file in question.
1957 */
1958static const char *
1959proc_map_files_follow_link(struct dentry *dentry, void **cookie)
1960{
1961 if (!capable(CAP_SYS_ADMIN))
1962 return ERR_PTR(-EPERM);
1963
1964 return proc_pid_follow_link(dentry, NULL);
1965}
1966
1967/*
1968 * Identical to proc_pid_link_inode_operations except for follow_link()
1969 */
1970static const struct inode_operations proc_map_files_link_inode_operations = {
1971 .readlink = proc_pid_readlink,
1972 .follow_link = proc_map_files_follow_link,
1973 .setattr = proc_setattr,
1974};
1975
1960static int 1976static int
1961proc_map_files_instantiate(struct inode *dir, struct dentry *dentry, 1977proc_map_files_instantiate(struct inode *dir, struct dentry *dentry,
1962 struct task_struct *task, const void *ptr) 1978 struct task_struct *task, const void *ptr)
@@ -1972,7 +1988,7 @@ proc_map_files_instantiate(struct inode *dir, struct dentry *dentry,
1972 ei = PROC_I(inode); 1988 ei = PROC_I(inode);
1973 ei->op.proc_get_link = proc_map_files_get_link; 1989 ei->op.proc_get_link = proc_map_files_get_link;
1974 1990
1975 inode->i_op = &proc_pid_link_inode_operations; 1991 inode->i_op = &proc_map_files_link_inode_operations;
1976 inode->i_size = 64; 1992 inode->i_size = 64;
1977 inode->i_mode = S_IFLNK; 1993 inode->i_mode = S_IFLNK;
1978 1994
@@ -1996,10 +2012,6 @@ static struct dentry *proc_map_files_lookup(struct inode *dir,
1996 int result; 2012 int result;
1997 struct mm_struct *mm; 2013 struct mm_struct *mm;
1998 2014
1999 result = -EPERM;
2000 if (!capable(CAP_SYS_ADMIN))
2001 goto out;
2002
2003 result = -ENOENT; 2015 result = -ENOENT;
2004 task = get_proc_task(dir); 2016 task = get_proc_task(dir);
2005 if (!task) 2017 if (!task)
@@ -2053,10 +2065,6 @@ proc_map_files_readdir(struct file *file, struct dir_context *ctx)
2053 struct map_files_info *p; 2065 struct map_files_info *p;
2054 int ret; 2066 int ret;
2055 2067
2056 ret = -EPERM;
2057 if (!capable(CAP_SYS_ADMIN))
2058 goto out;
2059
2060 ret = -ENOENT; 2068 ret = -ENOENT;
2061 task = get_proc_task(file_inode(file)); 2069 task = get_proc_task(file_inode(file));
2062 if (!task) 2070 if (!task)
@@ -2245,7 +2253,6 @@ static const struct file_operations proc_timers_operations = {
2245 .llseek = seq_lseek, 2253 .llseek = seq_lseek,
2246 .release = seq_release_private, 2254 .release = seq_release_private,
2247}; 2255};
2248#endif /* CONFIG_CHECKPOINT_RESTORE */
2249 2256
2250static int proc_pident_instantiate(struct inode *dir, 2257static int proc_pident_instantiate(struct inode *dir,
2251 struct dentry *dentry, struct task_struct *task, const void *ptr) 2258 struct dentry *dentry, struct task_struct *task, const void *ptr)
@@ -2744,9 +2751,7 @@ static const struct inode_operations proc_task_inode_operations;
2744static const struct pid_entry tgid_base_stuff[] = { 2751static const struct pid_entry tgid_base_stuff[] = {
2745 DIR("task", S_IRUGO|S_IXUGO, proc_task_inode_operations, proc_task_operations), 2752 DIR("task", S_IRUGO|S_IXUGO, proc_task_inode_operations, proc_task_operations),
2746 DIR("fd", S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations), 2753 DIR("fd", S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations),
2747#ifdef CONFIG_CHECKPOINT_RESTORE
2748 DIR("map_files", S_IRUSR|S_IXUSR, proc_map_files_inode_operations, proc_map_files_operations), 2754 DIR("map_files", S_IRUSR|S_IXUSR, proc_map_files_inode_operations, proc_map_files_operations),
2749#endif
2750 DIR("fdinfo", S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fdinfo_operations), 2755 DIR("fdinfo", S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fdinfo_operations),
2751 DIR("ns", S_IRUSR|S_IXUGO, proc_ns_dir_inode_operations, proc_ns_dir_operations), 2756 DIR("ns", S_IRUSR|S_IXUGO, proc_ns_dir_inode_operations, proc_ns_dir_operations),
2752#ifdef CONFIG_NET 2757#ifdef CONFIG_NET