As suggested by pageexec on gentoo-hardened list, I open this bug report. Read especialy here : http://article.gmane.org/gmane.linux.gentoo.hardened/3043 It seems that the /usr/sbin/apache2 binary (2.2.6) has a linking bug on hardened plateform that leads to a weird apache binary, even if it runs correctly apparently. I cannot reproduce this problem on my non-hardened system. Notice that this problem does not happen with apache-2.2.4-r12 Bug was discoverd with paxctl. It seems to be caused by incorrect GNU_RELRO header : ========================================================================= # paxctl -v /usr/sbin/apache2 PaX control v0.5 Copyright 2004,2005,2006,2007 PaX Team <pageexec@freemail.hu> file /usr/sbin/apache2 is not a valid ELF executable (invalid PT_ entry:8) ========================================================================= Here is readelf -e for the concerned /usr/sbin/apache2 (apache 2.2.6) ========================================================================= # readelf -e /usr/sbin/apache2 ELF Header: Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Class: ELF32 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: DYN (Shared object file) Machine: Intel 80386 Version: 0x1 Entry point address: 0x1cff0 Start of program headers: 52 (bytes into file) Start of section headers: 394028 (bytes into file) Flags: 0x0 Size of this header: 52 (bytes) Size of program headers: 32 (bytes) Number of program headers: 10 Size of section headers: 40 (bytes) Number of section headers: 27 Section header string table index: 26 Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 [ 1] .interp PROGBITS 00000174 000174 000013 00 A 0 0 1 [ 2] .note.ABI-tag NOTE 00000188 000188 000020 00 A 0 0 4 [ 3] .hash HASH 000001a8 0001a8 00429c 04 A 5 0 4 [ 4] .gnu.hash GNU_HASH 00004444 004444 002c1c 04 A 5 0 4 [ 5] .dynsym DYNSYM 00007060 007060 008a00 10 A 6 1 4 [ 6] .dynstr STRTAB 0000fa60 00fa60 007874 00 A 0 0 1 [ 7] .gnu.version VERSYM 000172d4 0172d4 001140 02 A 5 0 2 [ 8] .gnu.version_r VERNEED 00018414 018414 000090 00 A 6 2 4 [ 9] .rel.dyn REL 000184a4 0184a4 002e68 08 A 5 0 4 [10] .rel.plt REL 0001b30c 01b30c 000990 08 A 5 12 4 [11] .init PROGBITS 0001bc9c 01bc9c 000017 00 AX 0 0 4 [12] .plt PROGBITS 0001bcb4 01bcb4 001330 04 AX 0 0 4 [13] .text PROGBITS 0001cff0 01cff0 034a90 00 AX 0 0 16 [14] .fini PROGBITS 00051a80 051a80 00001a 00 AX 0 0 4 [15] .rodata PROGBITS 00051aa0 051aa0 00c0bc 00 A 0 0 32 [16] .eh_frame_hdr PROGBITS 0005db5c 05db5c 00001c 00 A 0 0 4 [17] .eh_frame PROGBITS 0005db78 05db78 00005c 00 A 0 0 4 [18] .ctors PROGBITS 0005ed14 05dd14 000008 00 WA 0 0 4 [19] .dtors PROGBITS 0005ed1c 05dd1c 000008 00 WA 0 0 4 [20] .jcr PROGBITS 0005ed24 05dd24 000004 00 WA 0 0 4 [21] .data.rel.ro PROGBITS 0005ed40 05dd40 000b48 00 WA 0 0 32 [22] .dynamic DYNAMIC 0005f888 05e888 000178 08 WA 6 0 4 [23] .got PROGBITS 0005fa00 05ea00 000600 04 WA 0 0 4 [24] .data PROGBITS 00060000 05f000 001258 00 WA 0 0 32 [25] .bss NOBITS 00061260 060258 002e34 00 WA 0 0 32 [26] .shstrtab STRTAB 00000000 060258 0000d4 00 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings) I (info), L (link order), G (group), x (unknown) O (extra OS processing required) o (OS specific), p (processor specific) Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000034 0x00000034 0x00000034 0x00140 0x00140 R E 0x4 INTERP 0x000174 0x00000174 0x00000174 0x00013 0x00013 R 0x1 [Requesting program interpreter: /lib/ld-linux.so.2] LOAD 0x000000 0x00000000 0x00000000 0x5dbd4 0x5dbd4 R E 0x1000 LOAD 0x05dd14 0x0005ed14 0x0005ed14 0x02544 0x05380 RW 0x1000 DYNAMIC 0x05e888 0x0005f888 0x0005f888 0x00178 0x00178 RW 0x4 NOTE 0x000188 0x00000188 0x00000188 0x00020 0x00020 R 0x4 GNU_EH_FRAME 0x05db5c 0x0005db5c 0x0005db5c 0x0001c 0x0001c R 0x4 GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4 GNU_RELRO 0x05dd14 0x0005ed14 0x0005ed14 0x012ec 0x012d4 R 0x1 PAX_FLAGS 0x000000 0x00000000 0x00000000 0x00000 0x00000 0x4 Section to Segment mapping: Segment Sections... 00 01 .interp 02 .interp .note.ABI-tag .hash .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame 03 .ctors .dtors .jcr .data.rel.ro .dynamic .got .data .bss 04 .dynamic 05 .note.ABI-tag 06 .eh_frame_hdr 07 08 .ctors .dtors .jcr .data.rel.ro .dynamic 09 ========================================================================= And here is the concerned emerge --info : ========================================================================= Portage 2.1.3.9 (hardened/x86/2.6, gcc-3.4.6, glibc-2.6.1-r0, 2.6.22-xwing-r2 i686) ================================================================= System uname: 2.6.22-xwing-r2 i686 Intel(R) Celeron(R) CPU 2.53GHz Timestamp of tree: Sat, 15 Sep 2007 06:30:01 +0000 app-shells/bash: 3.2_p17-r1 dev-lang/python: 2.5.1-r2 dev-python/pycrypto: 2.0.1-r6 sys-apps/baselayout: 1.12.10-r4 sys-apps/sandbox: 1.2.18.1 sys-devel/autoconf: 2.61-r1 sys-devel/automake: 1.7.9-r1, 1.10 sys-devel/binutils: 2.18 sys-devel/gcc-config: 1.4.0-r2 sys-devel/libtool: 1.5.24 virtual/os-headers: 2.6.22-r2 ACCEPT_KEYWORDS="x86 ~x86" CBUILD="i686-pc-linux-gnu" CFLAGS="-march=pentium4 -O2 -mtune=pentium4 -pipe" CHOST="i686-pc-linux-gnu" CONFIG_PROTECT="/etc /var/bind" CONFIG_PROTECT_MASK="/etc/env.d /etc/gconf /etc/php/apache2-php5/ext-active/ /etc/php/cgi-php5/ext-active/ /etc/php/cli-php5/ext-active/ /etc/revdep-rebuild /etc/terminfo /etc/udev/rules.d" CXXFLAGS="-march=pentium4 -O2 -mtune=pentium4 -pipe" DISTDIR="/usr/portage/distfiles" EMERGE_DEFAULT_OPTS="--with-bdeps y" FEATURES="buildsyspkg ccache distlocks fixpackages metadata-transfer sandbox sfperms strict unmerge-orphans userfetch userpriv usersandbox" GENTOO_MIRRORS="http://r2d2.v6.xwing.info/ http://mirror.ovh.net/gentoo-distfiles/ http://gentoo.modulix.net/gentoo/ http://gentoo.zie.pg.gda.pl http://gentoo.tiscali.nl/" LANG="fr_FR.UTF-8" LC_ALL="fr_FR.UTF-8" LINGUAS="fr" MAKEOPTS="-j2" PKGDIR="/usr/portage/packages" PORTAGE_RSYNC_OPTS="--recursive --links --safe-links --perms --times --compress --force --whole-file --delete --delete-after --stats --timeout=180 --exclude=/distfiles --exclude=/local --exclude=/packages --filter=H_**/files/digest-*" PORTAGE_TMPDIR="/var/tmp" PORTDIR="/usr/portage" PORTDIR_OVERLAY="/usr/local/gcpan-portage /usr/local/portage" SYNC="rsync://r2d2.v6.xwing.info/gentoo-portage" USE="4kstacks acl acpi acpi4linux apache2 async bash-completion bashlogger berkdb bzip2 clamav cracklib crypt dba dbx devmap dga enscript expat extensions fbcon freetype fs gd gdbm gif gmp gocr hardened idled idn imagemagick imap imlib2 iproute2 ipv6 ithreads jpeg l7filter ldap maildir md5sum mhash midi mmx ncurses nls nptl nptlonly ocrad pam pcre perl php pic png posix python readline rrdtool sasl slang soap sockets spf sse sse2 ssl subversion sysfs syslog tcpd threads tiff truetype truetype-fonts type1 type1-fonts udev unicode urandom usb vim-pager vim-syntax x86 xml2 xorg zlib" ALSA_PCM_PLUGINS="adpcm alaw asym copy dmix dshare dsnoop empty extplug file hooks iec958 ioplug ladspa lfloat linear meter mulaw multi null plug rate route share shm softvol" ELIBC="glibc" INPUT_DEVICES="mouse keyboard" KERNEL="linux" LCD_DEVICES="bayrad cfontz cfontz633 glk hd44780 lb216 lcdm001 mtxorb ncurses text" LINGUAS="fr" USERLAND="GNU" Unset: CTARGET, INSTALL_MASK, LDFLAGS, PORTAGE_COMPRESS, PORTAGE_COMPRESS_FLAGS, PORTAGE_RSYNC_EXTRA_OPTS =========================================================================
Here is what I get when not using binutils-2.18 (I'm on .17) hardened ~ # paxctl -v /usr/sbin/apache2 PaX control v0.4 Copyright 2004,2005,2006 PaX Team <pageexec@freemail.hu> - PaX flags: -------x-e-- [/usr/sbin/apache2] RANDEXEC is disabled EMUTRAMP is disabled hardened ~ # qlist -vUSe apache www-servers/apache-2.2.6 2 (ssl) hardened ~ # scanelf -a /usr/sbin/apache2 TYPE PAX STK/REL/PTL TEXTREL RPATH BIND FILE ET_DYN ---xe- RW- R-- RW- - - NOW /usr/sbin/apache2 hardened ~ # ld -v GNU ld version 2.17
I confirm this : after downgrading binutils to 2.17 and recompiling apache-2.2.6, the problem disappears : # readelf -l /usr/sbin/apache2 Type de fichier ELF est DYN (fichier objet partagé) Point d'entrée 0x1a630 Il y a 10 en-têtes de programme, débutant à l'adresse de décalage52 En-têtes de programme: Type Décalage Adr. vir. Adr.phys. T.Fich. T.Mém. Fan Alignement PHDR 0x000034 0x00000034 0x00000034 0x00140 0x00140 R E 0x4 INTERP 0x000174 0x00000174 0x00000174 0x00013 0x00013 R 0x1 [Réquisition de l'interpréteur de programme: /lib/ld-linux.so.2] LOAD 0x000000 0x00000000 0x00000000 0x5b5f4 0x5b5f4 R E 0x1000 LOAD 0x05bcfc 0x0005ccfc 0x0005ccfc 0x0255c 0x053b4 RW 0x1000 DYNAMIC 0x05c888 0x0005d888 0x0005d888 0x00170 0x00170 RW 0x4 NOTE 0x000188 0x00000188 0x00000188 0x00020 0x00020 R 0x4 GNU_EH_FRAME 0x05b57c 0x0005b57c 0x0005b57c 0x0001c 0x0001c R 0x4 GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4 GNU_RELRO 0x05bcfc 0x0005ccfc 0x0005ccfc 0x012ec 0x012ec R 0x20 PAX_FLAGS 0x000000 0x00000000 0x00000000 0x00000 0x00000 0x4 Section à la projection de segement: Sections de segment... 00 01 .interp 02 .interp .note.ABI-tag .hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame 03 .ctors .dtors .jcr .data.rel.ro .dynamic .got .data .bss 04 .dynamic 05 .note.ABI-tag 06 .eh_frame_hdr 07 08 .ctors .dtors .jcr .data.rel.ro .dynamic 09 # paxctl -v /usr/sbin/apache2 PaX control v0.5 Copyright 2004,2005,2006,2007 PaX Team <pageexec@freemail.hu> - PaX flags: -------x-e-- [/usr/sbin/apache2] RANDEXEC is disabled EMUTRAMP is disabled
that error should really spit out p_type so there's no confusion when trying to index the PT table by hand ... the PT in question: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align GNU_RELRO 0x05dd14 0x0005ed14 0x0005ed14 0x012ec 0x012d4 R 0x1 the check: phdr[i].p_align && (~(phdr[i].p_align - 1) + phdr[i].p_align)) || (phdr[i].p_align && ((phdr[i].p_offset ^ phdr[i].p_vaddr) & (phdr[i].p_align - 1))) || phdr[i].p_vaddr + phdr[i].p_memsz < phdr[i].p_vaddr || phdr[i].p_offset + phdr[i].p_filesz < phdr[i].p_offset || phdr[i].p_offset + phdr[i].p_filesz > state->size || phdr[i].p_filesz > phdr[i].p_memsz
Reassigning to toolchain@ This bug is reproducible simply by using binutils-2.18 and rebuilding apache. GNU_RELRO 0x05cdd4 0x0005ddd4 0x0005ddd4 0x01220 0x01208 R 0x1
the issue being that the program header has a filesize which is larger than the memsize ... i can only reproduce this on hardened though
before the strip, it's correct: $ readelf -Wl scanelf | grep RELRO GNU_RELRO 0x0106d0 0x00000000002106d0 0x00000000002106d0 0x000930 0x000930 R 0x1 after the strip, not so much: $ strip scanelf $ readelf -Wl scanelf | grep RELRO GNU_RELRO 0x0106d0 0x00000000002106d0 0x00000000002106d0 0x000930 0x000928 R 0x1
hmm, i can reproduce on non-hardened using gcc-3.4.6 and -fPIE ...
(In reply to comment #3) > that error should really spit out p_type so there's no confusion when trying to > index the PT table by hand ... problem is that the numerical value of p_type is of little help, and text representation needs BFD (i think, or rolling my own, which is even worse) which i intentionally didn't want as a dependency for paxctl (it wants to be a small self-contained utility ;). also, if you have multiple entries of the same type, your only unique identifier is really the index. last but not least, paxctl is not eu-elflint (i wonder what it says about this bad RELRO entry btw), so i'd rather not go overboard with these checks and error reporting.
i think even just having the hex would be useful ... i have no problem looking up the PT defines in elf headers ... my gripe is that unless you look at the code, it's unclear whether the output counts from 0 or 1 ... as for doing number<->text bindings, you dont need BFD ... we do it in scanelf easily enough since the libc elf.h provides most of the PT defines you can follow the progress upstream ... there is already a patch to address a different bug which seems to also fix this ...
the fix has been merged upstream and i'll put out binutils-2.18-r1 with this