NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
toolchain/59994: gcc/m68k generates bad code for stack protector
>Number: 59994
>Category: toolchain
>Synopsis: gcc/m68k generates bad code for stack protector
>Confidential: no
>Severity: serious
>Priority: high
>Responsible: toolchain-manager
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Wed Feb 11 07:00:00 +0000 2026
>Originator: Michael van Elst
>Release: NetBSD 11.0_RC1
>Organization:
--
Michael van Elst
Internet: mlelstv%serpens.de@localhost
"A potential Snark may lurk in every tree."
>Environment:
System: NetBSD serpens.de 11.0_RC1 NetBSD 11.0_RC1 (SERPENS) #0: Sat Feb 7 12:30:40 UTC 2026 root%aries.NetBSD.de@localhost:/home/netbsd/11/arch/amiga/obj/sys/arch/amiga/compile/SERPENS amiga
Architecture: m68k
Machine: amiga
>Description:
mutt from pkgsrc aborts when trying to forward a mail on a NetBSD/m68k-11.0RC1
system:
> #0 0x0ec23d8c in _lwp_kill () from /usr/lib/libc.so.12
> #1 0x0ec23702 in raise () from /usr/lib/libc.so.12
> #2 0x0ec0c274 in ?? () from /usr/lib/libc.so.12
> #3 0x0ec0c296 in __stack_chk_fail () from /usr/lib/libc.so.12
This is caused by gcc generating bad code for the stack protector.
A simple reproducer is:
#include <stdio.h>
extern void bar(const char *);
void foo(unsigned x)
{
char buf[1024];
snprintf(buf, sizeof(buf), "%u\n", x);
bar(buf);
}
Compiling with:
cc -fstack-protector -O -S c.c
generates the following code:
#NO_APP
.file "c.c"
.text
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "%u\n"
.text
.align 2
.globl foo
.type foo, @function
foo:
.LFB3:
.cfi_startproc
lea (-1028,%sp),%sp
.cfi_def_cfa_offset 1032
move.l %d2,-(%sp)
.cfi_def_cfa_offset 1036
.cfi_offset 2, -1036
move.w 1028(%sp),%d0
move.w 1030(%sp),%d0
move.l __stack_chk_guard,%d0
move.l 1036(%sp),-(%sp)
.cfi_def_cfa_offset 1040
pea .LC0
.cfi_def_cfa_offset 1044
pea 1024.w
.cfi_def_cfa_offset 1048
moveq #16,%d2
add.l %sp,%d2
move.l %d2,-(%sp)
.cfi_def_cfa_offset 1052
jsr snprintf
move.l %d2,-(%sp)
.cfi_def_cfa_offset 1056
jsr bar
lea (20,%sp),%sp
.cfi_def_cfa_offset 1036
move.w 1028(%sp),%d0
swap %d0
clr.w %d0
move.w 1030(%sp),%d1
or.w %d1,%d0
move.l __stack_chk_guard,%d1
cmp.l %d1,%d0
jne .L3
move.l (%sp)+,%d2
lea (1028,%sp),%sp
rts
.L3:
jsr __stack_chk_fail
.cfi_endproc
.LFE3:
.size foo, .-foo
.ident "GCC: (nb1 20260119) 12.5.0"
The stack check code at the end of the function is bad but correct,
maybe a consequence of trying to be coldfire compatible.
- assemble 32bit value from stack
move.w 1028(%sp),%d0
swap %d0
clr.w %d0
move.w 1030(%sp),%d1
or.w %d1,%d0
- fetch 32bit guard value
move.l __stack_chk_guard,%d1
- compare both
cmp.l %d1,%d0
The setup code is nonsense:
- read 32bit value from stack, but throw it away
move.w 1028(%sp),%d0
move.w 1030(%sp),%d0
- read 32bit guard value (and don't use it either).
move.l __stack_chk_guard,%d0
Instead of seeding the longword on the stack with the random
guard value, it just _reads_ the stack and the guard value.
>How-To-Repeat:
Compile reproducer.
Adding a simple main program:
#include <stdio.h>
extern void foo(unsigned);
void bar(const char *p)
{
puts(p);
}
int main()
{
foo(42);
return 0;
}
results in an abort when compiled with stack protector:
% ./a.out
42
Abort
>Fix:
>Unformatted:
Home |
Main Index |
Thread Index |
Old Index