Patchwork [hardy,CVE,1/1] close races in /proc/*/{environ,auxv}, CVE-2011-1020

login
register
mail settings
Submitter Andy Whitcroft
Date July 21, 2011, 1:13 p.m.
Message ID <1311254026-29719-2-git-send-email-apw@canonical.com>
Download mbox | patch
Permalink /patch/106044/
State New
Headers show

Comments

Andy Whitcroft - July 21, 2011, 1:13 p.m.
Equivalent to:
	commit ec6fd8a4355cda81cd9f06bebc048e83eb514ac7
	commit d6f64b89d7ff22ce05896ab4a93a653e8d0b123d
	commit 2fadaef41283aad7100fa73f01998cddaca25833

Note that the locking is looser than that in upstream this may leaves
a small window which may be exploitable, that said the locks which are
used to ensure there is no window are not in existance back in hardy.
Indeed the races in exec which they are introduced to fix are also present.

CVE-2011-1020
BugLink: http://bugs.launchpad.net/bugs/813026
Signed-off-by: Andy Whitcroft <apw@canonical.com>
---
 fs/proc/base.c |   25 ++++++++++++++++++++-----
 1 files changed, 20 insertions(+), 5 deletions(-)
Tim Gardner - July 21, 2011, 5:50 p.m.
On 07/21/2011 06:13 AM, Andy Whitcroft wrote:
> Equivalent to:
> 	commit ec6fd8a4355cda81cd9f06bebc048e83eb514ac7
> 	commit d6f64b89d7ff22ce05896ab4a93a653e8d0b123d
> 	commit 2fadaef41283aad7100fa73f01998cddaca25833
>
> Note that the locking is looser than that in upstream this may leaves
> a small window which may be exploitable, that said the locks which are
> used to ensure there is no window are not in existance back in hardy.
> Indeed the races in exec which they are introduced to fix are also present.
>
> CVE-2011-1020
> BugLink: http://bugs.launchpad.net/bugs/813026
> Signed-off-by: Andy Whitcroft<apw@canonical.com>
> ---
>   fs/proc/base.c |   25 ++++++++++++++++++++-----
>   1 files changed, 20 insertions(+), 5 deletions(-)
>
> diff --git a/fs/proc/base.c b/fs/proc/base.c
> index 338097a..a68a4ba 100644
> --- a/fs/proc/base.c
> +++ b/fs/proc/base.c
> @@ -222,6 +222,24 @@ out:
>   	return NULL;
>   }
>
> +struct mm_struct *mm_for_maps2(struct task_struct *task)
> +{
> +	struct mm_struct *mm = get_task_mm(task);
> +	if (!mm)
> +		return NULL;
> +	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);
> +	mmput(mm);
> +	return NULL;
> +}
> +
>   static int proc_pid_cmdline(struct task_struct *task, char * buffer)
>   {
>   	int res = 0;
> @@ -262,7 +280,7 @@ out:
>   static int proc_pid_auxv(struct task_struct *task, char *buffer)
>   {
>   	int res = 0;
> -	struct mm_struct *mm = get_task_mm(task);
> +	struct mm_struct *mm = mm_for_maps2(task);
>   	if (mm) {
>   		unsigned int nwords = 0;
>   		do
> @@ -827,9 +845,6 @@ static ssize_t environ_read(struct file *file, char __user *buf,
>   	if (!task)
>   		goto out_no_task;
>
> -	if (!ptrace_may_attach(task))
> -		goto out;
> -
>   	ret = -ENOMEM;
>   	page = (char *)__get_free_page(GFP_TEMPORARY);
>   	if (!page)
> @@ -837,7 +852,7 @@ static ssize_t environ_read(struct file *file, char __user *buf,
>
>   	ret = 0;
>
> -	mm = get_task_mm(task);
> +	mm = mm_for_maps2(task);
>   	if (!mm)
>   		goto out_free;
>

Patch

diff --git a/fs/proc/base.c b/fs/proc/base.c
index 338097a..a68a4ba 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -222,6 +222,24 @@  out:
 	return NULL;
 }
 
+struct mm_struct *mm_for_maps2(struct task_struct *task)
+{
+	struct mm_struct *mm = get_task_mm(task);
+	if (!mm)
+		return NULL;
+	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);
+	mmput(mm);
+	return NULL;
+}
+
 static int proc_pid_cmdline(struct task_struct *task, char * buffer)
 {
 	int res = 0;
@@ -262,7 +280,7 @@  out:
 static int proc_pid_auxv(struct task_struct *task, char *buffer)
 {
 	int res = 0;
-	struct mm_struct *mm = get_task_mm(task);
+	struct mm_struct *mm = mm_for_maps2(task);
 	if (mm) {
 		unsigned int nwords = 0;
 		do
@@ -827,9 +845,6 @@  static ssize_t environ_read(struct file *file, char __user *buf,
 	if (!task)
 		goto out_no_task;
 
-	if (!ptrace_may_attach(task))
-		goto out;
-
 	ret = -ENOMEM;
 	page = (char *)__get_free_page(GFP_TEMPORARY);
 	if (!page)
@@ -837,7 +852,7 @@  static ssize_t environ_read(struct file *file, char __user *buf,
 
 	ret = 0;
 
-	mm = get_task_mm(task);
+	mm = mm_for_maps2(task);
 	if (!mm)
 		goto out_free;