From: Dave Martin <Dave.Martin@arm.com>
To: "Maciej W. Rozycki" <macro@mips.com>
Cc: Ralf Baechle <ralf@linux-mips.org>,
James Hogan <james.hogan@mips.com>,
Paul Burton <Paul.Burton@mips.com>,
Alex Smith <alex@alex-smith.me.uk>,
"linux-mips@linux-mips.org" <linux-mips@linux-mips.org>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
"stable@vger.kernel.org" <stable@vger.kernel.org>
Subject: Re: [PATCH 4/5] MIPS: Execute any partial write of the last register with PTRACE_SETREGSET
Date: Fri, 1 Dec 2017 12:23:59 +0000 [thread overview]
Message-ID: <20171201122356.GR22781@e103592.cambridge.arm.com> (raw)
In-Reply-To: <alpine.DEB.2.00.1711301831540.31156@tp.orcam.me.uk>
On Thu, Nov 30, 2017 at 07:38:25PM +0000, Maciej W. Rozycki wrote:
> Hi Dave,
>
> > > linux-mips-nt-prfpreg-count.diff
> > > Index: linux-sfr-test/arch/mips/kernel/ptrace.c
> > > ===================================================================
> > > --- linux-sfr-test.orig/arch/mips/kernel/ptrace.c 2017-11-21 22:12:00.000000000 +0000
> > > +++ linux-sfr-test/arch/mips/kernel/ptrace.c 2017-11-21 22:13:13.471970000 +0000
> > > @@ -484,7 +484,7 @@ static int fpr_set_msa(struct task_struc
> > > int err;
> > >
> > > BUILD_BUG_ON(sizeof(fpr_val) != sizeof(elf_fpreg_t));
> > > - for (i = 0; i < NUM_FPU_REGS && *count >= sizeof(elf_fpreg_t); i++) {
> > > + for (i = 0; i < NUM_FPU_REGS && *count > 0; i++) {
> > >
> > > err = user_regset_copyin(pos, count, kbuf, ubuf,
> > > &fpr_val, i * sizeof(elf_fpreg_t),
> > > (i + 1) * sizeof(elf_fpreg_t));
> >
> > But mips*_regsets[REGSET_FPR].size == sizeof(elf_fpreg_t),
> > linux/kernel/regset.c:ptrace_regset() polices
> > iov_len % regset->size == 0, and each user_regset_copyout() call here
> > transfers sizeof(elf_fpreg_t) bytes, decrementing *count by that
> > amount unless something goest wrong in which case we return.
>
> Good point, I missed that check.
Understandable. If took me a fair while to figure out how the logic
typically works here.
> I don't think however that re-enforcing in arch code, especially in such
> a subtle way, a constraint that has already been enforced upstream in
> generic code is a good idea, because if we ever decide to relax the
> constraint, then all the arch code will have to be carefully reviewed.
>
> > If we can't end up with that, then this patch doesn't change ABI-
> > observable behaviour, unless I've missed something.
>
> Right, in which case there is no need to backport this change if it is
> given a go-ahead.
>
> > If we can end up with that somehow, then this patch reintroduces the
> > issue d614fd58a283 aims to fix, whereby fpr_val can contain
> > uninitialised kernel stack which userspace can then obtain via
> > PTRACE_GETREGSET.
>
> That wasn't actually clarified in the referred commit's description,
> which it should in the first place, and I wasn't able to track down any
> review of your change as submitted, which would be the potential second
> source of such support information. The description isn't even correct,
> as it states that if a short buffer is supplied, then the old values held
> in thread's registers are preserved, which clearly isn't correct as
> individual registers do get written from the beginning of the regset up to
> the point no more data is available to fill a whole register.
True, the commit message leaves something to be desired here. This was
one of a bunch of patches applying similar fixes to various arches, so
I pasted the same commit message as a general description for the changes
as a set -- but you're right, it doesn't describe this spefic change
correctly here. My bad.
> You are of course right about the (partially) uninitialised variable, and
> I think there are two ways to address it:
>
> 1. By preinitialising it, i.e.:
>
> for (i = 0; i < NUM_FPU_REGS && *count > 0; i++) {
> fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0);
> err = user_regset_copyin(pos, count, kbuf, ubuf,
> &fpr_val, i * sizeof(elf_fpreg_t),
> (i + 1) * sizeof(elf_fpreg_t));
> if (err)
> return err;
> set_fpr64(&target->thread.fpu.fpr[i], 0, fpr_val);
> }
>
> but that would be an overkill given that we assert that `count' is a
> multiple of `sizeof(elf_fpreg_t)'.
Agreed.
Was a partial write to fscr ever supported by this regset? Your commit
message suggested that my patch may have broken that, but I can't see
how it was ever possible in the first place... unless .size has been
changed for this regset at some point.
If my patch does cause an ABI regression, then it certainly should be
fixed though.
> 2. Actually assert what we rely on having been enforced by generic code,
> i.e.:
>
> BUG_ON(*count % sizeof(elf_fpreg_t));
> for (i = 0; i < NUM_FPU_REGS && *count > 0; i++) {
> err = user_regset_copyin(pos, count, kbuf, ubuf,
> &fpr_val, i * sizeof(elf_fpreg_t),
> (i + 1) * sizeof(elf_fpreg_t));
> if (err)
> return err;
> set_fpr64(&target->thread.fpu.fpr[i], 0, fpr_val);
> }
>
> so that a discrepancy between generic code and the arch handler is
> caught should it happen.
The important property is that *count is at least sufficient to fill
fpr_val, so that a zero return user_regset_copyin() means fpr_val has
been fully initialised with user data.
So while your check is not wrong
(since *count > 0 && *count % sizeof(elf_fpreg_t) == 0 implies
*count >= sizeof(elf_fpreg_t))
I don't see how this is an improvement on the original check.
Either way, maybe adding a comment to explain the purpose of the check
would be a good idea.
Cheers
---Dave
next prev parent reply other threads:[~2017-12-01 12:24 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-11-29 15:17 [PATCH 0/5] MIPS: NT_PRFPREG regset handling fixes Maciej W. Rozycki
2017-11-29 15:17 ` [PATCH 1/5] MIPS: Factor out NT_PRFPREG regset access helpers Maciej W. Rozycki
2017-11-29 15:19 ` [PATCH 2/5] MIPS: Fix an FCSR access API regression with NT_PRFPREG and MSA Maciej W. Rozycki
2017-11-29 15:20 ` [PATCH 3/5] MIPS: Also verify sizeof `elf_fpreg_t' with PTRACE_SETREGSET Maciej W. Rozycki
2017-11-29 15:21 ` [PATCH 4/5] MIPS: Execute any partial write of the last register " Maciej W. Rozycki
2017-11-30 17:28 ` Dave Martin
2017-11-30 19:38 ` Maciej W. Rozycki
2017-12-01 12:23 ` Dave Martin [this message]
2017-12-06 19:24 ` Maciej W. Rozycki
2017-12-11 17:25 ` Maciej W. Rozycki
2017-12-01 12:35 ` Dave Martin
2017-12-06 18:32 ` Maciej W. Rozycki
2017-11-29 15:22 ` [PATCH 5/5] MIPS: Disallow outsized PTRACE_SETREGSET NT_PRFPREG regset accesses Maciej W. Rozycki
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=20171201122356.GR22781@e103592.cambridge.arm.com \
--to=dave.martin@arm.com \
--cc=Paul.Burton@mips.com \
--cc=alex@alex-smith.me.uk \
--cc=james.hogan@mips.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mips@linux-mips.org \
--cc=macro@mips.com \
--cc=ralf@linux-mips.org \
--cc=stable@vger.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®