LKML Archive on lore.kernel.org
 help / Atom feed
* [PATCH] posix-timers: Protect posix clock array access against speculation
@ 2018-02-15 13:27 Thomas Gleixner
  2018-02-15 14:05 ` Rasmus Villemoes
  0 siblings, 1 reply; 13+ messages in thread
From: Thomas Gleixner @ 2018-02-15 13:27 UTC (permalink / raw)
  To: LKML; +Cc: Ingo Molnar, Linus Torvalds, David Woodhouse, Dan Williams, Greg KH

The (clock) id argument of clockid_to_kclock() comes straight from user
space via various syscalls and is used as index into the posix_clocks
array.

Protect it against spectre v1 array out of bounds speculation.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: stable@vger.kernel.org
---
 kernel/time/posix-timers.c |    6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -50,6 +50,7 @@
 #include <linux/export.h>
 #include <linux/hashtable.h>
 #include <linux/compat.h>
+#include <linux/nospec.h>
 
 #include "timekeeping.h"
 #include "posix-timers.h"
@@ -1346,11 +1347,14 @@ static const struct k_clock * const posi
 
 static const struct k_clock *clockid_to_kclock(const clockid_t id)
 {
+	clockid_t idx = id;
+
 	if (id < 0)
 		return (id & CLOCKFD_MASK) == CLOCKFD ?
 			&clock_posix_dynamic : &clock_posix_cpu;
 
 	if (id >= ARRAY_SIZE(posix_clocks) || !posix_clocks[id])
 		return NULL;
-	return posix_clocks[id];
+
+	return posix_clocks[array_index_nospec(idx, ARRAY_SIZE(posix_clocks))];
 }

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

* Re: [PATCH] posix-timers: Protect posix clock array access against speculation
  2018-02-15 13:27 [PATCH] posix-timers: Protect posix clock array access against speculation Thomas Gleixner
@ 2018-02-15 14:05 ` Rasmus Villemoes
  2018-02-15 14:39   ` Dan Williams
  0 siblings, 1 reply; 13+ messages in thread
From: Rasmus Villemoes @ 2018-02-15 14:05 UTC (permalink / raw)
  To: Thomas Gleixner, LKML
  Cc: Ingo Molnar, Linus Torvalds, David Woodhouse, Dan Williams, Greg KH

On 2018-02-15 14:27, Thomas Gleixner wrote:
> The (clock) id argument of clockid_to_kclock() comes straight from user
> space via various syscalls and is used as index into the posix_clocks
> array.
> 
> Protect it against spectre v1 array out of bounds speculation.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: stable@vger.kernel.org
> ---
>  kernel/time/posix-timers.c |    6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> --- a/kernel/time/posix-timers.c
> +++ b/kernel/time/posix-timers.c
> @@ -50,6 +50,7 @@
>  #include <linux/export.h>
>  #include <linux/hashtable.h>
>  #include <linux/compat.h>
> +#include <linux/nospec.h>
>  
>  #include "timekeeping.h"
>  #include "posix-timers.h"
> @@ -1346,11 +1347,14 @@ static const struct k_clock * const posi
>  
>  static const struct k_clock *clockid_to_kclock(const clockid_t id)
>  {
> +	clockid_t idx = id;
> +
>  	if (id < 0)
>  		return (id & CLOCKFD_MASK) == CLOCKFD ?
>  			&clock_posix_dynamic : &clock_posix_cpu;
>  
>  	if (id >= ARRAY_SIZE(posix_clocks) || !posix_clocks[id])
>  		return NULL;
> -	return posix_clocks[id];
> +
> +	return posix_clocks[array_index_nospec(idx, ARRAY_SIZE(posix_clocks))];
>  }
> 

Stupid questions from someone trying to learn what the rules for when
and how to apply these _nospec macros:

(1) why introduce the idx var? There's no assignment to it other than
the initialization. Is it some magic in array_index_nospec that prevents
the use of a const-qualified expression?

(2) The line "if (id >= ARRAY_SIZE(posix_clocks) || !posix_clocks[id])"
still seems to allow speculatively accessing posix_clocks[id]. Is that
ok, and even if so, wouldn't it be cleaner to elide the
!posix_clocks[id] check and just return the NULL safely fetched from the
array in the following line?

Rasmus

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

* Re: [PATCH] posix-timers: Protect posix clock array access against speculation
  2018-02-15 14:05 ` Rasmus Villemoes
