Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 326285 - sys-devel/gcc: files compiled with -fstack-protector -fPIE refer to hidden symbol __stack_chk_fail_local on 32-bit x86 and ppc
Summary: sys-devel/gcc: files compiled with -fstack-protector -fPIE refer to hidden sy...
Status: RESOLVED INVALID
Alias: None
Product: Gentoo Linux
Classification: Unclassified
Component: Hardened (show other bugs)
Hardware: x86 Linux
: High normal (vote)
Assignee: The Gentoo Linux Hardened Team
URL:
Whiteboard:
Keywords:
Depends on: 747346
Blocks: 325849
  Show dependency tree
 
Reported: 2010-06-30 09:42 UTC by Anthony Basile
Modified: 2020-10-08 16:54 UTC (History)
2 users (show)

See Also:
Package list:
Runtime testing required: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Anthony Basile gentoo-dev 2010-06-30 09:42:31 UTC
When compiling on x86 or 32-bit ppc, object files are produced with unresolved symbol __stack_chk_fail_local.  This is a problem because this is a hidden symbol in glibc and will cause linker problems when creating shared libraries, for example.  On their 64-bit equivalents, these object files have the correct symbol __stack_chk_fail.

Reproducible: Always

Steps to Reproduce:
1. echo "void doit1() {}" > test1.c
2. echo "void doit2() {}" > test2.c
3. gcc -c test1.c
4. gcc -c test2.c
5. ld -shared -o libtest.so test1.o test2.o #fails
6. gcc -Xlinker -shared -o libtest.so test1.o test2.o #succeeds




I give the full symbol tables for x86, x86_64, ppc and ppc64 below.
Comment 1 Anthony Basile gentoo-dev 2010-06-30 09:46:08 UTC
Here's the symbol table for x86:

# nm test1.o
         U __stack_chk_fail_local
00000000 T doit1

# ld -shared -o libtest.so test1.o test2.o
test1.o: In function `doit1':
test1.c:(.text+0x1e): undefined reference to `__stack_chk_fail_local'
test2.o: In function `doit2':
test2.c:(.text+0x1e): undefined reference to `__stack_chk_fail_local'
ld: libtest.so: hidden symbol `__stack_chk_fail_local' isn't defined
ld: final link failed: Nonrepresentable section on output

# gcc -Xlinker -shared -o libtest.so test1.o test2.o

# nm libtest.so 
00001ef4 a _DYNAMIC
00001fd4 a _GLOBAL_OFFSET_TABLE_
000006b8 R _IO_stdin_used
         w _Jv_RegisterClasses
00001eec D __DTOR_END__
00002008 A __bss_start
         w __cxa_finalize@@GLIBC_2.1.3
00002000 D __data_start
00002004 D __dso_handle
         w __gmon_start__
00000577 T __i686.get_pc_thunk.bx
00001ee0 d __init_array_end
00001ee0 d __init_array_start
000005d0 T __libc_csu_fini
000005e0 T __libc_csu_init
         U __libc_start_main@@GLIBC_2.0
         U __stack_chk_fail@@GLIBC_2.4
00000640 T __stack_chk_fail_local
00002008 A _edata
00002010 A _end
00000698 T _fini
000006b4 R _fp_hw
000003f0 T _init
00000460 T _start
00002000 W data_start
0000057c T doit1
000005a0 T doit2
         U main
Comment 2 Anthony Basile gentoo-dev 2010-06-30 09:48:18 UTC
Here's the symbol table for amd64:

# nm test1.o 
                 U _GLOBAL_OFFSET_TABLE_
                 U __stack_chk_fail
0000000000000000 T doit1

# ld -shared -o libtest.so test1.o test2.o
# nm libtest.so 
0000000000200ee8 a _DYNAMIC
0000000000200fe8 a _GLOBAL_OFFSET_TABLE_
0000000000201008 A __bss_start
                 U __stack_chk_fail
0000000000201008 A _edata
0000000000201008 A _end
0000000000000330 T doit1
0000000000000360 T doit2

# rm libtest.so 
# gcc -Xlinker -shared -o libtest.so test1.o test2.o
# nm libtest.so 
0000000000200de0 a _DYNAMIC
0000000000200fa0 a _GLOBAL_OFFSET_TABLE_
00000000000008f8 R _IO_stdin_used
                 w _Jv_RegisterClasses
0000000000200dd0 D __DTOR_END__
0000000000201010 A __bss_start
                 w __cxa_finalize@@GLIBC_2.2.5
0000000000201000 D __data_start
0000000000201008 D __dso_handle
                 w __gmon_start__
0000000000200db4 d __init_array_end
0000000000200db4 d __init_array_start
0000000000000810 T __libc_csu_fini
0000000000000820 T __libc_csu_init
                 U __libc_start_main@@GLIBC_2.2.5
                 U __stack_chk_fail@@GLIBC_2.4
0000000000201010 A _edata
0000000000201020 A _end
00000000000008e8 T _fini
0000000000000650 T _init
00000000000006b0 T _start
0000000000201000 W data_start
00000000000007ac T doit1
00000000000007dc T doit2
                 U main

Comment 3 Anthony Basile gentoo-dev 2010-06-30 09:50:51 UTC
# nm test1.o 
         U __stack_chk_fail_local
00000000 T doit1

# ld -shared -o libtest.so test1.o test2.o 
test1.o: In function `doit1':
test1.c:(.text+0x4c): undefined reference to `__stack_chk_fail_local'
test2.o: In function `doit2':
test2.c:(.text+0x4c): undefined reference to `__stack_chk_fail_local'
ld: libtest.so: hidden symbol `__stack_chk_fail_local' isn't defined
ld: final link failed: Nonrepresentable section on output

