All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bobby Powers <bobbypowers@gmail.com>
To: Ingo Molnar <mingo@kernel.org>
Cc: Kernel development list <linux-kernel@vger.kernel.org>,
	Andy Lutomirski <luto@amacapital.net>,
	Borislav Petkov <bp@alien8.de>,
	Dave Hansen <dave.hansen@linux.intel.com>,
	Fenghua Yu <fenghua.yu@intel.com>,
	"H. Peter Anvin" <hpa@zytor.com>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Oleg Nesterov <oleg@redhat.com>,
	Thomas Gleixner <tglx@linutronix.de>
Subject: Re: [PATCH] x86/fpu: Fix FPU register read access to the current task
Date: Fri, 29 May 2015 09:12:48 -0400	[thread overview]
Message-ID: <CAArOQ2USzHyJDXdtdiPK5YpDB07GEx2r6ZO-2mczg0FkD-v6CQ@mail.gmail.com> (raw)
In-Reply-To: <20150527104214.GA24822@gmail.com>

Ingo Molnar <mingo@kernel.org> wrote:
> Good catch, this shows a bug in the new FPU code.
>
> Could you check whether the fix below solves the problem?

Yes, it certainly does.  Thanks.

Tested-By: Bobby Powers <bobbypowers@gmail.com>

yours,
Bobby

