From: Ingo Molnar <mingo@kernel.org>
To: Kyle Huey <me@kylehuey.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>,
Thomas Gleixner <tglx@linutronix.de>,
Borislav Petkov <bp@alien8.de>, Ingo Molnar <mingo@redhat.com>,
x86@kernel.org, "H. Peter Anvin" <hpa@zytor.com>,
Paolo Bonzini <pbonzini@redhat.com>,
Andy Lutomirski <luto@kernel.org>,
Peter Zijlstra <peterz@infradead.org>,
linux-kernel@vger.kernel.org,
Robert O'Callahan <robert@ocallahan.org>,
David Manouchehri <david.manouchehri@riseup.net>,
kvm@vger.kernel.org, stable@vger.kernel.org
Subject: Re: [PATCH] x86/fpu: Allow PKRU to be (once again) written by ptrace.
Date: Wed, 3 Aug 2022 11:03:50 +0200 [thread overview]
Message-ID: <Yuo59tV071/i6yhf@gmail.com> (raw)
In-Reply-To: <20220731050342.56513-1-khuey@kylehuey.com>
* Kyle Huey <me@kylehuey.com> wrote:
> From: Kyle Huey <me@kylehuey.com>
>
> When management of the PKRU register was moved away from XSTATE, emulation
> of PKRU's existence in XSTATE was added for APIs that read XSTATE, but not
> for APIs that write XSTATE. This can be seen by running gdb and executing
> `p $pkru`, `set $pkru = 42`, and `p $pkru`. On affected kernels (5.14+) the
> write to the PKRU register (which gdb performs through ptrace) is ignored.
>
> There are three relevant APIs: PTRACE_SETREGSET with NT_X86_XSTATE,
> sigreturn, and KVM_SET_XSAVE. KVM_SET_XSAVE has its own special handling to
> make PKRU writes take effect (in fpu_copy_uabi_to_guest_fpstate). Push that
> down into copy_uabi_to_xstate and have PTRACE_SETREGSET with NT_X86_XSTATE
> and sigreturn pass in pointers to the appropriate PKRU value.
>
> This also adds code to initialize the PKRU value to the hardware init value
> (namely 0) if the PKRU bit is not set in the XSTATE header to match XRSTOR.
> This is a change to the current KVM_SET_XSAVE behavior.
>
> Signed-off-by: Kyle Huey <me@kylehuey.com>
> Cc: kvm@vger.kernel.org # For edge case behavior of KVM_SET_XSAVE
> Cc: stable@vger.kernel.org # 5.14+
> Fixes: e84ba47e313dbc097bf859bb6e4f9219883d5f78
> ---
> arch/x86/kernel/fpu/core.c | 11 +----------
> arch/x86/kernel/fpu/regset.c | 2 +-
> arch/x86/kernel/fpu/signal.c | 2 +-
> arch/x86/kernel/fpu/xstate.c | 26 +++++++++++++++++++++-----
> arch/x86/kernel/fpu/xstate.h | 4 ++--
> 5 files changed, 26 insertions(+), 19 deletions(-)
>
> diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c
> index 0531d6a06df5..dfb79e2ee81f 100644
> --- a/arch/x86/kernel/fpu/core.c
> +++ b/arch/x86/kernel/fpu/core.c
> @@ -406,16 +406,7 @@ int fpu_copy_uabi_to_guest_fpstate(struct fpu_guest *gfpu, const void *buf,
> if (ustate->xsave.header.xfeatures & ~xcr0)
> return -EINVAL;
>
> - ret = copy_uabi_from_kernel_to_xstate(kstate, ustate);
> - if (ret)
> - return ret;
> -
> - /* Retrieve PKRU if not in init state */
> - if (kstate->regs.xsave.header.xfeatures & XFEATURE_MASK_PKRU) {
> - xpkru = get_xsave_addr(&kstate->regs.xsave, XFEATURE_PKRU);
> - *vpkru = xpkru->pkru;
> - }
> - return 0;
> + return copy_uabi_from_kernel_to_xstate(kstate, ustate, vpkru);
> }
> EXPORT_SYMBOL_GPL(fpu_copy_uabi_to_guest_fpstate);
> #endif /* CONFIG_KVM */
> diff --git a/arch/x86/kernel/fpu/regset.c b/arch/x86/kernel/fpu/regset.c
> index 75ffaef8c299..6d056b68f4ed 100644
> --- a/arch/x86/kernel/fpu/regset.c
> +++ b/arch/x86/kernel/fpu/regset.c
> @@ -167,7 +167,7 @@ int xstateregs_set(struct task_struct *target, const struct user_regset *regset,
> }
>
> fpu_force_restore(fpu);
> - ret = copy_uabi_from_kernel_to_xstate(fpu->fpstate, kbuf ?: tmpbuf);
> + ret = copy_uabi_from_kernel_to_xstate(fpu->fpstate, kbuf ?: tmpbuf, &target->thread.pkru);
>
> out:
> vfree(tmpbuf);
> diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c
> index 91d4b6de58ab..558076dbde5b 100644
> --- a/arch/x86/kernel/fpu/signal.c
> +++ b/arch/x86/kernel/fpu/signal.c
> @@ -396,7 +396,7 @@ static bool __fpu_restore_sig(void __user *buf, void __user *buf_fx,
>
> fpregs = &fpu->fpstate->regs;
> if (use_xsave() && !fx_only) {
> - if (copy_sigframe_from_user_to_xstate(fpu->fpstate, buf_fx))
> + if (copy_sigframe_from_user_to_xstate(tsk, buf_fx))
> return false;
> } else {
> if (__copy_from_user(&fpregs->fxsave, buf_fx,
> diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c
> index c8340156bfd2..1eea7af4afd9 100644
> --- a/arch/x86/kernel/fpu/xstate.c
> +++ b/arch/x86/kernel/fpu/xstate.c
> @@ -1197,7 +1197,7 @@ static int copy_from_buffer(void *dst, unsigned int offset, unsigned int size,
>
>
> static int copy_uabi_to_xstate(struct fpstate *fpstate, const void *kbuf,
> - const void __user *ubuf)
> + const void __user *ubuf, u32 *pkru)
> {
> struct xregs_state *xsave = &fpstate->regs.xsave;
> unsigned int offset, size;
> @@ -1235,6 +1235,22 @@ static int copy_uabi_to_xstate(struct fpstate *fpstate, const void *kbuf,
> for (i = 0; i < XFEATURE_MAX; i++) {
> mask = BIT_ULL(i);
>
> + if (i == XFEATURE_PKRU) {
> + /*
> + * Retrieve PKRU if not in init state, otherwise
> + * initialize it.
> + */
> + if (hdr.xfeatures & mask) {
> + struct pkru_state xpkru = {0};
> +
> + copy_from_buffer(&xpkru, xstate_offsets[i],
> + sizeof(xpkru), kbuf, ubuf);
Shouldn't the failure case of copy_from_buffer() be handled?
Also, what's the security model for this register, do we trust all input
values user-space provides for the PKRU field in the XSTATE? I realize that
WRPKRU already gives user-space write access to the register - but does the
CPU write it all into the XSTATE, with no restrictions on content
whatsoever?
Thanks,
Ingo
next prev parent reply other threads:[~2022-08-03 9:03 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-07-31 5:03 [PATCH] x86/fpu: Allow PKRU to be (once again) written by ptrace Kyle Huey
2022-08-03 9:03 ` Ingo Molnar [this message]
2022-08-03 15:12 ` Kyle Huey
2022-08-03 17:25 ` Ingo Molnar
2022-08-03 17:33 ` Paolo Bonzini
2022-08-03 17:35 ` Kyle Huey
2022-11-09 10:23 ` Thorsten Leemhuis
2022-11-21 8:36 ` [PATCH] x86/fpu: Allow PKRU to be (once again) written by ptrace. #forregzbot Thorsten Leemhuis
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=Yuo59tV071/i6yhf@gmail.com \
--to=mingo@kernel.org \
--cc=bp@alien8.de \
--cc=dave.hansen@linux.intel.com \
--cc=david.manouchehri@riseup.net \
--cc=hpa@zytor.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@kernel.org \
--cc=me@kylehuey.com \
--cc=mingo@redhat.com \
--cc=pbonzini@redhat.com \
--cc=peterz@infradead.org \
--cc=robert@ocallahan.org \
--cc=stable@vger.kernel.org \
--cc=tglx@linutronix.de \
--cc=x86@kernel.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.