Wiki - https://fedoraproject.org/wiki/Changes/ShadowStack
Discussion thread -
https://discussion.fedoraproject.org/t/f45-change-proposal-enable-shadow-stack-by-default-on-x86-64-system-wide/195400


This is a proposed Change for Fedora Linux.
This document represents a proposed Change. As part of the Changes
process, proposals are publicly announced in order to receive
community feedback. This proposal will only be implemented if approved
by the Fedora Engineering Steering Committee.


== Summary ==
This change enables Shadow Stack protection on applications and
libraries built with gcc (C, C++), clang (C, C++), and rustc (Rust) by
default on x86_64 machines that support it on Fedora Linux 45. The
dynamic linker or static startup routines will activate Shadow Stack
for any process whose binary and shared library dependencies are all
built with Shadow Stack support (marked with ELF metadata), protecting
processes by default whenever possible.

== Owner ==
* Name: [[User:submachine| Arjun Shankar]]
* Email: [email protected]


== Detailed Description ==
Shadow Stacks are a hardware enforced security feature that maintains
a separate, tamper proof list of return addresses to protect against
Return-Oriented Programming style exploits. This change enables Shadow
Stack protection by default on x86_64 machines that support it on
Fedora Linux 45. The dynamic linker, or static startup routines, will
activate Shadow Stack for any process whose binary and shared library
dependencies are all built with Shadow Stack support, protecting
processes by default whenever possible. Shadow Stacks are one of two
Control-Flow Enforcement features introduced in Intel CET, alongside
Indirect Branch Tracking (IBT), designed to defend against
Return-Oriented Programming (ROP) and Jump-Oriented Programming (JOP)
attacks by protecting return addresses. This Fedora change only covers
enabling Shadow Stack support. Enabling Indirect Branch Tracking by
default is not in scope.

This change is backward compatible for the most part:
`-fcf-protection` is a default compile time flag already enabled in
`redhat-rpm-config` for Fedora since 2018 and thus the majority of
binaries are already built with the appropriate markup. Thus, after
this change is applied, applications whose dependencies carry Shadow
Stack markup gain protection transparently while applications that
load any non-compliant object at startup continue to run without
Shadow Stack protection. The only new failure mode is when a Shadow
Stack enabled process attempts to `dlopen` a non-compliant shared
object at runtime, which results in a `dlopen` error that looks like
`error: dlopen: /path/to/library.so: rebuild shared object with SHSTK
support enabled`.

Two mitigation strategies can be used, depending on the package:

# Where the `dlopen`ed library can be fixed to include Shadow Stack
support, the library is fixed and rebuilt with the appropriate markup.
This is the preferred fix because it preserves Shadow Stack protection
for the calling application.
# Where the non-compliant code cannot be fixed in time, the calling
application is opted out of Shadow Stack via glibc's
[https://inbox.sourceware.org/libc-alpha/[email protected]/T/#u
System-Wide Tunables] configuration that can be shipped
per-application as a configuration file. This disables Shadow Stack
for that specific application while all other processes retain
protection.

== Feedback ==
No community feedback has been received yet. This section will be
updated as feedback is collected.

== Benefit to Fedora ==
This change provides hardware-enforced protection against
Return-Oriented Programming (ROP) style attacks for the majority of
Fedora binaries at negligible performance cost.

Shadow Stacks are enforced by the CPU and do not require software
instrumentation at runtime. The overhead is limited to maintaining a
second copy of the return address stack in protected memory, which has
no measurable impact on typical workloads.

The change is transparent: compliant applications are protected
without any code change, rebuild, or user action. Because
`-fcf-protection` is already a default compile flag in Fedora, the
majority of packages are already built with the appropriate ELF
markup. Enabling Shadow Stack in the dynamic linker activates
protection for these packages immediately.

This also lays groundwork for enabling Indirect Branch Tracking (IBT)
in a future release, which together with Shadow Stack would provide
full Control-Flow Enforcement Technology (CET) protection.

== Scope ==
* Proposal owners: The glibc maintainers will:
# Apply a glibc downstream patch that reverts an upstream change that
deactivates Shadow Stack support.
# Include the upstream glibc
[https://inbox.sourceware.org/libc-alpha/[email protected]/T/#u
System-Wide Tunables] feature, which has obtained upstream consensus
and will be part of the next glibc release. This feature enables
per-application opt-out via configuration files.
# Ship `/etc/tunables.conf` with `include /etc/tunables.conf.d/*.conf`
so that individual packages can drop in their own configuration files
in order to opt-out.
# Validate that SUID/SGID applications correctly sanitize tunables so
that unprivileged users cannot disable Shadow Stack for privileged
programs.
# Open tracking bugs for all known incompatible packages.