# gcc -Xlinker -shared -o libtest.so test1.o test2.o 
# nm libtest.so 
00000920 t 00000000.plt_pic32.__gmon_start__
00000930 t 00000000.plt_pic32.__libc_start_main@@GLIBC_2.0
00000950 t 00008000.got2.plt_pic32.__cxa_finalize@@GLIBC_2.1.3
00000940 t 00008000.got2.plt_pic32.__stack_chk_fail@@GLIBC_2.4
00010ef8 a _DYNAMIC
00010fe4 a _GLOBAL_OFFSET_TABLE_
000009e8 R _IO_stdin_used
         w _Jv_RegisterClasses
00019018 D _SDA_BASE_
00010ec4 D __DTOR_END__
00011018 A __bss_start
         w __cxa_finalize@@GLIBC_2.1.3
00011010 D __data_start
00011014 D __dso_handle
00000960 t __glink
00000970 t __glink_PLTresolve
         w __gmon_start__
00010eb8 d __init_array_end
00010eb8 d __init_array_start
000007bc T __libc_csu_fini
000007c0 T __libc_csu_init
         U __libc_start_main@@GLIBC_2.0
         U __stack_chk_fail@@GLIBC_2.4
00000874 T __stack_chk_fail_local
00011018 A _edata
00011020 A _end
000009b0 T _fini
000004e4 T _init
00000510 T _start
00011010 W data_start
000006e4 T doit1
00000750 T doit2
         U main
Comment 4 Anthony Basile gentoo-dev 2010-06-30 09:51:48 UTC
It should be obvious from the symbol table, but I forgot to say this is for 32-bit ppc.


