broken configuration test with fortify source

Bug #601030 reported by Matthias Klose
14
This bug affects 2 people
Affects Status Importance Assigned to Milestone
GLibC
Fix Released
Medium
Linaro GCC
Invalid
Undecided
Unassigned
Linaro Toolchain Miscellanies
Fix Released
High
Chung-Lin Tang
eglibc (Ubuntu)
Fix Released
High
Unassigned
Lucid
Won't Fix
Medium
Unassigned
Maverick
Fix Released
High
Unassigned
gawk (Ubuntu)
Fix Released
Undecided
Canonical Foundations Team
Lucid
Invalid
Undecided
Unassigned
Maverick
Fix Released
Undecided
Canonical Foundations Team

Bug Description

Binary package hint: gcc-4.4

gcc-4.4 -g -O2 -U_FORTIFY_SOURCE -Wall conftest.c && ./a.out
works
while
gcc-4.4 -g -O2 -Wall conftest.c && ./a.out
does not (hangs). 4.3 and 4.5 do work, -O1 as well.

Tags: amd64 patch

Related branches

Revision history for this message
Matthias Klose (doko) wrote :
Revision history for this message
Matthias Klose (doko) wrote :

seen on amd64

Changed in gcc-4.4 (Ubuntu Maverick):
importance: Undecided → High
milestone: none → maverick-alpha-3
status: New → Confirmed
Revision history for this message
Matthias Klose (doko) wrote :

breaks the gawk build on amd64

Changed in gawk (Ubuntu Maverick):
importance: Undecided → High
milestone: none → maverick-alpha-3
status: New → Confirmed
Martin Pitt (pitti)
Changed in gawk (Ubuntu Maverick):
milestone: maverick-alpha-3 → ubuntu-10.10-beta
Changed in gcc-4.4 (Ubuntu Maverick):
milestone: maverick-alpha-3 → ubuntu-10.10-beta
Changed in gcc-4.4 (Ubuntu Maverick):
assignee: nobody → Canonical Foundations Team (canonical-foundations)
Changed in gawk (Ubuntu Maverick):
assignee: nobody → Canonical Foundations Team (canonical-foundations)
Revision history for this message
Colin Watson (cjwatson) wrote :

I can't seem to reproduce this in current Maverick; gawk builds fine.

Revision history for this message
Matthias Klose (doko) wrote :

still reproducible for me on maverick, note that on Debian/sid, it does work:

gcc-4.4 -g -O2 -fstack-protector -D_FORTIFY_SOURCE -Wall conftest.c && ./a.out

Revision history for this message
Matthias Klose (doko) wrote :

the test succeeds with gcc-4.4 in maverick built without the Linaro patchset.

Revision history for this message
Colin Watson (cjwatson) wrote :

Confirmed in ronne's maverick amd64 chroot. Attached conftest.c and preprocessed source. strace shows:

...
setrlimit(RLIMIT_STACK, {rlim_cur=1024*1024, rlim_max=1024*1024}) = 0
sigaltstack({ss_sp=0x7fffd7df0130, ss_flags=0, ss_size=8192}, NULL) = 0
rt_sigaction(SIGSEGV, {0x4008d0, [], SA_RESTORER|SA_STACK, 0x7f6373fe0c20}, NULL, 8) = 0
rt_sigaction(SIGBUS, {0x4008d0, [], SA_RESTORER|SA_STACK, 0x7f6373fe0c20}, NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [], [], 8) = 0
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
sigaltstack(NULL, {ss_sp=0x7fffd7df0130, ss_flags=SS_ONSTACK, ss_size=8192}) = 0
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
sigaltstack(NULL, {ss_sp=0x7fffd7df0130, ss_flags=SS_ONSTACK, ss_size=8192}) = 0
[repeats]

Revision history for this message
Colin Watson (cjwatson) wrote :
Revision history for this message
Colin Watson (cjwatson) wrote :

It seems to go into the same infinite loop under strace both with -O2 and -O1, although -O1 exits normally and immediately without strace.

Revision history for this message
Colin Watson (cjwatson) wrote :

I went through all the optimisations that are in -O2 but not -O1 (-falign-functions -falign-jumps -falign-labels -fcaller-saves -fcrossjumping -fcse-follow-jumps -fdelete-null-pointer-checks -fexpensive-optimizations -fforward-propagate -fgcse -finline-small-functions -fipa-cp -foptimize-register-move -foptimize-sibling-calls -fpeephole2 -fregmove -freorder-blocks -freorder-functions -frerun-cse-after-loop -fschedule-insns2 -fstrict-aliasing -fthread-jumps -ftree-builtin-call-dce -ftree-pre -ftree-switch-conversion -ftree-vrp). Not a single one of them produces this effect reliably, but the bulk of them produce it sometimes.

