[PATCH 1/2] aarch64: Lock GCS with glibc.cpu.aarch64_gcs_lock tunable
Adhemerval Zanella Netto
adhemerval.zanella@linaro.org
Thu Dec 18 16:57:39 GMT 2025
On 18/12/25 12:57, Yury Khrustalev wrote:
> * Adhemerval
>
> On Wed, Dec 17, 2025 at 05:17:36PM -0300, Adhemerval Zanella Netto wrote:
>>
>> On 12/12/25 12:46, Yury Khrustalev wrote:
>>> This tunable controls locking status of Guarded Control Stack
>>> (GCS) for the process when GCS is enabled:
>>>
>>> 0 = unlocked: GCS can be disabled via a prctl() call.
>>> 1 = locked: GCS is locked and cannot be disable for the process.
>>>
>>> By default, GCS will be locked if enabled. If GCS is not enabled
>>> at startup, this tunable has no effect.
>>>
>>> Issue a prctl() syscall to lock GCS status based on the value
>>> of the glibc.cpu.aarch64_gcs_lock tunable for static and also
>>> dynamically-linked binaries.
>>>
>>> All operation bits are locked including the future ones. The
>>> prctl() syscall will accept this and this will ensure that
>>> any future operations are locked as well.
>>
>> I am not sure if this hardening is better server with a tunable
>> than through a GNU property on the ET_EXEC itself.
>
> I don't think I follow you. It is expected that the same binary might
> be run with and without locking without recompiling this binary, for
> example a binary package for Linux distro is built with GCS support,
> and when someone installs this package they can choose whether to
> enforce GCS locking or not.
Because I am not sure tunables is right way to add and enforce security
hardening:
* Environment variables are inherently user-controlled data. Relying on
them for security breaks the trust boundary between the unprivileged
user (who sets the variable) and the privileged execution environment.
- We disable tunables for SUID/SGID binaries due security issues, and
although such binaries are becoming rare, it also means that the system
will need a different way to enforcing hardening in this situation.
* Environment variables rely on the parent process correctly passing them
to the child via execve. If an intermediate process (e.g., a shell
script, a daemon launcher, or a service manager) clears the environment
(using env -i or similar) or fails to forward the specific variable, the
security feature silently drops off for all subsequent child processes.
* Security controls should ideally be fail-closed (if the protection can't
be enabled, the program shouldn't run), while environment variables can
lead to silent failure (the environment is typoed, overrides, etc.).
We do have tunable to disable it, like glibc.rtld.execstack, but it was
added as opt-out due compatibility reasons for process that are marked
to *not* require a executable stack but for any reason requires it.
* It is hard to audit and verify, since it is a transient state of system
configuration. A GNU attribute is a binary characteristic that you can
easily check with different tools.
* We do not enforce ABI stability, so in the future we setting might be
removed or changed. Worse, we won't be able to change because someone
depends on it.
* It requires an extra layer for system-wide deployment. We do have a
long-standing system-wide tunable patchset [1] that might address it.
[1] https://sourceware.org/pipermail/libc-alpha/2025-June/167242.html
>
>> I would expect
>> this to be modeled PT_GNU_STACK, even though GCS state is fully
>> handled in userland by design.
>>
>> It has an extra burden enabling this through binutils and extra
>> marking;
>
> Yes, this could be quite prohibitive as it would require ensuring
> that supporting version of binutils is present.
>
>> but I think once we start to deploy GCS enable system
>> flipping the tunable switch might also have unforseen breakage
>
> Why? tunables are used in this case specifically to maximise
> flexibility of deployment.
I was hoping that we could also move the glibc.cpu.aarch64_gcs to be
GNU attributes to avoid the same aforementioned issues above.
My understanding is the idea is eventually make GCS enforcement an
opt-out security hardening; meaning that system will be built to
to use it for whatever reason (performance, etc.). This is similar
to any other security hardening that we have deployed recently.
>
>> (as we saw we start to enforce non-executable stacks).
>>
>> The tunable options for GCS is already somewhat complex with
>> multiple options depending whether the object has or not
>> GNU_PROPERTY_AARCH64_FEATURE_1_GCS.
>
> Hence the 2nd tunable rather than extension of the 1st one. The
> 1st tunable aarch64_gcs controls whether GCS is used or not. And
> the 2nd one applies locking if GCS is enabled.
>
> Thanks,
> Yury
>
More information about the Libc-alpha
mailing list