linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] x86/fpu/xstate: Clear uninitialized xstate areas in core dump
@ 2020-05-07 16:49 Yu-cheng Yu
  2020-05-07 16:52 ` Dave Hansen
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Yu-cheng Yu @ 2020-05-07 16:49 UTC (permalink / raw)
  To: linux-kernel, x86, H. Peter Anvin, Thomas Gleixner, Ingo Molnar,
	Dave Hansen, Tony Luck, Andy Lutomirski, Borislav Petkov,
	Rik van Riel, Ravi V. Shankar, Sebastian Andrzej Siewior,
	Fenghua Yu, Peter Zijlstra
  Cc: Yu-cheng Yu, sam, Kees Cook, Alexey Dobriyan, Dave Hansen,
	Jann Horn, Andrew Morton, Alexander Potapenko, Al Viro, stable

In a core dump, copy_xstate_to_kernel() copies only enabled user xfeatures
to a kernel buffer without touching areas for disabled xfeatures.  However,
those uninitialized areas may contain random data, which is then written to
the core dump file and can be read by a non-privileged user.

Fix it by clearing uninitialized areas.

Link: https://github.com/google/kmsan/issues/76
Link: https://lore.kernel.org/lkml/20200419100848.63472-1-glider@google.com/
Signed-off-by: Yu-cheng Yu <yu-cheng.yu@intel.com>
Reported-by: sam <sunhaoyl@outlook.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Dave Hansen <dave.hansen@intel.com>
Cc: Jann Horn <jannh@google.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Alexander Potapenko <glider@google.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: <stable@vger.kernel.org>
---
 arch/x86/kernel/fpu/xstate.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c
index 32b153d38748..0856daa29be7 100644
--- a/arch/x86/kernel/fpu/xstate.c
+++ b/arch/x86/kernel/fpu/xstate.c
@@ -983,6 +983,7 @@ int copy_xstate_to_kernel(void *kbuf, struct xregs_state *xsave, unsigned int of
 {
 	unsigned int offset, size;
 	struct xstate_header header;
+	int last_off;
 	int i;
 
 	/*
@@ -1006,7 +1007,17 @@ int copy_xstate_to_kernel(void *kbuf, struct xregs_state *xsave, unsigned int of
 
 	__copy_xstate_to_kernel(kbuf, &header, offset, size, size_total);
 
+	last_off = 0;
+
 	for (i = 0; i < XFEATURE_MAX; i++) {
+		/*
+		 * Clear uninitialized area before XSAVE header.
+		 */
+		if (i == FIRST_EXTENDED_XFEATURE) {
+			memset(kbuf + last_off, 0, XSAVE_HDR_OFFSET - last_off);
+			last_off = XSAVE_HDR_OFFSET + XSAVE_HDR_SIZE;
+		}
+
 		/*
 		 * Copy only in-use xstates:
 		 */
@@ -1020,11 +1031,16 @@ int copy_xstate_to_kernel(void *kbuf, struct xregs_state *xsave, unsigned int of
 			if (offset + size > size_total)
 				break;
 
+			memset(kbuf + last_off, 0, offset - last_off);
+			last_off = offset + size;
+
 			__copy_xstate_to_kernel(kbuf, src, offset, size, size_total);
 		}
 
 	}
 
+	memset(kbuf + last_off, 0, size_total - last_off);
+
 	if (xfeatures_mxcsr_quirk(header.xfeatures)) {
 		offset = offsetof(struct fxregs_state, mxcsr);
 		size = MXCSR_AND_FLAGS_SIZE;
-- 
2.21.0


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

* Re: [PATCH] x86/fpu/xstate: Clear uninitialized xstate areas in core dump
  2020-05-07 16:49 [PATCH] x86/fpu/xstate: Clear uninitialized xstate areas in core dump Yu-cheng Yu
@ 2020-05-07 16:52 ` Dave Hansen
  2020-05-07 17:12   ` Yu-cheng Yu
  2020-05-07 16:56 ` Sebastian Andrzej Siewior
  2020-05-07 18:22 ` Thomas Gleixner
  2 siblings, 1 reply; 7+ messages in thread
From: Dave Hansen @ 2020-05-07 16:52 UTC (permalink / raw)
  To: Yu-cheng Yu, linux-kernel, x86, H. Peter Anvin, Thomas Gleixner,
	Ingo Molnar, Dave Hansen, Tony Luck, Andy Lutomirski,
	Borislav Petkov, Rik van Riel, Ravi V. Shankar,
	Sebastian Andrzej Siewior, Fenghua Yu, Peter Zijlstra
  Cc: sam, Kees Cook, Alexey Dobriyan, Jann Horn, Andrew Morton,
	Alexander Potapenko, Al Viro, stable

On 5/7/20 9:49 AM, Yu-cheng Yu wrote:
> In a core dump, copy_xstate_to_kernel() copies only enabled user xfeatures
> to a kernel buffer without touching areas for disabled xfeatures.  However,
> those uninitialized areas may contain random data, which is then written to
> the core dump file and can be read by a non-privileged user.
> 
> Fix it by clearing uninitialized areas.

Do you have a Fixes: tag for this, or some background on where this
issue originated that might be helpful for backports?

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

* Re: [PATCH] x86/fpu/xstate: Clear uninitialized xstate areas in core dump
  2020-05-07 16:49 [PATCH] x86/fpu/xstate: Clear uninitialized xstate areas in core dump Yu-cheng Yu
  2020-05-07 16:52 ` Dave Hansen
