Nikita Kakuev Nikita Kakuev - 3 months ago 24
Linux Question

Stacks are executable even with `noexecstack`

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

flag (by passing
to gcc).

Everything seems fine -
confirms that
specifies correct permissions:

$ readelf -l target | grep -A1 GNU_STACK
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 10

So does

$ 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
. But in my case, it seems like
was ignored and
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:


if [ -z "$1" ]; then
    echo "Usage: $0 <target>"
    exit 1;

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"

And it worked! I found a library with RWE permissions:

$ ./ target
/target/dir/lib64/ 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 dlopening

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, was built using a different toolchain and that went unnoticed utill now.

Olaf, Employed Russian, thank you!