The Pedigree Project 0.1
signal-syscalls.cc
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include "pedigree/kernel/Log.h"
21#include "pedigree/kernel/process/Scheduler.h"
22#include "pedigree/kernel/process/Uninterruptible.h"
23#include "pedigree/kernel/processor/PhysicalMemoryManager.h"
24#include "pedigree/kernel/processor/SyscallManager.h"
25#include "pedigree/kernel/syscallError.h"
26
27#include "file-syscalls.h"
28#include "linux-amd64-signal-abi.h"
29#include "linux-amd64-signal.h"
30#include "linux-wait-abi.h"
31#include "pthread-syscalls.h"
32#include "signal-syscalls.h"
33#include "system-syscalls.h"
34
35#define MACHINE_FORWARD_DECL_ONLY
36#include "pedigree/kernel/Subsystem.h"
37#include "pedigree/kernel/machine/Machine.h"
38#include "pedigree/kernel/machine/Timer.h"
39
40#include <PosixProcess.h>
41#include <PosixSubsystem.h>
42#include <signal.h>
43#include <time.h>
44
45extern "C" {
46extern void sigret_stub();
47extern char sigret_stub_end;
48}
49
50// Internal result retained across process-group fanout.
51static constexpr int SignalQueueFull = -2;
52static int doProcessKill(Process* p, int sig);
53static int doThreadKill(Thread* p, int sig);
54static int queueThreadSignal(Process* process, Thread* thread, int sig);
55
57
58#define SIGNAL_HANDLER_EXIT(name, errcode) \
59 static void name(int) { \
60 Processor::information().getCurrentThread()->deferSignalExit(errcode); \
61 }
62#define SIGNAL_HANDLER_EMPTY(name) \
63 static void name(int s) { \
64 NOTICE("EMPTY handler."); \
65 }
66#define SIGNAL_HANDLER_EXITMSG(name, errcode, msg) \
67 static void name(int) { \
68 Processor::setInterrupts(true); \
69 posix_write(1, msg, StringLength(msg), true); \
70 Scheduler::instance().yield(); \
71 Processor::information().getCurrentThread()->deferSignalExit(errcode); \
72 }
73static char SSIGILL[] = "Illegal instruction.\n";
74static char SSIGSEGV[] = "Segmentation fault.\n";
75static char SSIGBUS[] = "Bus error.\n";
76static char SSIGABRT[] = "Abort.\n";
77
78SIGNAL_HANDLER_EXITMSG(sigabrt, SIGABRT, SSIGABRT)
79SIGNAL_HANDLER_EXIT(sigalrm, SIGALRM)
80SIGNAL_HANDLER_EXITMSG(sigbus, SIGBUS, SSIGBUS)
81SIGNAL_HANDLER_EMPTY(sigchld)
82static void sigcont(int) {}
83SIGNAL_HANDLER_EXIT(sigfpe, SIGFPE) // floating point exception signal
84SIGNAL_HANDLER_EXIT(sighup, SIGHUP)
85SIGNAL_HANDLER_EXITMSG(sigill, SIGILL, SSIGILL)
86SIGNAL_HANDLER_EXIT(sigint, SIGINT)
87SIGNAL_HANDLER_EXIT(sigkill, SIGKILL)
88SIGNAL_HANDLER_EXIT(sigpipe, SIGPIPE)
89SIGNAL_HANDLER_EXIT(sigquit, SIGQUIT)
90SIGNAL_HANDLER_EXITMSG(sigsegv, SIGSEGV, SSIGSEGV)
91SIGNAL_HANDLER_EXIT(sigstkflt, SIGSTKFLT)
92SIGNAL_HANDLER_EXIT(sigterm, SIGTERM)
93SIGNAL_HANDLER_EXIT(sigtrap, SIGTRAP)
94SIGNAL_HANDLER_EXIT(sigusr1, SIGUSR1)
95SIGNAL_HANDLER_EXIT(sigusr2, SIGUSR2)
96SIGNAL_HANDLER_EMPTY(sigurg) // high bandwdith data available at a sockeet
97SIGNAL_HANDLER_EXIT(sigxcpu, SIGXCPU)
98SIGNAL_HANDLER_EXIT(sigxfsz, SIGXFSZ)
99SIGNAL_HANDLER_EXIT(sigvtalrm, SIGVTALRM)
100SIGNAL_HANDLER_EXIT(sigprof, SIGPROF)
101SIGNAL_HANDLER_EXIT(sigio, SIGIO)
102SIGNAL_HANDLER_EXIT(sigpwr, SIGPWR)
103SIGNAL_HANDLER_EXIT(sigsys, SIGSYS)
104SIGNAL_HANDLER_EXIT(sigtimer, 32)
105SIGNAL_HANDLER_EXIT(sigcancel, 33)
106SIGNAL_HANDLER_EXIT(sigsynccall, 34)
107
108SIGNAL_HANDLER_EMPTY(sigign);
109
110static void suspendForDefaultSignal(int) {
111 Thread* thread = Processor::information().getCurrentThread();
112 size_t signal = 0;
113 size_t continuationEpoch = 0;
114 if (!thread || !thread->getCurrentSignalDelivery(signal, continuationEpoch)) {
115 ERROR("Default stop handler did not receive trusted signal metadata.");
116 return;
117 }
118 if (signal != SIGSTOP && signal != SIGTSTP && signal != SIGTTIN && signal != SIGTTOU) {
119 ERROR("Default stop handler received non-stop signal " << Dec << signal << ".");
120 return;
121 }
122
123 Process* process = thread->getParent();
124 NOTICE("SUSPEND [pid=" << process->getId() << ", signal " << signal << "]");
125 process->suspendIfContinuationEpoch(static_cast<int>(signal), continuationEpoch);
126}
127
128static _sig_func_ptr default_sig_handlers[PosixSubsystem::SignalDispositionCount] = {
129 sigign, // 0
130 sighup, // SIGHUP
131 sigint, // SIGINT
132 sigquit, // SIGQUIT
133 sigill, // SIGILL
134 sigtrap, // SIGTRAP
135 sigabrt, // SIGABRT
136 sigbus, // SIGBUS
137 sigfpe, // SIGFPE
138 sigkill, // SIGKILL
139 sigusr1, // SIGUSR1
140 sigsegv, // SIGSEGV
141 sigusr2, // SIGUSR2
142 sigpipe, // SIGPIPE
143 sigalrm, // SIGALRM
144 sigterm, // SIGTERM
145 sigstkflt, // SIGSTKFLT
146 sigchld, // SIGCHLD
147 sigcont, // SIGCONT
148 suspendForDefaultSignal, // SIGSTOP
149 suspendForDefaultSignal, // SIGTSTP
150 suspendForDefaultSignal, // SIGTTIN
151 suspendForDefaultSignal, // SIGTTOU
152 sigurg, // SIGURG
153 sigxcpu, // SIGXCPU
154 sigxfsz, // SIGXFSZ
155 sigvtalrm, // SIGVTALRM
156 sigprof, // SIGPROF
157 sigign, // SIGWINCH
158 sigio, // SIGIO/SIGPOLL
159 sigpwr, // SIGPWR
160 sigsys, // SIGSYS
161 sigtimer, // musl SIGTIMER
162 sigcancel, // musl SIGCANCEL
163 sigsynccall, // musl SIGSYNCCALL
164};
165
166static void realtimeDefault(int) {
167 Thread* thread = Processor::information().getCurrentThread();
168 size_t signal = 0, epoch = 0;
169 if (thread->getCurrentSignalDelivery(signal, epoch))
170 thread->deferSignalExit(signal);
171}
172
173uintptr_t pedigree_default_signal_handler(size_t signal) {
174 if (signal >= 35 && signal <= PosixSubsystem::MaximumSupportedSignal)
175 return reinterpret_cast<uintptr_t>(realtimeDefault);
176 return signal < PosixSubsystem::SignalDispositionCount
177 ? reinterpret_cast<uintptr_t>(default_sig_handlers[signal])
178 : 0;
179}
180
181static int posix_sigaction_impl(int sig, const struct sigaction* act, struct sigaction* oact,
182 bool allowLinuxPrivateSignals) {
183 Thread* pThread = Processor::information().getCurrentThread();
184 Process* pProcess = pThread->getParent();
185 PosixSubsystem* pSubsystem = static_cast<PosixSubsystem*>(pProcess->getSubsystem());
186 if (!pSubsystem) {
187 ERROR("posix_sigaction: no subsystem");
188 return -1;
189 }
190
191 // sanity and safety checks
192 if ((sig <= 0) || (sig > static_cast<int>(PosixSubsystem::MaximumSupportedSignal)) ||
193 (!allowLinuxPrivateSignals &&
194 sig >= static_cast<int>(PosixSubsystem::LinuxPrivateSignalFirst) && sig <= 34) ||
195 (sig == SIGKILL || sig == SIGSTOP)) {
196 SYSCALL_ERROR(InvalidArgument);
197 return -1;
198 }
199
200 uintptr_t newHandler = 0;
201 int handlerType = 1;
202 if (act) {
203 newHandler = reinterpret_cast<uintptr_t>(act->sa_handler);
204 if (newHandler == 0) {
205 SG_NOTICE(" + SIG_DFL");
206 newHandler = pedigree_default_signal_handler(sig);
207 handlerType = 1;
208 } else if (newHandler == 1) {
209 SG_NOTICE(" + SIG_IGN");
210 newHandler = reinterpret_cast<uintptr_t>(sigign);
211 handlerType = 2;
212 } else if (newHandler == static_cast<uintptr_t>(-1)) {
213 SG_NOTICE(" + Invalid");
214 SYSCALL_ERROR(InvalidArgument);
215 return -1;
216 } else {
217 handlerType = 0;
218 if (!PosixSubsystem::checkAddress(newHandler, 1, PosixSubsystem::SafeExecute)) {
219 SG_NOTICE(" + Handler is not executable userspace memory");
220 SYSCALL_ERROR(BadAddress);
221 return -1;
222 }
223 }
224 }
225
226 // Store the old signal handler information only after the replacement has
227 // passed validation.
228 if (oact) {
230 ByteSet(oact, 0, sizeof(struct sigaction));
231 if (pSubsystem->getSignalDisposition(sig, oldDisposition)) {
232 oact->sa_flags = oldDisposition.flags;
233 oact->sa_restorer = reinterpret_cast<void (*)()>(oldDisposition.restorer);
234 MemoryCopy(&oact->sa_mask, &oldDisposition.signalMask, sizeof(oldDisposition.signalMask));
235 if (oldDisposition.type == 0)
236 oact->sa_handler = reinterpret_cast<void (*)(int)>(oldDisposition.handler);
237 else if (oldDisposition.type == 1)
238 oact->sa_handler = reinterpret_cast<void (*)(int)>(0);
239 else if (oldDisposition.type == 2)
240 oact->sa_handler = reinterpret_cast<void (*)(int)>(1);
241 }
242 }
243
244 // Publish the validated replacement disposition.
245 if (act) {
246 bool legacyUserHandler = handlerType == 0;
247#if X64
248 legacyUserHandler = legacyUserHandler && pSubsystem->getAbi() != PosixSubsystem::LinuxAbi;
249#endif
251 sigHandler->flags = act->sa_flags;
252 sigHandler->restorer = reinterpret_cast<uintptr_t>(act->sa_restorer);
253 sigHandler->type = handlerType;
254 MemoryCopy(&sigHandler->sigMask, &act->sa_mask, sizeof(sigHandler->sigMask));
255
256#if X64
257 if (handlerType == 0 && !legacyUserHandler) {
258 sigHandler->pEvent = new LinuxAmd64Signal::AsyncEvent(
259 newHandler, static_cast<size_t>(sig), sigHandler->sigMask,
260 !(sigHandler->flags & SA_NODEFER), sigHandler->flags, sigHandler->restorer,
261 sigHandler->flags & SA_ONSTACK);
262 } else
263#endif
264 {
265 sigHandler->pEvent = new SignalEvent(
266 newHandler, static_cast<size_t>(sig), ~0UL, sigHandler->sigMask,
267 !(sigHandler->flags & SA_NODEFER), false,
268 handlerType == 0 ? Event::HandlerPrivilege::User : Event::HandlerPrivilege::Kernel,
269 handlerType == 0 ? SignalEvent::DeliveryDisposition::CaughtHandler
270 : SignalEvent::DeliveryDisposition::DefaultAction,
271 handlerType == 0 && (sigHandler->flags & SA_ONSTACK));
272 }
273 if (legacyUserHandler && !pSubsystem->admitLegacyUserSignals()) {
274 delete sigHandler;
275 SYSCALL_ERROR(OperationNotSupported);
276 return -1;
277 }
278 SG_NOTICE("Creating the event (" << reinterpret_cast<uintptr_t>(sigHandler->pEvent) << ").");
279 pSubsystem->setSignalHandler(sig, sigHandler);
280 } else if (!oact) {
281 // no valid arguments!
282 SYSCALL_ERROR(InvalidArgument);
283 return -1;
284 }
285 return 0;
286}
287
288int posix_sigaction(int sig, const struct sigaction* act, struct sigaction* oact) {
289 SG_NOTICE("sigaction(" << Dec << sig << Hex << ", " << reinterpret_cast<uintptr_t>(act) << ", "
290 << reinterpret_cast<uintptr_t>(oact) << ")");
291 struct sigaction requested = {};
292 if ((act && !PosixSubsystem::copyFromUser(&requested, act, sizeof(requested))) ||
293 (oact && !PosixSubsystem::checkAddress(reinterpret_cast<uintptr_t>(oact), sizeof(*oact),
294 PosixSubsystem::SafeWrite))) {
295 SYSCALL_ERROR(BadAddress);
296 return -1;
297 }
298
299 struct sigaction previous = {};
300 int result =
301 posix_sigaction_impl(sig, act ? &requested : nullptr, oact ? &previous : nullptr, false);
302 if ((result == 0) && oact && !PosixSubsystem::copyToUser(oact, &previous, sizeof(previous))) {
303 SYSCALL_ERROR(BadAddress);
304 return -1;
305 }
306 return result;
307}
308
309#if ARMV7
310struct LinuxArmv7KernelSigaction {
311 uint32_t handler;
312 uint32_t flags;
313 uint32_t restorer;
314 uint32_t mask[2];
315};
316
317static_assert(sizeof(LinuxArmv7KernelSigaction) == 20);
318
319int posix_linux_armv7_sigaction(int sig, const LinuxArmv7KernelSigaction* act,
320 LinuxArmv7KernelSigaction* oact) {
321 LinuxArmv7KernelSigaction linuxAct = {};
322 if ((act && !PosixSubsystem::copyFromUser(&linuxAct, act, sizeof(linuxAct))) ||
323 (oact && !PosixSubsystem::checkAddress(reinterpret_cast<uintptr_t>(oact), sizeof(*oact),
324 PosixSubsystem::SafeWrite))) {
325 SYSCALL_ERROR(BadAddress);
326 return -1;
327 }
328
329 struct sigaction nativeAct = {};
330 if (act) {
331 nativeAct.sa_handler = reinterpret_cast<void (*)(int)>(linuxAct.handler);
332 nativeAct.sa_flags = linuxAct.flags;
333 nativeAct.sa_restorer = reinterpret_cast<void (*)()>(linuxAct.restorer);
334 MemoryCopy(&nativeAct.sa_mask, &linuxAct.mask, sizeof(linuxAct.mask));
335 }
336
337 struct sigaction nativeOld = {};
338 const int result =
339 posix_sigaction_impl(sig, act ? &nativeAct : nullptr, oact ? &nativeOld : nullptr, true);
340 if (result == 0 && oact) {
341 LinuxArmv7KernelSigaction linuxOld = {};
342 linuxOld.handler = reinterpret_cast<uintptr_t>(nativeOld.sa_handler);
343 linuxOld.flags = nativeOld.sa_flags;
344 linuxOld.restorer = reinterpret_cast<uintptr_t>(nativeOld.sa_restorer);
345 MemoryCopy(&linuxOld.mask, &nativeOld.sa_mask, sizeof(linuxOld.mask));
346 if (!PosixSubsystem::copyToUser(oact, &linuxOld, sizeof(linuxOld))) {
347 SYSCALL_ERROR(BadAddress);
348 return -1;
349 }
350 }
351 return result;
352}
353#endif
354
355#if BITS_64
357 uint64_t handler;
358 uint64_t flags;
359 uint64_t restorer;
360 uint64_t mask;
361};
362
363static_assert(sizeof(LinuxAmd64KernelSigaction) == 32,
364 "Linux amd64 kernel sigaction layout must remain 32 bytes");
365static_assert(sizeof(stack_t) == 24 && __builtin_offsetof(stack_t, ss_flags) == 8 &&
366 __builtin_offsetof(stack_t, ss_size) == 16,
367 "Linux amd64 sigaltstack layout must remain 24 bytes");
368
369int posix_linux_amd64_sigaction(int sig, const LinuxAmd64KernelSigaction* act,
371 SG_NOTICE("linux-amd64 sigaction(" << Dec << sig << Hex << ", "
372 << reinterpret_cast<uintptr_t>(act) << ", "
373 << reinterpret_cast<uintptr_t>(oact) << ")");
374 LinuxAmd64KernelSigaction linuxAct = {};
375 if ((act && !PosixSubsystem::copyFromUser(&linuxAct, act, sizeof(linuxAct))) ||
376 (oact && !PosixSubsystem::checkAddress(reinterpret_cast<uintptr_t>(oact),
378 PosixSubsystem::SafeWrite))) {
379 SYSCALL_ERROR(BadAddress);
380 return -1;
381 }
382
383 struct sigaction nativeAct = {};
384 const struct sigaction* nativeActPtr = nullptr;
385 if (act) {
386 nativeAct.sa_handler =
387 reinterpret_cast<void (*)(int)>(static_cast<uintptr_t>(linuxAct.handler));
388 nativeAct.sa_flags = static_cast<int>(linuxAct.flags);
389 nativeAct.sa_restorer = reinterpret_cast<void (*)()>(static_cast<uintptr_t>(linuxAct.restorer));
390 MemoryCopy(&nativeAct.sa_mask, &linuxAct.mask, sizeof(linuxAct.mask));
391 nativeActPtr = &nativeAct;
392 }
393
394 struct sigaction nativeOld = {};
395 struct sigaction* nativeOldPtr = oact ? &nativeOld : nullptr;
396 int result = posix_sigaction_impl(sig, nativeActPtr, nativeOldPtr, true);
397 if ((result == 0) && oact) {
398 LinuxAmd64KernelSigaction linuxOld = {};
399 linuxOld.handler = reinterpret_cast<uintptr_t>(nativeOld.sa_handler);
400 linuxOld.flags = static_cast<uint64_t>(static_cast<uint32_t>(nativeOld.sa_flags));
401 linuxOld.restorer = reinterpret_cast<uintptr_t>(nativeOld.sa_restorer);
402 MemoryCopy(&linuxOld.mask, &nativeOld.sa_mask, sizeof(linuxOld.mask));
403 if (!PosixSubsystem::copyToUser(oact, &linuxOld, sizeof(linuxOld))) {
404 SYSCALL_ERROR(BadAddress);
405 return -1;
406 }
407 }
408
409 return result;
410}
411#endif
412
413uintptr_t posix_signal(int sig, void* func) {
414 ERROR("signal called but glue signal should redirect to sigaction");
415 return 0;
416}
417
418int posix_raise(int sig) {
419 SG_NOTICE("raise");
420
421 // Create the pending signal and pass it in
422 Thread* pThread = Processor::information().getCurrentThread();
423 Process* pProcess = pThread->getParent();
424 PosixSubsystem* pSubsystem = static_cast<PosixSubsystem*>(pProcess->getSubsystem());
425 if (!pSubsystem) {
426 ERROR("posix_raise: no subsystem");
427 return -1;
428 }
429
430 {
431 // The common syscall return boundary owns delivery after the callback's
432 // handler lease and terminal deferral have retired.
433 Uninterruptible whileQueueing;
434 if (pSubsystem->queueSignalDelivery(pThread, sig) ==
435 PosixSubsystem::SignalDeliveryResult::Full) {
436 SYSCALL_ERROR(NoMoreProcesses);
437 return -1;
438 }
439 }
440
441 // All done
442 return 0;
443}
444
445int pedigree_sigret() {
446 SG_NOTICE("pedigree_sigret");
447
448 if (!SyscallManager::instance().requestEventReturn()) {
449 SYSCALL_ERROR(InvalidArgument);
450 return -1;
451 }
452 return 0;
453}
454
455int pedigree_unwind_signal() {
456 SG_NOTICE("pedigree_unwind_signal");
457
458 if (!SyscallManager::instance().requestEventStatePop()) {
459 SYSCALL_ERROR(InvalidArgument);
460 return -1;
461 }
462 return 0;
463}
464
465static int doThreadKill(Thread* p, int sig) {
466 // Build the pending signal and pass it in
467 PosixSubsystem* pSubsystem = static_cast<PosixSubsystem*>(p->getParent()->getSubsystem());
468 if (!pSubsystem) {
469 ERROR("posix_kill: no subsystem on process " << p->getParent()->getId());
470 return -1;
471 }
472 if (pSubsystem->queueSignalDelivery(p, sig, nullptr, 0, true) ==
473 PosixSubsystem::SignalDeliveryResult::Full) {
474 SYSCALL_ERROR(NoMoreProcesses);
475 return SignalQueueFull;
476 }
477
478 return 0;
479}
480
481static int doProcessKill(Process* p, int sig) {
483 return p->acquireProcessSignalThread(target) ? doThreadKill(target.get(), sig) : -1;
484}
485
486static bool canSignalProcess(const PosixProcess* caller, const PosixProcess* target, int sig) {
487 const int64_t callerReal = caller->getUserId();
488 const int64_t callerEffective = caller->getEffectiveUserId();
489 if (callerEffective == 0) {
490 return true;
491 }
492
493 const int64_t targetReal = target->getUserId();
494 const int64_t targetSaved = target->getSavedUserId();
495 const bool realMatches = callerReal >= 0 && (callerReal == targetReal ||
496 (targetSaved >= 0 && callerReal == targetSaved));
497 const bool effectiveMatches =
498 callerEffective >= 0 &&
499 (callerEffective == targetReal || (targetSaved >= 0 && callerEffective == targetSaved));
500 if (realMatches || effectiveMatches) {
501 return true;
502 }
503
504 return sig == SIGCONT && caller->sharesSession(*target);
505}
506
507static int queueThreadSignal(Process* process, Thread* thread, int sig) {
508 if (!sig) {
509 return 0;
510 }
511
512 PosixSubsystem* subsystem = static_cast<PosixSubsystem*>(process->getSubsystem());
513 if (!subsystem) {
514 SYSCALL_ERROR(InvalidArgument);
515 return -1;
516 }
517
518 const PosixSubsystem::SignalDeliveryResult result =
519 subsystem->queueSignalDelivery(thread, static_cast<size_t>(sig), nullptr, -6);
520 if (result == PosixSubsystem::SignalDeliveryResult::Full) {
521 SYSCALL_ERROR(NoMoreProcesses);
522 return -1;
523 }
524 if (result == PosixSubsystem::SignalDeliveryResult::Unavailable) {
525 SYSCALL_ERROR(InvalidArgument);
526 return -1;
527 }
528
529 // A concurrently exiting task can reject the event after a successful
530 // lookup. Linux reports that race as a successful signal send.
531 return 0;
532}
533
534int posix_tkill(int tid, int sig, bool linuxAbi) {
535 SG_NOTICE("tkill(" << tid << ", " << sig << ")");
536
537 if (tid <= 0) {
538 SYSCALL_ERROR(InvalidArgument);
539 return -1;
540 }
541
542 Thread* current = Processor::information().getCurrentThread();
543 Process* caller = current ? current->getParent() : nullptr;
545 if (!caller ||
546 !(linuxAbi ? Scheduler::instance().acquireThreadByUserspaceId(thread, tid)
547 : caller->acquireThreadById(thread, tid)) ||
548 thread->getParent()->getType() != Process::Posix) {
549 SYSCALL_ERROR(NoSuchProcess);
550 return -1;
551 }
552
553 if (sig < 0 || sig > static_cast<int>(PosixSubsystem::MaximumSupportedSignal)) {
554 SYSCALL_ERROR(InvalidArgument);
555 return -1;
556 }
557
558 Process* target = thread->getParent();
559 if (caller->getType() != Process::Posix ||
560 (caller != target && !canSignalProcess(static_cast<PosixProcess*>(caller),
561 static_cast<PosixProcess*>(target), sig))) {
562 SYSCALL_ERROR(NotEnoughPermissions);
563 return -1;
564 }
565 return queueThreadSignal(target, thread.get(), sig);
566}
567
568int posix_tgkill(int tgid, int tid, int sig, bool linuxAbi) {
569 SG_NOTICE("tgkill(" << tgid << ", " << tid << ", " << sig << ")");
570
571 if (tgid <= 0 || tid <= 0) {
572 SYSCALL_ERROR(InvalidArgument);
573 return -1;
574 }
575
578 if (!Scheduler::instance().acquireProcessByUserspaceId(process, static_cast<size_t>(tgid)) ||
579 process->getType() != Process::Posix ||
580 !(linuxAbi
581 ? process->acquireThreadByUserspaceId(
582 thread, static_cast<size_t>(tid),
583 Processor::information().getCurrentThread()->getParent()->pidNamespace().get())
584 : process->acquireThreadById(thread, static_cast<size_t>(tid)))) {
585 SYSCALL_ERROR(NoSuchProcess);
586 return -1;
587 }
588
589 if (sig < 0 || sig > static_cast<int>(PosixSubsystem::MaximumSupportedSignal)) {
590 SYSCALL_ERROR(InvalidArgument);
591 return -1;
592 }
593
594 Thread* current = Processor::information().getCurrentThread();
595 Process* callerProcess = current ? current->getParent() : nullptr;
596 if (!callerProcess || callerProcess->getType() != Process::Posix) {
597 SYSCALL_ERROR(NotEnoughPermissions);
598 return -1;
599 }
600
601 PosixProcess* caller = static_cast<PosixProcess*>(callerProcess);
602 PosixProcess* target = static_cast<PosixProcess*>(process.get());
603 if (callerProcess != process.get() && !canSignalProcess(caller, target, sig)) {
604 SYSCALL_ERROR(NotEnoughPermissions);
605 return -1;
606 }
607
608 const int result = queueThreadSignal(process.get(), thread.get(), sig);
609 thread.reset();
610 process.reset();
611 return result;
612}
613
614int posix_kill(int pid, int sig) {
615 SG_NOTICE("kill(" << pid << ", " << sig << ")");
616
617 // Signals 32..34 are supported only for bundled musl's thread-directed
618 // runtime protocols in this slice.
619 if (sig < 0 || sig > static_cast<int>(PosixSubsystem::MaximumSupportedSignal) ||
620 (sig >= 32 && sig <= 34)) {
621 SYSCALL_ERROR(InvalidArgument);
622 return -1;
623 }
624
625 List<size_t> processList;
626
627 // Metadata about the calling process.
628 PosixProcess* pThisProcess =
629 static_cast<PosixProcess*>(Processor::information().getCurrentThread()->getParent());
630 size_t thisGroupId = 0;
631 const bool thisHasGroup =
632 pThisProcess->getProcessGroupId(thisGroupId, pThisProcess->pidNamespace().get());
633
634 bool bKillingSelf = false;
635 bool foundTarget = false;
636
637 // Check for the process(es) we are about to kill.
638 size_t i = 0;
639 for (; i < Scheduler::instance().getNumProcesses(); ++i) {
641 if (!Scheduler::instance().acquireProcess(process, i)) {
642 continue;
643 }
644 Process* pProcess = process.get();
645 Process::ThreadLease primaryThread;
646 if (!pProcess->acquireProcessSignalThread(primaryThread)) {
647 continue;
648 }
649
650 if (pProcess->getType() != Process::Posix) {
651 continue;
652 }
653
654 if (!pProcess->getUserspaceId(pThisProcess->pidNamespace().get())) {
655 continue;
656 }
657 PosixProcess* pPosixProcess = static_cast<PosixProcess*>(pProcess);
658 bool selected = false;
659 if (pid > 0) {
660 selected =
661 static_cast<int>(pProcess->getUserspaceId(pThisProcess->pidNamespace().get())) == pid;
662 } else {
663 size_t groupId = 0;
664 const bool hasGroup =
665 pPosixProcess->getProcessGroupId(groupId, pThisProcess->pidNamespace().get());
666 if (pid == 0) {
667 // Any process in the same process group as the caller.
668 selected = hasGroup && thisHasGroup && groupId == thisGroupId;
669 if (selected) {
670 SC_NOTICE(" -> selecting process " << pProcess->getId() << " in group [" << groupId
671 << "]");
672 }
673 } else if (pid == -1) {
674 // Linux broadcasts exclude init and the caller, including when
675 // init uses this to stop userspace during shutdown.
676 selected = pProcess->getUserspaceId(pThisProcess->pidNamespace().get()) > 1 &&
677 pProcess != pThisProcess;
678 } else {
679 // Absolute group ID reference
680 selected = hasGroup && groupId == static_cast<size_t>(-static_cast<int64_t>(pid));
681 }
682 }
683
684 if (!selected) {
685 continue;
686 }
687
688 foundTarget = true;
689 if (!canSignalProcess(pThisProcess, pPosixProcess, sig)) {
690 continue;
691 }
692
693 processList.pushBack(pProcess->getUserspaceId(pThisProcess->pidNamespace().get()));
694 }
695
696 // No process(es) found?
697 if (processList.count() == 0) {
698 if (foundTarget) {
699 SYSCALL_ERROR(NotEnoughPermissions);
700 SG_NOTICE(" -> target exists, but permission was denied");
701 } else {
702 SYSCALL_ERROR(NoSuchProcess);
703 SG_NOTICE(" -> no such process");
704 }
705 return -1;
706 }
707
708 // Signal zero performs the same target and permission checks without
709 // allocating, queueing, or dispatching an event.
710 if (!sig) {
711 return 0;
712 }
713
714 bool accepted = false;
715 bool quotaFailed = false;
716
717 // Go ahead and kill each process.
718 for (List<size_t>::Iterator it = processList.begin(); it != processList.end(); ++it) {
719 if (*it != pThisProcess->getUserspaceId()) {
721 if (!Scheduler::instance().acquireProcessByUserspaceId(member, *it) ||
722 member->getType() != Process::Posix) {
723 continue;
724 }
725 SG_NOTICE(" -> not killing current process, killing " << member->getId());
726 NOTICE("sending #" << Dec << member->getId() << " signal #" << sig << " from #"
727 << pThisProcess->getId());
728 const int result = doProcessKill(member.get(), sig);
729 accepted |= result == 0;
730 quotaFailed |= result == SignalQueueFull;
731 } else {
732 SG_NOTICE(" -> killing current process (" << pThisProcess->getId() << ")");
733 bKillingSelf = true;
734 }
735 }
736
737 // Yield to allow the events to be propagated across the process(es)
739
740 if (bKillingSelf) {
741 SG_NOTICE("performing kill of " << pThisProcess->getId() << "...");
742 NOTICE("sending self #" << Dec << pThisProcess->getId() << " signal #" << sig);
743 const int result = doProcessKill(pThisProcess, sig);
744 accepted |= result == 0;
745 quotaFailed |= result == SignalQueueFull;
746 }
747
748 if (!accepted && quotaFailed) {
749 SYSCALL_ERROR(NoMoreProcesses);
750 return -1;
751 }
752 return 0;
753}
754
755int posix_sigprocmask(int how, const void* set, void* oset, size_t sigsetSize, bool linuxCompat) {
756 constexpr size_t KernelSigsetSize = sizeof(uint64_t);
757 constexpr uint64_t UnblockableSignals =
758 (static_cast<uint64_t>(1) << (SIGKILL - 1)) | (static_cast<uint64_t>(1) << (SIGSTOP - 1));
759 static_assert(sizeof(sigset_t) >= KernelSigsetSize,
760 "native sigset_t must hold Pedigree's signal mask");
761
762 if (linuxCompat && sigsetSize != KernelSigsetSize) {
763 SYSCALL_ERROR(InvalidArgument);
764 return -1;
765 }
766
767 const size_t userSigsetSize = linuxCompat ? KernelSigsetSize : sizeof(sigset_t);
768 sigset_t requestedSet = {};
769 uint64_t requestedMask = 0;
770 if (set) {
771 if (!PosixSubsystem::copyFromUser(&requestedSet, set, userSigsetSize)) {
772 SYSCALL_ERROR(BadAddress);
773 return -1;
774 }
775 if (how != SIG_BLOCK && how != SIG_UNBLOCK && how != SIG_SETMASK) {
776 SYSCALL_ERROR(InvalidArgument);
777 return -1;
778 }
779 MemoryCopy(&requestedMask, &requestedSet, KernelSigsetSize);
780 }
781
782 Thread* pThread = Processor::information().getCurrentThread();
783 uint64_t oldMask = pThread->getSignalMask();
784 if (oset) {
785 sigset_t previousSet = {};
786 MemoryCopy(&previousSet, &oldMask, KernelSigsetSize);
787 if (!PosixSubsystem::copyToUser(oset, &previousSet, userSigsetSize)) {
788 SYSCALL_ERROR(BadAddress);
789 return -1;
790 }
791 }
792
793 if (set) {
794 uint64_t newMask = oldMask;
795 if (how == SIG_BLOCK) {
796 newMask |= requestedMask;
797 } else if (how == SIG_UNBLOCK) {
798 newMask &= ~requestedMask;
799 } else {
800 newMask = requestedMask;
801 }
802
803 // Linux silently leaves SIGKILL and SIGSTOP unblocked.
804 pThread->setSignalMask(newMask & ~UnblockableSignals);
805 }
806
807 return 0;
808}
809
810int posix_rt_sigsuspend(const uint64_t* signalMask, size_t signalMaskSize) {
811 constexpr size_t KernelSigsetSize = sizeof(uint64_t);
812 constexpr uint64_t UnblockableSignals =
813 (static_cast<uint64_t>(1) << (SIGKILL - 1)) | (static_cast<uint64_t>(1) << (SIGSTOP - 1));
814
815 if (signalMaskSize != KernelSigsetSize) {
816 SYSCALL_ERROR(InvalidArgument);
817 return -1;
818 }
819
820 uint64_t temporaryMask = 0;
821 if (!PosixSubsystem::copyFromUser(&temporaryMask, signalMask, KernelSigsetSize)) {
822 SYSCALL_ERROR(BadAddress);
823 return -1;
824 }
825 temporaryMask &= ~UnblockableSignals;
826
827 Thread* thread = Processor::information().getCurrentThread();
828 if (!thread) {
829 FATAL("rt_sigsuspend has no current Thread.");
830 }
831
832 Thread::TemporarySignalMask signalWait(*thread, temporaryMask);
833 while (thread->getUnwindState() == Thread::Continue &&
835 }
836 signalWait.finish();
837
838 SYSCALL_ERROR(Interrupted);
839 return -1;
840}
841
842size_t posix_alarm(uint32_t seconds) {
843 SG_NOTICE("alarm(" << seconds << ")");
844
845 Thread* currentThread = Processor::information().getCurrentThread();
846 Process* process = currentThread ? currentThread->getParent() : nullptr;
847 if (!process || process->getType() != Process::Posix) {
848 ERROR("posix_alarm: no POSIX process");
849 return 0;
850 }
851
852 PosixProcess* posixProcess = static_cast<PosixProcess*>(process);
853 Time::Timestamp previousValue = 0;
854 posixProcess->getRealIntervalTimer().setIntervalAndValue(
855 0, static_cast<Time::Timestamp>(seconds) * Time::Multiplier::Second, nullptr, &previousValue);
856
857 Time::Timestamp previousSeconds = previousValue / Time::Multiplier::Second;
858 const Time::Timestamp subsecond = previousValue % Time::Multiplier::Second;
859 // A live alarm must not look disarmed, while longer remainders use Linux's
860 // historical half-second rounding rule.
861 if ((!previousSeconds && subsecond) || subsecond >= (Time::Multiplier::Second / 2)) {
862 ++previousSeconds;
863 }
864 return static_cast<uint32_t>(previousSeconds);
865}
866
867int posix_sleep(uint32_t seconds) {
868 SG_NOTICE("sleep");
869
870 uint64_t startTick = Machine::instance().getTimer()->getTickCount();
871 const bool completed = Time::delay(seconds * Time::Multiplier::Second);
872 Thread* thread = Processor::information().getCurrentThread();
873 if (!completed && thread->getInterruptionReason() == Thread::InterruptedBySignal) {
874 uint64_t endTick = Machine::instance().getTimer()->getTickCount();
875 uint64_t elapsed = endTick - startTick;
876 uint32_t elapsedSecs = static_cast<uint32_t>(elapsed / 1000);
877 thread->clearInterruption();
878
879 if (elapsedSecs >= seconds)
880 return 0;
881 else
882 return seconds - elapsedSecs;
883 }
884
885 return 0;
886}
887
888int posix_usleep(size_t useconds) {
889 SG_NOTICE("usleep");
890
891 const bool completed = Time::delay(useconds * Time::Multiplier::Microsecond);
892 Thread* thread = Processor::information().getCurrentThread();
893 if (!completed && thread->getInterruptionReason() == Thread::InterruptedBySignal) {
894 thread->clearInterruption();
895 SYSCALL_ERROR(Interrupted);
896 return -1;
897 }
898
899 return 0;
900}
901
902int posix_sigaltstack(const stack_t* stack, stack_t* oldstack) {
903 stack_t requested = {};
904 if (stack && !PosixSubsystem::copyFromUser(&requested, stack, sizeof(requested))) {
905 SYSCALL_ERROR(BadAddress);
906 return -1;
907 }
908 if (stack) {
909 if (requested.ss_flags & ~SS_DISABLE) {
910 SYSCALL_ERROR(InvalidArgument);
911 return -1;
912 }
913 }
914
915 Thread* pThread = Processor::information().getCurrentThread();
916 Thread::AlternateSignalStack& currStack = pThread->getAlternateSignalStack();
917
918 if (stack && currStack.inUse) {
919 SYSCALL_ERROR(NotEnoughPermissions);
920 return -1;
921 }
922
923 if (stack && !(requested.ss_flags & SS_DISABLE)) {
924 uintptr_t base = reinterpret_cast<uintptr_t>(requested.ss_sp);
925 if (requested.ss_size < MINSIGSTKSZ) {
926 SYSCALL_ERROR(OutOfMemory);
927 return -1;
928 }
929 if (!base || requested.ss_size > (~static_cast<uintptr_t>(0) - base) ||
930 !PosixSubsystem::checkAddress(base, requested.ss_size, PosixSubsystem::SafeWrite)) {
931 SYSCALL_ERROR(BadAddress);
932 return -1;
933 }
934 }
935
936 if (oldstack) {
937 stack_t previous = {};
938 if (currStack.enabled) {
939 previous.ss_sp = reinterpret_cast<void*>(currStack.base);
940 previous.ss_size = currStack.size;
941 previous.ss_flags = currStack.inUse ? SS_ONSTACK : 0;
942 } else {
943 previous.ss_flags = SS_DISABLE;
944 }
945 if (!PosixSubsystem::copyToUser(oldstack, &previous, sizeof(previous))) {
946 SYSCALL_ERROR(BadAddress);
947 return -1;
948 }
949 }
950
951 if (stack) {
952 if (requested.ss_flags & SS_DISABLE) {
953 currStack.base = 0;
954 currStack.size = 0;
955 currStack.enabled = false;
956 } else {
957 currStack.base = reinterpret_cast<uintptr_t>(requested.ss_sp);
958 currStack.size = requested.ss_size;
959 currStack.enabled = true;
960 }
961 }
962
963 return 0;
964}
965
966void pedigree_init_sigret() {
967 SG_NOTICE("init_sigret");
968 static physical_uintptr_t sigretPhys = 0;
969
970 // Handle allocation if needed.
971 if (sigretPhys == 0) {
974
975 // Map trampoline page in and bring across the sigret code.
976 Processor::information().getVirtualAddressSpace().map(
977 sigretPhys, reinterpret_cast<void*>(Event::getTrampoline()),
980
981 MemoryCopy(
982 reinterpret_cast<void*>(Event::getTrampoline()), reinterpret_cast<void*>(sigret_stub),
983 (reinterpret_cast<uintptr_t>(&sigret_stub_end) - reinterpret_cast<uintptr_t>(sigret_stub)));
984
985 // Mark read-only now that we have mapped in the page.
986 Processor::information().getVirtualAddressSpace().setFlags(
987 reinterpret_cast<void*>(Event::getTrampoline()), VirtualAddressSpace::Execute |
990 }
991
992 // Map the signal return stub to the correct location
993 if (!Processor::information().getVirtualAddressSpace().isMapped(
994 reinterpret_cast<void*>(Event::getTrampoline()))) {
995 Processor::information().getVirtualAddressSpace().map(
996 sigretPhys, reinterpret_cast<void*>(Event::getTrampoline()),
999 }
1000
1001 Thread* pThread = Processor::information().getCurrentThread();
1002 Process* pProcess = pThread->getParent();
1003 PosixSubsystem* pSubsystem = static_cast<PosixSubsystem*>(pProcess->getSubsystem());
1004 if (!pSubsystem) {
1005 pSubsystem = new PosixSubsystem();
1006 pProcess->setSubsystem(pSubsystem);
1007 pSubsystem->setProcess(pProcess);
1008 }
1009
1010 pedigree_reset_signals_for_exec(pThread);
1011}
1012
1013void pedigree_reset_signals_for_exec(Thread* pThread) {
1014 if (!pThread || !pThread->getParent()) {
1015 FATAL("Cannot reset exec signal state without a process thread.");
1016 }
1017
1018 PosixSubsystem* pSubsystem = static_cast<PosixSubsystem*>(pThread->getParent()->getSubsystem());
1019 if (!pSubsystem) {
1020 FATAL("Cannot reset exec signal state without a POSIX subsystem.");
1021 }
1022
1023 PosixSubsystem::SignalHandler* replacements[PosixSubsystem::SignalDispositionCount] = {};
1024
1025 for (size_t i = 0; i < PosixSubsystem::SignalDispositionCount; i++) {
1026 // Set all dispositions back to default, except if an ignore
1027 // disposition was present (SIG_IGN does in fact carry through an exec)
1028 int signalDisposition = 1;
1029
1030 PosixSubsystem::SignalDisposition existingDisposition;
1031 if (pSubsystem->getSignalDisposition(i, existingDisposition)) {
1032 if (existingDisposition.type == 2) {
1033 signalDisposition = 2;
1034 }
1035 }
1036
1037 // Constructor zeroes out everything, which is correct for this initial
1038 // setup of the signal handlers (except, of course, the handler
1039 // location).
1041 sigHandler->sig = i;
1042 sigHandler->type = signalDisposition;
1043
1044 uintptr_t newHandler = signalDisposition == 1 ? pedigree_default_signal_handler(i)
1045 : reinterpret_cast<uintptr_t>(sigign);
1046
1047 sigHandler->pEvent =
1048 new SignalEvent(newHandler, i, ~0UL, 0, true, false, Event::HandlerPrivilege::Kernel,
1049 SignalEvent::DeliveryDisposition::DefaultAction);
1050
1051 replacements[i] = sigHandler;
1052 }
1053
1054 pSubsystem->resetSignalHandlersForExec(pThread, replacements);
1055 pThread->prepareSignalStateForExec();
1056
1057 SG_NOTICE("Creating initial set of signal handlers is complete");
1058}
Definition Event.h:49
static uintptr_t getTrampoline()
Definition Event.cc:201
void setIntervalAndValue(Time::Timestamp interval, Time::Timestamp value, Time::Timestamp *prevInterval=nullptr, Time::Timestamp *prevValue=nullptr)
Set both interval and value atomically.
Definition List.h:61
Iterator begin()
Definition List.h:122
::Iterator< T, node_t > Iterator
Definition List.h:67
Iterator end()
Definition List.h:132
virtual Timer * getTimer()=0
virtual physical_uintptr_t allocatePage(size_t pageConstraints=0)=0
static PhysicalMemoryManager & instance()
virtual void pin(physical_uintptr_t page)=0
int64_t getUserId() const final
void resetSignalHandlersForExec(Thread *thread, SignalHandler *const handlers[SignalDispositionCount])
static bool copyFromUser(void *destination, const void *source, size_t count, size_t elementSize=1)
static constexpr size_t LinuxPrivateSignalFirst
Abi getAbi() const
void setProcess(Process *process) override
SignalDeliveryResult queueSignalDelivery(Thread *target, size_t sig, uint32_t *flags=nullptr, int32_t signalCode=0, bool processDirected=false, uint64_t signalValue=0, const SharedPointer< SignalEventState > &state=SharedPointer< SignalEventState >())
static bool copyToUser(void *destination, const void *source, size_t count, size_t elementSize=1)
void setSignalHandler(size_t sig, SignalHandler *handler)
bool getSignalDisposition(size_t sig, SignalDisposition &disposition, bool beginDelivery=false)
static bool checkAddress(uintptr_t addr, size_t extent, size_t flags)
size_t getUserspaceId() const
Definition Process.h:504
size_t getId()
Definition Process.h:499
MUST_USE_RESULT bool acquireProcessSignalThread(ThreadLease &lease)
Definition Process.cc:1407
void suspendIfContinuationEpoch(int stopSignal, size_t continuationEpoch)
Definition Process.cc:2055
static ProcessorInformation & information()
static Scheduler & instance()
Definition Scheduler.h:96
size_t getNumProcesses()
Definition Scheduler.cc:268
MUST_USE_RESULT bool acquireProcess(ProcessLease &lease, size_t n)
Definition Scheduler.cc:275
void yield()
Definition Scheduler.cc:236
T * get() const
static EXPORTED_PUBLIC SyscallManager & instance()
@ Continue
No unwind necessary, carry on as normal.
Definition Thread.h:517
uint64_t getSignalMask()
Definition Thread.cc:1981
void deferSignalExit(int signal)
Definition Thread.cc:3612
UnwindType getUnwindState()
Definition Thread.h:535
Process * getParent() const
Definition Thread.h:340
void prepareSignalStateForExec()
Definition Thread.cc:2040
void setSignalMask(uint64_t mask)
Definition Thread.cc:1986
bool waitForEventOrSignalInterruption(WaitQueue::StackDiscardCleanup onStackDiscard=nullptr, void *stackDiscardContext=nullptr)
Definition Thread.cc:1207
bool getCurrentSignalDelivery(size_t &signalNumber, size_t &continuationEpoch)
Definition Thread.cc:2028
virtual uint64_t getTickCount()=0
@ Dec
Definition Log.h:126
@ Hex
Definition Log.h:124
size_t count() const
Definition List.h:212
void pushBack(const T &value)
Definition List.h:216
int type
Type - 0 = normal, 1 = SIG_DFL, 2 = SIG_IGN.
SignalEvent * pEvent
Event for the signal handler.
uintptr_t restorer
Userspace restorer for Linux-compatible signal delivery.
uint64_t sigMask
Signal mask to set when this signal handler is called.
uint32_t flags
Signal handler flags.