@ 2020-05-07 16:56 ` Sebastian Andrzej Siewior
  2020-05-07 17:11   ` Yu-cheng Yu
  2020-05-07 18:22 ` Thomas Gleixner
  2 siblings, 1 reply; 7+ messages in thread
From: Sebastian Andrzej Siewior @ 2020-05-07 16:56 UTC (permalink / raw)
  To: Yu-cheng Yu
  Cc: linux-kernel, x86, H. Peter Anvin, Thomas Gleixner, Ingo Molnar,
	Dave Hansen, Tony Luck, Andy Lutomirski, Borislav Petkov,
	Rik van Riel, Ravi V. Shankar, Fenghua Yu, Peter Zijlstra, sam,
	Kees Cook, Alexey Dobriyan, Dave Hansen, Jann Horn,
	Andrew Morton, Alexander Potapenko, Al Viro, stable

On 2020-05-07 09:49:04 [-0700], Yu-cheng Yu wrote:
> In a core dump, copy_xstate_to_kernel() copies only enabled user xfeatures
> to a kernel buffer without touching areas for disabled xfeatures.  However,
> those uninitialized areas may contain random data, which is then written to
> the core dump file and can be read by a non-privileged user.
> 
> Fix it by clearing uninitialized areas.

Is the problem that copy_xstate_to_kernel() gets `kbuf' passed which
isn't zeroed? If so, would it work clean that upfront?

Sebastian

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

* Re: [PATCH] x86/fpu/xstate: Clear uninitialized xstate areas in core dump
  2020-05-07 16:56 ` Sebastian Andrzej Siewior
@ 2020-05-07 17:11   ` Yu-cheng Yu
  0 siblings, 0 replies; 7+ messages in thread
From: Yu-cheng Yu @ 2020-05-07 17:11 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-kernel, x86, H. Peter Anvin, Thomas Gleixner, Ingo Molnar,
	Dave Hansen, Tony Luck, Andy Lutomirski, Borislav Petkov,
	Rik van Riel, Ravi V. Shankar, Fenghua Yu, Peter Zijlstra, sam,
	Kees Cook, Alexey Dobriyan, Dave Hansen, Jann Horn,
	Andrew Morton, Alexander Potapenko, Al Viro, stable

On Thu, 2020-05-07 at 18:56 +0200, Sebastian Andrzej Siewior wrote:
> On 2020-05-07 09:49:04 [-0700], Yu-cheng Yu wrote:
> > In a core dump, copy_xstate_to_kernel() copies only enabled user xfeatures
> > to a kernel buffer without touching areas for disabled xfeatures.  However,
> > those uninitialized areas may contain random data, which is then written to
> > the core dump file and can be read by a non-privileged user.
> > 
> > Fix it by clearing uninitialized areas.
> 
> Is the problem that copy_xstate_to_kernel() gets `kbuf' passed which
> isn't zeroed? If so, would it work clean that upfront?

Alexander Potapenko's patch (in the Link:) fixes the buffer in
fill_thread_core_info().  My patch prevents the same issue if this function is
called from somewhere else in the future.

Yu-cheng


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

* Re: [PATCH] x86/fpu/xstate: Clear uninitialized xstate areas in core dump
  2020-05-07 16:52 ` Dave Hansen
