This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: rseq/x86: choosing rseq code signature
- From: Zack Weinberg <zackw at panix dot com>
- To: Mathieu Desnoyers <mathieu dot desnoyers at efficios dot com>
- Cc: Thomas Gleixner <tglx at linutronix dot de>, Andy Lutomirski <luto at amacapital dot net>, Peter Zijlstra <peterz at infradead dot org>, "H. Peter Anvin" <hpa at zytor dot com>, Andi Kleen <andi at firstfloor dot org>, Ingo Molnar <mingo at redhat dot com>, Borislav Petkov <bp at alien8 dot de>, libc-alpha <libc-alpha at sourceware dot org>, linux-kernel <linux-kernel at vger dot kernel dot org>, "Carlos O'Donell" <carlos at redhat dot com>, x86 <x86 at kernel dot org>
- Date: Tue, 9 Apr 2019 20:50:49 -0400
- Subject: Re: rseq/x86: choosing rseq code signature
- References: <11513896.2624.1554838336494.JavaMail.zimbra@efficios.com> <913288111.2663.1554842622822.JavaMail.zimbra@efficios.com>
On Tue, Apr 9, 2019 at 4:43 PM Mathieu Desnoyers
<mathieu.desnoyers@efficios.com> wrote:
> ----- On Apr 9, 2019, at 3:32 PM, Mathieu Desnoyers mathieu.desnoyers@efficios.com wrote:
> >
> > We are about to include the code signature required prior to restartable
> > sequences abort handlers into glibc, which will make this ABI choice final.
> > We need architecture maintainer input on that signature value.
> >
> > That code signature is placed before each abort handler, so the kernel can
> > validate that it is indeed jumping to an abort handler (and not some
> > arbitrary attacker-chosen code). The signature is never executed.
> >
> > Currently, tools/testing/selftests/rseq/rseq-x86.h defines RSEQ_SIG
> > as 0x53053053, and uses it as an immediate operand to the following
> > instruction opcodes (as suggested by Andy Lutomirski):
> >
> > x86-32:
> > - .byte 0x0f, 0x1f, 0x05: nopl <sig>
> >
> > x86-64:
> > - .byte 0x0f, 0x1f, 0x05: nopl <sig>(%rip)
> >
> > The current discussion thread on the glibc mailing list leads us towards
> > using a trap with uncommon immediate operand, which simplifies integration
> > with disassemblers, emulators, makes it easier to debug if the control
> > flow gets redirected there by mistake, and is nicer for some architecture's
> > speculative execution.
...
> Peter Zijlstra suggested to use "invlpg" in user-space, which should generate
> a trap. The only concern would be emulators, but ideally they would not try to
> decode an instruction that is never executed. This would lead to the following
> patch. Any objections/ack ?
...
> +/*
> + * RSEQ_SIG is used with the following privileged instructions, which trap in user-space:
> + * x86-32: 0f 01 3d 53 30 05 53 invlpg 0x53053053
> + * x86-64: 0f 01 3d 53 30 05 53 invlpg 0x53053053(%rip)
> + */
> #define RSEQ_SIG 0x53053053
On x86, you have to worry about what happens if control flow gets
redirected to an arbitrary byte address. The proposed sequence `0f 01
3d 53 30 05 53` is a trap instruction if control lands seven bytes
before the beginning of the abort handler, but if it lands anywhere
_else_ within the marker sequence, you get one of these instruction
sequences, none of which trap, all but one of which will corrupt the
process state, and three of which will consume three bytes from the
beginning of the abort handler's code, continuing execution with a
misaligned PC:
01 3d 53 30 05 53 add %edi,0x53053053(%rip)
3d 53 30 05 53 cmp $0x53053053,%eax
53 30 05 53 XX XX XX push %rbx; xor %al,0xXXXXXX78(%rip)
30 05 53 XX XX XX xor %al,0xXXXXXX78(%rip)
05 53 XX XX XX add $0xXXXXXX53,%eax
53 push %rbx
So I'm going to suggest instead the four-byte sequence CD CF CD CF.
That's INT $0xCF if control lands either two or four bytes before the
beginning of the abort handler, and IRET if it lands one or three
bytes before. I believe both of these possibilities are currently
also forbidden in user mode. It doesn't need to be longer, does it?
zw