Case 136: Executable Stack Removed (the fix direction)¶
| Field | Value |
|---|---|
| Verdict | ๐ข COMPATIBLE |
| Category | Quality (Compatible) |
| Platforms | Linux |
| Flags | โ |
Detected ChangeKinds |
executable_stack_removed |
| Source files | examples/case136_executable_stack_removed/ |
Category: Quality | Verdict: ๐ข COMPATIBLE
Verdict and consumer impact¶
This is the fix counterpart to case49 (which goes the bad direction). v1 has
an executable stack โ PT_GNU_STACK with flags RWE (-Wl,-z,execstack).
v2 corrects it to RW (-Wl,-z,noexecstack), restoring NX (No-eXecute)
protection on the process stack. The exported ABI surface is byte-identical
between versions, so every existing binary keeps working unmodified โ this
change only tightens a security property, it never breaks a caller.
Old/new diff¶
| old/lib.c | new/lib.c |
|---|---|
linked with -Wl,-z,execstack (PT_GNU_STACK = RWE) |
linked with -Wl,-z,noexecstack (PT_GNU_STACK = RW) |
(library source is identical โ see old/lib.c / new/lib.c) |
abicheck command¶
gcc -shared -fPIC -g old/lib.c -o libfoo_v1.so -Wl,-z,execstack
gcc -shared -fPIC -g new/lib.c -o libfoo_v2.so -Wl,-z,noexecstack
abicheck compare libfoo_v1.so libfoo_v2.so
Expected abicheck finding¶
Verdict: COMPATIBLE (exit 0)
- executable_stack_removed: Executable stack removed: library now uses a
non-executable stack - NX protection restored (good practice)
Minimum evidence¶
min_evidence: L0 โ PT_GNU_STACK's flags are read directly from the ELF
program headers; no debug info or headers are needed to see the change.
Why abicheck catches it¶
abicheck reads each library's PT_GNU_STACK segment flags from the ELF
program header table and diffs the executable bit between versions โ a pure
L0 ELF fact, tracked as the symmetric complement of the executable-stack
regression case49 demonstrates, so a hardening improvement is reported as
compatible rather than silently ignored or mis-flagged as a regression.
Runtime failure demonstration¶
No observable effect on existing binaries โ both versions run identically; v2 only restores NX protection on the process stack.
readelf -lW libfoo_v1.so | grep GNU_STACK
# โ GNU_STACK ... RWE 0x10
readelf -lW libfoo_v2.so | grep GNU_STACK
# โ GNU_STACK ... RW 0x10
gcc -shared -fPIC -g old/lib.c -o libfoo.so -Wl,-z,execstack
gcc -g app.c -L. -lfoo -Wl,-rpath,. -o app
./app
# โ compute(7) = 50
# โ transform(3, 4) = 11
gcc -shared -fPIC -g new/lib.c -o libfoo.so -Wl,-z,noexecstack
./app
# โ compute(7) = 50
# โ transform(3, 4) = 11 โ identical
Safe redesign¶
This case is the safe redesign โ the fix is exactly -Wl,-z,noexecstack
(or, in CMake, add_link_options(-Wl,-z,noexecstack)), and ensuring any
hand-written assembly inputs carry a .section .note.GNU-stack,"",@progbits
marker so the linker never unions in an executable-stack requirement from an
unmarked object file.
References¶
Source files¶
CMakeLists.txtapp.c
See also: Examples overview ยท All COMPATIBLE cases ยท Category: Quality (Compatible).