> ====================>
> From 47f01e8cc23f3d041f6b9fb97627369eaf75ba7f Mon Sep 17 00:00:00 2001
> From: Ingo Molnar <mingo@kernel.org>
> Date: Wed, 27 May 2015 12:22:29 +0200
> Subject: [PATCH] x86/fpu: Fix FPU register read access to the current task
>
> Bobby Powers reported the following FPU warning during ELF coredumping:
>
>    WARNING: CPU: 0 PID: 27452 at arch/x86/kernel/fpu/core.c:324 fpu__activate_stopped+0x8a/0xa0()
>
> This warning unearthed an invalid assumption about fpu__activate_stopped()
> that I added in:
>
>   67e97fc2ec57 ("x86/fpu: Rename init_fpu() to fpu__unlazy_stopped() and add debugging check")
>
> the old init_fpu() function had an (intentional but obscure) side effect:
> when FPU registers are accessed for the current task, for reading, then
> it synchronized live in-register FPU state with the fpstate by saving it.
>
> So fix this bug by saving the FPU if we are the current task. We'll
> still warn in fpu__save() if this is called for not yet stopped
> child tasks, so the debugging check is still preserved.
>
> Also rename the function to fpu__activate_fpstate(), because it's not
> exclusively used for stopped tasks, but for the current task as well.
>
> ( Note that this bug calls for a cleaner separation of access-for-read
>   and access-for-modification FPU methods, but we'll do that in separate
>   patches. )
>
> Reported-by: Bobby Powers <bobbypowers@gmail.com>
> Cc: Andy Lutomirski <luto@amacapital.net>
> Cc: Borislav Petkov <bp@alien8.de>
> Cc: Dave Hansen <dave.hansen@linux.intel.com>
> Cc: Fenghua Yu <fenghua.yu@intel.com>
> Cc: H. Peter Anvin <hpa@zytor.com>
> Cc: Linus Torvalds <torvalds@linux-foundation.org>
> Cc: Oleg Nesterov <oleg@redhat.com>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Signed-off-by: Ingo Molnar <mingo@kernel.org>
> ---
>  arch/x86/include/asm/fpu/internal.h |  2 +-
>  arch/x86/kernel/fpu/core.c          | 43 +++++++++++++++++++++----------------
>  arch/x86/kernel/fpu/regset.c        | 12 +++++------
>  3 files changed, 32 insertions(+), 25 deletions(-)
>
> diff --git a/arch/x86/include/asm/fpu/internal.h b/arch/x86/include/asm/fpu/internal.h
> index 99690bed920a..62d13d515f95 100644
> --- a/arch/x86/include/asm/fpu/internal.h
> +++ b/arch/x86/include/asm/fpu/internal.h
> @@ -22,7 +22,7 @@
>   * High level FPU state handling functions:
>   */
>  extern void fpu__activate_curr(struct fpu *fpu);
> -extern void fpu__activate_stopped(struct fpu *fpu);
> +extern void fpu__activate_fpstate(struct fpu *fpu);
>  extern void fpu__save(struct fpu *fpu);
>  extern void fpu__restore(struct fpu *fpu);
>  extern int  fpu__restore_sig(void __user *buf, int ia32_frame);
> diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c
> index 01a15503c3be..b41049247cfa 100644
> --- a/arch/x86/kernel/fpu/core.c
> +++ b/arch/x86/kernel/fpu/core.c
> @@ -296,40 +296,47 @@ void fpu__activate_curr(struct fpu *fpu)
>  EXPORT_SYMBOL_GPL(fpu__activate_curr);
>
>  /*
> - * This function must be called before we modify a stopped child's
> - * fpstate.
> + * This function must be called before we read or write a task's fpstate.
>   *
> - * If the child has not used the FPU before then initialize its
> + * If the task has not used the FPU before then initialize its
>   * fpstate.
>   *
> - * If the child has used the FPU before then unlazy it.
> + * If the task has used the FPU before then save and unlazy it.
>   *
> - * [ After this function call, after registers in the fpstate are
> + * [ If this function is used for non-current child tasks, then
> + *   after this function call, after registers in the fpstate are
>   *   modified and the child task has woken up, the child task will
>   *   restore the modified FPU state from the modified context. If we
>   *   didn't clear its lazy status here then the lazy in-registers
>   *   state pending on its former CPU could be restored, corrupting
> - *   the modifications. ]
> + *   the modifications.
>   *
> - * This function is also called before we read a stopped child's
> - * FPU state - to make sure it's initialized if the child has
> - * no active FPU state.
> + *   This function can be used for the current task as well, but
> + *   only for reading the fpstate. Modifications to the fpstate
> + *   will be lost on eagerfpu systems. ]
>   *
>   * TODO: A future optimization would be to skip the unlazying in
>   *       the read-only case, it's not strictly necessary for
>   *       read-only access to the context.
>   */
> -void fpu__activate_stopped(struct fpu *child_fpu)
> +void fpu__activate_fpstate(struct fpu *fpu)
>  {
> -       WARN_ON_FPU(child_fpu == &current->thread.fpu);
> -
> -       if (child_fpu->fpstate_active) {
> -               child_fpu->last_cpu = -1;
> +       /*
> +        * If fpregs are active (in the current CPU), then
> +        * copy them to the fpstate:
> +        */
> +       if (fpu->fpregs_active) {
> +               fpu__save(fpu);
>         } else {
> -               fpstate_init(&child_fpu->state);
> -
> -               /* Safe to do for stopped child tasks: */
> -               child_fpu->fpstate_active = 1;
> +               if (fpu->fpstate_active) {
> +                       /* Invalidate any lazy state: */
> +                       fpu->last_cpu = -1;
> +               } else {
> +                       fpstate_init(&fpu->state);
> +
> +                       /* Safe to do for current and for stopped child tasks: */
> +                       fpu->fpstate_active = 1;
> +               }
>         }
>  }
>
> diff --git a/arch/x86/kernel/fpu/regset.c b/arch/x86/kernel/fpu/regset.c
> index 297b3da8e4c4..a1f97d9d6a45 100644
> --- a/arch/x86/kernel/fpu/regset.c
> +++ b/arch/x86/kernel/fpu/regset.c
> @@ -33,7 +33,7 @@ int xfpregs_get(struct task_struct *target, const struct user_regset *regset,
>         if (!cpu_has_fxsr)
>                 return -ENODEV;
>
> -       fpu__activate_stopped(fpu);
> +       fpu__activate_fpstate(fpu);
>         fpstate_sanitize_xstate(fpu);
>
>         return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
> @@ -50,7 +50,7 @@ int xfpregs_set(struct task_struct *target, const struct user_regset *regset,
>         if (!cpu_has_fxsr)
>                 return -ENODEV;
>
> -       fpu__activate_stopped(fpu);
> +       fpu__activate_fpstate(fpu);
>         fpstate_sanitize_xstate(fpu);
>
>         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
> @@ -82,7 +82,7 @@ int xstateregs_get(struct task_struct *target, const struct user_regset *regset,
>         if (!cpu_has_xsave)
>                 return -ENODEV;
>
> -       fpu__activate_stopped(fpu);
> +       fpu__activate_fpstate(fpu);
>
>         xsave = &fpu->state.xsave;
>
> @@ -111,7 +111,7 @@ int xstateregs_set(struct task_struct *target, const struct user_regset *regset,
>         if (!cpu_has_xsave)
>                 return -ENODEV;
>
> -       fpu__activate_stopped(fpu);
> +       fpu__activate_fpstate(fpu);
>
>         xsave = &fpu->state.xsave;
>
> @@ -273,7 +273,7 @@ int fpregs_get(struct task_struct *target, const struct user_regset *regset,
>         struct fpu *fpu = &target->thread.fpu;
>         struct user_i387_ia32_struct env;
>
> -       fpu__activate_stopped(fpu);
> +       fpu__activate_fpstate(fpu);
>
>         if (!static_cpu_has(X86_FEATURE_FPU))
>                 return fpregs_soft_get(target, regset, pos, count, kbuf, ubuf);
> @@ -303,7 +303,7 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset,
>         struct user_i387_ia32_struct env;
>         int ret;
>
> -       fpu__activate_stopped(fpu);
> +       fpu__activate_fpstate(fpu);
>         fpstate_sanitize_xstate(fpu);
>
>         if (!static_cpu_has(X86_FEATURE_FPU))

      reply	other threads:[~2015-05-29 13:12 UTC|newest]

Thread overview: 74+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-05 17:57 [PATCH 000/208] big x86 FPU code rewrite Ingo Molnar
2015-05-05 17:57 ` [PATCH 162/208] x86/fpu, crypto x86/cast6_avx: Simplify the cast6_init() xfeature checks Ingo Molnar
2015-05-05 17:57 ` [PATCH 163/208] x86/fpu, crypto x86/sha1_ssse3: Simplify the sha1_ssse3_mod_init() " Ingo Molnar
2015-05-05 17:57 ` [PATCH 164/208] x86/fpu, crypto x86/serpent_avx2: Simplify the init() " Ingo Molnar
2015-05-05 17:57 ` [PATCH 165/208] x86/fpu, crypto x86/sha1_mb: Remove FPU internal headers from sha1_mb.c Ingo Molnar
2015-05-05 17:57 ` [PATCH 166/208] x86/fpu: Move asm/xcr.h to asm/fpu/internal.h Ingo Molnar
2015-05-05 17:57 ` [PATCH 167/208] x86/fpu: Rename sanitize_i387_state() to fpstate_sanitize_xstate() Ingo Molnar
2015-05-05 17:57 ` [PATCH 168/208] x86/fpu: Simplify fpstate_sanitize_xstate() calls Ingo Molnar
2015-05-05 17:57 ` [PATCH 169/208] x86/fpu: Pass 'struct fpu' to fpstate_sanitize_xstate() Ingo Molnar
2015-05-05 17:57 ` [PATCH 170/208] x86/fpu: Rename save_xstate_sig() to copy_fpstate_to_sigframe() Ingo Molnar
2015-05-05 17:57 ` [PATCH 171/208] x86/fpu: Rename save_user_xstate() to copy_fpregs_to_sigframe() Ingo Molnar
2015-05-05 17:57 ` [PATCH 172/208] x86/fpu: Clarify ancient comments in fpu__restore() Ingo Molnar
2015-05-05 17:57 ` [PATCH 173/208] x86/fpu: Rename user_has_fpu() to fpregs_active() Ingo Molnar
2015-05-05 17:57 ` [PATCH 174/208] x86/fpu: Initialize fpregs in fpu__init_cpu_generic() Ingo Molnar
2015-05-05 17:57 ` [PATCH 175/208] x86/fpu: Clean up fpu__clear() state handling Ingo Molnar
2015-05-05 17:58 ` [PATCH 176/208] x86/alternatives, x86/fpu: Add 'alternatives_patched' debug flag and use it in xsave_state() Ingo Molnar
2015-05-05 22:47   ` Borislav Petkov
2015-05-06  2:57     ` Ingo Molnar
2015-05-05 17:58 ` [PATCH 177/208] x86/fpu: Synchronize the naming of drop_fpu() and fpu_reset_state() Ingo Molnar
2015-05-05 17:58 ` [PATCH 178/208] x86/fpu: Rename restore_fpu_checking() to copy_fpstate_to_fpregs() Ingo Molnar
2015-05-05 17:58 ` [PATCH 179/208] x86/fpu: Move all the fpu__*() high level methods closer to each other Ingo Molnar
2015-05-05 17:58 ` [PATCH 180/208] x86/fpu: Move fpu__clear() to 'struct fpu *' parameter passing Ingo Molnar
2015-05-05 17:58 ` [PATCH 181/208] x86/fpu: Rename restore_xstate_sig() to fpu__restore_sig() Ingo Molnar
2015-05-05 17:58 ` [PATCH 182/208] x86/fpu: Move the signal frame handling code closer to each other Ingo Molnar
2015-05-05 17:58 ` [PATCH 183/208] x86/fpu: Merge fpu__reset() and fpu__clear() Ingo Molnar
2015-05-05 17:58 ` [PATCH 184/208] x86/fpu: Move is_ia32*frame() helpers out of fpu/internal.h Ingo Molnar
2015-05-05 17:58 ` [PATCH 185/208] x86/fpu: Split out fpu/signal.h from fpu/internal.h for signal frame handling functions Ingo Molnar
2015-05-05 17:58 ` [PATCH 186/208] x86/fpu: Factor out fpu/regset.h from fpu/internal.h Ingo Molnar
2015-05-05 17:58 ` [PATCH 187/208] x86/fpu: Remove run-once init quirks Ingo Molnar
2015-05-05 17:58 ` [PATCH 188/208] x86/fpu: Factor out the exception error code handling code Ingo Molnar
2015-05-05 17:58 ` [PATCH 189/208] x86/fpu: Harmonize the names of the fpstate_init() helper functions Ingo Molnar
2015-05-05 17:58 ` [PATCH 190/208] x86/fpu: Create 'union thread_xstate' helper for fpstate_init() Ingo Molnar
2015-05-05 17:58 ` [PATCH 191/208] x86/fpu: Generalize 'init_xstate_ctx' Ingo Molnar
2015-05-05 17:58 ` [PATCH 192/208] x86/fpu: Move restore_init_xstate() out of fpu/internal.h Ingo Molnar
2015-05-05 17:58 ` [PATCH 193/208] x86/fpu: Rename all the fpregs, xregs, fxregs and fregs handling functions Ingo Molnar
2015-05-12 21:54   ` Dave Hansen
2015-05-05 17:58 ` [PATCH 194/208] x86/fpu: Factor out fpu/signal.c Ingo Molnar
2015-05-05 17:58 ` [PATCH 195/208] x86/fpu: Factor out the FPU regset code into fpu/regset.c Ingo Molnar
2015-05-05 17:58 ` [PATCH 196/208] x86/fpu: Harmonize FPU register state types Ingo Molnar
2015-05-05 17:58 ` [PATCH 197/208] x86/fpu: Change fpu->fpregs_active from 'int' to 'char', add lazy switching comments Ingo Molnar
2015-05-05 17:58 ` [PATCH 198/208] x86/fpu: Document the various fpregs state formats Ingo Molnar
2015-05-05 19:52   ` Dave Hansen
2015-05-05 22:55     ` Yu, Fenghua
2015-05-06  4:20     ` Ingo Molnar
2015-05-05 17:58 ` [PATCH 199/208] x86/fpu: Move debugging check from kernel_fpu_begin() to __kernel_fpu_begin() Ingo Molnar
2015-05-05 17:58 ` [PATCH 200/208] x86/fpu/xstate: Don't assume the first zero xfeatures zero bit means the end Ingo Molnar
2015-05-05 20:10   ` Dave Hansen
2015-05-05 23:04   ` Yu, Fenghua
2015-05-06  4:13     ` Ingo Molnar
2015-05-05 17:58 ` [PATCH 201/208] x86/fpu: Clean up xstate feature reservation Ingo Molnar
2015-05-05 20:12   ` Dave Hansen
2015-05-06  4:54     ` Ingo Molnar
2015-05-05 17:58 ` [PATCH 202/208] x86/fpu/xstate: Clean up setup_xstate_comp() call Ingo Molnar
2015-05-05 17:58 ` [PATCH 203/208] x86/fpu/init: Propagate __init annotations Ingo Molnar
2015-05-05 17:58 ` [PATCH 204/208] x86/fpu: Pass 'struct fpu' to fpu__restore() Ingo Molnar
2015-05-05 17:58 ` [PATCH 205/208] x86/fpu: Fix the 'nofxsr' boot parameter to also clear X86_FEATURE_FXSR_OPT Ingo Molnar
2015-05-05 17:58 ` [PATCH 206/208] x86/fpu: Add CONFIG_X86_DEBUG_FPU=y FPU debugging code Ingo Molnar
2015-05-05 19:41   ` Borislav Petkov
2015-05-06  3:35     ` Ingo Molnar
2015-05-05 17:58 ` [PATCH 207/208] x86/fpu: Add FPU performance measurement subsystem Ingo Molnar
2015-05-05 19:15   ` Dave Hansen
2015-05-05 19:22     ` Borislav Petkov
2015-05-06  4:11     ` Ingo Molnar
2015-05-06  0:52   ` Andy Lutomirski
2015-05-06  4:52     ` Ingo Molnar
2015-05-06 15:53       ` Borislav Petkov
2015-05-07  2:52       ` Andy Lutomirski
2015-05-05 17:58 ` [PATCH 208/208] x86/fpu: Reorganize fpu/internal.h Ingo Molnar
2015-05-12 17:46 ` [PATCH 000/208] big x86 FPU code rewrite Dave Hansen
2015-05-29 18:53   ` Ingo Molnar
2015-05-19 21:41 ` Ingo Molnar
2015-05-27  1:22   ` Bobby Powers
2015-05-27 10:42     ` [PATCH] x86/fpu: Fix FPU register read access to the current task Ingo Molnar
2015-05-29 13:12       ` Bobby Powers [this message]

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=CAArOQ2USzHyJDXdtdiPK5YpDB07GEx2r6ZO-2mczg0FkD-v6CQ@mail.gmail.com \
    --to=bobbypowers@gmail.com \
    --cc=bp@alien8.de \
    --cc=dave.hansen@linux.intel.com \
    --cc=fenghua.yu@intel.com \
    --cc=hpa@zytor.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@amacapital.net \
    --cc=mingo@kernel.org \
    --cc=oleg@redhat.com \
    --cc=tglx@linutronix.de \
    --cc=torvalds@linux-foundation.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.