Skip to content

Case 49: Executable Stack (GNU_STACK RWX)

Field Value
Verdict ๐ŸŸข COMPATIBLE
Category Quality (Compatible)
Platforms Linux
Flags Bad practice
Detected ChangeKinds โ€”
Source files browse on GitHub

Category: ELF / Security | Verdict: BAD PRACTICE

What this case is about

Both libraries export identical symbols with identical signatures. The difference is in the PT_GNU_STACK program header: v1 has flags RWE (read-write-execute), while v2 has RW (read-write, non-executable).

An executable stack is a security bad practice: it disables NX (No-eXecute) protection for the entire process, making stack-based buffer overflow exploits trivially exploitable.

How executable stacks sneak in

The most common cause is linking a single .o file compiled from assembly that has .section .note.GNU-stack,"x",@progbits. The GNU linker takes the union of all stack permissions โ€” if any input object requests an executable stack, the entire shared library (and any process loading it) gets one.

This happens frequently with: - Hand-written assembly without the proper .note.GNU-stack annotation - Old assembly files generated by compilers that defaulted to executable stacks - Third-party object files or static archives

What abicheck detects

  • EXECUTABLE_STACK: The library has PT_GNU_STACK with execute permission. This is classified as a security metadata issue. Because the actual symbols and types are identical, the functional ABI is compatible.

Overall verdict: COMPATIBLE (same ABI surface; executable stack is security concern).

How to reproduce

# Build bad version (with executable stack via linker flag)
gcc -shared -fPIC -g bad.c -o libbad.so -Wl,-z,execstack

# Build good version (non-executable stack)
gcc -shared -fPIC -g good.c -o libgood.so -Wl,-z,noexecstack

# Verify GNU_STACK flags
readelf -l libbad.so  | grep -A1 GNU_STACK
# โ†’ GNU_STACK  0x000000 ... RWE  โ† executable!
readelf -l libgood.so | grep -A1 GNU_STACK
# โ†’ GNU_STACK  0x000000 ... RW   โ† correct

# Run abicheck
python3 -m abicheck.cli dump libbad.so  -o /tmp/v1.json
python3 -m abicheck.cli dump libgood.so -o /tmp/v2.json
python3 -m abicheck.cli compare /tmp/v1.json /tmp/v2.json
# โ†’ COMPATIBLE + EXECUTABLE_STACK warning

How to fix

Ensure all assembly files include a non-executable stack annotation:

.section .note.GNU-stack,"",@progbits

Or use the linker flag to force a non-executable stack:

gcc -shared -fPIC lib.c asm.S -o libfoo.so -Wl,-z,noexecstack

In CMake:

target_link_options(foo PRIVATE -Wl,-z,noexecstack)

Real-world example

The Linux kernel, glibc, and all major distributions flag executable stack as a security defect. Fedora and Debian both have policies requiring -Wl,-z,noexecstack and lintian/rpmlint checks that reject packages with executable stacks.

References


Source files

See also: Examples overview ยท All COMPATIBLE cases ยท Category: Quality (Compatible).