Index | Thread | Search

From:
Greg Steuck <gnezdo@openbsd.org>
Subject:
GHC on OpenBSD/arm64 -> retguard fail?
To:
حبيب محمد الأمين محمد الهـاد <ha.alamin@gmail.com>
Cc:
Lydia Sobot <chilledfrogs@disroot.org>, ports@openbsd.org
Date:
Wed, 13 Nov 2024 22:51:36 -0800

Download raw body.

Thread
حبيب محمد الأمين محمد الهـاد <ha.alamin@gmail.com> writes:

> I reproduced your same error, and figured out the cause. I'll just embed
> it as a diff inline, you'll spot it in the script instantly :).

AFAICT we are out of the cross-compilation woods and straight into the
OpenBSD mitigations paradise :) I pushed a tiny patch which takes care
of -fPIC at which point cross-compiling works:

% _build/stage1/bin/aarch64-unknown-openbsd-ghc -o a /tmp/a.hs

It produces a somewhat working binary:

% file a
a: ELF 64-bit LSB shared object, AArch64, version 1
% ./a
Hello World
[1]    13634 trace trap (core dumped)  ./a
(gdb) r
Starting program: /home/greg/a
Hello World

Program received signal SIGTRAP, Trace/breakpoint trap.
0x0000001f6f167a1c in StgRun ()
(gdb) bt
#0  0x0000001f6f167a1c in StgRun ()
#1  0x000000702fc5caf0 [PAC] in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
(gdb) disassemble
Dump of assembler code for function StgRun:
   0x0000001f6f167950 <+0>:	bti	c
   0x0000001f6f167954 <+4>:	adrp	x15, 0x1f6f1bf000
   0x0000001f6f167958 <+8>:	ldr	x15, [x15, #2952]
   0x0000001f6f16795c <+12>:	eor	x15, x15, x30
   0x0000001f6f167960 <+16>:	paciasp
   0x0000001f6f167964 <+20>:	str	x30, [sp, #-96]!
   0x0000001f6f167968 <+24>:	stp	x28, x27, [sp, #16]
   0x0000001f6f16796c <+28>:	stp	x26, x25, [sp, #32]
   0x0000001f6f167970 <+32>:	stp	x24, x23, [sp, #48]
   0x0000001f6f167974 <+36>:	stp	x22, x21, [sp, #64]
   0x0000001f6f167978 <+40>:	stp	x20, x19, [sp, #80]
   0x0000001f6f16797c <+44>:	stp	x29, x30, [sp, #-16]!
   0x0000001f6f167980 <+48>:	mov	x29, sp
   0x0000001f6f167984 <+52>:	stp	x16, x17, [sp, #-16]!
   0x0000001f6f167988 <+56>:	stp	x19, x20, [sp, #-16]!
   0x0000001f6f16798c <+60>:	stp	x21, x22, [sp, #-16]!
   0x0000001f6f167990 <+64>:	stp	x23, x24, [sp, #-16]!
   0x0000001f6f167994 <+68>:	stp	x25, x26, [sp, #-16]!
   0x0000001f6f167998 <+72>:	stp	x27, x28, [sp, #-16]!
   0x0000001f6f16799c <+76>:	stp	d8, d9, [sp, #-16]!
   0x0000001f6f1679a0 <+80>:	stp	d10, d11, [sp, #-16]!
   0x0000001f6f1679a4 <+84>:	stp	d12, d13, [sp, #-16]!
   0x0000001f6f1679a8 <+88>:	stp	d14, d15, [sp, #-16]!
   0x0000001f6f1679ac <+92>:	sub	sp, sp, #0x4, lsl #12
   0x0000001f6f1679b0 <+96>:	mov	x19, x1
   0x0000001f6f1679b4 <+100>:	br	x0
   0x0000001f6f1679b8 <+104>:	add	sp, sp, #0x4, lsl #12
   0x0000001f6f1679bc <+108>:	mov	x0, x22
   0x0000001f6f1679c0 <+112>:	ldp	d14, d15, [sp], #16
   0x0000001f6f1679c4 <+116>:	ldp	d12, d13, [sp], #16
   0x0000001f6f1679c8 <+120>:	ldp	d10, d11, [sp], #16
   0x0000001f6f1679cc <+124>:	ldp	d8, d9, [sp], #16
   0x0000001f6f1679d0 <+128>:	ldp	x27, x28, [sp], #16
   0x0000001f6f1679d4 <+132>:	ldp	x25, x26, [sp], #16
   0x0000001f6f1679d8 <+136>:	ldp	x23, x24, [sp], #16
   0x0000001f6f1679dc <+140>:	ldp	x21, x22, [sp], #16
   0x0000001f6f1679e0 <+144>:	ldp	x19, x20, [sp], #16
   0x0000001f6f1679e4 <+148>:	ldp	x16, x17, [sp], #16
   0x0000001f6f1679e8 <+152>:	ldp	x29, x30, [sp], #16
   0x0000001f6f1679ec <+156>:	ldp	x20, x19, [sp, #80]
   0x0000001f6f1679f0 <+160>:	ldp	x22, x21, [sp, #64]
   0x0000001f6f1679f4 <+164>:	ldp	x24, x23, [sp, #48]
   0x0000001f6f1679f8 <+168>:	ldp	x26, x25, [sp, #32]
   0x0000001f6f1679fc <+172>:	ldp	x28, x27, [sp, #16]
   0x0000001f6f167a00 <+176>:	ldr	x30, [sp], #96
   0x0000001f6f167a04 <+180>:	adrp	x9, 0x1f6f1bf000
   0x0000001f6f167a08 <+184>:	autiasp
   0x0000001f6f167a0c <+188>:	ldr	x9, [x9, #2952]
   0x0000001f6f167a10 <+192>:	eor	x15, x15, x30
   0x0000001f6f167a14 <+196>:	subs	x15, x15, x9
   0x0000001f6f167a18 <+200>:	cbz	x15, 0x1f6f167a20 <StgRun+208>
=> 0x0000001f6f167a1c <+204>:	brk	#0x1
   0x0000001f6f167a20 <+208>:	ret
End of assembler dump.

This code is very special (it is mostly coded in arm64 assembly[0]).  We
could really use help from somebody who understands what is happening in
our arm64 epilogue that this magical Haskell runtime is running afoul
of. It looks like retguard, so maybe just somehow marking this function
with no-retguard-please is enough?

My hypothesis for why the same works on amd64 is they have an explicit
retq, so we don't get to inject retguard in there. That function is like
this:
$ objdump -d /usr/local/lib/ghc-9.6.6/lib/x86_64-openbsd-ghc-9.6.6/rts-1.0.2/libHSrts-1.0.2.a
...
  4f:   4c 8b 64 24 10          mov    0x10(%rsp),%r12
  54:   4c 8b 6c 24 18          mov    0x18(%rsp),%r13
  59:   4c 8b 74 24 20          mov    0x20(%rsp),%r14
  5e:   4c 8b 7c 24 28          mov    0x28(%rsp),%r15
  63:   48 83 c4 30             add    $0x30,%rsp
  67:   c3                      retq
  68:   4c 33 1c 24             xor    (%rsp),%r11
  6c:   4c 3b 1d 00 00 00 00    cmp    0(%rip),%r11        # 73 <StgReturn+0x37>
  73:   74 0a                   je     7f <StgReturn+0x43>
  75:   cc                      int3
  76:   cc                      int3
  77:   cc                      int3
  78:   cc                      int3
  79:   cc                      int3
  7a:   cc                      int3
  7b:   cc                      int3
  7c:   cc                      int3
  7d:   cc                      int3
  7e:   cc                      int3
  7f:   c3                      retq

[0]https://gitlab.haskell.org/blackgnezdo/ghc/-/blob/ghc-9.10.1-openbsd/rts/StgCRun.c?ref_type=heads#L833

Thanks
Greg