Repository navigation
Add performance conscious hardening flags to linux targets - #1166
Conversation
Enable stack protection and immediate binding for all Linux builds. Enable source fortification for optimized glibc targets. closes #837
Enable stack-clash protection on aarch64 and x86-64 linux targets. Other architectures are cross-compiled and the toolchains may lack support for this functionality.
Extend validate-distribution to reject
* non-PIE executables
* writable and executable load segments
* missing RELRO
* lazy symbol binding
* text relocations.
Preserve the existing executable-stack validation and skip dynamic
binding checks when validating static binaries.
|
This improves the hardening check results: PBS 20260623 on aarch64 Linux With these changes: Stack clash protection is enabled but the binary lacks allocation that would exercise this protection so in cannot be detected. |
|
Validation is failing with: This is likely a false positive as the binary is PIE rather than PIC. |
|
Before merging this I was to examine the performance difference these flags introduce. I will not be able to get to this until next week at the earliest. |
|
I benchmarked these changes using fastmark. Using the 20260623 release of CPython 3.14.6 for x86-64 Linux with pgo+lto fastmarks on my Intel i9-9900k gave a value of 13951 (average of five runs). On the same setup after applying these flags gave a value of 13590. This is ~97.4% of the original value, so the hardening flags cause a 2-3% drop in performance. This is larger than I expected but not way off. |
|
Is there any impact on startup time? |
Not by a significant amount, <2%, and within the measured error. Reference (20260623 release) With these flags: |
|
Dug a little deeper into performance and |
This is not a false positive, the x86-64 binary not position independent. Need to figure out why not. |
|
When BOLT is enabled CPython explicitly turns off PIE for performance |
|
uh... that's interesting. I wonder if that's still true? |
I suspect not. I'm testing the effects now. |
|
Expanded the test matrix here to capture any issues on other architectures+python versions. Likely a bit more that needed but I would rather catch issues here than post merge. |
|
Making the BOLT optimized binary position independent has a significant effect on performance: Fastmark scores:
Startup time is also effected going to ~13.5 ms (+8.9%) |
|
PIE with BOLT is faster? |
|
For fastmark larger scores are better (more performant). So the best performance is without hardening flags and without PIE. |
|
It is worth noting that the system provided by Debian Trixie is non-PIE and uses the weaker |
|
So now we're talking about an 8% performance regression instead? That's feeling pretty questionable. |
Yes, enabling PIE and -fstack-protection-strong causes a ~8% performance regression. A set of performance conscious hardening flags that adjusting the existing flags to leave off PIE and use the less aggressive |
This reverts commit 26601eb.
Apply the -fstack-protector flag rather that the strong -fstack-protector-strong. The strong version has a notiable effect on performance and is excluded in other builds within in ecosystem for performance reasons, including Debian's 3.13 builds in Trixie.
ld-linux-aarch64.so.1 is an allowed library on aarch64-linux. Hardening flags can promote this library to DT_NEEDED where as before it was only DT_INTERP.
|
The ppc64le validation failure is caused by the wrong startup file being selected (crt1.o) and linked when building a PIE executable resulting in text relocations, see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81170 |
|
I think this set of flags is a good balance between security and performance. With these flags the performance measured by fastmark between the 20260623 and a x86-64 Python 3.14 interpreter build with these flags is within the spread of multiple runs of the benchmark. I'm running the full pyperformance benchmark suite overnight to get more details. |
|
The results from running Startup is slightly decreased with these flags, but the |
EliteTK
left a comment
There was a problem hiding this comment.
Looks good generally, only some minor comments!
There was a problem hiding this comment.
We don't seem to include heuristics for stack protector or fortify (could look for __stack_chk_fail and __<func>_chk I think). Maybe something to follow up on?
Build CPython and dependencies with a set of hardening flags that take into account performance.
validate-distributioncommand.Control-flow and branch protection flags are not included.
On x86-64
-fcf-protectionrequires modern kernels, glibc and hardware (CET). Additionally, native extensions can fail to load when they are built without CET (which most are not) if the interpreter includes these protections.On aarch64,
-mbranch-protectionis of limited use unless all objects include the necessary markers. This includes the CRT and compiler runtimes which come from the base image which pre-dates these features.The
-fstack-protectorflag is used rather than-fstack-protector-strongwhich would instrument additional functions. The later was found to have a negative effect on performance (~2-3%). Debian currently uses this flag when building CPython in the 3.13 release for Trixie.Executable are not validate or required to be position independent (PIE). Testing found that requiring this has significant negative effects on performance (~5%). Debian builds CPython without PIE in the 3.13 release for Trixie.
closes #837