[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