Loïc Minier (lool)
tags: added: amd64
Revision history for this message
Michael Hope (michaelh1) wrote :

The fault occurs as the 'pass' value given to longjmp() gets corrupted before use by setjmp(), causing the 'setjmp() < 2' test to fail and the system to loop forever. The only assembler level fortify/non-fortify difference is a call to longjmp_chk instead of longjmp.

Note that shifting 'mystack' off the stack and into static memory also works around the problem.

(Tested using gcc 4.4.4-9ubuntu1)

Revision history for this message
Michael Hope (michaelh1) wrote :

eglibc-2.11.1/sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S is broken. It saves the value of 'pass' in ecx for later use but ecx is trashed by a syscall.

The syscall is used to bring in the signal stack so that the fortify code can print an error message if needed. The problem goes away with -U_FORTIFY_SOURCE as no such syscall is used.

Michael Hope (michaelh1)
Changed in gcc-linaro:
status: New → Invalid
Changed in linaro-toolchain-misc:
importance: Undecided → High
assignee: nobody → Chung-Lin Tang (cltang)
status: New → Confirmed
Revision history for this message
Kees Cook (kees) wrote :

FWIW, this is broken on Lucid too. I've attached a slightly more minimal testcase that disables stack randomization and adds an alarm call to make the loop more obvious.

Revision history for this message
Kees Cook (kees) wrote :
Revision history for this message
Kees Cook (kees) wrote :

Oh, and it fails for me with gcc-4.3 and gcc-4.5 as well. I think the differences in failure modes was due to stack randomization somehow.

Revision history for this message
In , Kees Cook (kees) wrote :

Since 2.11 and later, it seems that longjmp will fail on x86_64 when
_FORTIFY_SOURCE is enabled.

Works on x86_32, and 2.10 and earlier.

https://launchpad.net/bugs/601030

Revision history for this message
In , Kees Cook (kees) wrote :

Created attachment 4962
reproducer

Here is the reproducer. This dies on alarm on Ubuntu x86_64 (eglibc 2.11 and
2.12) and Fedora x86_64 (2.12) when using more recent glibc:

$ gcc -O2 -fno-stack-protector -D_FORTIFY_SOURCE=2 -Wall minimal.c -o minimal
/tmp
$ ./minimal
Alarm Clock

It doesn't always fail, and I tried to mitigate this by disabling ASLR.

Michael Hope noticed:

"The fault occurs as the 'pass' value given to longjmp() gets corrupted before
use by setjmp(), causing the 'setjmp() < 2' test to fail and the system to loop
forever. The only assembler level fortify/non-fortify difference is a call to
longjmp_chk instead of longjmp.

Note that shifting 'mystack' off the stack and into static memory also works
around the problem.

glibc-2.11.1/sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S is broken. It
saves the value of 'pass' in ecx for later use but ecx is trashed by a syscall.

The syscall is used to bring in the signal stack so that the fortify code can
print an error message if needed. The problem goes away with -U_FORTIFY_SOURCE
as no such syscall is used."

affects: gcc-4.4 (Ubuntu Maverick) → eglibc (Ubuntu Maverick)
Changed in gawk (Ubuntu Maverick):
status: Confirmed → Invalid
importance: High → Undecided
Kees Cook (kees)
Changed in eglibc (Ubuntu Lucid):
status: New → Confirmed
Changed in gawk (Ubuntu Lucid):
status: New → Invalid
Changed in eglibc (Ubuntu Lucid):
importance: Undecided → Medium
Changed in glibc:
status: Unknown → Confirmed
Revision history for this message
In , Drepper-fsp (drepper-fsp) wrote :

Fixed in git.

Revision history for this message
In , Kees Cook (kees) wrote :
Revision history for this message
Kees Cook (kees) wrote :
Matthias Klose (doko)
Changed in eglibc (Ubuntu Maverick):
assignee: Canonical Foundations Team (canonical-foundations) → nobody
milestone: ubuntu-10.10-beta → ubuntu-10.10
status: Confirmed → In Progress
tags: added: patch
Revision history for this message
Matthias Klose (doko) wrote :

fixed in maverick, and gawk built

Changed in eglibc (Ubuntu Maverick):
status: In Progress → Fix Released
Changed in gawk (Ubuntu Maverick):
milestone: ubuntu-10.10-beta → none
status: Invalid → Fix Released
Changed in glibc:
importance: Unknown → Medium
status: Confirmed → Fix Released
Changed in linaro-toolchain-misc:
status: Confirmed → Fix Released
Revision history for this message
Rolf Leggewie (r0lf) wrote :

lucid has seen the end of its life and is no longer receiving any updates. Marking the lucid task for this ticket as "Won't Fix".

Changed in eglibc (Ubuntu Lucid):
status: Confirmed → Won't Fix
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.