@ 2020-05-07 17:12   ` Yu-cheng Yu
  0 siblings, 0 replies; 7+ messages in thread
From: Yu-cheng Yu @ 2020-05-07 17:12 UTC (permalink / raw)
  To: Dave Hansen, linux-kernel, x86, H. Peter Anvin, Thomas Gleixner,
	Ingo Molnar, Dave Hansen, Tony Luck, Andy Lutomirski,
	Borislav Petkov, Rik van Riel, Ravi V. Shankar,
	Sebastian Andrzej Siewior, Fenghua Yu, Peter Zijlstra
  Cc: sam, Kees Cook, Alexey Dobriyan, Jann Horn, Andrew Morton,
	Alexander Potapenko, Al Viro, stable

On Thu, 2020-05-07 at 09:52 -0700, Dave Hansen wrote:
> On 5/7/20 9:49 AM, Yu-cheng Yu wrote:
> > In a core dump, copy_xstate_to_kernel() copies only enabled user xfeatures
> > to a kernel buffer without touching areas for disabled xfeatures.  However,
> > those uninitialized areas may contain random data, which is then written to
> > the core dump file and can be read by a non-privileged user.
> > 
> > Fix it by clearing uninitialized areas.
> 
> Do you have a Fixes: tag for this, or some background on where this
> issue originated that might be helpful for backports?

I will add that.


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

* Re: [PATCH] x86/fpu/xstate: Clear uninitialized xstate areas in core dump
  2020-05-07 16:49 [PATCH] x86/fpu/xstate: Clear uninitialized xstate areas in core dump Yu-cheng Yu
  2020-05-07 16:52 ` Dave Hansen
  2020-05-07 16:56 ` Sebastian Andrzej Siewior
@ 2020-05-07 18:22 ` Thomas Gleixner
  2020-05-07 18:41   ` Yu-cheng Yu
  2 siblings, 1 reply; 7+ messages in thread
From: Thomas Gleixner @ 2020-05-07 18:22 UTC (permalink / raw)
  To: Yu-cheng Yu, linux-kernel, x86, H. Peter Anvin, Ingo Molnar,
	Dave Hansen, Tony Luck, Andy Lutomirski, Borislav Petkov,
	Rik van Riel, Ravi V. Shankar, Sebastian Andrzej Siewior,
	Fenghua Yu, Peter Zijlstra
  Cc: Yu-cheng Yu, sam, Kees Cook, Alexey Dobriyan, Dave Hansen,
	Jann Horn, Andrew Morton, Alexander Potapenko, Al Viro, stable

Yu-cheng Yu <yu-cheng.yu@intel.com> writes:
> @@ -983,6 +983,7 @@ int copy_xstate_to_kernel(void *kbuf, struct xregs_state *xsave, unsigned int of
>  {
>  	unsigned int offset, size;
>  	struct xstate_header header;
> +	int last_off;
>  	int i;
>  
>  	/*
> @@ -1006,7 +1007,17 @@ int copy_xstate_to_kernel(void *kbuf, struct xregs_state *xsave, unsigned int of
>  
>  	__copy_xstate_to_kernel(kbuf, &header, offset, size, size_total);
>  
> +	last_off = 0;
> +
>  	for (i = 0; i < XFEATURE_MAX; i++) {
> +		/*
> +		 * Clear uninitialized area before XSAVE header.
> +		 */
> +		if (i == FIRST_EXTENDED_XFEATURE) {
> +			memset(kbuf + last_off, 0, XSAVE_HDR_OFFSET - last_off);
> +			last_off = XSAVE_HDR_OFFSET + XSAVE_HDR_SIZE;
> +		}
> +
>  		/*
>  		 * Copy only in-use xstates:
>  		 */
> @@ -1020,11 +1031,16 @@ int copy_xstate_to_kernel(void *kbuf, struct xregs_state *xsave, unsigned int of
>  			if (offset + size > size_total)
>  				break;
>  
> +			memset(kbuf + last_off, 0, offset - last_off);
> +			last_off = offset + size;
> +
>  			__copy_xstate_to_kernel(kbuf, src, offset, size, size_total);
>  		}
>  
>  	}
>  
> +	memset(kbuf + last_off, 0, size_total - last_off);

Why doing all this partial zeroing? There is absolutely no point.

Either the caller clears the buffer or this function clears it right at
the beginning with:

    memset(kbuf, 0, min(size_total, XSAVE_MAX_SIZE));

Thanks,

        tglx

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

* Re: [PATCH] x86/fpu/xstate: Clear uninitialized xstate areas in core dump
  2020-05-07 18:22 ` Thomas Gleixner
