FS#12559 - -O breaks sigaltstack threads in Ubuntu due to _FORTIFY_SOURCE

Attached to Project: Rockbox
Opened by Boris Gjenero (dreamlayers) - Monday, 23 January 2012, 05:53 GMT
Last edited by Boris Gjenero (dreamlayers) - Friday, 27 January 2012, 01:37 GMT
Task Type Bugs
Category Simulator
Status Closed
Assigned To No-one
Operating System All players
Severity Low
Priority Normal
Reported Version Daily build (which?)
Due in Version Undecided
Due Date Undecided
Percent Complete 100%
Votes 0
Private No


When I try to run a simulator compiled with default settings in amd64 Xubuntu 11.10, it hangs with:
*** longjmp causes uninitialized stack frame ***: /home/bgjenero/Rockbox/rockbox/build1sim/rockboxui terminated

Ubuntu sets _FORTIFY_SOURCE to 2. The gcc man page claims it is "activated when -O is set to 2 or higher", but this means it's also activated by just -O, which is equivalent to -O1. The problem goes away if I recompile firmware/threads.o with -U_FORTIFY_SOURCE. It remains if I use -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1.

Fortify doesn't like the longjmp() near the end of make_context() in firmware/asm/thread-unix.c. It's a jump to the setjmp() in trampoline(). trampoline() was called earlier as signal handler, in response to a signal sent from make_context(). The stack frame was definitely initialized, because make_context() waits for sig_handler_called to be set by trampoline().

As a simple workaround, you use SDL threads by giving the --sdl-threads argument to configure.

Here is a partial gdb backtrace:
#12 0x00007ffff71fb7f7 in __fortify_fail ()
from /lib/x86_64-linux-gnu/
#13 0x00007ffff71fb789 in ?? () from /lib/x86_64-linux-gnu/
#14 0x00007ffff71fb6f3 in __longjmp_chk () from /lib/x86_64-linux-gnu/
#15 0x0000000000462844 in make_context (ctx=0x898b08,
f=0x4668d0 <scroll_thread>,
sp=0x8ae9c0 <<snipped out junk here>>
at /home/bgjenero/Rockbox/rockbox/firmware/asm/thread-unix.c:186
#16 0x0000000000463943 in setup_thread (context=0x4882c58)
at /home/bgjenero/Rockbox/rockbox/firmware/asm/thread-unix.c:277
#17 load_context (addr=0x4882c58)
at /home/bgjenero/Rockbox/rockbox/firmware/asm/thread-unix.c:303
#18 switch_thread () at /home/bgjenero/Rockbox/rockbox/firmware/thread.c:1256
#19 0x0000000000460576 in sleep (ticks=25)
at /home/bgjenero/Rockbox/rockbox/firmware/kernel.c:247
#20 0x0000000000406e8c in init_tagcache ()
at /home/bgjenero/Rockbox/rockbox/apps/main.c:329
#21 init () at /home/bgjenero/Rockbox/rockbox/apps/main.c:390
#22 main (argc=<optimized out>, argv=<optimized out>)
at /home/bgjenero/Rockbox/rockbox/apps/main.c:163
This task depends upon

Closed by  Boris Gjenero (dreamlayers)
Friday, 27 January 2012, 01:37 GMT
Reason for closing:  Fixed
Additional comments about closing:  f4954c4
Comment by Thomas Martitz (kugel.) - Monday, 23 January 2012, 09:41 GMT
Can we undef _FORTIFY_SOURCE for that file only?
Comment by Thomas Martitz (kugel.) - Monday, 23 January 2012, 10:20 GMT
Alternatively: Apply something similar to ?
Comment by Boris Gjenero (dreamlayers) - Monday, 23 January 2012, 17:51 GMT
_FORTIFY_SOURCE just needs to be disabled before including setjmp.h. This can't be done in thread-unix.c because something included from thread.c includes setjmp.h. It can be done from thread.c, like in the attached patch. I'm don't know if you'll like the use of HAVE_SIGALTSTACK_THREADS in thread.c. Alternatively, the #undef could unconditional, before any include.

Here's the failing check:
What it accepts is ( destination sp >= current sp ) or ( the alternate signal stack being used now and destination sp is outside of the alternate signal stack ). This check is only helpful when using longjmp() in the conventional way.

I think disabling fortify is a better solution than trying to undo longjmp() redirection. The redirection could be dependent on the platform or C library version.
Comment by Thomas Martitz (kugel.) - Wednesday, 25 January 2012, 21:38 GMT
Looks good to me. I had considered undefing it unconditionally and before including anything, but this works too I guess.