* Other developers:
Most packages built with Fedora's default flags already produce Shadow
Stack compatible binaries and no action is needed in this case.
Packages that include hand-written assembly or build with different
flags might ship ELF objects without Shadow Stack markup. Maintainers
of such packages will need to make changes to their package to include
Shadow Stack markup (e.g., annotate assembly routines).

A special case is applications built with Shadow Stack support that
currently `dlopen` shared objects built without it.  These
applications will encounter a runtime error at `dlopen` unless one of
these fixes is applied:

# The `dlopen`ed library is compiled with Shadow Stack support enabled.
# The application opts out of Shadow Stack support using glibc's
System-Wide Tunables feature. For example, a package named `app`
providing `/usr/bin/app` would install `/etc/tunables.conf.d/app.conf`
containing:

<pre>
[proc:/usr/bin/app]
glibc.cpu.x86_shstk=off
</pre>

This disables Shadow Stack for that specific application while all
other processes retain protection. The drop-in file is owned by the
affected package's RPM, so it is added and removed with the package.
Once the dependency is fixed, the package update removes the drop-in
file and the application gains Shadow Stack protection.

* Release engineering:
[https://forge.fedoraproject.org/releng/tickets/issues/13388 #13388]
Most objects are already built with support, and enablement is via a
glibc update. For Rust, binary packages need to be rebuilt once the
Rust dependency is in place. This can be done as part of the regularly
scheduled Fedora 45 mass-rebuild. We will track this as part of the
F45 GNU Toolchain release engineering ticket linked to above.

* Policies and guidelines:
No changes to packaging guidelines are required at this time. Default
build configuration already builds objects with support and for the
majority of packages, the change is transparent.

* Trademark approval: N/A (not needed for this Change)

* Alignment with the Fedora Strategy:
This change is in line with Fedora's security posture and commitment
to shipping secure-by-default systems.


== Upgrade/compatibility impact ==
After upgrading to Fedora 45, Shadow Stack support will be enabled
automatically for processes whose binary and all loaded shared
libraries carry the appropriate markup. Processes that load any
non-compliant shared object will have Shadow Stack silently disabled
at startup.

The only exception is applications that are fully Shadow Stack
compliant at startup and then use `dlopen` to load a shared object
without Shadow Stack markup at runtime. This will lead to a `dlopen`
failure. However, affected applications can be configured to opt out
of Shadow Stack protection, or have their dependencies fixed.
Incompatible packages will be identified by scanning the Fedora
package set for ELF objects missing the SHSTK property note, and by
testing critical desktop and server workloads against the COPR
repository with Shadow Stack enabled. Tracking bugs will be filed for
all known incompatible packages. This work has already started and is
being tracked in [https://bugzilla.redhat.com/show_bug.cgi?id=2458434
Bugzilla].

# Where the `dlopen`ed library is under Fedora's control, it can
either be fixed and rebuilt with support, or the dependent package
configured to run with Shadow Stack turned off as described in the
Scope section above.
# Users who encounter this problem with third party applications can
work around it using the System-Wide Tunables feature as described
earlier.



== Early Testing (Optional) ==
A COPR repository with the updated glibc (Shadow Stack enabled) is
available for Fedora 43, 44, and Rawhide for early testing:
https://copr.fedorainfracloud.org/coprs/submachine/glibc-x86_64-SHSTK-Testing/

Do you require 'QA Blueprint' support? No <!-- Optional Step for
System-Wide Changes only -->

== How To Test ==
1. Shadow Stack hardware support is available on Intel 11th Generation
and newer CPUs, and AMD Zen3 and newer CPUs, so testing does not
require any special hardware except a recent enough x86_64 processor.

2. Machine learning workloads that use GPU acceleration via AMD ROCm
are a specific area of interest because the ROCm runtime libraries may
lack Shadow Stack markup. Testing these workloads (e.g., pytorch with
ROCm) requires access to AMD GPUs.

3. Once the runtime has been enabled for Shadow Stack, testing
involves (a) verifying the shadow stack status of running processes
(`cat /proc/$pid/status | grep x86_Thread_features`), and (b)
verifying that there are no application errors or crashes due to
incompatible binaries.

4. The majority of running processes should be protected, with Shadow
Stack enabled.



== User Experience ==
This change is transparent to users. No action is required to enable
or configure support. Applications that are not compatible with Shadow
Stack run without the protection; they continue to function normally
but do not benefit from the additional security. In rare cases, an
application that loads a non-compliant plugin at runtime may encounter
a `dlopen` error. Known affected applications ship with a drop-in
configuration file that prevents this. Users who encounter this with
other applications can create a file in `/etc/tunables.conf.d/` to opt
the application out, and then run `ldconfig`.

== Dependencies ==
1. Rust: The rust compiler needs to be able to generate Shadow Stack
compatible binaries. This affects a significant part of the Fedora
runtime and applications, including `rpm` and `firefox`. However, we
are collaborating with the Rust team and have already tested a `rustc`
change that enables emitting compatible binaries by default (without
the use of any flags). The
[https://bugzilla.redhat.com/show_bug.cgi?id=2196282 Rust Fedora Bug]
tracks this.

2. Firefox and Chrome: Both browsers are currently not compatible with
Shadow Stack although the Firefox binary and some objects are built
with Shadow Stack enabled. Upstream work, in particular around their
JIT compilers, as well as the rust tooling change mentioned above are
needed in order to fix this. Until then, we propose to disable Shadow
Stack protection flags when building Firefox. Both browsers will gain
Shadow Stack protection once their upstream dependencies are resolved,
at which point they can be rebuilt with protection turned on.

== Contingency Plan ==
* Contingency mechanism: Downstream patch applied to glibc to enable
Shadow Stacks by default in Fedora will be reverted.
* Contingency deadline: No deadline. The patch can be reverted as late
as necessary in the development cycle.
* Blocks release? No.


== Documentation ==


=== Guide for package maintainers ===

==== Checking an ELF object for CET support ====

Use `readelf` to inspect the GNU property note on any object file,
shared library, or binary. e.g.:

<pre>
readelf -n /usr/lib64/libc.so.6 | grep 'IBT\|SHSTK'
</pre>

A fully compliant object shows both properties:

<pre>
      Properties: x86 feature: IBT, SHSTK
</pre>

While this change only requires `SHSTK`, IBT (Indirect Branch
Tracking) will be enabled in a future release and fixing both now
avoids having to revisit these packages later. For this change, only
`SHSTK` is required. An object with `IBT` but not `SHSTK` will still
cause Shadow Stack to be disabled for the process. An object with
`SHSTK` but not `IBT` is fully compliant with this change. Fixing both
properties is recommended so that packages are ready for a future IBT
enablement, but only `SHSTK` is needed now. The linker ANDs these bits
across all inputs, so a single unmarked object will strip the property
from the final binary.  Packages are built by default with
`-fcf-protection` enabled, so source files when compiled with default
flags are automatically built with SHSTK/IBT support. However,
hand-written assembly needs annotations in order to be built with the
property enabled. This leads to situations where linking against
objects built with hand-written assembly without the appropriate
annotations strips the final binary or shared object of CET support.

==== Annotating a GAS assembly file ====

Hand-written `.S` files compiled through GCC do not automatically
receive the CET property note. To fix this, add one line near the top
of the file:

<pre>
#include <cet.h>
</pre>

For IBT compatibility, add `_CET_ENDBR` (also defined by `cet.h`) at
the entry point of any function that may be reached via an indirect
branch (e.g. function pointer):

<pre>
#include <cet.h>

  .text
  .globl my_handwritten_func
  .type my_handwritten_func, @function
my_handwritten_func:
  _CET_ENDBR
  /* ..function body */
  ret
</pre>

== Release Notes ==



-- 
Aoife Moloney

Fedora Operations Architect

Fedora Project

Matrix: @amoloney:fedora.im

IRC: amoloney

-- 
_______________________________________________
devel-announce mailing list -- [email protected]
To unsubscribe send an email to [email protected]
Fedora Code of Conduct: 
https://docs.fedoraproject.org/en-US/project/code-of-conduct/
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: 
https://lists.fedoraproject.org/archives/list/[email protected]
Do not reply to spam, report it: 
https://forge.fedoraproject.org/infra/tickets/issues/new

Reply via email to