@ 2018-02-15 14:39   ` Dan Williams
  2018-02-15 14:53     ` Thomas Gleixner
  2018-02-15 19:52     ` [PATCH] linux/nospec.h: allow index argument to have const-qualified type Rasmus Villemoes
  0 siblings, 2 replies; 13+ messages in thread
From: Dan Williams @ 2018-02-15 14:39 UTC (permalink / raw)
  To: Rasmus Villemoes
  Cc: Thomas Gleixner, LKML, Ingo Molnar, Linus Torvalds,
	David Woodhouse, Greg KH

On Thu, Feb 15, 2018 at 6:05 AM, Rasmus Villemoes
<rasmus.villemoes@prevas.dk> wrote:
> On 2018-02-15 14:27, Thomas Gleixner wrote:
>> The (clock) id argument of clockid_to_kclock() comes straight from user
>> space via various syscalls and is used as index into the posix_clocks
>> array.
>>
>> Protect it against spectre v1 array out of bounds speculation.
>>
>> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
>> Cc: stable@vger.kernel.org
>> ---
>>  kernel/time/posix-timers.c |    6 +++++-
>>  1 file changed, 5 insertions(+), 1 deletion(-)
>>
>> --- a/kernel/time/posix-timers.c
>> +++ b/kernel/time/posix-timers.c
>> @@ -50,6 +50,7 @@
>>  #include <linux/export.h>
>>  #include <linux/hashtable.h>
>>  #include <linux/compat.h>
>> +#include <linux/nospec.h>
>>
>>  #include "timekeeping.h"
>>  #include "posix-timers.h"
>> @@ -1346,11 +1347,14 @@ static const struct k_clock * const posi
>>
>>  static const struct k_clock *clockid_to_kclock(const clockid_t id)
>>  {
>> +     clockid_t idx = id;
>> +
>>       if (id < 0)
>>               return (id & CLOCKFD_MASK) == CLOCKFD ?
>>                       &clock_posix_dynamic : &clock_posix_cpu;
>>
>>       if (id >= ARRAY_SIZE(posix_clocks) || !posix_clocks[id])
>>               return NULL;
>> -     return posix_clocks[id];
>> +
>> +     return posix_clocks[array_index_nospec(idx, ARRAY_SIZE(posix_clocks))];
>>  }
>>
>
> Stupid questions from someone trying to learn what the rules for when
> and how to apply these _nospec macros:
>
> (1) why introduce the idx var? There's no assignment to it other than
> the initialization. Is it some magic in array_index_nospec that prevents
> the use of a const-qualified expression?

It does currently, but perhaps it can be fixed.

>
> (2) The line "if (id >= ARRAY_SIZE(posix_clocks) || !posix_clocks[id])"
> still seems to allow speculatively accessing posix_clocks[id]. Is that
> ok, and even if so, wouldn't it be cleaner to elide the
> !posix_clocks[id] check and just return the NULL safely fetched from the
> array in the following line?

Right, this looks broken. I would expect:

        if (id >= ARRAY_SIZE(posix_clocks))
                return NULL;
        idx = array_index_nospec(idx, ARRAY_SIZE(posix_clocks));
        if (!posix_clocks[idx])
                return NULL;
        return posix_clocks[idx];

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

* Re: [PATCH] posix-timers: Protect posix clock array access against speculation
  2018-02-15 14:39   ` Dan Williams
