[PATCH v7 09/23] aarch64: Try to free the GCS of makecontext
Adhemerval Zanella Netto
adhemerval.zanella@linaro.org
Fri Jan 10 13:09:24 GMT 2025
On 10/01/25 10:01, Yury Khrustalev wrote:
> On Thu, Jan 09, 2025 at 03:53:14PM -0300, Adhemerval Zanella Netto wrote:
>>
>>>> I think this will make makecontext non async-signal-safe when GCS is used,
>>>> when we explict document it as AS-Safe and AC-Safe. I think using
>>>> internal_signal_block_all/internal_signal_restore_set would be suffice,
>>>> but it is also a performance regression.
>>>
>>> Do you refer to the call to malloc() in record_gcs()?
>>>
>>> We need to keep track of shadow stacks allocated via map_shadow_stack()
>>> when a new context is created with makecontext() so that we can munmap
>>> it when it is no longer required.
>>>
>>> I think this is not on a performance critical path, so we can add the
>>> internal_signal_block_all / internal_signal_restore_set pair. Could you
>>> recommend where it would be best to use it?
>>
>> Yes, glibc malloc is not async-signal-safe and thus calling on makecontext
>> make it async-signal-unsafe (similar for setcontext, which ends up calling
>> free).
>>
>> I am not sure if you can really use malloc here, since a makecontext call
>> potentially interrupt malloc itself. We had the same issue on the getrandom
>> vDSO call; where we ended up using mmap directly instead.
>>
>> You will still need to block/unblock signal to avoid reentrant signal
>> handlers; and there is the consideration of extra the mmap overhead per thread.
>>
>> Another possibility, which I think would be simpler, is to add a TCB buffer
>> of N entries and use instead of a linked-list. It would add an small
>> memory overhead on each thread, and it would limit the number of in-flight
>> makecontext a thread can make; but at least makecontext can to return
>> ENOMEM if it can not create a new context, and it way simpler than adding
>> the mmap-allocator.
>
> makecontext() does not return a value and doesn't set errno, so we probably
> cannot "return" ENOMEM. In existing code, when makecontext() failes, it calls
> abort(). Would the same be appropriate when we reach max number of context
> instances per thread?
Sigh, you are right (I confused it with setcontext for some reason). I think
it would be the best option and x86_64 already does this if
__allocate_shadow_stack fails.
>
> Another option is to silently stop freeing shadow stacks after reaching max
> number. This will allow code that needs more makecontext's to continue with
> memory leak being downside (potentially leading to ENOMEM).
I don't think a silent leak is the best option, specially one that user can
not take some course of action without a lot of hackery.
More information about the Libc-alpha
mailing list