20#include "linux-amd64-signal.h"
24#include "pedigree/kernel/process/Thread.h"
25#include "pedigree/kernel/processor/NMFaultHandler.h"
26#include "pedigree/kernel/processor/Processor.h"
27#include "pedigree/kernel/processor/SyscallManager.h"
28#include "pedigree/kernel/processor/VirtualAddressSpace.h"
29#include "pedigree/kernel/processor/state.h"
30#include "pedigree/kernel/utilities/lib.h"
35#include "linux-amd64-signal-abi.h"
36#include "signal-syscalls.h"
37#include "syscalls/translate.h"
38#include "system-syscalls.h"
41using namespace LinuxAmd64SignalAbi;
43constexpr uint64_t UnblockableSignals =
44 (
static_cast<uint64_t
>(1) << (SIGKILL - 1)) | (
static_cast<uint64_t
>(1) << (SIGSTOP - 1));
45constexpr uint64_t HandlerFlagsToClear = 0x100 | 0x400 | 0x10000;
46constexpr uint64_t RestorableRflags = 0x50DD5;
47constexpr uint64_t SafeUserRflags = 0x202;
48constexpr uint64_t SupportedUcontextFlags = 0x6;
49constexpr uintptr_t MaximumCanonicalUserAddress = 0x00007FFFFFFFFFFF;
50constexpr uint16_t IretUserCodeSegment = 0x1B;
51constexpr uint16_t SysretUserCodeSegment = 0x2B;
52constexpr uint16_t UserStackSegment = 0x23;
54bool userCodeSegment(uint16_t selector) {
57 return selector == IretUserCodeSegment || selector == SysretUserCodeSegment;
60uintptr_t alignDown(uintptr_t value, uintptr_t alignment) {
61 return value & ~(alignment - 1);
64bool userBounds(uintptr_t address,
size_t extent) {
65 if (!extent || !address || extent - 1 > (~
static_cast<uintptr_t
>(0) - address)) {
69 uintptr_t end = address + extent - 1;
71 return address >= va.
getUserStart() && end <= MaximumCanonicalUserAddress &&
76bool userRegion(uintptr_t address,
size_t extent,
size_t access) {
77 if (!userBounds(address, extent)) {
87bool userExecutable(uintptr_t address) {
88 return userRegion(address, 1, PosixSubsystem::SafeExecute);
92 if (!stack.enabled || !stack.base || stack.size > (~
static_cast<uintptr_t
>(0) - stack.base)) {
96 return stackPointer >= stack.base && stackPointer < stack.base + stack.size;
99void setSiginfo32(
Siginfo& info,
size_t offset, int32_t value) {
100 MemoryCopy(info.bytes + offset, &value,
sizeof(value));
103void setSiginfo64(
Siginfo& info,
size_t offset, uint64_t value) {
104 MemoryCopy(info.bytes + offset, &value,
sizeof(value));
107void populateSigcontext(
Sigcontext& context,
const InterruptState& state, uint64_t oldMask,
108 uintptr_t faultAddress, uintptr_t errorCode, uintptr_t fpstate) {
109 context.rax = state.getRegister(0);
110 context.rbx = state.getRegister(1);
111 context.rcx = state.getRegister(2);
112 context.rdx = state.getRegister(3);
113 context.rdi = state.getRegister(4);
114 context.rsi = state.getRegister(5);
115 context.rbp = state.getRegister(6);
116 context.r8 = state.getRegister(7);
117 context.r9 = state.getRegister(8);
118 context.r10 = state.getRegister(9);
119 context.r11 = state.getRegister(10);
120 context.r12 = state.getRegister(11);
121 context.r13 = state.getRegister(12);
122 context.r14 = state.getRegister(13);
123 context.r15 = state.getRegister(14);
124 context.rsp = state.getStackPointer();
125 context.rip = state.getInstructionPointer();
126 context.rflags = state.getFlags();
127 context.cs = state.getCodeSegment();
128 context.ss = state.getStackSegment();
129 context.errorCode = errorCode;
130 context.trapNumber = state.getInterruptNumber();
131 context.oldMask = oldMask;
132 context.cr2 = faultAddress;
133 context.fpstate = fpstate;
136void populateSigcontext(
Sigcontext& context,
const SyscallState& state, uint64_t oldMask,
138 context.rax = state.getRegister(0);
139 context.rbx = state.getRegister(1);
140 context.rcx = state.getInstructionPointer();
141 context.rdx = state.getRegister(2);
142 context.rdi = state.getRegister(3);
143 context.rsi = state.getRegister(4);
144 context.rbp = state.getRegister(5);
145 context.r8 = state.getRegister(6);
146 context.r9 = state.getRegister(7);
147 context.r10 = state.getRegister(8);
148 context.r11 = state.getFlags();
149 context.r12 = state.getRegister(9);
150 context.r13 = state.getRegister(10);
151 context.r14 = state.getRegister(11);
152 context.r15 = state.getRegister(12);
153 context.rsp = state.getStackPointer();
154 context.rip = state.getInstructionPointer();
155 context.rflags = state.getFlags();
156 context.cs = SysretUserCodeSegment;
157 context.ss = UserStackSegment;
158 context.oldMask = oldMask;
159 context.fpstate = fpstate;
164 case Subsystem::PageFault:
165 return (errorCode & 1) ? SEGV_ACCERR : SEGV_MAPERR;
166 case Subsystem::InvalidOpcode:
168 case Subsystem::GeneralProtectionFault:
169 case Subsystem::FileMappingFault:
171 case Subsystem::DivideByZero:
173 case Subsystem::FpuError:
174 case Subsystem::SpecialFpuError:
182 uintptr_t faultAddress) {
183 return exception == Subsystem::PageFault || exception == Subsystem::FileMappingFault
185 : state.getInstructionPointer();
192struct AsyncHandlerState {
193 uintptr_t frameAddress;
194 uintptr_t infoAddress;
195 uintptr_t ucontextAddress;
196 uintptr_t handlerAddress;
200bool restartableSyscall(
const SyscallState& state) {
201 switch (state.getSyscallNumber()) {
202 case PedigreeLinuxAmd64Syscall_read:
203 case PedigreeLinuxAmd64Syscall_write:
204 case PedigreeLinuxAmd64Syscall_open:
205 case PedigreeLinuxAmd64Syscall_openat:
206 case PedigreeLinuxAmd64Syscall_readv:
207 case PedigreeLinuxAmd64Syscall_writev:
208 case PedigreeLinuxAmd64Syscall_pread64:
209 case PedigreeLinuxAmd64Syscall_pwrite64:
210 case PedigreeLinuxAmd64Syscall_preadv:
211 case PedigreeLinuxAmd64Syscall_pwritev:
212 case PedigreeLinuxAmd64Syscall_preadv2:
213 case PedigreeLinuxAmd64Syscall_pwritev2:
214 case PedigreeLinuxAmd64Syscall_wait4:
215 case PedigreeLinuxAmd64Syscall_waitid:
216 case PedigreeLinuxAmd64Syscall_accept:
217 case PedigreeLinuxAmd64Syscall_accept4:
218 case PedigreeLinuxAmd64Syscall_sendto:
219 case PedigreeLinuxAmd64Syscall_recvfrom:
220 case PedigreeLinuxAmd64Syscall_sendmsg:
221 case PedigreeLinuxAmd64Syscall_recvmsg:
222 case PedigreeLinuxAmd64Syscall_mq_timedsend:
223 case PedigreeLinuxAmd64Syscall_mq_timedreceive:
225 case PedigreeLinuxAmd64Syscall_recvmmsg:
227 return state.getSyscallParameter(10) == 0;
228 case PedigreeLinuxAmd64Syscall_futex:
231 return (state.getSyscallParameter(7) & ~
static_cast<uintptr_t
>(128)) == 0 &&
232 state.getSyscallParameter(9) == 0;
240void restartInterruptedSyscall(
Thread* thread, uint32_t flags,
Sigcontext& context) {
242 if (!(flags & SA_RESTART) || context.rax !=
static_cast<uint64_t
>(-EINTR) || !original ||
243 original->getSyscallService() != linuxCompat ||
244 context.rip != original->getInstructionPointer() ||
245 context.rsp != original->getStackPointer() || context.rip < 2 ||
246 !restartableSyscall(*original)) {
252 context.rax = original->getRegister(0);
253 context.rdi = original->getSyscallParameter(6);
254 context.rsi = original->getSyscallParameter(7);
255 context.rdx = original->getSyscallParameter(8);
256 context.r10 = original->getSyscallParameter(9);
257 context.r8 = original->getSyscallParameter(10);
258 context.r9 = original->getSyscallParameter(11);
264 if (!event.deliveryActive())
265 return Event::UserReturnDelivery::Delivered;
266 const size_t signal =
event.getNumber();
269 process ?
static_cast<PosixSubsystem*
>(process->getSubsystem()) : nullptr;
272 return Event::UserReturnDelivery::Failed;
274 if (disposition.type == 0) {
275 return Event::UserReturnDelivery::NotApplicable;
278 if (disposition.type == 1 && signal != SIGCHLD && signal != SIGURG && signal != SIGWINCH) {
280 reinterpret_cast<_sig_func_ptr
>(disposition.handler)(
static_cast<int>(signal));
282 return Event::UserReturnDelivery::Delivered;
287 AsyncHandlerState& handlerState) {
288 const int signal =
static_cast<int>(
event.getNumber());
290 signal > 64 || !userCodeSegment(context.cs) || context.ss != UserStackSegment ||
291 !(disposition.flags & SA_RESTORER) || !userExecutable(disposition.handler) ||
292 !userExecutable(disposition.restorer)) {
296 const uintptr_t originalStack = context.rsp;
297 if (!userBounds(originalStack, 1)) {
302 const bool wasOnAlternate = onAlternateStack(originalStack, alternate);
303 const bool enterAlternate =
304 (disposition.flags & SA_ONSTACK) && alternate.enabled && !wasOnAlternate;
306 uintptr_t stackTop = 0;
307 if (enterAlternate) {
308 if (!alternate.base || alternate.size > (~
static_cast<uintptr_t
>(0) - alternate.base)) {
311 stackTop = alternate.base + alternate.size;
313 if (originalStack < 128) {
316 stackTop = originalStack - 128;
319 if (stackTop <
sizeof(
Fpstate)) {
322 const uintptr_t fpstateAddress = alignDown(stackTop -
sizeof(
Fpstate), 64);
323 if (fpstateAddress <
sizeof(
RtSigframe) + 8) {
326 const uintptr_t frameAddress = alignDown(fpstateAddress -
sizeof(
RtSigframe), 16) - 8;
328 if (!userRegion(frameAddress,
sizeof(
RtSigframe), PosixSubsystem::SafeWrite) ||
329 !userRegion(fpstateAddress,
sizeof(
Fpstate), PosixSubsystem::SafeWrite)) {
332 if (enterAlternate || wasOnAlternate) {
333 const uintptr_t alternateEnd = alternate.base + alternate.size;
334 if (frameAddress < alternate.base || fpstateAddress +
sizeof(
Fpstate) > alternateEnd) {
344 Fpstate fpstate = savedFpstate;
345 ByteSet(fpstate.reserved3, 0,
sizeof(fpstate.reserved3));
349 frame.restorer = disposition.restorer;
350 frame.ucontext.flags = SupportedUcontextFlags;
351 if (alternate.enabled) {
352 frame.ucontext.stack.stackPointer = alternate.base;
353 frame.ucontext.stack.size = alternate.size;
354 frame.ucontext.stack.flags = wasOnAlternate ? SS_ONSTACK : 0;
356 frame.ucontext.stack.flags = SS_DISABLE;
358 context.oldMask = oldMask;
359 context.fpstate = fpstateAddress;
360 frame.ucontext.mcontext = context;
361 frame.ucontext.signalMask = oldMask;
363 setSiginfo32(frame.info, 0, signal);
364 setSiginfo32(frame.info, 4, 0);
365 setSiginfo32(frame.info, 8, event.getSignalCode());
366 setSiginfo32(frame.info, 16, event.getSenderProcess());
367 setSiginfo32(frame.info, 20,
static_cast<int32_t
>(event.getSenderUser()));
368 setSiginfo64(frame.info, 24, event.getSignalValue());
369 int32_t timerId = 0, overrun = 0;
370 event.timerInfo(timerId, overrun);
371 if (event.getSignalCode() == -2) {
372 setSiginfo32(frame.info, 16, timerId);
373 setSiginfo32(frame.info, 20, overrun);
374 }
else if (signal == SIGCHLD && event.getSignalCode() > 0 && event.getSignalCode() <= 6) {
375 setSiginfo32(frame.info, 24, event.childStatus());
376 setSiginfo64(frame.info, 32, event.childUserTime());
377 setSiginfo64(frame.info, 40, event.childSystemTime());
384 FATAL(
"Could not restore FPU state after a failed signal-frame copy.");
389 event.completeSignalDelivery(overrun);
390 uint64_t handlerMask = currentMask | disposition.signalMask;
391 if (!(disposition.flags & SA_NODEFER)) {
392 handlerMask |=
static_cast<uint64_t
>(1) << (signal - 1);
395 alternate.inUse = wasOnAlternate || enterAlternate;
397 handlerState.frameAddress = frameAddress;
398 handlerState.infoAddress = frameAddress + __builtin_offsetof(
RtSigframe, info);
399 handlerState.ucontextAddress = frameAddress + __builtin_offsetof(
RtSigframe, ucontext);
400 handlerState.handlerAddress = disposition.handler;
401 handlerState.flags = (context.rflags & ~HandlerFlagsToClear) | SafeUserRflags;
406LinuxAmd64Signal::AsyncEvent::AsyncEvent(uintptr_t handler,
size_t signal, uint64_t signalMask,
407 bool deferSignal, uint32_t flags, uintptr_t restorer,
408 bool useAlternateStack,
bool isDeletable)
409 :
SignalEvent(handler, signal, ~0UL, signalMask, deferSignal, isDeletable,
410 Event::HandlerPrivilege::
User, DeliveryDisposition::CaughtHandler,
413 m_Restorer(restorer) {}
415LinuxAmd64Signal::AsyncEvent::AsyncEvent(
const AsyncEvent& other,
bool isDeletable)
416 :
SignalEvent(other, isDeletable), m_Flags(other.m_Flags), m_Restorer(other.m_Restorer) {}
431 populateSigcontext(context, state, 0, 0, state.getErrorCode(), 0);
432 AsyncHandlerState handlerState = {};
436 if (resolved != Event::UserReturnDelivery::NotApplicable) {
439 if (!buildAsyncFrame(thread, *
this, context, disposition, handlerState)) {
441 return Event::UserReturnDelivery::Failed;
444 state.setRegister(0, 0);
445 state.setRegister(4, getNumber());
446 state.setRegister(5, handlerState.infoAddress);
447 state.setRegister(3, handlerState.ucontextAddress);
448 state.setInstructionPointer(handlerState.handlerAddress);
449 state.setStackPointer(handlerState.frameAddress);
450 state.setFlags(handlerState.flags);
451 return Event::UserReturnDelivery::Delivered;
456 populateSigcontext(context, state, 0, 0);
457 AsyncHandlerState handlerState = {};
461 if (resolved != Event::UserReturnDelivery::NotApplicable) {
464 restartInterruptedSyscall(thread, disposition.flags, context);
465 if (!buildAsyncFrame(thread, *
this, context, disposition, handlerState)) {
467 return Event::UserReturnDelivery::Failed;
470 state.setRegister(0, 0);
471 state.setRegister(3, getNumber());
472 state.setRegister(4, handlerState.infoAddress);
473 state.setRegister(2, handlerState.ucontextAddress);
474 state.setInstructionPointer(handlerState.handlerAddress);
475 state.setStackPointer(handlerState.frameAddress);
476 state.setFlags(handlerState.flags);
477 return Event::UserReturnDelivery::Delivered;
480LinuxAmd64Signal::DeliveryResult LinuxAmd64Signal::deliverSynchronous(
483 uintptr_t errorCode) {
485 return NotApplicable;
488 if (signal <= 0 || signal > 64 || state.kernelMode() ||
489 !userCodeSegment(state.getCodeSegment()) || state.getStackSegment() != UserStackSegment ||
490 !(disposition.flags & SA_RESTORER) || !userExecutable(disposition.handler) ||
491 !userExecutable(disposition.restorer)) {
495 uintptr_t originalStack = state.getStackPointer();
496 if (!userBounds(originalStack, 1)) {
501 bool wasOnAlternate = onAlternateStack(originalStack, alternate);
502 bool enterAlternate = (disposition.flags & SA_ONSTACK) && alternate.enabled && !wasOnAlternate;
504 uintptr_t stackTop = 0;
505 if (enterAlternate) {
506 if (!alternate.base || alternate.size > (~
static_cast<uintptr_t
>(0) - alternate.base)) {
509 stackTop = alternate.base + alternate.size;
511 if (originalStack < 128) {
514 stackTop = originalStack - 128;
517 if (stackTop <
sizeof(
Fpstate)) {
520 uintptr_t fpstateAddress = alignDown(stackTop -
sizeof(
Fpstate), 64);
521 if (fpstateAddress <
sizeof(
RtSigframe) + 8) {
524 uintptr_t frameAddress = alignDown(fpstateAddress -
sizeof(
RtSigframe), 16) - 8;
526 if (!userRegion(frameAddress,
sizeof(
RtSigframe), PosixSubsystem::SafeWrite) ||
527 !userRegion(fpstateAddress,
sizeof(
Fpstate), PosixSubsystem::SafeWrite)) {
531 if (enterAlternate || wasOnAlternate) {
532 uintptr_t alternateEnd = alternate.base + alternate.size;
533 if (frameAddress < alternate.base || fpstateAddress +
sizeof(
Fpstate) > alternateEnd) {
543 Fpstate fpstate = savedFpstate;
544 ByteSet(fpstate.reserved3, 0,
sizeof(fpstate.reserved3));
548 frame.restorer = disposition.restorer;
549 frame.ucontext.flags = SupportedUcontextFlags;
550 if (alternate.enabled) {
551 frame.ucontext.stack.stackPointer = alternate.base;
552 frame.ucontext.stack.size = alternate.size;
553 frame.ucontext.stack.flags = wasOnAlternate ? SS_ONSTACK : 0;
555 frame.ucontext.stack.flags = SS_DISABLE;
557 populateSigcontext(frame.ucontext.mcontext, state, oldMask,
558 exception == Subsystem::PageFault || exception == Subsystem::FileMappingFault
561 errorCode, fpstateAddress);
562 frame.ucontext.signalMask = oldMask;
564 setSiginfo32(frame.info, 0, signal);
565 setSiginfo32(frame.info, 4, 0);
566 setSiginfo32(frame.info, 8, signalCode(exception, errorCode));
567 setSiginfo64(frame.info, 16, signalAddress(exception, state, faultAddress));
568 setSiginfo32(frame.info, 24,
static_cast<int32_t
>(state.getInterruptNumber()));
574 FATAL(
"Could not restore FPU state after a failed signal-frame copy.");
579 uint64_t handlerMask = currentMask | disposition.signalMask;
580 if (!(disposition.flags & SA_NODEFER)) {
581 handlerMask |=
static_cast<uint64_t
>(1) << (signal - 1);
584 alternate.inUse = wasOnAlternate || enterAlternate;
586 state.setRegister(0, 0);
587 state.setRegister(4,
static_cast<uintptr_t
>(signal));
588 state.setRegister(5, frameAddress + __builtin_offsetof(
RtSigframe, info));
589 state.setRegister(3, frameAddress + __builtin_offsetof(
RtSigframe, ucontext));
590 state.setInstructionPointer(disposition.handler);
591 state.setStackPointer(frameAddress);
592 state.setFlags((state.getFlags() & ~HandlerFlagsToClear) | SafeUserRflags);
596void LinuxAmd64Signal::sigreturn(SyscallState& state) {
597 uintptr_t syscallStack = state.getStackPointer();
598 if (syscallStack < 8) {
602 uintptr_t frameAddress = syscallStack - 8;
603 if (!userRegion(frameAddress,
sizeof(
RtSigframe), PosixSubsystem::SafeRead)) {
614 const Sigcontext& context = frame.ucontext.mcontext;
616 if ((frame.ucontext.flags & ~SupportedUcontextFlags) || !userCodeSegment(context.cs) ||
617 context.ss != UserStackSegment || !userBounds(context.rip, 1) ||
618 !userBounds(context.rsp, 1) || !context.fpstate || (context.fpstate & 0x3F) ||
619 !userRegion(context.fpstate,
sizeof(
Fpstate), PosixSubsystem::SafeRead)) {
624 int alternateFlags = frame.ucontext.stack.flags;
625 if (alternateFlags & ~(SS_ONSTACK | SS_DISABLE) ||
626 ((alternateFlags & SS_ONSTACK) && (alternateFlags & SS_DISABLE))) {
632 if (!(alternateFlags & SS_DISABLE)) {
633 restoredAlternate.base = frame.ucontext.stack.stackPointer;
634 restoredAlternate.size = frame.ucontext.stack.size;
635 restoredAlternate.enabled =
true;
636 restoredAlternate.inUse = alternateFlags & SS_ONSTACK;
637 if (restoredAlternate.size < MINSIGSTKSZ ||
638 !userBounds(restoredAlternate.base, restoredAlternate.size) ||
639 (restoredAlternate.inUse && !onAlternateStack(context.rsp, restoredAlternate))) {
651 for (
size_t i = 0; i < 12; ++i) {
652 if (fpstate.reserved3[i]) {
663 thread->
setSignalMask(frame.ucontext.signalMask & ~UnblockableSignals);
664 thread->getAlternateSignalStack() = restoredAlternate;
667 restored.
r8 = context.r8;
668 restored.
r9 = context.r9;
669 restored.
r10 = context.r10;
670 restored.
r11 = context.r11;
671 restored.
r12 = context.r12;
672 restored.
r13 = context.r13;
673 restored.
r14 = context.r14;
674 restored.
r15 = context.r15;
675 restored.
rdi = context.rdi;
676 restored.
rsi = context.rsi;
677 restored.
rbp = context.rbp;
678 restored.
rbx = context.rbx;
679 restored.
rdx = context.rdx;
680 restored.
rax = context.rax;
681 restored.
rcx = context.rcx;
682 restored.
rip = context.rip;
683 restored.
rflags = (context.rflags & RestorableRflags) | SafeUserRflags;
684 restored.
rsp = context.rsp;
687 FATAL(
"Signal state restoration was not dispatched.");
virtual bool isDeletable()
SignalEvent * cloneForDisposition() override
Event * cloneForDelivery() override
Event::UserReturnDelivery deliverAtUserReturn(InterruptState &state) override
static EXPORTED_PUBLIC bool saveCurrentThreadFpuState(void *buffer, bool resetForSignalHandler)
static EXPORTED_PUBLIC bool restoreCurrentThreadFpuState(const void *buffer)
static bool copyFromUser(void *destination, const void *source, size_t count, size_t elementSize=1)
static bool copyToUser(void *destination, const void *source, size_t count, size_t elementSize=1)
bool getSignalDisposition(size_t sig, SignalDisposition &disposition, bool beginDelivery=false)
static bool checkAddress(uintptr_t addr, size_t extent, size_t flags)
static ProcessorInformation & information()
static EXPORTED_PUBLIC SyscallManager & instance()
void commitSignalHandlerMask(uint64_t mask)
const SyscallState * getOriginalSyscallState() const
Process * getParent() const
void setSignalMask(uint64_t mask)
uint64_t getSignalMaskForReturnFrame()
void setCurrentSignalDelivery(size_t signalNumber, size_t continuationEpoch)
virtual uintptr_t getUserStart() const =0
virtual uintptr_t getKernelStart() const =0
virtual bool isAddressValid(void *virtualAddress)=0