Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <d9a53f72-f7f5-4cde-b530-ed26196c2fa2@bu.edu>
Date: Tue, 22 Sep 2026 13:38:19 -0400
From: Khosro Moeini <khosro@...edu>
To: Rich Felker <dalias@...c.org>
Cc: musl@...ts.openwall.com
Subject: Re: [PATCH v3] x86_64: add CET shadow stack support

On 9/20/26 10:56 PM, Rich Felker wrote:
> On Sun, Sep 20, 2026 at 07:33:17PM +0000, Khosro Moeini wrote:
>> Enable CET shadow stack on x86_64 when the executable and all loaded
>> shared objects have the GNU_PROPERTY_X86_FEATURE_1_SHSTK bit set in
>> their .note.gnu.property note. If shadow stack is enabled for a process
>> dlopen of an object without the shadow stack property note fails.
>> Unlike glibc, this implementation does not check environment variables.
>> All the changes are guarded by SHSTK_ENABLED which is set through
>> the --enable-cet configuration option.
>>
>> Signed-off-by: Khosro Moeini <khosro@...edu>
>> ---
>>>> Thanks for the feedback. Regarding the concerns discussed in the older
>>>> thread:
>>>>
>>>> sigaltstack: The main program and its signal handlers use the same
>>>> shadow stack, so there won't be resource problems. Please see:
>>>>       https://docs.kernel.org/next/x86/shstk.html#signal
>>>
>>> That is exactly the problem. It breaks the property that overflow of
>>> the normal stack cannot prevent the signal handler from running.
>>
>> The size of the shadow stack is MIN(RLIMIT_STACK, 4 GB) and the shadow
>> stack only stores return addresses. Given the 16-byte stack alignment
>> in the x86_64 calling convention, in the extreme case where no extra
>> stack space is used, the shadow stack would be half empty when the
>> normal stack is overflowing. The Linux doc says:
>> "Because the shadow stack stores only return addresses, a large shadow
>> stack covers the condition that both the program stack and the signal
>> alternate stack run out."
> 
> You mean there's RLIMIT_STACK committed for every thread?
> 
> Or is it not committed and crashes the process on OOM?
>

The kernel allocates a new shadow stack for every thread/process.

> What happens if RLIMIT_STACK is small but the thread stack size
> selected in the pthread_attr_t is large?
>

Depends on how the thread is created. If via clone, RLIMIT_STACK is
allocated and as you mentioned that might be a problem. If via clone3,
the stack size specified in clone3 is allocated. Would it be possible to
use clone3 in pthread_create? If using clone3 is not an option, there
might be a way to use the map_shadow_stack syscall to allocate a new
shadow stack of the right size.
>>>> ucontext: removed from POSIX and not supported in musl
>>>
>>> That just means we don't presently have it in musl; distros are using
>>> libucontext.
>>
>> This shouldn't be an issue. If the library supports shadow stack and
>> has the shadow stack note, then shadow stack can be safely activated.
>> If the library does not support shadow stack it wouldn't have the
>> shadow stack note and thus shadow stack won't be activated for programs
>> using this library.
> 
> So on a system built for shadow stack by default, would someone
> building libuconext need to explicitly pass LDFLAGS to mark it not
> compatible?
>
> Also, it sounds like you are assuming "library" means .so; that is not
> an assumption we make. Or are there .o level markings that would cause
> the program to link without shadow stack?
>

The SHSTK mark/note is at .o level and lack of it means incompatibility.
Compilers don't mark objects by default so when building libucontext (or
any program) extra flags must be passed to mark it as compatible. So if
libucontext isn't explicitly marked as compatible, shadow stack won't be
activated in both static and dynamic linking scenarios.

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.