linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Borislav Petkov <bp@alien8.de>
To: Thomas Gleixner <tglx@linutronix.de>
Cc: LKML <linux-kernel@vger.kernel.org>,
	x86@kernel.org, Andy Lutomirski <luto@kernel.org>,
	Dave Hansen <dave.hansen@linux.intel.com>,
	Fenghua Yu <fenghua.yu@intel.com>,
	Tony Luck <tony.luck@intel.com>,
	Yu-cheng Yu <yu-cheng.yu@intel.com>
Subject: Re: [patch V2 5/8] x86/fpu: Sanitize xstateregs_set()
Date: Thu, 3 Jun 2021 13:32:20 +0200	[thread overview]
Message-ID: <YLi9xCjkHrNMzwls@zn.tnic> (raw)
In-Reply-To: <87sg20z25y.ffs@nanos.tec.linutronix.de>

On Wed, Jun 02, 2021 at 06:01:13PM +0200, Thomas Gleixner wrote:
> xstateregs_set() operates on a stopped task and tries to copy the provided
> buffer into the tasks fpu.state.xsave buffer.

task's

> 
> Any error while copying or invalid state detected after copying results in
> wiping the target tasks FPU state completely including supervisor states.

Ditto.

> 
> That's just wrong. The caller supplied invalid data or has a problem with
> unmapped memory, so there is absolutely no justification to wreckage the
> target.
> 
> Fix this with the following modifications:
> 
>  1) If data has to be copied from userspace, allocate a buffer and copy from
>     user first.
> 
>  2) Use copy_kernel_to_xstate() unconditionally so that header checking
>     works correctly.
> 
>  3) Return on error without wreckaging the target state.
> 
> This prevents corrupting supervisor states and lets the caller deal with
> the problem it caused in the first place.
> 
> Make validate_user_xstate_header() static as this was the last user
> outside of xstate.c

Niice.


