Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 831830b5 authored by Al Viro's avatar Al Viro Committed by Linus Torvalds
Browse files

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: default avatarAl Viro <viro@zeniv.linux.org.uk>
Acked-by: default avatarRik van Riel <riel@redhat.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent ac40532e
Loading
Loading
Loading
Loading
+20 −0
Original line number Original line Diff line number Diff line
@@ -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) && \
	 (task->state == TASK_STOPPED || task->state == TASK_TRACED) && \
	 security_ptrace(current,task) == 0))
	 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)
static int proc_pid_cmdline(struct task_struct *task, char * buffer)
{
{
	int res = 0;
	int res = 0;
+2 −0
Original line number Original line Diff line number Diff line
@@ -27,6 +27,8 @@ struct vmalloc_info {
	unsigned long	largest_chunk;
	unsigned long	largest_chunk;
};
};


extern struct mm_struct *mm_for_maps(struct task_struct *);

#ifdef CONFIG_MMU
#ifdef CONFIG_MMU
#define VMALLOC_TOTAL (VMALLOC_END - VMALLOC_START)
#define VMALLOC_TOTAL (VMALLOC_END - VMALLOC_START)
extern void get_vmalloc_info(struct vmalloc_info *vmi);
extern void get_vmalloc_info(struct vmalloc_info *vmi);
+1 −2
Original line number Original line Diff line number Diff line
@@ -397,12 +397,11 @@ static void *m_start(struct seq_file *m, loff_t *pos)
	if (!priv->task)
	if (!priv->task)
		return NULL;
		return NULL;


	mm = get_task_mm(priv->task);
	mm = mm_for_maps(priv->task);
	if (!mm)
	if (!mm)
		return NULL;
		return NULL;


	priv->tail_vma = tail_vma = get_gate_vma(priv->task);
	priv->tail_vma = tail_vma = get_gate_vma(priv->task);
	down_read(&mm->mmap_sem);


	/* Start with last addr hint */
	/* Start with last addr hint */
	if (last_addr && (vma = find_vma(mm, last_addr))) {
	if (last_addr && (vma = find_vma(mm, last_addr))) {
+1 −3
Original line number Original line Diff line number Diff line
@@ -165,15 +165,13 @@ static void *m_start(struct seq_file *m, loff_t *pos)
	if (!priv->task)
	if (!priv->task)
		return NULL;
		return NULL;


	mm = get_task_mm(priv->task);
	mm = mm_for_maps(priv->task);
	if (!mm) {
	if (!mm) {
		put_task_struct(priv->task);
		put_task_struct(priv->task);
		priv->task = NULL;
		priv->task = NULL;
		return NULL;
		return NULL;
	}
	}


	down_read(&mm->mmap_sem);

	/* start from the Nth VMA */
	/* start from the Nth VMA */
	for (vml = mm->context.vmlist; vml; vml = vml->next)
	for (vml = mm->context.vmlist; vml; vml = vml->next)
		if (n-- == 0)
		if (n-- == 0)
+1 −0
Original line number Original line Diff line number Diff line
@@ -97,6 +97,7 @@ extern void __ptrace_link(struct task_struct *child,
extern void __ptrace_unlink(struct task_struct *child);
extern void __ptrace_unlink(struct task_struct *child);
extern void ptrace_untrace(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);
extern int __ptrace_may_attach(struct task_struct *task);


static inline void ptrace_link(struct task_struct *child,
static inline void ptrace_link(struct task_struct *child,
			       struct task_struct *new_parent)
			       struct task_struct *new_parent)
Loading