(In reply to comment #3)
> # nm test1.o 
>          U __stack_chk_fail_local
> 00000000 T doit1
> 
> # ld -shared -o libtest.so test1.o test2.o 
> test1.o: In function `doit1':
> test1.c:(.text+0x4c): undefined reference to `__stack_chk_fail_local'
> test2.o: In function `doit2':
> test2.c:(.text+0x4c): undefined reference to `__stack_chk_fail_local'
> ld: libtest.so: hidden symbol `__stack_chk_fail_local' isn't defined
> ld: final link failed: Nonrepresentable section on output
> 
> # gcc -Xlinker -shared -o libtest.so test1.o test2.o 
> # nm libtest.so 
> 00000920 t 00000000.plt_pic32.__gmon_start__
> 00000930 t 00000000.plt_pic32.__libc_start_main@@GLIBC_2.0
> 00000950 t 00008000.got2.plt_pic32.__cxa_finalize@@GLIBC_2.1.3
> 00000940 t 00008000.got2.plt_pic32.__stack_chk_fail@@GLIBC_2.4
> 00010ef8 a _DYNAMIC
> 00010fe4 a _GLOBAL_OFFSET_TABLE_
> 000009e8 R _IO_stdin_used
>          w _Jv_RegisterClasses
> 00019018 D _SDA_BASE_
> 00010ec4 D __DTOR_END__
> 00011018 A __bss_start
>          w __cxa_finalize@@GLIBC_2.1.3
> 00011010 D __data_start
> 00011014 D __dso_handle
> 00000960 t __glink
> 00000970 t __glink_PLTresolve
>          w __gmon_start__
> 00010eb8 d __init_array_end
> 00010eb8 d __init_array_start
> 000007bc T __libc_csu_fini
> 000007c0 T __libc_csu_init
>          U __libc_start_main@@GLIBC_2.0
>          U __stack_chk_fail@@GLIBC_2.4
> 00000874 T __stack_chk_fail_local
> 00011018 A _edata
> 00011020 A _end
> 000009b0 T _fini
> 000004e4 T _init
> 00000510 T _start
> 00011010 W data_start
> 000006e4 T doit1
> 00000750 T doit2
>          U main
> 

Comment 5 Anthony Basile gentoo-dev 2010-06-30 09:54:12 UTC
Here's the symbol table for ppc64:

# nm test1.o 
                 U __stack_chk_fail
0000000000000000 D doit1


# ld -shared -o libtest.so test1.o test2.o
# nm libtest.so 
0000000000000350 t 00000010.plt_call.__stack_chk_fail+0
0000000000010ec0 a _DYNAMIC
0000000000011038 A __bss_start
0000000000000430 t __glink_PLTresolve
                 U __stack_chk_fail
0000000000011038 A _edata
0000000000011068 A _end
0000000000011000 D doit1
0000000000011018 D doit2


# gcc -Xlinker -shared -o libtest.so test1.o test2.o
# nm libtest.so 
0000000000000910 t 00000011.plt_call.__cxa_finalize@@GLIBC_2.3+0
00000000000008f8 t 00000011.plt_call.__libc_start_main@@GLIBC_2.3+0
00000000000008e0 t 00000011.plt_call.__stack_chk_fail@@GLIBC_2.4+0
0000000000010e30 a _DYNAMIC
0000000000000d50 R _IO_stdin_used
                 w _Jv_RegisterClasses
0000000000010e00 D __DTOR_END__
0000000000011188 A __bss_start
                 w __cxa_finalize@@GLIBC_2.3
0000000000011000 D __data_start
0000000000011008 D __dso_handle
0000000000000cd8 t __glink_PLTresolve
                 w __gmon_start__
0000000000010de4 d __init_array_end
0000000000010de4 d __init_array_start
00000000000110d0 D __libc_csu_fini
00000000000110e8 D __libc_csu_init
                 U __libc_start_main@@GLIBC_2.3
                 U __stack_chk_fail@@GLIBC_2.4
0000000000011188 A _edata
00000000000111f8 A _end
0000000000011058 D _fini
0000000000011040 D _init
0000000000011010 D _start
0000000000011000 W data_start
00000000000110a0 D doit1
00000000000110b8 D doit2
                 U main
Comment 6 Anthony Basile gentoo-dev 2010-06-30 10:00:11 UTC
This bug results from an analysis of bug #325849 but seems to be a bigger issue.  I've made them dependent/blocker, but its not a hard block because you can always work around using gcc -Xlinker on the 32-bit archs.
Comment 7 Anthony Basile gentoo-dev 2010-06-30 23:58:25 UTC
Okay Zorry and I have narrowed this down and it doesn't seem to be a hardened issues.  Using i686-pc-linux-gnu-4.4.3 we can reproduce the problem.  Here are the steps:

echo "void doit1() { char buff[256] ; }" > test1.c
echo "void doit2() { char buff[256] ; }" > test2.c
gcc -c -fstack-protector -fPIE test1.c
gcc -c -fstack-protector -fPIE test2.c
ld -shared -o libtest.so test1.o test2.o #FAIL

test1.o: In function `doit1':
test1.c:(.text+0x21): undefined reference to `__stack_chk_fail_local'
test2.o: In function `doit2':
test2.c:(.text+0x21): undefined reference to `__stack_chk_fail_local'
ld: libtest.so: hidden symbol `__stack_chk_fail_local' isn't defined
ld: final link failed: Nonrepresentable section on output

nm test1.o
         U __stack_chk_fail_local
00000000 T doit1

Comment 8 Anthony Basile gentoo-dev 2010-06-30 23:59:13 UTC
(In reply to comment #7)

emerge --info for that system is

Portage 2.1.8.3 (default/linux/x86/10.0, gcc-4.4.3, glibc-2.11.2-r0, 2.6.32-gentoo-r7 i686)
=================================================================
System uname: Linux-2.6.32-gentoo-r7-i686-Intel-R-_Core-TM-_i7_CPU_920_@_2.67GHz-with-gentoo-1.12.13
Timestamp of tree: Wed, 30 Jun 2010 07:00:01 +0000
app-shells/bash:     4.0_p37
dev-lang/python:     2.6.5-r2, 3.1.2-r3
sys-apps/baselayout: 1.12.13
sys-apps/sandbox:    1.6-r2
sys-devel/autoconf:  2.13, 2.65
sys-devel/automake:  1.10.3, 1.11.1
sys-devel/binutils:  2.20.1-r1
sys-devel/gcc:       4.3.4, 4.4.3-r2
sys-devel/gcc-config: 1.4.1
sys-devel/libtool:   2.2.6b
virtual/os-headers:  2.6.30-r1
ACCEPT_KEYWORDS="x86"
ACCEPT_LICENSE="* -@EULA"
CBUILD="i686-pc-linux-gnu"
CFLAGS="-O2 -march=i686 -pipe"
CHOST="i686-pc-linux-gnu"
CONFIG_PROTECT="/etc"
CONFIG_PROTECT_MASK="/etc/ca-certificates.conf /etc/env.d /etc/gconf /etc/revdep-rebuild /etc/sandbox.d /etc/terminfo"
CXXFLAGS="-O2 -march=i686 -pipe"
DISTDIR="/usr/portage/distfiles"
FEATURES="assume-digests distlocks fixpackages news parallel-fetch protect-owned sandbox sfperms strict unmerge-logs unmerge-orphans userfetch"
GENTOO_MIRRORS="ftp://192.168.100.9/pub/gentoo"
LDFLAGS="-Wl,-O1"
MAKEOPTS="-j3"
PKGDIR="/usr/portage/packages"
PORTAGE_CONFIGROOT="/"
PORTAGE_RSYNC_OPTS="--recursive --links --safe-links --perms --times --compress --force --whole-file --delete --stats --timeout=180 --exclude=/distfiles --exclude=/local --exclude=/packages"
PORTAGE_TMPDIR="/var/tmp"
PORTDIR="/usr/portage"
PORTDIR_OVERLAY="/usr/local/portage"
SYNC="rsync://192.168.100.7/portage"
USE="acl berkdb bzip2 cli cracklib crypt cups cxx dri fortran gdbm gpm iconv ipv6 modules mudflap ncurses nls nptl nptlonly openmp pam pcre perl pppd python readline reflection session spl ssl sysfs tcpd unicode x86 xorg zlib" ALSA_CARDS="ali5451 als4000 atiixp atiixp-modem bt87x ca0106 cmipci emu10k1 emu10k1x ens1370 ens1371 es1938 es1968 fm801 hda-intel intel8x0 intel8x0m maestro3 trident usb-audio via82xx via82xx-modem ymfpci" ALSA_PCM_PLUGINS="adpcm alaw asym copy dmix dshare dsnoop empty extplug file hooks iec958 ioplug ladspa lfloat linear meter mmap_emul mulaw multi null plug rate route share shm softvol" APACHE2_MODULES="actions alias auth_basic authn_alias authn_anon authn_dbm authn_default authn_file authz_dbm authz_default authz_groupfile authz_host authz_owner authz_user autoindex cache dav dav_fs dav_lock deflate dir disk_cache env expires ext_filter file_cache filter headers include info log_config logio mem_cache mime mime_magic negotiation rewrite setenvif speling status unique_id userdir usertrack vhost_alias" ELIBC="glibc" INPUT_DEVICES="keyboard mouse evdev" KERNEL="linux" LCD_DEVICES="bayrad cfontz cfontz633 glk hd44780 lb216 lcdm001 mtxorb ncurses text" RUBY_TARGETS="ruby18" USERLAND="GNU" VIDEO_CARDS="fbdev glint intel mach64 mga neomagic nv r128 radeon savage sis tdfx trident vesa via vmware voodoo" XTABLES_ADDONS="quota2 psd pknock lscan length2 ipv4options ipset ipp2p iface geoip fuzzy condition tee tarpit sysrq steal rawnat logmark ipmark dhcpmac delude chaos account" 
Unset:  CPPFLAGS, CTARGET, EMERGE_DEFAULT_OPTS, FFLAGS, INSTALL_MASK, LANG, LC_ALL, LINGUAS, PORTAGE_COMPRESS, PORTAGE_COMPRESS_FLAGS, PORTAGE_RSYNC_EXTRA_OPTS



Comment 9 Anthony Basile gentoo-dev 2010-07-01 00:23:45 UTC
To be complete, this also happens with -fPIC instead of PIE.  Using the test code from Comment #7, we get

gcc -c -fstack-protector -fPIC test1.c 
gcc -c -fstack-protector -fPIC test2.c
ld -shared -o libtest.so test1.o test2.o

test1.o: In function `doit1':
test1.c:(.text+0x21): undefined reference to `__stack_chk_fail_local'
test2.o: In function `doit2':
test2.c:(.text+0x21): undefined reference to `__stack_chk_fail_local'
ld: libtest.so: hidden symbol `__stack_chk_fail_local' isn't defined
ld: final link failed: Nonrepresentable section on output

nm test1.o 
         U __stack_chk_fail_local
00000000 T doit1
Comment 10 Magnus Granberg gentoo-dev 2010-07-01 00:40:35 UTC
4.3.4 works fine with the same test code.
Comment 11 Anthony Basile gentoo-dev 2010-07-01 01:05:57 UTC
I've now tested gcc-4.5.0 on both 32 and 64 bits.  Here's a summary of where the test code fails.

On x86:

 [1] i686-pc-linux-gnu-4.3.4  # works
 [2] i686-pc-linux-gnu-4.4.3  # fails
 [3] i686-pc-linux-gnu-4.5.0  # fails


On x86_64:

 [1] x86_64-pc-linux-gnu-4.3.4  # works
 [2] x86_64-pc-linux-gnu-4.4.3  # works
 [3] x86_64-pc-linux-gnu-4.5.0  # works


So the problem seems to be for 32-bit >= gcc-4.4

Comment 12 SpanKY gentoo-dev 2010-07-01 01:44:43 UTC
i dont see that.  looks to me like gcc has always behaved this way.  every version from 4.1.0 to 4.5.0 on my system certainly does.

$ gcc-4.1.2 -c -fstack-protector -fPIE test1.c -m32
$ readelf -s test1.o | grep stack
     8: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND __stack_chk_fail_local

it also seems to be doing this on purpose.  look at targhooks.c:default_hidden_stack_protect_fail() and how config/rs6000/rs6000.c and config/i386/i386.c call this for 32bit targets.
Comment 13 SpanKY gentoo-dev 2010-07-01 02:09:47 UTC
running the linker directly is wrong.  use gcc so that it adds all the internal glibc files such as /usr/lib32/libc_nonshared.a which does provide __stack_chk_fail_local.

if you do wish to run the linker directly, do it right.
Comment 14 Alexis Ballier gentoo-dev 2010-07-01 07:06:04 UTC
(In reply to comment #13)
> running the linker directly is wrong.  use gcc so that it adds all the internal
> glibc files such as /usr/lib32/libc_nonshared.a which does provide
> __stack_chk_fail_local.
> 
> if you do wish to run the linker directly, do it right.
> 

what is the "right" way of doing it ? how can one guess if it needs to link to libc_nonshared.a or not considering one has no control on the specs/cflags used at compile time ? wont that fail in the same way with gcc -nostdlib instead of ld ?
Comment 15 SpanKY gentoo-dev 2010-07-01 17:08:35 UTC
when dealing with anything beyond machine code generation, the compiler output is highly tied to the C library.  so if you break the gcc/link process by invoking the linker directly, it's on your head to do it right.

the only supported linking method is via `gcc`.  this is especially true for anything coming out of the hardened toolchain with the heavy ssp usage.
Comment 16 Anthony Basile gentoo-dev 2010-07-01 19:22:35 UTC
(In reply to comment #15)
> when dealing with anything beyond machine code generation, the compiler output
> is highly tied to the C library.

Actually this bug is a case in point.  We were confused because the object code produced on each of the four arches looked so different.  And yet, if you link via gcc, it all worked in the end.

"How can one guess?"  Best not to guess at what needs to be linked in, and just use gcc.  Lesson learned :)