I'm trying to protect my application against buffer overflow exploits. Among other things, I'm using non-executable stacks and link my binaries with the noexecstack
flag (by passing -Wl,-z,noexecstack
to gcc).
Everything seems fine - readelf
confirms that PT_GNU_STACK
specifies correct permissions:
$ readelf -l target | grep -A1 GNU_STACK
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 10
So does execstack
:
$ execstack -q target
- target
There's only one problem. All my stacks are actually executable:
root@170ubuntu16p04-64smp-1:~# cat /proc/12878/task/*/maps | grep stack
7ffcac654000-7ffcac675000 rwxp 00000000 00:00 0 [stack]
7fe540e66000-7fe541666000 rwxp 00000000 00:00 0 [stack]
7fe540665000-7fe540e65000 rwxp 00000000 00:00 0 [stack]
7fe53b800000-7fe53c000000 rwxp 00000000 00:00 0 [stack]
I've trapped allocate_stack calls and examined protection flags. In theory, they should be initialized according to PT_GNU_STACK
. But in my case, it seems like PT_GNU_STACK
was ignored and _dl_stack_flags
was initialized with default permissions.
Does anyone know what could have caused this? Everything seems correct, but stacks are still executable.
I'm using gcc 4.8.3 / glibc 2.11.
Olaf and Employed Russian pushed me in the right direction. A third-party shared object was poisoning my stacks.
But it wasn't linked to my main executable directly. Both ldd
and lddtree
weren't showing any libraries with RWE stacks, so I've decided to dig deeper and wrote a script that checked all shared objects currently mapped into a process memory:
#!/bin/bash
if [ -z "$1" ]; then
echo "Usage: $0 <target>"
exit 1;
fi
kav_pid=`pidof $1`
for so in `cat /proc/$kav_pid/task/*/maps | awk '/.so$/ {print $6}' | sort | uniq`; do
stack_perms=`readelf -Wl $so | awk '/GNU_STACK/ {print $7}'`
if [ -z "$stack_perms" ]; then
echo "$so doesn't have PT_GNU_STACK"
elif [ "$stack_perms" != "RW" ]; then
echo "$so has unexpected permissions: $stack_perms"
fi
done
And it worked! I found a library with RWE permissions:
$ ./find_execstack.sh target
/target/dir/lib64/lib3rdparty.so has unexpected permissions: RWE
To make sure that it was this library that poisoned my stacks, I opened my application with gdb
and set a breakpoint in dlopen
. And Bingo! Here are the permissions before dlopen
ing lib3rdparty.so:
7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0 [stack]
And here are they right after the dlopen
:
7ffffffde000-7ffffffff000 rwxp 00000000 00:00 0 [stack]
As it turned out, lib3rdparty.so
was built using a different toolchain and that went unnoticed utill now.
Olaf, Employed Russian, thank you!