linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] sched: fix a potential double-fetch bug in sched_copy_attr
@ 2018-12-25 22:16 Kangjie Lu
  2019-01-07 17:11 ` Peter Zijlstra
  0 siblings, 1 reply; 9+ messages in thread
From: Kangjie Lu @ 2018-12-25 22:16 UTC (permalink / raw)
  To: kjlu; +Cc: pakki001, Ingo Molnar, Peter Zijlstra, linux-kernel

"uattr->size" is copied in from user space and checked. However, it is
copied in again after the security check. A malicious user may race to
change it. The fix checks if uattr->size is ever changed after the
check.

Signed-off-by: Kangjie Lu <kjlu@umn.edu>
---
 kernel/sched/core.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 6fedf3a98581..0a55bdce9a42 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -4447,7 +4447,7 @@ do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param)
  */
 static int sched_copy_attr(struct sched_attr __user *uattr, struct sched_attr *attr)
 {
-	u32 size;
+	u32 size, size_cp;
 	int ret;
 
 	if (!access_ok(VERIFY_WRITE, uattr, SCHED_ATTR_SIZE_VER0))
@@ -4460,15 +4460,17 @@ static int sched_copy_attr(struct sched_attr __user *uattr, struct sched_attr *a
 	if (ret)
 		return ret;
 
+	size_cp = size;
+
 	/* Bail out on silly large: */
 	if (size > PAGE_SIZE)
 		goto err_size;
 
 	/* ABI compatibility quirk: */
 	if (!size)
-		size = SCHED_ATTR_SIZE_VER0;
+		size_cp = SCHED_ATTR_SIZE_VER0;
 
-	if (size < SCHED_ATTR_SIZE_VER0)
+	else if (size < SCHED_ATTR_SIZE_VER0)
 		goto err_size;
 
 	/*
@@ -4483,7 +4485,7 @@ static int sched_copy_attr(struct sched_attr __user *uattr, struct sched_attr *a
 		unsigned char val;
 
 		addr = (void __user *)uattr + sizeof(*attr);
-		end  = (void __user *)uattr + size;
+		end  = (void __user *)uattr + size_cp;
 
 		for (; addr < end; addr++) {
 			ret = get_user(val, addr);
@@ -4492,13 +4494,17 @@ static int sched_copy_attr(struct sched_attr __user *uattr, struct sched_attr *a
 			if (val)
 				goto err_size;
 		}
-		size = sizeof(*attr);
+		size_cp = sizeof(*attr);
 	}
 
-	ret = copy_from_user(attr, uattr, size);
+	ret = copy_from_user(attr, uattr, size_cp);
 	if (ret)
 		return -EFAULT;
 
+	/* Sanity check if size was changed in user space */
+	if (attr->size != size)
+		return -EINVAL;
+
 	/*
 	 * XXX: Do we want to be lenient like existing syscalls; or do we want
 	 * to be strict and return an error on out-of-bounds values?
-- 
2.17.2 (Apple Git-113)


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH] sched: fix a potential double-fetch bug in sched_copy_attr
  2018-12-25 22:16 [PATCH] sched: fix a potential double-fetch bug in sched_copy_attr Kangjie Lu
@ 2019-01-07 17:11 ` Peter Zijlstra
  2019-01-09  7:45   ` [PATCH v2] " Kangjie Lu
  0 siblings, 1 reply; 9+ messages in thread
From: Peter Zijlstra @ 2019-01-07 17:11 UTC (permalink / raw)
  To: Kangjie Lu; +Cc: pakki001, Ingo Molnar, linux-kernel

On Tue, Dec 25, 2018 at 04:16:47PM -0600, Kangjie Lu wrote:
> "uattr->size" is copied in from user space and checked. However, it is
> copied in again after the security check. A malicious user may race to
> change it. The fix checks if uattr->size is ever changed after the
> check.
> 
> Signed-off-by: Kangjie Lu <kjlu@umn.edu>
> ---

> +	/* Sanity check if size was changed in user space */
> +	if (attr->size != size)
> +		return -EINVAL;
> +

What perf_copy_attr() does (from whence we copied this code) is:

	attr->size = size;

Would that not also fix things?

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2] sched: fix a potential double-fetch bug in sched_copy_attr
  2019-01-07 17:11 ` Peter Zijlstra
