mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1038900 - Dynamically allocate signal number for sandbox startup. r=kang
This commit is contained in:
parent
d61ca8ca45
commit
285d65221e
@ -224,12 +224,31 @@ InstallSyscallFilter(const sock_fprog *prog)
|
||||
// Use signals for permissions that need to be set per-thread.
|
||||
// The communication channel from the signal handler back to the main thread.
|
||||
static mozilla::Atomic<int> sSetSandboxDone;
|
||||
// about:memory has the first 3 RT signals. (We should allocate
|
||||
// signals centrally instead of hard-coding them like this.)
|
||||
static const int sSetSandboxSignum = SIGRTMIN + 3;
|
||||
// Pass the filter itself through a global.
|
||||
static const sock_fprog *sSetSandboxFilter;
|
||||
|
||||
// We have to dynamically allocate the signal number; see bug 1038900.
|
||||
// This function returns the first realtime signal currently set to
|
||||
// default handling (i.e., not in use), or 0 if none could be found.
|
||||
//
|
||||
// WARNING: if this function or anything similar to it (including in
|
||||
// external libraries) is used on multiple threads concurrently, there
|
||||
// will be a race condition.
|
||||
static int
|
||||
FindFreeSignalNumber()
|
||||
{
|
||||
for (int signum = SIGRTMIN; signum <= SIGRTMAX; ++signum) {
|
||||
struct sigaction sa;
|
||||
|
||||
if (sigaction(signum, nullptr, &sa) == 0 &&
|
||||
(sa.sa_flags & SA_SIGINFO) == 0 &&
|
||||
sa.sa_handler == SIG_DFL) {
|
||||
return signum;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
SetThreadSandbox()
|
||||
{
|
||||
@ -268,6 +287,7 @@ SetThreadSandboxHandler(int signum)
|
||||
static void
|
||||
BroadcastSetThreadSandbox()
|
||||
{
|
||||
int signum;
|
||||
pid_t pid, tid;
|
||||
DIR *taskdp;
|
||||
struct dirent *de;
|
||||
@ -283,8 +303,16 @@ BroadcastSetThreadSandbox()
|
||||
LOG_ERROR("opendir /proc/self/task: %s\n", strerror(errno));
|
||||
MOZ_CRASH();
|
||||
}
|
||||
if (signal(sSetSandboxSignum, SetThreadSandboxHandler) != SIG_DFL) {
|
||||
LOG_ERROR("signal %d in use!\n", sSetSandboxSignum);
|
||||
signum = FindFreeSignalNumber();
|
||||
if (signum == 0) {
|
||||
LOG_ERROR("No available signal numbers!");
|
||||
MOZ_CRASH();
|
||||
}
|
||||
void (*oldHandler)(int);
|
||||
oldHandler = signal(signum, SetThreadSandboxHandler);
|
||||
if (oldHandler != SIG_DFL) {
|
||||
// See the comment on FindFreeSignalNumber about race conditions.
|
||||
LOG_ERROR("signal %d in use by handler %p!\n", signum, oldHandler);
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
@ -309,7 +337,7 @@ BroadcastSetThreadSandbox()
|
||||
}
|
||||
// Reset the futex cell and signal.
|
||||
sSetSandboxDone = 0;
|
||||
if (syscall(__NR_tgkill, pid, tid, sSetSandboxSignum) != 0) {
|
||||
if (syscall(__NR_tgkill, pid, tid, signum) != 0) {
|
||||
if (errno == ESRCH) {
|
||||
LOG_ERROR("Thread %d unexpectedly exited.", tid);
|
||||
// Rescan threads, in case it forked before exiting.
|
||||
@ -378,7 +406,12 @@ BroadcastSetThreadSandbox()
|
||||
}
|
||||
rewinddir(taskdp);
|
||||
} while (sandboxProgress);
|
||||
unused << signal(sSetSandboxSignum, SIG_DFL);
|
||||
oldHandler = signal(signum, SIG_DFL);
|
||||
if (oldHandler != SetThreadSandboxHandler) {
|
||||
// See the comment on FindFreeSignalNumber about race conditions.
|
||||
LOG_ERROR("handler for signal %d was changed to %p!", signum, oldHandler);
|
||||
MOZ_CRASH();
|
||||
}
|
||||
unused << closedir(taskdp);
|
||||
// And now, deprivilege the main thread:
|
||||
SetThreadSandbox();
|
||||
|
Loading…
Reference in New Issue
Block a user