@ 2018-02-15 14:53     ` Thomas Gleixner
  2018-02-15 16:21       ` [PATCH V2] " Thomas Gleixner
  2018-02-15 19:52     ` [PATCH] linux/nospec.h: allow index argument to have const-qualified type Rasmus Villemoes
  1 sibling, 1 reply; 13+ messages in thread
From: Thomas Gleixner @ 2018-02-15 14:53 UTC (permalink / raw)
  To: Dan Williams
  Cc: Rasmus Villemoes, LKML, Ingo Molnar, Linus Torvalds,
	David Woodhouse, Greg KH

On Thu, 15 Feb 2018, Dan Williams wrote:
> On Thu, Feb 15, 2018 at 6:05 AM, Rasmus Villemoes
> <rasmus.villemoes@prevas.dk> wrote:
> > (2) The line "if (id >= ARRAY_SIZE(posix_clocks) || !posix_clocks[id])"
> > still seems to allow speculatively accessing posix_clocks[id]. Is that
> > ok, and even if so, wouldn't it be cleaner to elide the
> > !posix_clocks[id] check and just return the NULL safely fetched from the
> > array in the following line?
> 
> Right, this looks broken. I would expect:

Indeed. Missed that.

>         if (id >= ARRAY_SIZE(posix_clocks))
>                 return NULL;
>         idx = array_index_nospec(idx, ARRAY_SIZE(posix_clocks));
>         if (!posix_clocks[idx])
>                 return NULL;
>         return posix_clocks[idx];

The !posix_clocks[idx] check is pointless and always was.

	if (id >= ARRAY_SIZE(posix_clocks))
		return NULL;

	idx = array_index_nospec(idx, ARRAY_SIZE(posix_clocks));
	return posix_clocks[idx];

is sufficient. It returns NULL for !posix_clocks[idx] anyway.

Thanks,

	tglx

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

* [PATCH V2] posix-timers: Protect posix clock array access against speculation
  2018-02-15 14:53     ` Thomas Gleixner
@ 2018-02-15 16:21       ` " Thomas Gleixner
  2018-02-15 17:01         ` Peter Zijlstra
  2018-03-22 11:34         ` [tip:timers/urgent] " tip-bot for Thomas Gleixner
  0 siblings, 2 replies; 13+ messages in thread
From: Thomas Gleixner @ 2018-02-15 16:21 UTC (permalink / raw)
  To: Dan Williams
  Cc: Rasmus Villemoes, LKML, Ingo Molnar, Linus Torvalds,
	David Woodhouse, Greg KH, Peter Zijlstra

The clockid argument of clockid_to_kclock() comes straight from user space
via various syscalls and is used as index into the posix_clocks array.

Protect it against spectre v1 array out of bounds speculation. Remove the
redundant check for !posix_clock[id] as this is another source for
speculation and does not provide any advantage over the return
posix_clock[id] path which returns NULL in that case anyway.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: stable@vger.kernel.org
---

V2: Remove the redundant !posix_clocks[id] check.

 kernel/time/posix-timers.c |   11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -50,6 +50,7 @@
 #include <linux/export.h>
 #include <linux/hashtable.h>
 #include <linux/compat.h>
+#include <linux/nospec.h>
 
 #include "timekeeping.h"
 #include "posix-timers.h"
@@ -1346,11 +1347,15 @@ static const struct k_clock * const posi
 
 static const struct k_clock *clockid_to_kclock(const clockid_t id)
 {
-	if (id < 0)
+	clockid_t idx = id;
+
+	if (id < 0) {
 		return (id & CLOCKFD_MASK) == CLOCKFD ?
 			&clock_posix_dynamic : &clock_posix_cpu;
+	}
 
-	if (id >= ARRAY_SIZE(posix_clocks) || !posix_clocks[id])
+	if (id >= ARRAY_SIZE(posix_clocks))
 		return NULL;
-	return posix_clocks[id];
+
+	return posix_clocks[array_index_nospec(idx, ARRAY_SIZE(posix_clocks))];
 }

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

* Re: [PATCH V2] posix-timers: Protect posix clock array access against speculation
  2018-02-15 16:21       ` [PATCH V2] " Thomas Gleixner