@ 2019-01-09  7:45   ` Kangjie Lu
  2019-01-21 11:32     ` [tip:sched/core] sched/core: Fix a potential double-fetch bug in sched_copy_attr() tip-bot for Kangjie Lu
  0 siblings, 1 reply; 9+ messages in thread
From: Kangjie Lu @ 2019-01-09  7:45 UTC (permalink / raw)
  To: kjlu; +Cc: pakki001, Ingo Molnar, Peter Zijlstra, linux-kernel

"uattr->size" is copied in from user space and checked. However, it is
copied in again after the security check. A malicious user may race to
change it. The fix sets uattr->size to be the checked size.

Signed-off-by: Kangjie Lu <kjlu@umn.edu>
---
 kernel/sched/core.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 6fedf3a98581..e868cc25ac2a 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -4499,6 +4499,9 @@ static int sched_copy_attr(struct sched_attr __user *uattr, struct sched_attr *a
 	if (ret)
 		return -EFAULT;
 
+	/* In case attr->size was changed in the user space */
+	attr->size = size;
+
 	/*
 	 * XXX: Do we want to be lenient like existing syscalls; or do we want
 	 * to be strict and return an error on out-of-bounds values?
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [tip:sched/core] sched/core: Fix a potential double-fetch bug in sched_copy_attr()
  2019-01-09  7:45   ` [PATCH v2] " Kangjie Lu
@ 2019-01-21 11:32     ` tip-bot for Kangjie Lu
  2019-01-27 11:04       ` Thomas Gleixner
  0 siblings, 1 reply; 9+ messages in thread
From: tip-bot for Kangjie Lu @ 2019-01-21 11:32 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, peterz, torvalds, tglx, hpa, stable, mingo, kjlu

Commit-ID:  120e4e76857ddbc9268e1aa3f9de61a498e84618
Gitweb:     https://git.kernel.org/tip/120e4e76857ddbc9268e1aa3f9de61a498e84618
Author:     Kangjie Lu <kjlu@umn.edu>
AuthorDate: Wed, 9 Jan 2019 01:45:24 -0600
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Mon, 21 Jan 2019 11:26:17 +0100

sched/core: Fix a potential double-fetch bug in sched_copy_attr()

"uattr->size" is copied in from user space and checked. However, it is
copied in again after the security check. A malicious user may race to
change it. The fix sets uattr->size to be the checked size.

Signed-off-by: Kangjie Lu <kjlu@umn.edu>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: pakki001@umn.edu
Cc: <stable@vger.kernel.org>
Link: https://lkml.kernel.org/r/20190109074524.10176-1-kjlu@umn.edu
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 kernel/sched/core.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index a674c7db2f29..d4d3514c4fe9 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -4499,6 +4499,9 @@ static int sched_copy_attr(struct sched_attr __user *uattr, struct sched_attr *a
 	if (ret)
 		return -EFAULT;
 
+	/* In case attr->size was changed by user-space: */
+	attr->size = size;
+
 	/*
 	 * XXX: Do we want to be lenient like existing syscalls; or do we want
 	 * to be strict and return an error on out-of-bounds values?

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [tip:sched/core] sched/core: Fix a potential double-fetch bug in sched_copy_attr()
  2019-01-21 11:32     ` [tip:sched/core] sched/core: Fix a potential double-fetch bug in sched_copy_attr() tip-bot for Kangjie Lu
@ 2019-01-27 11:04       ` Thomas Gleixner
  2019-01-27 11:28         ` Ingo Molnar
  2019-01-28  7:58         ` Peter Zijlstra
  0 siblings, 2 replies; 9+ messages in thread
From: Thomas Gleixner @ 2019-01-27 11:04 UTC (permalink / raw)
  To: mingo, kjlu, hpa, stable, peterz, torvalds, linux-kernel
  Cc: linux-tip-commits

On Mon, 21 Jan 2019, tip-bot for Kangjie Lu wrote:
> Commit-ID:  120e4e76857ddbc9268e1aa3f9de61a498e84618
> Gitweb:     https://git.kernel.org/tip/120e4e76857ddbc9268e1aa3f9de61a498e84618
> Author:     Kangjie Lu <kjlu@umn.edu>
> AuthorDate: Wed, 9 Jan 2019 01:45:24 -0600
> Committer:  Ingo Molnar <mingo@kernel.org>
> CommitDate: Mon, 21 Jan 2019 11:26:17 +0100
> 
> sched/core: Fix a potential double-fetch bug in sched_copy_attr()
> 
> "uattr->size" is copied in from user space and checked. However, it is
> copied in again after the security check. A malicious user may race to
> change it. The fix sets uattr->size to be the checked size.
> 
> Signed-off-by: Kangjie Lu <kjlu@umn.edu>
> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> Cc: Linus Torvalds <torvalds@linux-foundation.org>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: pakki001@umn.edu
> Cc: <stable@vger.kernel.org>
> Link: https://lkml.kernel.org/r/20190109074524.10176-1-kjlu@umn.edu
> Signed-off-by: Ingo Molnar <mingo@kernel.org>
> ---
>  kernel/sched/core.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/kernel/sched/core.c b/kernel/sched/core.c
> index a674c7db2f29..d4d3514c4fe9 100644
> --- a/kernel/sched/core.c
> +++ b/kernel/sched/core.c
> @@ -4499,6 +4499,9 @@ static int sched_copy_attr(struct sched_attr __user *uattr, struct sched_attr *a
>  	if (ret)
>  		return -EFAULT;
>  
> +	/* In case attr->size was changed by user-space: */
> +	attr->size = size;
> +

Just when pondering to send that to Linus, I tried to write up a concise
summary for this which made me look at the patch.

If the size changed, then its clear that user space fiddled with the date
between the size fetch and the full copy from user. So why restoring the
size instead of doing the obvious:

   	 if (attr->size != size)
	 	return -ECRAP;

Hmm?

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [tip:sched/core] sched/core: Fix a potential double-fetch bug in sched_copy_attr()
  2019-01-27 11:04       ` Thomas Gleixner
@ 2019-01-27 11:28         ` Ingo Molnar
  2019-01-28  7:58         ` Peter Zijlstra
  1 sibling, 0 replies; 9+ messages in thread
From: Ingo Molnar @ 2019-01-27 11:28 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: kjlu, hpa, stable, peterz, torvalds, linux-kernel, linux-tip-commits


* Thomas Gleixner <tglx@linutronix.de> wrote:

> On Mon, 21 Jan 2019, tip-bot for Kangjie Lu wrote:
> > Commit-ID:  120e4e76857ddbc9268e1aa3f9de61a498e84618
> > Gitweb:     https://git.kernel.org/tip/120e4e76857ddbc9268e1aa3f9de61a498e84618
> > Author:     Kangjie Lu <kjlu@umn.edu>
> > AuthorDate: Wed, 9 Jan 2019 01:45:24 -0600
> > Committer:  Ingo Molnar <mingo@kernel.org>
> > CommitDate: Mon, 21 Jan 2019 11:26:17 +0100
> > 
> > sched/core: Fix a potential double-fetch bug in sched_copy_attr()
> > 
> > "uattr->size" is copied in from user space and checked. However, it is
> > copied in again after the security check. A malicious user may race to
> > change it. The fix sets uattr->size to be the checked size.
> > 
> > Signed-off-by: Kangjie Lu <kjlu@umn.edu>
> > Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> > Cc: Linus Torvalds <torvalds@linux-foundation.org>
> > Cc: Peter Zijlstra <peterz@infradead.org>
> > Cc: Thomas Gleixner <tglx@linutronix.de>
> > Cc: pakki001@umn.edu
> > Cc: <stable@vger.kernel.org>
> > Link: https://lkml.kernel.org/r/20190109074524.10176-1-kjlu@umn.edu
> > Signed-off-by: Ingo Molnar <mingo@kernel.org>
> > ---
> >  kernel/sched/core.c | 3 +++
> >  1 file changed, 3 insertions(+)
> > 
> > diff --git a/kernel/sched/core.c b/kernel/sched/core.c
> > index a674c7db2f29..d4d3514c4fe9 100644
> > --- a/kernel/sched/core.c
> > +++ b/kernel/sched/core.c
> > @@ -4499,6 +4499,9 @@ static int sched_copy_attr(struct sched_attr __user *uattr, struct sched_attr *a
> >  	if (ret)
> >  		return -EFAULT;
> >  
> > +	/* In case attr->size was changed by user-space: */
> > +	attr->size = size;
> > +
> 
> Just when pondering to send that to Linus, I tried to write up a concise
> summary for this which made me look at the patch.
> 
> If the size changed, then its clear that user space fiddled with the date
> between the size fetch and the full copy from user. So why restoring the
> size instead of doing the obvious:
> 
>    	 if (attr->size != size)
> 	 	return -ECRAP;
> 
> Hmm?

Yeah, indeed - and that's a much more reliable interface behavior in any 
case. It's probably also faster.

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [tip:sched/core] sched/core: Fix a potential double-fetch bug in sched_copy_attr()
  2019-01-27 11:04       ` Thomas Gleixner
  2019-01-27 11:28         ` Ingo Molnar
@ 2019-01-28  7:58         ` Peter Zijlstra
  2019-01-28 13:15           ` Thomas Gleixner
  1 sibling, 1 reply; 9+ messages in thread
From: Peter Zijlstra @ 2019-01-28  7:58 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: mingo, kjlu, hpa, stable, torvalds, linux-kernel, linux-tip-commits

On Sun, Jan 27, 2019 at 12:04:44PM +0100, Thomas Gleixner wrote:
> On Mon, 21 Jan 2019, tip-bot for Kangjie Lu wrote:
> > diff --git a/kernel/sched/core.c b/kernel/sched/core.c
> > index a674c7db2f29..d4d3514c4fe9 100644
> > --- a/kernel/sched/core.c
> > +++ b/kernel/sched/core.c
> > @@ -4499,6 +4499,9 @@ static int sched_copy_attr(struct sched_attr __user *uattr, struct sched_attr *a
> >  	if (ret)
> >  		return -EFAULT;
> >  
> > +	/* In case attr->size was changed by user-space: */
> > +	attr->size = size;
> > +
> 
> Just when pondering to send that to Linus, I tried to write up a concise
> summary for this which made me look at the patch.
> 
> If the size changed, then its clear that user space fiddled with the date
> between the size fetch and the full copy from user. So why restoring the
> size instead of doing the obvious:
> 
>    	 if (attr->size != size)
> 	 	return -ECRAP;
> 
> Hmm?

Sure; but if we do that we should also change perf_copy_attr() which has
the exact same thing.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [tip:sched/core] sched/core: Fix a potential double-fetch bug in sched_copy_attr()
  2019-01-28  7:58         ` Peter Zijlstra
@ 2019-01-28 13:15           ` Thomas Gleixner
  2019-03-10 10:09             ` Thomas Gleixner
  0 siblings, 1 reply; 9+ messages in thread
From: Thomas Gleixner @ 2019-01-28 13:15 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: mingo, kjlu, hpa, stable, torvalds, linux-kernel, linux-tip-commits

On Mon, 28 Jan 2019, Peter Zijlstra wrote:
> On Sun, Jan 27, 2019 at 12:04:44PM +0100, Thomas Gleixner wrote:
> > On Mon, 21 Jan 2019, tip-bot for Kangjie Lu wrote:
> > > diff --git a/kernel/sched/core.c b/kernel/sched/core.c
> > > index a674c7db2f29..d4d3514c4fe9 100644
> > > --- a/kernel/sched/core.c
> > > +++ b/kernel/sched/core.c
> > > @@ -4499,6 +4499,9 @@ static int sched_copy_attr(struct sched_attr __user *uattr, struct sched_attr *a
> > >  	if (ret)
> > >  		return -EFAULT;
> > >  
> > > +	/* In case attr->size was changed by user-space: */
> > > +	attr->size = size;
> > > +
> > 
> > Just when pondering to send that to Linus, I tried to write up a concise
> > summary for this which made me look at the patch.
> > 
> > If the size changed, then its clear that user space fiddled with the date
> > between the size fetch and the full copy from user. So why restoring the
> > size instead of doing the obvious:
> > 
> >    	 if (attr->size != size)
> > 	 	return -ECRAP;
> > 
> > Hmm?
> 
> Sure; but if we do that we should also change perf_copy_attr() which has
> the exact same thing.

Yes please.

The point is that by default the data passed to a function (and it does not
matter whether it's a syscall) by pointer is immutable. There is exactly
ONE syscall which is specifically designed to deal with mutable data and
that's a constant source of headache ....

Kangjie is right that all double fetch operations like the one in
sched_copy_attr() are prone to concurrent modification problems. But then
we really should say NO instead of silently trying to fix things up. I
personally would even kill the process immediately, no matter whether the
corruption is caused by malicious intent or by sheer stupidity.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [tip:sched/core] sched/core: Fix a potential double-fetch bug in sched_copy_attr()
  2019-01-28 13:15           ` Thomas Gleixner
@ 2019-03-10 10:09             ` Thomas Gleixner
  0 siblings, 0 replies; 9+ messages in thread
From: Thomas Gleixner @ 2019-03-10 10:09 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: mingo, kjlu, hpa, stable, torvalds, linux-kernel, linux-tip-commits

On Mon, 28 Jan 2019, Thomas Gleixner wrote:
> On Mon, 28 Jan 2019, Peter Zijlstra wrote:
> > On Sun, Jan 27, 2019 at 12:04:44PM +0100, Thomas Gleixner wrote:
> > > On Mon, 21 Jan 2019, tip-bot for Kangjie Lu wrote:
> > > > diff --git a/kernel/sched/core.c b/kernel/sched/core.c
> > > > index a674c7db2f29..d4d3514c4fe9 100644
> > > > --- a/kernel/sched/core.c
> > > > +++ b/kernel/sched/core.c
> > > > @@ -4499,6 +4499,9 @@ static int sched_copy_attr(struct sched_attr __user *uattr, struct sched_attr *a
> > > >  	if (ret)
> > > >  		return -EFAULT;
> > > >  
> > > > +	/* In case attr->size was changed by user-space: */
> > > > +	attr->size = size;
> > > > +
> > > 
> > > Just when pondering to send that to Linus, I tried to write up a concise
> > > summary for this which made me look at the patch.
> > > 
> > > If the size changed, then its clear that user space fiddled with the date
> > > between the size fetch and the full copy from user. So why restoring the
> > > size instead of doing the obvious:
> > > 
> > >    	 if (attr->size != size)
> > > 	 	return -ECRAP;
> > > 
> > > Hmm?
> > 
> > Sure; but if we do that we should also change perf_copy_attr() which has
> > the exact same thing.
> 
> Yes please.
> 
> The point is that by default the data passed to a function (and it does not
> matter whether it's a syscall) by pointer is immutable. There is exactly
> ONE syscall which is specifically designed to deal with mutable data and
> that's a constant source of headache ....
> 
> Kangjie is right that all double fetch operations like the one in
> sched_copy_attr() are prone to concurrent modification problems. But then
> we really should say NO instead of silently trying to fix things up. I
> personally would even kill the process immediately, no matter whether the
> corruption is caused by malicious intent or by sheer stupidity.

Just noticed that this fell through the cracks. Is anyone working on a fix
for this?

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2019-03-10 10:10 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-12-25 22:16 [PATCH] sched: fix a potential double-fetch bug in sched_copy_attr Kangjie Lu
2019-01-07 17:11 ` Peter Zijlstra
2019-01-09  7:45   ` [PATCH v2] " Kangjie Lu
2019-01-21 11:32     ` [tip:sched/core] sched/core: Fix a potential double-fetch bug in sched_copy_attr() tip-bot for Kangjie Lu
2019-01-27 11:04       ` Thomas Gleixner
2019-01-27 11:28         ` Ingo Molnar
2019-01-28  7:58         ` Peter Zijlstra
2019-01-28 13:15           ` Thomas Gleixner
2019-03-10 10:09             ` Thomas Gleixner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).