> @@ -120,32 +124,21 @@ int xstateregs_set(struct task_struct *t
>  	if (pos != 0 || count != fpu_user_xstate_size)
>  		return -EFAULT;
>  
> -	xsave = &fpu->state.xsave;
> -
> -	fpu__prepare_write(fpu);
> -
> -	if (using_compacted_format()) {
> -		if (kbuf)
> -			ret = copy_kernel_to_xstate(xsave, kbuf);
> -		else
> -			ret = copy_user_to_xstate(xsave, ubuf);
> -	} else {
> -		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, xsave, 0, -1);
> -		if (!ret)
> -			ret = validate_user_xstate_header(&xsave->header);
> +	if (!kbuf) {
> +		xbuf = vmalloc(count);
> +		if (!xbuf)
> +			return -ENOMEM;

<---- newline here.

Btw, AFAICT and if I'm staring properly at the bowels of ptrace, that
ENOMEM would percolate up the chain when ptrace(2) is called.

The ptrace(2) manpage doesn't mention ENOMEM and I guess this is a small
ABI change. I say "small" because it is still a negative error and
properly written luserspace code should check it anyway...

Or am I being overly cautious here?

 ( Frankly, can you blame me, with that madness called xstate?! )

> +		ret = user_regset_copyin(&pos, &count, NULL, &ubuf, xbuf, 0, -1);
> +		if (ret)
> +			goto out;
>  	}
>  
> -	/*
> -	 * mxcsr reserved bits must be masked to zero for security reasons.
> -	 */
> -	xsave->i387.mxcsr &= mxcsr_feature_mask;
> -
> -	/*
> -	 * In case of failure, mark all states as init:
> -	 */
> -	if (ret)
> -		fpstate_init(&fpu->state);
> +	xsave = &fpu->state.xsave;
> +	fpu__prepare_write(fpu);
> +	ret = copy_kernel_to_xstate(xsave, kbuf ? kbuf : xbuf);

Uff, three buffers in a single function. How about we call "xbuf"
"tmp_buf" so that it is even more visible what it is and it differs more
from the other <letter>buf thingies?

>  /*
> - * Convert from a ptrace or sigreturn standard-format user-space buffer to
> - * kernel XSAVES format and copy to the target thread. This is called from
> - * xstateregs_set(), as well as potentially from the sigreturn() and
> - * rt_sigreturn() system calls.
> + * Convert from a sigreturn standard-format user-space buffer to kernel
> + * XSAVES format and copy to the target thread. This is called from the

Yeah, I guess we call that the "compacted" format. Just getting our
terminology simplified because this is one helluva mess, as we all know.

> + * sigreturn() and rt_sigreturn() system calls.
>   */
>  int copy_user_to_xstate(struct xregs_state *xsave, const void __user *ubuf)
>  {

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

  reply	other threads:[~2021-06-03 11:32 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-06-02  9:55 [patch 0/8] x86/fpu: Mop up XSAVES and related damage Thomas Gleixner
2021-06-02  9:55 ` [patch 1/8] selftests/x86: Test signal frame XSTATE header corruption handling Thomas Gleixner
2021-06-02 12:38   ` Borislav Petkov
2021-06-02 14:15     ` Thomas Gleixner
2021-06-03 13:16       ` Shuah Khan
2021-06-02 15:59   ` [patch V2 " Thomas Gleixner
2021-06-02 16:02     ` [patch V2a " Thomas Gleixner
2021-06-02  9:55 ` [patch 2/8] x86/fpu: Prevent state corruption in __fpu__restore_sig() Thomas Gleixner
2021-06-02 13:12   ` Borislav Petkov
2021-06-02 14:46     ` Thomas Gleixner
2021-06-02 15:58   ` [patch V2 " Thomas Gleixner
2021-06-02  9:55 ` [patch 3/8] x86/fpu: Invalidate FPU state after a failed XRSTOR from a user buffer Thomas Gleixner
2021-06-02 15:06   ` Borislav Petkov
2021-06-03 17:30     ` Andy Lutomirski
2021-06-03 19:28       ` Borislav Petkov
2021-06-02  9:55 ` [patch 4/8] x86/fpu: Limit xstate copy size in xstateregs_set() Thomas Gleixner
2021-06-02 17:44   ` Borislav Petkov
2021-06-02  9:55 ` [patch 5/8] x86/fpu: Sanitize xstateregs_set() Thomas Gleixner
2021-06-02 16:01   ` [patch V2 " Thomas Gleixner
2021-06-03 11:32     ` Borislav Petkov [this message]
2021-06-03 17:24   ` [patch " Andy Lutomirski
2021-06-02  9:55 ` [patch 6/8] x86/fpu: Add address range checks to copy_user_to_xstate() Thomas Gleixner
2021-06-02  9:55 ` [patch 7/8] x86/fpu: Clean up the fpu__clear() variants Thomas Gleixner
2021-06-02  9:55 ` [patch 8/8] x86/fpu: Deduplicate copy_xxx_to_xstate() Thomas Gleixner
2021-06-03 16:56   ` Andy Lutomirski
2021-06-02 21:28 ` [patch 0/8] x86/fpu: Mop up XSAVES and related damage Yu, Yu-cheng
2021-06-04 14:05   ` Thomas Gleixner
2021-06-04 16:27     ` Yu, Yu-cheng
2021-06-04 17:46     ` Dave Hansen
2021-06-04 18:14       ` Thomas Gleixner
2021-06-04 22:04 ` Dave Hansen
2021-06-05 10:18   ` Thomas Gleixner
2021-06-05 11:56     ` Thomas Gleixner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=YLi9xCjkHrNMzwls@zn.tnic \
    --to=bp@alien8.de \
    --cc=dave.hansen@linux.intel.com \
    --cc=fenghua.yu@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=tglx@linutronix.de \
    --cc=tony.luck@intel.com \
    --cc=x86@kernel.org \
    --cc=yu-cheng.yu@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).