@ 2020-05-07 18:41   ` Yu-cheng Yu
  0 siblings, 0 replies; 7+ messages in thread
From: Yu-cheng Yu @ 2020-05-07 18:41 UTC (permalink / raw)
  To: Thomas Gleixner, linux-kernel, x86, H. Peter Anvin, Ingo Molnar,
	Dave Hansen, Tony Luck, Andy Lutomirski, Borislav Petkov,
	Rik van Riel, Ravi V. Shankar, Sebastian Andrzej Siewior,
	Fenghua Yu, Peter Zijlstra
  Cc: sam, Kees Cook, Alexey Dobriyan, Dave Hansen, Jann Horn,
	Andrew Morton, Alexander Potapenko, Al Viro, stable

On Thu, 2020-05-07 at 20:22 +0200, Thomas Gleixner wrote:
> Yu-cheng Yu <yu-cheng.yu@intel.com> writes:
> > @@ -983,6 +983,7 @@ int copy_xstate_to_kernel(void *kbuf, struct xregs_state *xsave, unsigned int of
> >  {
> >  	unsigned int offset, size;
> >  	struct xstate_header header;
> > +	int last_off;
> >  	int i;
> >  
> >  	/*
> > @@ -1006,7 +1007,17 @@ int copy_xstate_to_kernel(void *kbuf, struct xregs_state *xsave, unsigned int of
> >  
> >  	__copy_xstate_to_kernel(kbuf, &header, offset, size, size_total);
> >  
> > +	last_off = 0;
> > +
> >  	for (i = 0; i < XFEATURE_MAX; i++) {
> > +		/*
> > +		 * Clear uninitialized area before XSAVE header.
> > +		 */
> > +		if (i == FIRST_EXTENDED_XFEATURE) {
> > +			memset(kbuf + last_off, 0, XSAVE_HDR_OFFSET - last_off);
> > +			last_off = XSAVE_HDR_OFFSET + XSAVE_HDR_SIZE;
> > +		}
> > +
> >  		/*
> >  		 * Copy only in-use xstates:
> >  		 */
> > @@ -1020,11 +1031,16 @@ int copy_xstate_to_kernel(void *kbuf, struct xregs_state *xsave, unsigned int of
> >  			if (offset + size > size_total)
> >  				break;
> >  
> > +			memset(kbuf + last_off, 0, offset - last_off);
> > +			last_off = offset + size;
> > +
> >  			__copy_xstate_to_kernel(kbuf, src, offset, size, size_total);
> >  		}
> >  
> >  	}
> >  
> > +	memset(kbuf + last_off, 0, size_total - last_off);
> 
> Why doing all this partial zeroing? There is absolutely no point.
> 
> Either the caller clears the buffer or this function clears it right at
> the beginning with:
> 
>     memset(kbuf, 0, min(size_total, XSAVE_MAX_SIZE));

I was concerned that the XSAVES buffer can be large, but this is not in a
performance-critical path.  Yes, clear it in the beginning is simpler.

Yu-cheng


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

end of thread, other threads:[~2020-05-07 18:41 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-07 16:49 [PATCH] x86/fpu/xstate: Clear uninitialized xstate areas in core dump Yu-cheng Yu
2020-05-07 16:52 ` Dave Hansen
2020-05-07 17:12   ` Yu-cheng Yu
2020-05-07 16:56 ` Sebastian Andrzej Siewior
2020-05-07 17:11   ` Yu-cheng Yu
2020-05-07 18:22 ` Thomas Gleixner
2020-05-07 18:41   ` Yu-cheng Yu

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).