>Synopsis: macppc base-gcc secure-plt bug
>Category: powerpc
>Environment:
System : OpenBSD 6.6
Details : OpenBSD 6.6-current (GENERIC) #0: Fri Feb 14 08:49:11 EST
2020
[email protected]:/usr/src/sys/arch/macppc/compile/GENERIC
Architecture: OpenBSD.macppc
Machine : macppc
>Description:
When code casts a function pointer, base-gcc may emit PowerPC
code that tries to use the secure PLT, but forgets to set %r30. The
incorrect code will crash at runtime.
A macro in ports/devel/glib2 has such a cast. Some code in
devel/gtk+3 uses the macro; base-gcc emits wrong code. The code
crashes games/galois; cwen@ mentioned the crash on Jan 31 in
https://marc.info/?l=openbsd-ports&m=158049571603706&w=2
>How-To-Repeat:
games/galois segfaults when closing certain dialog boxes, like
the Scores box.
The next example reproduces the crash without needing glib2 or
any ports. It casts puts(3) to int (*)(void *), then calls the casted
pointer, but gcc forgets to set %r30 for the call. Apply the patch in
an empty directory, then run $ make && ./main
--- /dev/null Mon Feb 24 22:47:20 2020
+++ Makefile Mon Feb 24 22:18:17 2020
@@ -0,0 +1,8 @@
+main: main.c trial.so
+ $(CC) $(CFLAGS) -o main main.c -Wl,-R. trial.so
+
+trial.so: trial.c
+ $(CC) $(CFLAGS) -shared -o trial.so trial.c
+
+clean:
+ rm -rf main trial.so
--- /dev/null Mon Feb 24 22:47:20 2020
+++ main.c Mon Feb 24 22:15:27 2020
@@ -0,0 +1,7 @@
+void wrap_puts(char *);
+
+int
+main(void) {
+ wrap_puts("No bug!");
+ return 0;
+}
--- /dev/null Mon Feb 24 22:47:20 2020
+++ trial.c Mon Feb 24 22:43:58 2020
@@ -0,0 +1,9 @@
+#include <stdio.h>
+
+void
+wrap_puts(char *arg)
+{
+ int (*pointer)(void *) = (int (*)(void *))puts;
+
+ pointer(arg);
+}
x11/gtk+3 crashes at WRKSRC/gtk/gtkpixelcache.c near line 386,
static void
gtk_pixel_cache_blow_cache (GtkPixelCache *cache)
{
g_clear_pointer (&cache->timeout_source, g_source_destroy);
g_clear_pointer (&cache->surface, cairo_surface_destroy);
g_clear_pointer (&cache->surface_dirty, cairo_region_destroy);
}
where g_clear_pointer is a macro. Two versions of the macro exist in
/usr/local/include/glib-2.0/glib/gmem.h; the version for compilers
other than gcc>=4.8 casts a function like g_source_destroy to
void (*)(void *), then calls it. The code must use the procedure
linkage table (PLT) to find g_source_destroy in libglib-2.0.
Back to wrap_puts(), the entire instruction sequence from
"gcc -O2 -S trial.c" is (with my added comments),
wrap_puts:
mflr 0
stwu 1,-48(1)
stw 30,40(1) # save %r30
stw 0,52(1) # save return address
bl puts+32768@plt # call puts(3)
lwz 0,52(1)
lwz 30,40(1) # restore %r30
addi 1,1,48
mtlr 0 # restore return address
blr # return
This "+32768" is an undocumented part of the secure PLT ABI. It needs
%r30 to point into .got2 (the secondary global offset table), but the
code to set %r30 is missing.
The crash is in the PLT stub, when the code tries to load the
address of puts(3) from some offset(%r30). There would be no crash if
the caller of wrap_puts() accidentally set %r30 to the expected value.
I placed wrap_puts() in its own shared object trial.so, so its caller
would not have the same .got2.
Power-Arch-32-bit-ABI-supp-1.0-Unified.pdf describes the
secure PLT, but doesn't document the +32768 and .got2 stuff.
>Fix:
The problem doesn't happen when I build wrap_puts() with
ports-gcc or with clang. It also doesn't happen at base-gcc -O0, but
does happen at -O1.
Some changes to the code in wrap_puts(), like changing the
pointer type to void (*)(const char *), or changing _arg_ to a
literal string, might avoid the problem.
It might be difficult to find all the code that causes this
bug; g_clear_pointer() uses might be too many. I would prefer to fix
the bug in base-gcc, but don't know how. There are 2 instances in
src/gnu/gcc/gcc/config/rs6000/rs6000.md of,
if (DEFAULT_ABI == ABI_V4 && TARGET_SECURE_PLT
&& flag_pic
&& GET_CODE (operands[0]) == SYMBOL_REF
&& !SYMBOL_REF_LOCAL_P (operands[0]))
{
...
use_reg (&CALL_INSN_FUNCTION_USAGE (call), pic_offset_table_rtx);
This use_reg (...) might set regs_ever_live[...] so rs6000.c would call
rs6000_emit_load_toc_table (TRUE) and emit the code to set %r30. I
suspect the cast of a function pointer gets around this code and misses
the use_reg (...), but I don't know.
(Here follows dmesg, pcidump, usbdevs for my iMac. The attachment has
the output of "eeprom -p", probably not useful for this bug.)
dmesg:
OpenBSD 6.6-current (GENERIC) #0: Fri Feb 14 08:49:11 EST 2020
[email protected]:/usr/src/sys/arch/macppc/compile/GENERIC
real mem = 536870912 (512MB)
avail mem = 504664064 (481MB)
mpath0 at root
scsibus0 at mpath0: 256 targets
mainbus0 at root: model PowerMac2,1
cpu0 at mainbus0: 750 (Revision 0x202): 400 MHz: 512KB backside cache
mem0 at mainbus0
spdmem0 at mem0: 256MB SDRAM non-parity PC133CL2
spdmem1 at mem0: 256MB SDRAM non-parity PC133CL2
memc0 at mainbus0: uni-n rev 0x3
kiic0 at memc0 offset 0xf8001000
iic0 at kiic0
mpcpcibr0 at mainbus0 pci: uni-north
pci0 at mpcpcibr0 bus 0
pchb0 at pci0 dev 11 function 0 "Apple Uni-N AGP" rev 0x00
agp at pchb0 not configured
vgafb0 at pci0 dev 16 function 0 "ATI Rage 128" rev 0x00, mmio
wsdisplay0 at vgafb0 mux 1: console (std, vt100 emulation)
wsdisplay0: screen 1-5 added (std, vt100 emulation)
mpcpcibr1 at mainbus0 pci: uni-north
pci1 at mpcpcibr1 bus 0
macobio0 at pci1 dev 23 function 0 "Apple Keylargo" rev 0x02
openpic0 at macobio0 offset 0x40000: version 0x4614 feature 3f0302 LE
macgpio0 at macobio0 offset 0x50
macgpio1 at macgpio0: irq 47
pgs0 at macgpio0: irq 55
"escc-legacy" at macobio0 offset 0x12000 not configured
zs0 at macobio0 offset 0x13000: irq 22,50
zstty0 at zs0 channel 0
zstty1 at zs0 channel 1
awacs0 at macobio0 offset 0x14000: irq 24,9,10 speaker
audio0 at awacs0
"timer" at macobio0 offset 0x15000 not configured
adb0 at macobio0 offset 0x16000
apm0 at adb0: battery flags 0x9, 0% charged
kiic1 at macobio0 offset 0x18000
iic1 at kiic1
wdc0 at macobio0 offset 0x1f000 irq 19: DMA
wd0 at wdc0 channel 0 drive 0: <Maxtor 91020U3>
wd0: 16-sector PIO, LBA, 9736MB, 19941264 sectors
atapiscsi0 at wdc0 channel 0 drive 1
scsibus1 at atapiscsi0: 2 targets
cd0 at scsibus1 targ 0 lun 0: <MATSHITA, DVD-ROM SR-8184, AA27> removable
wd0(wdc0:0:0): using PIO mode 4, DMA mode 2, Ultra-DMA mode 2
cd0(wdc0:0:1): using PIO mode 4, DMA mode 2, Ultra-DMA mode 2
wdc1 at macobio0 offset 0x20000 irq 20: DMA
wdc2 at macobio0 offset 0x21000 irq 21: DMA
"TI TSB12LV23 FireWire" rev 0x00 at pci1 dev 18 function 0 not configured
ohci0 at pci1 dev 24 function 0 "Apple USB" rev 0x00: irq 27, version 1.0
ohci1 at pci1 dev 25 function 0 "Apple USB" rev 0x00: irq 28, version 1.0
usb0 at ohci0: USB revision 1.0
uhub0 at usb0 configuration 1 interface 0 "Apple OHCI root hub" rev 1.00/1.00
addr 1
usb1 at ohci1: USB revision 1.0
uhub1 at usb1 configuration 1 interface 0 "Apple OHCI root hub" rev 1.00/1.00
addr 1
mpcpcibr2 at mainbus0 pci: uni-north
pci2 at mpcpcibr2 bus 0
gem0 at pci2 dev 15 function 0 "Apple Uni-N GMAC" rev 0x00: irq 41, address
00:0a:27:b1:66:00
bmtphy0 at gem0 phy 0: BCM5201 10/100 PHY, rev. 2
uhidev0 at uhub0 port 1 configuration 1 interface 0 "Logitech USB-PS/2 Optical
Mouse" rev 2.00/11.10 addr 2
uhidev0: iclass 3/1
ums0 at uhidev0: 3 buttons, Z dir
wsmouse0 at ums0 mux 0
uhidev1 at uhub1 port 1 configuration 1 interface 0 "CHESEN USB Keyboard" rev
1.10/1.10 addr 2
uhidev1: iclass 3/1
ukbd0 at uhidev1: 8 variable keys, 6 key codes, country code 33
wskbd0 at ukbd0: console keyboard, using wsdisplay0
uhidev2 at uhub1 port 1 configuration 1 interface 1 "CHESEN USB Keyboard" rev
1.10/1.10 addr 2
uhidev2: iclass 3/0, 3 report ids
uhid0 at uhidev2 reportid 2: input=1, output=0, feature=0
uhid1 at uhidev2 reportid 3: input=3, output=0, feature=0
vscsi0 at root
scsibus2 at vscsi0: 256 targets
softraid0 at root
scsibus3 at softraid0: 256 targets
bootpath: /pci@f2000000/mac-io@17/ata-4@1f000/disk@0:/bsd
root on wd0a (c3db149b5ec148e9.a) swap on wd0b dump on wd0b
WARNING: / was not properly unmounted
WARNING: clock lost 7285 days, using FS time -- CHECK AND RESET THE DATE!
usbdevs:
Controller /dev/usb0:
addr 01: 106b:0000 Apple, OHCI root hub
full speed, self powered, config 1, rev 1.00
driver: uhub0
addr 02: 046d:c00e Logitech, USB-PS/2 Optical Mouse
low speed, power 98 mA, config 1, rev 11.10
driver: uhidev0
Controller /dev/usb1:
addr 01: 106b:0000 Apple, OHCI root hub
full speed, self powered, config 1, rev 1.00
driver: uhub1
addr 02: 0a81:0101 CHESEN, USB Keyboard
low speed, power 100 mA, config 1, rev 1.10
driver: uhidev1
driver: uhidev2
pcidump:
Domain /dev/pci0:
0:11:0: Apple Uni-N AGP
0x0000: Vendor ID: 106b, Product ID: 0020
0x0004: Command: 0016, Status: 0230
0x0008: Class: 06 Bridge, Subclass: 00 Host,
Interface: 00, Revision: 00
0x000c: BIST: 00, Header Type: 00, Latency Timer: 10,
Cache Line Size: 08
0x0010: BAR empty (00000000)
0x0014: BAR empty (00000000)
0x0018: BAR empty (00000000)
0x001c: BAR empty (00000000)
0x0020: BAR empty (00000000)
0x0024: BAR empty (00000000)
0x0028: Cardbus CIS: 00000000
0x002c: Subsystem Vendor ID: 0000 Product ID: 0000
0x0030: Expansion ROM Base Address: 00000000
0x0038: 00000000
0x003c: Interrupt Pin: 00 Line: 00 Min Gnt: 00 Max Lat: 00
0x0080: Capability 0x02: AGP
0x0000: 0020106b 02300016 06000000 00001008
0x0010: 00000000 00000000 00000000 00000000
0x0020: 00000000 00000000 00000000 00000000
0x0030: 00000000 00000080 00000000 00000000
0x0040: 00000840 00000000 02000002 00000000
0x0050: 00000040 00000000 00000000 00000000
0x0060: 00000000 00000000 00000000 00000000
0x0070: 00000000 00000000 00000000 00000000
0x0080: 00100002 07000203 00000000 00000000
0x0090: 00000000 00000000 00000001 00000000
0x00a0: 00000000 00000000 00000000 00000000
0x00b0: 00000000 00000000 00000000 00000000
0x00c0: 00000000 00000000 00000000 00000000
0x00d0: 00000000 00000000 00000000 00000000
0x00e0: 00000000 00000000 00000000 00000000
0x00f0: 00000000 00000000 00000000 00000000
0:16:0: ATI Rage 128
0x0000: Vendor ID: 1002, Product ID: 524c
0x0004: Command: 0086, Status: 02b0
0x0008: Class: 03 Display, Subclass: 80 Miscellaneous,
Interface: 00, Revision: 00
0x000c: BIST: 00, Header Type: 00, Latency Timer: ff,
Cache Line Size: 08
0x0010: BAR mem prefetchable 32bit addr: 0x94000000/0x04000000
0x0014: BAR io addr: 0x00000400/0x0100
0x0018: BAR mem 32bit addr: 0x90000000/0x00004000
0x001c: BAR empty (00000000)
0x0020: BAR empty (00000000)
0x0024: BAR empty (00000000)
0x0028: Cardbus CIS: 00000000
0x002c: Subsystem Vendor ID: 1002 Product ID: 524c
0x0030: Expansion ROM Base Address: 90020000
0x0038: 00000000
0x003c: Interrupt Pin: 01 Line: ff Min Gnt: 08 Max Lat: 00
0x0050: Capability 0x02: AGP
0x005c: Capability 0x01: Power Management
State: D0
0x0000: 524c1002 02b00086 03800000 0000ff08
0x0010: 94000008 00000401 90000000 00000000
0x0020: 00000000 00000000 00000000 524c1002
0x0030: 90020000 00000050 00000000 000801ff
0x0040: 00000000 00000000 00000000 00000000
0x0050: 00205c02 1f000203 00000200 02010001
0x0060: 00000000 00000000 00000000 00000000
0x0070: 00000000 00000000 00000000 00000000
0x0080: 00000000 00000000 00000000 00000000
0x0090: 00000000 00000000 00000000 00000000
0x00a0: 00000000 00000000 00000000 00000000
0x00b0: 00000000 00000000 00000000 00000000
0x00c0: 00000000 00000000 00000000 00000000
0x00d0: 00000000 00000000 00000000 00000000
0x00e0: 00000000 00000000 00000000 00000000
0x00f0: 00000000 00000000 00000000 00000000
Domain /dev/pci1:
0:18:0: TI TSB12LV23 FireWire
0x0000: Vendor ID: 104c, Product ID: 8019
0x0004: Command: 0016, Status: 0210
0x0008: Class: 0c Serial Bus, Subclass: 00 FireWire,
Interface: 10, Revision: 00
0x000c: BIST: 00, Header Type: 00, Latency Timer: 10,
Cache Line Size: 08
0x0010: BAR mem 32bit addr: 0x80082000/0x00000800
0x0014: BAR mem 32bit addr: 0x80084000/0x00004000
0x0018: BAR empty (00000000)
0x001c: BAR empty (00000000)
0x0020: BAR empty (00000000)
0x0024: BAR empty (00000000)
0x0028: Cardbus CIS: 00000000
0x002c: Subsystem Vendor ID: 0000 Product ID: 0000
0x0030: Expansion ROM Base Address: 00000000
0x0038: 00000000
0x003c: Interrupt Pin: 01 Line: 00 Min Gnt: 02 Max Lat: 04
0x0044: Capability 0x01: Power Management
State: D0
0x0000: 8019104c 02100016 0c001000 00001008
0x0010: 80082000 80084000 00000000 00000000
0x0020: 00000000 00000000 00000000 00000000
0x0030: 00000000 00000044 00000000 04020100
0x0040: 00000000 64110001 00000000 00000000
0x0050: 00000000 00000000 00000000 00000000
0x0060: 00000000 00000000 00000000 00000000
0x0070: 00000000 00000000 00000000 00000000
0x0080: 00000000 00000000 00000000 00000000
0x0090: 00000000 00000000 00000000 00000000
0x00a0: 00000000 00000000 00000000 00000000
0x00b0: 00000000 00000000 00000000 00000000
0x00c0: 00000000 00000000 00000000 00000000
0x00d0: 00000000 00000000 00000000 00000000
0x00e0: 00000000 00000000 00000000 00000000
0x00f0: 00002400 00001000 00000000 00000000
0:23:0: Apple Keylargo
0x0000: Vendor ID: 106b, Product ID: 0022
0x0004: Command: 0016, Status: 0200
0x0008: Class: ff (unknown), Subclass: 00 (unknown),
Interface: 00, Revision: 02
0x000c: BIST: 00, Header Type: 00, Latency Timer: 10,
Cache Line Size: 08
0x0010: BAR mem 32bit addr: 0x80000000/0x00080000
0x0014: BAR empty (00000000)
0x0018: BAR empty (00000000)
0x001c: BAR empty (00000000)
0x0020: BAR empty (00000000)
0x0024: BAR empty (00000000)
0x0028: Cardbus CIS: 00000000
0x002c: Subsystem Vendor ID: 0000 Product ID: 0000
0x0030: Expansion ROM Base Address: 00000000
0x0038: 00000000
0x003c: Interrupt Pin: 00 Line: 00 Min Gnt: 00 Max Lat: 00
0x0000: 0022106b 02000016 ff000002 00001008
0x0010: 80000000 00000000 00000000 00000000
0x0020: 00000000 00000000 00000000 00000000
0x0030: 00000000 00000000 00000000 00000000
0x0040: 00000000 00000000 00000000 00000000
0x0050: 00000000 00000000 00000000 00000000
0x0060: 00000000 00000000 00000000 00000000
0x0070: 00000000 00000000 00000000 00000000
0x0080: 00000000 00000000 00000000 00000000
0x0090: 00000000 00000000 00000000 00000000
0x00a0: 00000000 00000000 00000000 00000000
0x00b0: 00000000 00000000 00000000 00000000
0x00c0: 00000000 00000000 00000000 00000000
0x00d0: 00000000 00000000 00000000 00000000
0x00e0: 00000000 00000000 00000000 00000000
0x00f0: 00000000 00000000 00000000 00000000
0:24:0: Apple USB
0x0000: Vendor ID: 106b, Product ID: 0019
0x0004: Command: 0006, Status: 0200
0x0008: Class: 0c Serial Bus, Subclass: 03 USB,
Interface: 10, Revision: 00
0x000c: BIST: 00, Header Type: 00, Latency Timer: 10,
Cache Line Size: 00
0x0010: BAR mem 32bit addr: 0x80081000/0x00001000
0x0014: BAR empty (00000000)
0x0018: BAR empty (00000000)
0x001c: BAR empty (00000000)
0x0020: BAR empty (00000000)
0x0024: BAR empty (00000000)
0x0028: Cardbus CIS: 00000000
0x002c: Subsystem Vendor ID: 0000 Product ID: 0000
0x0030: Expansion ROM Base Address: 00000000
0x0038: 00000000
0x003c: Interrupt Pin: 01 Line: 00 Min Gnt: 03 Max Lat: 56
0x0000: 0019106b 02000006 0c031000 00001000
0x0010: 80081000 00000000 00000000 00000000
0x0020: 00000000 00000000 00000000 00000000
0x0030: 00000000 00000000 00000000 56030100
0x0040: 00000000 00000000 00000000 00000000
0x0050: 00000000 00000000 00000000 00000000
0x0060: 00000000 00000000 00000000 00000000
0x0070: 00000000 00000000 00000000 00000000
0x0080: 00000000 00000000 00000000 00000000
0x0090: 00000000 00000000 00000000 00000000
0x00a0: 00000000 00000000 00000000 00000000
0x00b0: 00000000 00000000 00000000 00000000
0x00c0: 00000000 00000000 00000000 00000000
0x00d0: 00000000 00000000 00000000 00000000
0x00e0: 00000000 00000000 00000000 00000000
0x00f0: 00000000 00000000 00000000 00000000
0:25:0: Apple USB
0x0000: Vendor ID: 106b, Product ID: 0019
0x0004: Command: 0006, Status: 0200
0x0008: Class: 0c Serial Bus, Subclass: 03 USB,
Interface: 10, Revision: 00
0x000c: BIST: 00, Header Type: 00, Latency Timer: 10,
Cache Line Size: 00
0x0010: BAR mem 32bit addr: 0x80080000/0x00001000
0x0014: BAR empty (00000000)
0x0018: BAR empty (00000000)
0x001c: BAR empty (00000000)
0x0020: BAR empty (00000000)
0x0024: BAR empty (00000000)
0x0028: Cardbus CIS: 00000000
0x002c: Subsystem Vendor ID: 0000 Product ID: 0000
0x0030: Expansion ROM Base Address: 00000000
0x0038: 00000000
0x003c: Interrupt Pin: 01 Line: 00 Min Gnt: 03 Max Lat: 56
0x0000: 0019106b 02000006 0c031000 00001000
0x0010: 80080000 00000000 00000000 00000000
0x0020: 00000000 00000000 00000000 00000000
0x0030: 00000000 00000000 00000000 56030100
0x0040: 00000000 00000000 00000000 00000000
0x0050: 00000000 00000000 00000000 00000000
0x0060: 00000000 00000000 00000000 00000000
0x0070: 00000000 00000000 00000000 00000000
0x0080: 00000000 00000000 00000000 00000000
0x0090: 00000000 00000000 00000000 00000000
0x00a0: 00000000 00000000 00000000 00000000
0x00b0: 00000000 00000000 00000000 00000000
0x00c0: 00000000 00000000 00000000 00000000
0x00d0: 00000000 00000000 00000000 00000000
0x00e0: 00000000 00000000 00000000 00000000
0x00f0: 00000000 00000000 00000000 00000000
Domain /dev/pci2:
0:15:0: Apple Uni-N GMAC
0x0000: Vendor ID: 106b, Product ID: 0021
0x0004: Command: 0016, Status: 84a0
0x0008: Class: 02 Network, Subclass: 00 Ethernet,
Interface: 00, Revision: 00
0x000c: BIST: 00, Header Type: 00, Latency Timer: 10,
Cache Line Size: 08
0x0010: BAR mem 32bit addr: 0xf5200000/0x00200000
0x0014: BAR empty (00000000)
0x0018: BAR empty (00000000)
0x001c: BAR empty (00000000)
0x0020: BAR empty (00000000)
0x0024: BAR empty (00000000)
0x0028: Cardbus CIS: 00000000
0x002c: Subsystem Vendor ID: 0000 Product ID: 0000
0x0030: Expansion ROM Base Address: f5000000
0x0038: 00000000
0x003c: Interrupt Pin: 01 Line: ff Min Gnt: 40 Max Lat: 40
0x0000: 0021106b 84a00016 02000000 00001008
0x0010: f5200000 00000000 00000000 00000000
0x0020: 00000000 00000000 00000000 00000000
0x0030: f5000000 00000000 00000000 404001ff
0x0040: 00000000 00000000 00000000 00000000
0x0050: 00000000 00000000 00000000 00000000
0x0060: 00000000 00000000 00000000 00000000
0x0070: 00000000 00000000 00000000 00000000
0x0080: 00000000 00000000 00000000 00000000
0x0090: 00000000 00000000 00000000 00000000
0x00a0: 00000000 00000000 00000000 00000000
0x00b0: 00000000 00000000 00000000 00000000
0x00c0: 00000000 00000000 00000000 00000000
0x00d0: 00000000 00000000 00000000 00000000
0x00e0: 00000000 00000000 00000000 00000000
0x00f0: 00000000 00000000 00000000 00000000
acpidump:
eeprom-p.gz
Description: Binary data
