restrict reading from /proc/<pid>/maps to those who share ->mm or can ptrace pid
Contents of /proc/*/maps is sensitive and may become sensitive after open() (e.g. if target originally shares our ->mm and later does exec on suid-root binary). Check at read() (actually, ->start() of iterator) time that mm_struct we'd grabbed and locked is - still the ->mm of target - equal to reader's ->mm or the target is ptracable by reader. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Acked-by: Rik van Riel <riel@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
ac40532ef0
commit
831830b5a2
|
@ -202,6 +202,26 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf
|
|||
(task->state == TASK_STOPPED || task->state == TASK_TRACED) && \
|
||||
security_ptrace(current,task) == 0))
|
||||
|
||||
struct mm_struct *mm_for_maps(struct task_struct *task)
|
||||
{
|
||||
struct mm_struct *mm = get_task_mm(task);
|
||||
if (!mm)
|
||||
return NULL;
|
||||
down_read(&mm->mmap_sem);
|
||||
task_lock(task);
|
||||
if (task->mm != mm)
|
||||
goto out;
|
||||
if (task->mm != current->mm && __ptrace_may_attach(task) < 0)
|
||||
goto out;
|
||||
task_unlock(task);
|
||||
return mm;
|
||||
out:
|
||||
task_unlock(task);
|
||||
up_read(&mm->mmap_sem);
|
||||
mmput(mm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int proc_pid_cmdline(struct task_struct *task, char * buffer)
|
||||
{
|
||||
int res = 0;
|
||||
|
|
|
@ -27,6 +27,8 @@ struct vmalloc_info {
|
|||
unsigned long largest_chunk;
|
||||
};
|
||||
|
||||
extern struct mm_struct *mm_for_maps(struct task_struct *);
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
#define VMALLOC_TOTAL (VMALLOC_END - VMALLOC_START)
|
||||
extern void get_vmalloc_info(struct vmalloc_info *vmi);
|
||||
|
|
|
@ -397,12 +397,11 @@ static void *m_start(struct seq_file *m, loff_t *pos)
|
|||
if (!priv->task)
|
||||
return NULL;
|
||||
|
||||
mm = get_task_mm(priv->task);
|
||||
mm = mm_for_maps(priv->task);
|
||||
if (!mm)
|
||||
return NULL;
|
||||
|
||||
priv->tail_vma = tail_vma = get_gate_vma(priv->task);
|
||||
down_read(&mm->mmap_sem);
|
||||
|
||||
/* Start with last addr hint */
|
||||
if (last_addr && (vma = find_vma(mm, last_addr))) {
|
||||
|
|
|
@ -165,15 +165,13 @@ static void *m_start(struct seq_file *m, loff_t *pos)
|
|||
if (!priv->task)
|
||||
return NULL;
|
||||
|
||||
mm = get_task_mm(priv->task);
|
||||
mm = mm_for_maps(priv->task);
|
||||
if (!mm) {
|
||||
put_task_struct(priv->task);
|
||||
priv->task = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
down_read(&mm->mmap_sem);
|
||||
|
||||
/* start from the Nth VMA */
|
||||
for (vml = mm->context.vmlist; vml; vml = vml->next)
|
||||
if (n-- == 0)
|
||||
|
|
|
@ -97,6 +97,7 @@ extern void __ptrace_link(struct task_struct *child,
|
|||
extern void __ptrace_unlink(struct task_struct *child);
|
||||
extern void ptrace_untrace(struct task_struct *child);
|
||||
extern int ptrace_may_attach(struct task_struct *task);
|
||||
extern int __ptrace_may_attach(struct task_struct *task);
|
||||
|
||||
static inline void ptrace_link(struct task_struct *child,
|
||||
struct task_struct *new_parent)
|
||||
|
|
|
@ -120,7 +120,7 @@ int ptrace_check_attach(struct task_struct *child, int kill)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int may_attach(struct task_struct *task)
|
||||
int __ptrace_may_attach(struct task_struct *task)
|
||||
{
|
||||
/* May we inspect the given task?
|
||||
* This check is used both for attaching with ptrace
|
||||
|
@ -154,7 +154,7 @@ int ptrace_may_attach(struct task_struct *task)
|
|||
{
|
||||
int err;
|
||||
task_lock(task);
|
||||
err = may_attach(task);
|
||||
err = __ptrace_may_attach(task);
|
||||
task_unlock(task);
|
||||
return !err;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue