PING: V7 [PATCH] sysconf: Add _SC_MINSIGSTKSZ/_SC_SIGSTKSZ [BZ #20305]

Dave Martin Dave.Martin@arm.com
Thu Nov 19 16:37:45 GMT 2020


On Thu, Nov 19, 2020 at 02:59:34PM +0000, Szabolcs Nagy via Libc-alpha wrote:
> The 11/18/2020 18:09, Dave Martin via Libc-alpha wrote:
> > On Wed, Nov 18, 2020 at 06:35:00PM +0100, Florian Weimer wrote:
> > > * Dave Martin:
> > > > I have some thoughts on what a better interface might look like --
> > > > basically separating the signal ucontext_t type from the setcontext()/
> > > > getcontext() etc. type, and providing accessors for the architectural
> > > > register state rather than just having a fixed struct definition for
> > > > mcontext_t.
> > > >
> > > > But, there also may not be a lot of appetite for such a change, and
> > > > I can't see how it could be backwards compatible.
> > > >
> > > > I can elaborate if people think it's worth discussing.
> > > 
> > > I think Rich Felker wants to copy signal contexts around to implement
> > > critical sections that can't be interrupted by a signal handler, I
> > > think that would need this fully fixed.
> > 
> > Is rseq a more suitable way to do that sort of thing on new-ish Linux?
> > I guess a fallback may be needed for older / other kernels though.
> 
> rseq does not help with libc critical sections:
> 
> the point is not to restart the critical section
> (which would require no side effect or mechanisms
> to roll side effects back and that the section is
> entirely written in asm between begin/end labels
> so the kernel knows when the section is left),
> 
> but to let the critical section with all its side
> effects complete and delay the signal handler
> until then. (the slow and easy way to do this is
> masking signals using syscalls around critical
> sections, a fast solution needs signal wrapping
> and saving the sigcontext.)
> 
> for example the entire malloc call can be a critical
> section and an incomming signal delayed until malloc
> completes. such solution allows hiding all libc
> internal inconsistent state from user code so async
> signal handlers can call all libc apis.

Isn't this a bit backwards.  This "makes" trivial signal handlers easier
to write, but this is a bit of a Trojan horse: precisely because signal
handlers can interrupt things, subtleties abound.  So, while there are
plenty of naive signal handlers out there, there are far fewer that are
genuinely trivial -- i.e., free from subtleties.

In any case, the problem of async signal safety remains: even if libc
uses internal locks to hide it, library functions in general may not.

A better approach would be to have function attributes that identify
code that may run in signal context and async-signal-safe functions, so
that the compiler can actually enforce that only reentrant functions are
called from signal context.

Finally, if a fault signal is delivered while blocked or ignored it
kills the process.  So handlers for fault signals raised by the kernel
still wouldn't be able to call random libc functions: to prevent sudden
death while in the middle of malloc etc., libc must not mask these
signals, and wouldn't be safely reentrant while handling then -- thus we
still have the problem we intended to solve.

This is ironic, since these signals are the _only_ signals that must be
handled using signal handlers.  Other signals can all be accepted by
other means, such as signalfd.

The other reason to use signal handlers is to minimise response latency
for asynchronous signals.  Masking signals in order to bulletproof
code that the signal handler probably isn't going to use anyway would
interfere with this goal.

> > For aarch64 an explicit prctl()/sysctl opt-in is needed to enable jumbo
> > vector registers before you see oversized signal frames, though I don't
> > think there is a similar control for AVX-512.
> > 
> > Even on aarch64, this interface is not very friendly though.  It might
> > be better to have some ELF attribute that ld.so or the libc startup can
> > arbitrate on and twiddle the appropriate switches.
> 
> we can probably mark binaries if they are large
> vector length compatible. (but the incompatible
> binaries have to be hunted down manually and all
> we can do with them at dlopen time is to give a
> nice dlerror in case the vlengh got increased)

Unless libc obeys the flag and actively prevents the setting of a larger
vector length.  It could do that, though I don't have a strong view on
whether it should...

dlopening a library with a smaller maximum vector length than the
established one would still be a problem though: we might have to fail
that.  But only in a process where some library uses SVE at all.  I
think there are ELF attributes for that too, no?

I think the incompatible binaries don't necessarily have to be hunted
down:  if a program was built with _GNU_SOURCE and a new enough C
library, it can't use the compile-time constant MINSIGSTKSZ etc., so we
can take the opportunity to mark the binary.  Other binaries can't be
assumed to be compatible with large vectors.

Cheers
---Dave


More information about the Libc-alpha mailing list