[PATCH v9 6/6] arm64: expose FAR_EL1 tag bits in siginfo
Dave Martin
Dave.Martin at arm.com
Mon Aug 24 10:23:49 EDT 2020
On Wed, Aug 19, 2020 at 06:49:01PM -0700, Peter Collingbourne wrote:
> On Wed, Aug 19, 2020 at 8:56 AM Dave Martin <Dave.Martin at arm.com> wrote:
> >
> > On Mon, Aug 17, 2020 at 08:33:51PM -0700, Peter Collingbourne wrote:
> > > The kernel currently clears the tag bits (i.e. bits 56-63) in the fault
> > > address exposed via siginfo.si_addr and sigcontext.fault_address. However,
> > > the tag bits may be needed by tools in order to accurately diagnose
> > > memory errors, such as HWASan [1] or future tools based on the Memory
> > > Tagging Extension (MTE).
> > >
> > > We should not stop clearing these bits in the existing fault address
> > > fields, because there may be existing userspace applications that are
> > > expecting the tag bits to be cleared. Instead, create a new pair of
> > > union fields in siginfo._sigfault, and store the tag bits of FAR_EL1
> > > there, together with a mask specifying which bits are valid.
> > >
> > > A flag is added to si_xflags to allow userspace to determine whether
> > > the values in the fields are valid.
> > >
> > > [1] http://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html
> > >
> > > Signed-off-by: Peter Collingbourne <pcc at google.com>
> > > ---
[...]
> > > diff --git a/kernel/signal.c b/kernel/signal.c
> > > index 72182eed1b8d..1f1e42adc57d 100644
> > > --- a/kernel/signal.c
> > > +++ b/kernel/signal.c
[...]
> > > @@ -1706,7 +1722,9 @@ int send_sig_fault(int sig, int code, void __user *addr
> > > return send_sig_info(info.si_signo, &info, t);
> > > }
> > >
> > > -int force_sig_mceerr(int code, void __user *addr, short lsb)
> > > +int force_sig_mceerr(int code, void __user *addr, short lsb,
> > > + unsigned long addr_ignored_bits,
> > > + unsigned long addr_ignored_bits_mask)
> >
> > Rather than having to pass these extra arguments all over the place, can
> > we just pass the far for addr, and have an arch-specific hook for
> > splitting the ignored from non-ignored bits. For now at least, I expect
> > that ignored bits mask to be constant for a given platform and kernel.
>
> That sounds like a good idea. I think that for MTE we will want to
> make it conditional on the si_code (so SEGV_MTESERR would get 0xf <<
> 56 while everything else would get 0xff << 56) so I can hook that up
> at the same time.
OK, I think that's reasonable.
Mind you, we seem to have 3 kinds of bits here, so I'm starting to
wonder whether this is really sufficient:
1) address bits used in the faulted access
2) attribute/permission bits used in the faulted access
3) unavailable bits.
si_addr contains (1).
si_addr_ignored_bits contains (2).
The tag bits from non-MTE faults seem to fall under case (3). Code that
looks for these bits in si_addr_ignored_bits won't find them.
So perhaps it would make sense to amend the design a bit. We'd have
si_addr = address bits only
si_attr = attribute bits only
si_attr_mask = mask of valid bits in si_addr
Thinking about it, I've just shortened/changed some named and changed
the meaning of the mask, so it's very similar to what you already have.
The mask of valid bits in si_addr is decided by architectural
convention (i.e., ~0xffUL << 56), but we could also expose
si_addr_mask = mask of valid bits in si_addr
This is a bit redundant though. I think people would already assume
that all bits required for classifying the faulting location accurately
must already be provided there.
>
> > > {
> > > struct kernel_siginfo info;
> > >
> > > @@ -1717,7 +1735,9 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
> > > info.si_code = code;
> > > info.si_addr = addr;
> > > info.si_addr_lsb = lsb;
> > > - info.si_xflags = 0;
> > > + info.si_xflags = SI_XFLAG_IGNORED_BITS;
> >
> > Maybe drop the first _, so that this becomes
> >
> > SIXFLAG_IGNORED_BITS
> >
> > ? This may help to avoid anyone thinking this might be an si_code
> > value. Maybe ..._IGNORED_ADDR_BITS would also help make it clearer what
> > this bit is referring to.
>
> Yes, it should have been spelled the same way as the field name (i.e.
> SIXFLAG_ADDR_IGNORED_BITS), that was my mistake. I don't have a strong
> opinion on whether to keep the underscore in the middle or not.
Fair enough (modulo possible changes above).
[...]
> > > case SIL_FAULT_BNDERR:
> > > to->si_addr = compat_ptr(from->si_addr);
> > > @@ -3399,6 +3431,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> > > to->si_lower = compat_ptr(from->si_lower);
> > > to->si_upper = compat_ptr(from->si_upper);
> > > to->si_xflags = from->si_xflags;
> > > + to->si_addr_ignored_bits = from->si_addr_ignored_bits;
> > > + to->si_addr_ignored_bits_mask = from->si_addr_ignored_bits_mask;
> > > break;
> > > case SIL_FAULT_PKUERR:
> > > to->si_addr = compat_ptr(from->si_addr);
> > > @@ -3407,6 +3441,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> > > #endif
> > > to->si_pkey = from->si_pkey;
> > > to->si_xflags = from->si_xflags;
> > > + to->si_addr_ignored_bits = from->si_addr_ignored_bits;
> > > + to->si_addr_ignored_bits_mask = from->si_addr_ignored_bits_mask;
> >
> > Again, can you justify why this is exhaustive? If there any way to
> > factor this so as to reduce the number of places we need to hack this
> > in?
>
> Addressed on the other patch. Once I've factored the various
> SIL_FAULT* cases there should be only a handful of places requiring
> changes.
And that looked like a reasonable justification.
Cheers
---Dave
More information about the linux-arm-kernel
mailing list