@ 2018-02-15 17:01         ` Peter Zijlstra
  2018-03-07 18:13           ` Dan Williams
  2018-03-22 11:34         ` [tip:timers/urgent] " tip-bot for Thomas Gleixner
  1 sibling, 1 reply; 13+ messages in thread
From: Peter Zijlstra @ 2018-02-15 17:01 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Dan Williams, Rasmus Villemoes, LKML, Ingo Molnar,
	Linus Torvalds, David Woodhouse, Greg KH

On Thu, Feb 15, 2018 at 05:21:55PM +0100, Thomas Gleixner wrote:
> The clockid argument of clockid_to_kclock() comes straight from user space
> via various syscalls and is used as index into the posix_clocks array.
> 
> Protect it against spectre v1 array out of bounds speculation. Remove the
> redundant check for !posix_clock[id] as this is another source for
> speculation and does not provide any advantage over the return
> posix_clock[id] path which returns NULL in that case anyway.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: stable@vger.kernel.org

Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>

It might also be useful to figure out why the automation didn't flag
this one, its about as trivial as it gets.

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

* [PATCH] linux/nospec.h: allow index argument to have const-qualified type
  2018-02-15 14:39   ` Dan Williams
  2018-02-15 14:53     ` Thomas Gleixner
@ 2018-02-15 19:52     ` Rasmus Villemoes
  2018-02-15 20:59       ` Linus Torvalds
  1 sibling, 1 reply; 13+ messages in thread
From: Rasmus Villemoes @ 2018-02-15 19:52 UTC (permalink / raw)
  To: Thomas Gleixner, Dan Williams, Will Deacon, Ingo Molnar,
	Rasmus Villemoes
  Cc: Linus Torvalds, stable, linux-kernel

The last expression in a statement expression need not be a bare
variable, quoting gcc docs

  The last thing in the compound statement should be an expression
  followed by a semicolon; the value of this subexpression serves as the
  value of the entire construct.

and we already use that in e.g. the min/max macros which end with a
ternary expression.

This way, we can allow index to have const-qualified type, which will in
some cases avoid the need for introducing a local copy of index of
non-const qualified type. That, in turn, can prevent readers not
familiar with the internals of array_index_nospec from wondering about
the seemingly redundant extra variable, and I think that's worthwhile
considering how confusing the whole _nospec business is.

The expression _i&_mask has type unsigned long (since that is the type
of _mask, and the BUILD_BUG_ONs guarantee that _i will get promoted to
that), so in order not to change the type of the whole expression, add
a cast back to typeof(_i).

Cc: stable@vger.kernel.org
Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk>
---
cc stable because if this is ok, there will probably be future users
relying on this which also get cc'ed to -stable.

include/linux/nospec.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/include/linux/nospec.h b/include/linux/nospec.h
index fbc98e2c8228..132e3f5a2e0d 100644
--- a/include/linux/nospec.h
+++ b/include/linux/nospec.h
@@ -72,7 +72,6 @@ static inline unsigned long array_index_mask_nospec(unsigned long index,
 	BUILD_BUG_ON(sizeof(_i) > sizeof(long));			\
 	BUILD_BUG_ON(sizeof(_s) > sizeof(long));			\
 									\
-	_i &= _mask;							\
-	_i;								\
+	(typeof(_i)) (_i & _mask);					\
 })
 #endif /* _LINUX_NOSPEC_H */
-- 
2.15.1

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

* Re: [PATCH] linux/nospec.h: allow index argument to have const-qualified type
  2018-02-15 19:52     ` [PATCH] linux/nospec.h: allow index argument to have const-qualified type Rasmus Villemoes
@ 2018-02-15 20:59       ` Linus Torvalds
  2018-02-15 21:56         ` Dan Williams
  0 siblings, 1 reply; 13+ messages in thread
From: Linus Torvalds @ 2018-02-15 20:59 UTC (permalink / raw)
  To: Rasmus Villemoes
  Cc: Thomas Gleixner, Dan Williams, Will Deacon, Ingo Molnar, stable,
	Linux Kernel Mailing List

On Thu, Feb 15, 2018 at 11:52 AM, Rasmus Villemoes
<linux@rasmusvillemoes.dk> wrote:
>
> This way, we can allow index to have const-qualified type, which will in
> some cases avoid the need for introducing a local copy of index of
> non-const qualified type.

Ack.

That said, looking at this header file, I find a couple of of other issues..

 (a) we should just remove the array_index_mask_nospec_check() thing.

 (b) once fixed, there's no reason for that extra "_s" variable in
array_index_nospec()

That (a) thing causes horrible code generation, and is pointless and wrong.

The "wrong" part is because it wants about "index" being larger than
LONG_MAX, and that's really stupid and wrong, because by *definition*
we don't trust index and it came from user space. The whole point was
that array_index_nospec() would limit those things!

Yes, it's true that the compiler may optimize that warning away if the
type of 'index' is such that it cannot happen, but that doesn't make
the warning any more valid.

It is only the sign of *size* that can matter and be an issue.
HOWEVER, even then it's wrong, because if "size" is of a signed type,
the check in WARN_ONCE is pure garbage.

