Linux Improvements in Memory Corruption Based Protections presented at DORS/CLUC 2025, Zagreb, Croatia.
Intel Indirect Branch Tracking (IBT) in Linux.
Intel Shadow Stack (SS) implementation in Linux.
9. Relevant Linux Security Mechanisms
9
Memory Corruption Protection
NX
• v2.6.8
• 14 aug
2004
ASLR
• v2.6.12
• 17 jun
2005
PAC
• V4.2.1
(ARM)
• 14 dec
2018
BTI/SCS
• v5.8 (ARM)
• 2 aug
2020
CFI
• v5.13
(ARM)
• 27 jun
2021
IBT
• v5.18
(x86)
• 22 aug
2022
• Kernel
ISS
• v6.6 (x86)
• 28 oct
2023
• Userland
10. Intel CET = IBT + SS
10
Intel Control-Flow Enforcement Technology
https://www.phoronix.com/news/Intel-CET-IBT-For-Linux-5.18
11. IBT Requirements
11
From Hardware to Kernel
• Forward-edge CFI
• Hardware
• Tigerlake (11th gen) or higher
• Kernel Version
• 5.18 or higher
• 6.2 or higher (on by default!)
• Kernel Configuration
• X86_KERNEL_IBT
• Current Support
• Kernel only
Lot of ibt=off advices for different drivers (nvidia, etc
):
https://bbs.archlinux.org/viewtopic.php?id=277205
https://github.com/v4l2loopback/v4l2loopback/issu
es/476
…
13. Shadow stack – Software only implementation in clang
13
Invocation via -fsanitize=shadow-call-stack
push %rax
callq bar
add $0x1,%eax
pop %rcx
retq
mov (%rsp),%r10
xor %r11,%r11
addq $0x8,%gs:(%r11)
mov %gs:(%r11),%r11
mov %r10,%gs:(%r11)
push %rax
callq bar
add $0x1,%eax
pop %rcx
xor %r11,%r11
mov %gs:(%r11),%r10
mov %gs:(%r10),%r10
subq $0x8,%gs:(%r11)
cmp %r10,(%rsp)
jne trap
retq
trap:
ud2
int foo() {
return bar() + 1;
}
https://releases.llvm.org/7.0.1/tools/clang/docs/ShadowCallStack.html
DISCARDED
14. Q
u
o
t
e
“ShadowCallStack on x86_64 suffered from the
same racy security issues as Return Flow
Guard and had performance overhead as high
as 13% depending on the benchmark.
x86_64 ShadowCallStack was always an
experimental feature and never shipped a
runtime required to support it, as such there
are no expected downstream users.”
14
https://github.com/llvm-mirror/llvm/commit/863ea8c618b1f88ba8c9ec355a07cb3783481642
15. CPU
Hardware CPU
CPU with support for Shadow
Stack
OS
Operating System
Kernel
Loader/(G)Libc
BIN
Binary
Usually produced by
compiler which can produce
binary with Shadow Stack
support
Requirements
Linux and Intel Shadow Stack
16. # apt install cpuid
$ cpuid -1 -i | grep -E 'CET_[SIBT]{2,3}'
CET_SS: CET shadow stack = false
CET_IBT: CET indirect branch tracking = false
$ cpuid -1 -i | grep -E 'CET_[SIBT]{2,3}'
CET_SS: CET shadow stack = true
CET_IBT: CET indirect branch tracking = true
Hardware - CPU
16
How to check if Intel CET is supported?
17. #include <cpuid.h>
#include <stdint.h>
int cpu_supports_cet_shadow_stack() {
uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
__cpuid_count(7, 0, eax, ebx, ecx, edx);
return (ecx & (1 << 7)) != 0;
}
int cpu_supports_cet_ibt() {
uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
__cpuid_count(7, 0, eax, ebx, ecx, edx);
return (edx & (1 << 20)) != 0;
}
Hardware - CPU
17
How to check if Intel CET is supported in C(++)?
https://gist.github.com/kohnakagawa/fb77904fcc44fc5652ef6d338c35a718
20. Requirements - OS - Linux kernel
20
Kernel version and options
• Version
• 6.6 or higher
• Current Support
• User space only
• Configuration
• X86_USER_SHADOW_STACK
• Prerequisits
• Binutils v2.29 or
• LLVM v6
• /proc/cpuinfo shows CET features (if processor
supports it)
• "user_shstk” in flags means userspace shadow
stack
21. Requirements - OS - glibc
21
glibc version and compilation flags
• Version
• 2.39 or higher
• Released 31th of January, 2024
• Support
• 64bit only
• Compilation flag
• --enable-cet
• Compilation of libc with CET support
• 32 bit compilation failed on 32bit build in the past, patches flying in
• Configuration options
• Available at run-time
• Using standard GLIBC tunables mechanism
22. Requirements - OS - glibc
22
glibc options – glibc.cpu.x86_shstk
Value Description
Off off always turns off SHSTK regardless of
whether SHSTK is enabled in the executable
and its dependent shared libraries
Permissive permissive changes how dlopen works on
non-CET shared libraries. By default, when
SHSTK is enabled, dlopening a non-CET
shared library returns an error. With
permissive, it turns off SHSTK instead
On on always turns on SHSTK regardless of
whether SHSTK is enabled in the executable
and its dependent shared libraries
https://www.gnu.org/software/libc/manual/html_node/Hardware-Capability-Tunables.
html
23. Requirements - binary
23
How to produce and check compatible binary
• Need to produce ELF binary with SHSTK flag
• x86 feature: SHSTK
• Compiler
• gcc
• clang
• Compilation flags
• --mshstk
• --fcf-protection=full
• Test with
• $ readelf -n <application> | grep -a SHSTK
• properties: x86 feature: SHSTK
24. Testing with vulnerable binary
24
Not yet. Hitting other overflow security control – Which one?
$./vuln
Hello World
dalkjdlksjalkkkkkkkkkkkkkkkkkjkdssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
sssss
*** stack smashing detected ***: terminated
Aborted
25. glibc requires to set tunables
25
Feature is not on by default, because it needs more testing
# cat /proc/$PID/status | grep x86_Thread_features
x86_Thread_features:
x86_Thread_features_locked:
Not all CET enabled applications and libraries have been properly tested in CET
enabled environments. Some CET enabled applications or libraries will crash or
misbehave when CET is enabled. Don't set CET active by default so that all
applications and libraries will run normally regardless
of whether CET is active or not. Shadow stack can be enabled by
$ export GLIBC_TUNABLES=glibc.cpu.hwcaps=SHSTK
https://sourceware.org/git/?p=glibc.git;a=commit;h=55d63e731253de82e96ed4ddca2e294076cd0bc5
26. glibc requires to set tunables
26
Feature is not on by default, because it needs more testing
$ export GLIBC_TUNABLES=glibc.cpu.hwcaps=SHSTK
$ ./vuln
# cat /proc/$PID/status | grep x86_Thread_features
x86_Thread_features: shstk
x86_Thread_features_locked: shstk wrss
YEY! Complete security
control of Shadow stack is
working!
28. Testing with vulnerable binary
28
Not yet. Hitting other overflow security control – Which one?
$ ./testss < input.dat
Enter some data:
Segmentation fault
# dmesg
[81297.420577] testss[909181] control protection ip:64372cb8a1dd sp:7fffb71e2678 ssp:7f5dcdbfffe0
error:1(near ret) in testss[64372cb8a000+1000]
YEY! We prevented return
address overwrite using
hardware implementation of
Intel Shadow stack
29. Distribution support
29
Current status in distributions
• Ubuntu 24.04 LTS
• All components in place, not enabled by default
• Need to set glibc tunables
• 64 bit support starting to appear, not default
• 32bit support from 6.10+
• Libraries and components
• All parts should be compiled with shadow stack support
• Virtualization
• Patches still flying in
• CI/CD testing limited
30. Compatibility
30
Compatibility with older system and legacy applications
• Legacy applications not getting security for free
• Work and testing involved
• Recompilation neccessary (worth setting other compilation
security flags!)
• 64 bit support in full stack from 6.6+
• 32bit support in Linux kernel 6.10+
• Libraries and components
• All parts should be compiled with shadow stack support
• Virtualization
• Patches still flying in
• CI/CD testing limited
31. Compatibility with AMD CPU?
31
Does it work on AMD CPU?
„…Thanks, I ran some smoke
tests with the updated glibc
and it's looking good so far.
Additionally, I ran the new
kselftest and it passed…” -John
Allen (AMD)
https://lore.kernel.org/lkml/Yf2m1ETkcRpk3v+u@dell9853host/
33. Any bypass?
33
Any known weaknesses?
• Find component which is not protected
• Components and complexity
• Hardware
• Kernel
• Glibc
• Compiler
• Binary
• Techniques from other OS or architectures
• Implementation details
• For example: „On exec, shadow stack features are disabled by the
kernel. At which point, userspace can choose to re-enable, or lock
them.”
34. Take away
34
What have we learned from different perspective
• System administrator
• If something stops working, where/what to check
• How to implement yet another overflow security control
• Developer
• What new compiler flags you should use
• How you should test your program if it works with ISS controls
• Security Specialist
• How to additionaly harden your system
• How to check if hardening really works
• Security Researcher
• Fundamentals to get you started
35. Current Intel CET support in Linux
35
Summary
Feature Kernel Userland
Indirect Branch
Tracking (IBT)
Implemented ✅ Not implemented
Shadow Stack (SS) Not implemented Implemented ✅
36. Summary
36
TLDR
• Getting shell even if process is vulnerable is getting harder
• Hard to say impossible
• definitively it raises the bar
• Shadow stack and Intel/AMD Linux
• Implementation is now complete
• Only user space protection
• Old applications/systems do not get it for free
• Current limitations
• virtualization non existant
• Not yet (by default) in your favourite distribution
• Recommended
• Fixing at source
37. References
37
Not specified on slides directly
• Control-flow Enforcement Technology Specification, Intel,
May 2019, Revision 3.0
• Control-flow Enforcement Technology (CET) Shadow Stack
• https://www.kernel.org/doc/html/next/x86/shstk.html
• Glibc CET branch (before official glibc release)
• https://gitlab.com/x86-glibc/glibc/-/commits/users/hjl/cet/
master
39. 39
// bunch of includes, skipped for brewity
/* function to act as gadget to simplify */
void win() {
printf("You have successfully called the win function!n");
exit(0);
}
/* vulnerable function */
void vulnerable() {
char buffer[64];
printf("Enter some data:n");
read(STDIN_FILENO, buffer, 256);
}
int main() {
vulnerable();
return 0;
}
40. 40
# Example pwn script to trigger vulnerability
from pwn import *
binary = './testss'
elf = ELF(binary)
vulnerable binary
win_function = elf.symbols['win']
p = process(binary)
# Buffer size is 64 bytes, let's add 8 more to overwrite the saved return pointer
(total 72 bytes)
padding = b"A" * 72
payload = padding + p64(win_function)
print(p.recv())
p.sendline(payload)
p.interactive()