Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20190306160740.GF28106@voyager>
Date: Wed, 6 Mar 2019 17:07:40 +0100
From: Markus Wichmann <nullplan@....net>
To: musl@...ts.openwall.com
Subject: Re: sigaltstack for implementation-internal signals?

On Wed, Mar 06, 2019 at 01:56:02PM +0100, Florian Weimer wrote:
> * Rich Felker:
> 
> > If we add unblockable, implementation-internal signals that are
> > flagged SA_ONSTACK, however, this breaks; now even if an application
> > has taken the "proper precautions", they can be delivered in a state
> > where the alt stack is nonempty but the stack pointer doesn't point
> > into it, thereby causing it to get clobbered.
> 
> There's also the matter of applications which do not use signal handlers
> at all (and thus never invoke sigaltstack) and have really small stacks,
> or use the stack pointer register for something else.  Is either of that
> supported?
> 

If you or any library you use install signal handlers, your code is
constantly at an interface boundary, since a signal can appear at any
time.

libc uses signal handlers. And you use libc. Connect the dots...

> I think it is not clear whether a libc implementation may generate
> sporadic signals *at all* to support implementation needs.
> 

Well, then we're at an impasse, as POSIX requires certain semantics and
the kernel provides different ones, and we need the signals as a
go-between. Alright, what implementation-internal signals are there?

SIGTIMER:
That one is needed in timer_create() to be able to spawn a thread if
someone creates a timer with SIGEV_THREAD. Since the handling thread is
spawned immediately, the signal is taken only on the stack of the
internal thread. And the handler itself does nothing. BTW, is there a
reason that handler is installed with SA_SIGINFO if it does nothing with
the extra info?

Anyway, this signal has no impact on application stacks.

SIGCANCEL:
The cancelled thread will take this signal. Wanting to cancel a thread
without signalling it is like wanting to be washed without being made
wet; it simply makes no sense. Applications can trivially prevent the
generation of this signal by simply foregoing the use of
pthread_cancel().

SIGSYNCCALL:
This is going to be the sticking point, isn't it? This signal really
does appear in each thread, even application threads, without warning.
It is currently used to implement setrlimit(), setegid(), seteuid(),
setgid(), setuid(), setregid(), setreuid(), setresgid() and setresuid().
Except for setrlimit(), I would not expect applications with tiny stacks
and lots of threads to call any of these. Much less often enough to
cause an issue. So setrlimit() is probably the only call that will cause
problems in the kind of applications you speak of.

Thus the entire problem could be solved if the kernel allowed setting
rlimits for the entire process, or at least for other threads. Seems
like the smaller change to me.

> Does musl use asynchronous implementation signals?  For glibc, we would
> prefer synchronous delivery, that is, the handler runs before the
> signal-generating system call returns.  This makes me wonder if we
> should try to get the kernel to provide us a system call which allows us
> to run code on a different thread, with signals disabled, but with the
> caller's stack (from the original thread).  I think this would address
> issues caused by strange stack pointer values in the target thread.
> 

Hmmm... if the kernel supported remote sigaltstack() (i.e. setting a
signal stack for another thread), then this would all be done. But alas,
no such luck.

> Thanks,
> Florian

Ciao,
Markus

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.