To make matters worse, that warning means that
array_index_mask_nospec_check() currently uses it's arguments twice.
It so happens that the only current use of that macro is ok with that,
because it's being extra careful, but it's *WRONG*. Macros that look
like functions should not use arguments twice.

So (a) is just wrong right now. It's better to just remove it.

A valid warning *might* be

    WARN_ONCE((long)(size) < 0, "array_index_mask only works for sizes
that fit in a positive long");

but honestly, it's just not worth the code generation pain.

             Linus

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

* Re: [PATCH] linux/nospec.h: allow index argument to have const-qualified type
  2018-02-15 20:59       ` Linus Torvalds
@ 2018-02-15 21:56         ` Dan Williams
  2018-02-15 22:03           ` Linus Torvalds
  0 siblings, 1 reply; 13+ messages in thread
From: Dan Williams @ 2018-02-15 21:56 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Rasmus Villemoes, Thomas Gleixner, Will Deacon, Ingo Molnar,
	stable, Linux Kernel Mailing List

On Thu, Feb 15, 2018 at 12:59 PM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
> On Thu, Feb 15, 2018 at 11:52 AM, Rasmus Villemoes
> <linux@rasmusvillemoes.dk> wrote:
>>
>> This way, we can allow index to have const-qualified type, which will in
>> some cases avoid the need for introducing a local copy of index of
>> non-const qualified type.
>
> Ack.
>
> That said, looking at this header file, I find a couple of of other issues..
>
>  (a) we should just remove the array_index_mask_nospec_check() thing.
>
>  (b) once fixed, there's no reason for that extra "_s" variable in
> array_index_nospec()
>
> That (a) thing causes horrible code generation, and is pointless and wrong.
>
> The "wrong" part is because it wants about "index" being larger than
> LONG_MAX, and that's really stupid and wrong, because by *definition*
> we don't trust index and it came from user space. The whole point was
> that array_index_nospec() would limit those things!
>
> Yes, it's true that the compiler may optimize that warning away if the
> type of 'index' is such that it cannot happen, but that doesn't make
> the warning any more valid.
>
> It is only the sign of *size* that can matter and be an issue.
> HOWEVER, even then it's wrong, because if "size" is of a signed type,
> the check in WARN_ONCE is pure garbage.
>
> To make matters worse, that warning means that
> array_index_mask_nospec_check() currently uses it's arguments twice.
> It so happens that the only current use of that macro is ok with that,
> because it's being extra careful, but it's *WRONG*. Macros that look
> like functions should not use arguments twice.

Yes, that piece is new and I should have noticed that breakage when I
reviewed that patch from Will.

>
> So (a) is just wrong right now. It's better to just remove it.
>
> A valid warning *might* be
>
>     WARN_ONCE((long)(size) < 0, "array_index_mask only works for sizes
> that fit in a positive long");
>
> but honestly, it's just not worth the code generation pain.

So I don't mind removing it, but I don't think it is garbage. It's
there purely as a notification to the odd kernel developer that wants
to pass "insane" index values, It compiles away in most cases because
all current users are sane and have indexes that are right sized. It
also used to be the case that it was only used when the arch did not
provide a custom array_index_mask_nospec(), but now that it is "on all
the time" I do think it is in the way.

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

* Re: [PATCH] linux/nospec.h: allow index argument to have const-qualified type
  2018-02-15 21:56         ` Dan Williams
@ 2018-02-15 22:03           ` Linus Torvalds
  2018-02-15 22:08             ` Dan Williams
  0 siblings, 1 reply; 13+ messages in thread
From: Linus Torvalds @ 2018-02-15 22:03 UTC (permalink / raw)
  To: Dan Williams
  Cc: Rasmus Villemoes, Thomas Gleixner, Will Deacon, Ingo Molnar,
	stable, Linux Kernel Mailing List

On Thu, Feb 15, 2018 at 1:56 PM, Dan Williams <dan.j.williams@intel.com> wrote:
>
> So I don't mind removing it, but I don't think it is garbage. It's
> there purely as a notification to the odd kernel developer that wants
> to pass "insane" index values,

But the thing is, the "index" value isn't even kernel-supplied.

Here's a test:  run a 32-bit kernel, and then do an ioctl() or
something with a negative fd.

What I think will happen is:

 - the negative fd will be seen as a big 'unsigned int' here:

        fcheck_files(struct files_struct *files, unsigned int fd)

which then does

                fd = array_index_nospec(fd, fdt->max_fds);

and that existing *STUPID* and *WRONG* WARN_ON() will trigger.

Sure, you can't trigger it on 64-bit kernels because there the
"unsigned int" will be small compared to LONG_MAX, but..

It is simply is *wrong* to check the "index".  It really fundamentally
is complete garbage.

Because the whole - and ONLY - *point* of this is that you have an
untrusted index. So checking it and giving a warning when it's out of
range is pure garbage.

Really. That warning must go away. Stop arguing for it, it's stupid and wrong.

Checking _size_ is one thing, but honestly, that's questionable too.

                  Linus

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

* Re: [PATCH] linux/nospec.h: allow index argument to have const-qualified type
  2018-02-15 22:03           ` Linus Torvalds
@ 2018-02-15 22:08             ` Dan Williams
  0 siblings, 0 replies; 13+ messages in thread
From: Dan Williams @ 2018-02-15 22:08 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Rasmus Villemoes, Thomas Gleixner, Will Deacon, Ingo Molnar,
	stable, Linux Kernel Mailing List

On Thu, Feb 15, 2018 at 2:03 PM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
> On Thu, Feb 15, 2018 at 1:56 PM, Dan Williams <dan.j.williams@intel.com> wrote:
>>
>> So I don't mind removing it, but I don't think it is garbage. It's
>> there purely as a notification to the odd kernel developer that wants
>> to pass "insane" index values,
>
> But the thing is, the "index" value isn't even kernel-supplied.
>
> Here's a test:  run a 32-bit kernel, and then do an ioctl() or
> something with a negative fd.
>
> What I think will happen is:
>
>  - the negative fd will be seen as a big 'unsigned int' here:
>
>         fcheck_files(struct files_struct *files, unsigned int fd)
>
> which then does
>
>                 fd = array_index_nospec(fd, fdt->max_fds);
>
> and that existing *STUPID* and *WRONG* WARN_ON() will trigger.
>
> Sure, you can't trigger it on 64-bit kernels because there the
> "unsigned int" will be small compared to LONG_MAX, but..
>
> It is simply is *wrong* to check the "index".  It really fundamentally
> is complete garbage.
>
> Because the whole - and ONLY - *point* of this is that you have an
> untrusted index. So checking it and giving a warning when it's out of
> range is pure garbage.
>
> Really. That warning must go away. Stop arguing for it, it's stupid and wrong.

True, I had been myopically focused on the 64-bit case.

> Checking _size_ is one thing, but honestly, that's questionable too.

Nah, I'm not going to argue for that.

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

* Re: [PATCH V2] posix-timers: Protect posix clock array access against speculation
  2018-02-15 17:01         ` Peter Zijlstra
@ 2018-03-07 18:13           ` Dan Williams
  0 siblings, 0 replies; 13+ messages in thread
From: Dan Williams @ 2018-03-07 18:13 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Thomas Gleixner, Rasmus Villemoes, LKML, Ingo Molnar,
	Linus Torvalds, David Woodhouse, Greg KH

On Thu, Feb 15, 2018 at 9:01 AM, Peter Zijlstra <peterz@infradead.org> wrote:
> On Thu, Feb 15, 2018 at 05:21:55PM +0100, Thomas Gleixner wrote:
>> The clockid argument of clockid_to_kclock() comes straight from user space
>> via various syscalls and is used as index into the posix_clocks array.
>>
>> Protect it against spectre v1 array out of bounds speculation. Remove the
>> redundant check for !posix_clock[id] as this is another source for
>> speculation and does not provide any advantage over the return
>> posix_clock[id] path which returns NULL in that case anyway.
>>
>> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
>> Cc: stable@vger.kernel.org
>
> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
>

Curious where this ended up, I don't see it on tip/master. In any event:

Acked-by: Dan Williams <dan.j.williams@intel.com>

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

* [tip:timers/urgent] posix-timers: Protect posix clock array access against speculation
  2018-02-15 16:21       ` [PATCH V2] " Thomas Gleixner
  2018-02-15 17:01         ` Peter Zijlstra
@ 2018-03-22 11:34         ` " tip-bot for Thomas Gleixner
  1 sibling, 0 replies; 13+ messages in thread
From: tip-bot for Thomas Gleixner @ 2018-03-22 11:34 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: dwmw, linux-kernel, mingo, peterz, rasmus.villemoes,
	dan.j.williams, torvalds, tglx, gregkh, hpa

Commit-ID:  19b558db12f9f4e45a22012bae7b4783e62224da
Gitweb:     https://git.kernel.org/tip/19b558db12f9f4e45a22012bae7b4783e62224da
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Thu, 15 Feb 2018 17:21:55 +0100
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Thu, 22 Mar 2018 12:29:27 +0100

posix-timers: Protect posix clock array access against speculation

The clockid argument of clockid_to_kclock() comes straight from user space
via various syscalls and is used as index into the posix_clocks array.

Protect it against spectre v1 array out of bounds speculation. Remove the
redundant check for !posix_clock[id] as this is another source for
speculation and does not provide any advantage over the return
posix_clock[id] path which returns NULL in that case anyway.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Dan Williams <dan.j.williams@intel.com>
Cc: Rasmus Villemoes <rasmus.villemoes@prevas.dk>
Cc: Greg KH <gregkh@linuxfoundation.org>
Cc: stable@vger.kernel.org
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: David Woodhouse <dwmw@amazon.co.uk>
Link: https://lkml.kernel.org/r/alpine.DEB.2.21.1802151718320.1296@nanos.tec.linutronix.de

---
 kernel/time/posix-timers.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index 75043046914e..10b7186d0638 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -50,6 +50,7 @@
 #include <linux/export.h>
 #include <linux/hashtable.h>
 #include <linux/compat.h>
+#include <linux/nospec.h>
 
 #include "timekeeping.h"
 #include "posix-timers.h"
@@ -1346,11 +1347,15 @@ static const struct k_clock * const posix_clocks[] = {
 
 static const struct k_clock *clockid_to_kclock(const clockid_t id)
 {
-	if (id < 0)
+	clockid_t idx = id;
+
+	if (id < 0) {
 		return (id & CLOCKFD_MASK) == CLOCKFD ?
 			&clock_posix_dynamic : &clock_posix_cpu;
+	}
 
-	if (id >= ARRAY_SIZE(posix_clocks) || !posix_clocks[id])
+	if (id >= ARRAY_SIZE(posix_clocks))
 		return NULL;
-	return posix_clocks[id];
+
+	return posix_clocks[array_index_nospec(idx, ARRAY_SIZE(posix_clocks))];
 }

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

end of thread, back to index

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-15 13:27 [PATCH] posix-timers: Protect posix clock array access against speculation Thomas Gleixner
2018-02-15 14:05 ` Rasmus Villemoes
2018-02-15 14:39   ` Dan Williams
2018-02-15 14:53     ` Thomas Gleixner
2018-02-15 16:21       ` [PATCH V2] " Thomas Gleixner
2018-02-15 17:01         ` Peter Zijlstra
2018-03-07 18:13           ` Dan Williams
2018-03-22 11:34         ` [tip:timers/urgent] " tip-bot for Thomas Gleixner
2018-02-15 19:52     ` [PATCH] linux/nospec.h: allow index argument to have const-qualified type Rasmus Villemoes
2018-02-15 20:59       ` Linus Torvalds
2018-02-15 21:56         ` Dan Williams
2018-02-15 22:03           ` Linus Torvalds
2018-02-15 22:08             ` Dan Williams

LKML Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/lkml/0 lkml/git/0.git
	git clone --mirror https://lore.kernel.org/lkml/1 lkml/git/1.git
	git clone --mirror https://lore.kernel.org/lkml/2 lkml/git/2.git
	git clone --mirror https://lore.kernel.org/lkml/3 lkml/git/3.git
	git clone --mirror https://lore.kernel.org/lkml/4 lkml/git/4.git
	git clone --mirror https://lore.kernel.org/lkml/5 lkml/git/5.git
	git clone --mirror https://lore.kernel.org/lkml/6 lkml/git/6.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 lkml lkml/ https://lore.kernel.org/lkml \
		linux-kernel@vger.kernel.org linux-kernel@archiver.kernel.org
	public-inbox-index lkml


Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-kernel


AGPL code for this site: git clone https://public-inbox.org/ public-inbox