Kernel: Add support for SA_SIGINFO
This commit is contained in:
parent
a44c45ff9e
commit
dd636ffcb2
|
|
@ -2,15 +2,41 @@
|
||||||
|
|
||||||
// stack contains
|
// stack contains
|
||||||
// return address
|
// return address
|
||||||
|
// return stack
|
||||||
|
// return rflags
|
||||||
|
// siginfo_t
|
||||||
// signal number
|
// signal number
|
||||||
// signal handler
|
// signal handler
|
||||||
|
|
||||||
.global signal_trampoline
|
.global signal_trampoline
|
||||||
signal_trampoline:
|
signal_trampoline:
|
||||||
pusha
|
pushl %esi // gregs
|
||||||
|
pushl %edi
|
||||||
|
pushl %edx
|
||||||
|
pushl %ecx
|
||||||
|
pushl %ebx
|
||||||
|
pushl %eax
|
||||||
|
pushl %ebp
|
||||||
|
|
||||||
movl 40(%esp), %edi
|
movl 76(%esp), %eax // return sp
|
||||||
movl 36(%esp), %eax
|
addl $4, %eax // return address
|
||||||
|
movl 80(%esp), %ebx // return ip
|
||||||
|
pushl %eax;
|
||||||
|
pushl %ebx
|
||||||
|
|
||||||
|
// FIXME: populate these
|
||||||
|
xorl %eax, %eax
|
||||||
|
pushl %eax // stack
|
||||||
|
pushl %eax
|
||||||
|
pushl %eax
|
||||||
|
pushl %eax // sigset
|
||||||
|
pushl %eax
|
||||||
|
pushl %eax // link
|
||||||
|
|
||||||
|
movl %esp, %edx // ucontext
|
||||||
|
leal 68(%esp), %esi // siginfo
|
||||||
|
movl 64(%esp), %edi // signal number
|
||||||
|
movl 60(%esp), %eax // handlers
|
||||||
|
|
||||||
// align stack to 16 bytes
|
// align stack to 16 bytes
|
||||||
movl %esp, %ebp
|
movl %esp, %ebp
|
||||||
|
|
@ -19,7 +45,9 @@ signal_trampoline:
|
||||||
subl $512, %esp
|
subl $512, %esp
|
||||||
fxsave (%esp)
|
fxsave (%esp)
|
||||||
|
|
||||||
subl $12, %esp
|
subl $4, %esp
|
||||||
|
pushl %edx
|
||||||
|
pushl %esi
|
||||||
pushl %edi
|
pushl %edi
|
||||||
call *%eax
|
call *%eax
|
||||||
addl $16, %esp
|
addl $16, %esp
|
||||||
|
|
@ -29,9 +57,21 @@ signal_trampoline:
|
||||||
|
|
||||||
// restore stack
|
// restore stack
|
||||||
movl %ebp, %esp
|
movl %ebp, %esp
|
||||||
popa
|
addl $32, %esp
|
||||||
|
|
||||||
addl $8, %esp
|
// restore registers
|
||||||
|
popl %ebp
|
||||||
|
popl %eax
|
||||||
|
popl %ebx
|
||||||
|
popl %ecx
|
||||||
|
popl %edx
|
||||||
|
popl %edi
|
||||||
|
popl %esi
|
||||||
|
|
||||||
|
// skip handler, number, siginfo_t
|
||||||
|
addl $44, %esp
|
||||||
|
|
||||||
|
// restore flags
|
||||||
popf
|
popf
|
||||||
|
|
||||||
movl (%esp), %esp
|
movl (%esp), %esp
|
||||||
|
|
|
||||||
|
|
@ -2,29 +2,48 @@
|
||||||
|
|
||||||
// stack contains
|
// stack contains
|
||||||
// return address
|
// return address
|
||||||
|
// return stack
|
||||||
|
// return rflags
|
||||||
|
// siginfo_t
|
||||||
// signal number
|
// signal number
|
||||||
// signal handler
|
// signal handler
|
||||||
|
|
||||||
.global signal_trampoline
|
.global signal_trampoline
|
||||||
signal_trampoline:
|
signal_trampoline:
|
||||||
pushq %rax
|
pushq %r15 // gregs
|
||||||
pushq %rbx
|
|
||||||
pushq %rcx
|
|
||||||
pushq %rdx
|
|
||||||
pushq %rbp
|
|
||||||
pushq %rdi
|
|
||||||
pushq %rsi
|
|
||||||
pushq %r8
|
|
||||||
pushq %r9
|
|
||||||
pushq %r10
|
|
||||||
pushq %r11
|
|
||||||
pushq %r12
|
|
||||||
pushq %r13
|
|
||||||
pushq %r14
|
pushq %r14
|
||||||
pushq %r15
|
pushq %r13
|
||||||
|
pushq %r12
|
||||||
|
pushq %r11
|
||||||
|
pushq %r10
|
||||||
|
pushq %r9
|
||||||
|
pushq %r8
|
||||||
|
pushq %rsi
|
||||||
|
pushq %rdi
|
||||||
|
pushq %rdx
|
||||||
|
pushq %rcx
|
||||||
|
pushq %rbx
|
||||||
|
pushq %rax
|
||||||
|
pushq %rbp
|
||||||
|
|
||||||
movq 128(%rsp), %rdi
|
movq 200(%rsp), %rax // return sp
|
||||||
movq 120(%rsp), %rax
|
addq $(128 + 8), %rax // red-zone and return address
|
||||||
|
movq 208(%rsp), %rbx // return ip
|
||||||
|
pushq %rax;
|
||||||
|
pushq %rbx
|
||||||
|
|
||||||
|
// FIXME: populate these
|
||||||
|
xorq %rax, %rax
|
||||||
|
pushq %rax // stack
|
||||||
|
pushq %rax
|
||||||
|
pushq %rax
|
||||||
|
pushq %rax // sigset
|
||||||
|
pushq %rax // link
|
||||||
|
|
||||||
|
movq %rsp, %rdx // ucontext
|
||||||
|
leaq 192(%rsp), %rsi // siginfo
|
||||||
|
movq 184(%rsp), %rdi // signal number
|
||||||
|
movq 176(%rsp), %rax // handler
|
||||||
|
|
||||||
// align stack to 16 bytes
|
// align stack to 16 bytes
|
||||||
movq %rsp, %rbp
|
movq %rsp, %rbp
|
||||||
|
|
@ -40,26 +59,32 @@ signal_trampoline:
|
||||||
|
|
||||||
// restore stack
|
// restore stack
|
||||||
movq %rbp, %rsp
|
movq %rbp, %rsp
|
||||||
popq %r15
|
addq $56, %rsp
|
||||||
popq %r14
|
|
||||||
popq %r13
|
|
||||||
popq %r12
|
|
||||||
popq %r11
|
|
||||||
popq %r10
|
|
||||||
popq %r9
|
|
||||||
popq %r8
|
|
||||||
popq %rsi
|
|
||||||
popq %rdi
|
|
||||||
popq %rbp
|
|
||||||
popq %rdx
|
|
||||||
popq %rcx
|
|
||||||
popq %rbx
|
|
||||||
popq %rax
|
|
||||||
|
|
||||||
addq $16, %rsp
|
// restore registers
|
||||||
|
popq %rbp
|
||||||
|
popq %rax
|
||||||
|
popq %rbx
|
||||||
|
popq %rcx
|
||||||
|
popq %rdx
|
||||||
|
popq %rdi
|
||||||
|
popq %rsi
|
||||||
|
popq %r8
|
||||||
|
popq %r9
|
||||||
|
popq %r10
|
||||||
|
popq %r11
|
||||||
|
popq %r12
|
||||||
|
popq %r13
|
||||||
|
popq %r14
|
||||||
|
popq %r15
|
||||||
|
|
||||||
|
// skip handler, number, siginfo_t
|
||||||
|
addq $72, %rsp
|
||||||
|
|
||||||
|
// restore flags
|
||||||
popfq
|
popfq
|
||||||
|
|
||||||
movq (%rsp), %rsp
|
movq (%rsp), %rsp
|
||||||
|
|
||||||
// return over red-zone
|
// return over red-zone and siginfo_t
|
||||||
ret $128
|
ret $128
|
||||||
|
|
|
||||||
|
|
@ -192,7 +192,7 @@ namespace Kernel
|
||||||
void set_stopped(bool stopped, int signal);
|
void set_stopped(bool stopped, int signal);
|
||||||
void wait_while_stopped();
|
void wait_while_stopped();
|
||||||
|
|
||||||
static BAN::ErrorOr<void> kill(pid_t pid, int signal);
|
static BAN::ErrorOr<void> kill(pid_t pid, int signal, const siginfo_t& = {});
|
||||||
BAN::ErrorOr<long> sys_kill(pid_t pid, int signal);
|
BAN::ErrorOr<long> sys_kill(pid_t pid, int signal);
|
||||||
BAN::ErrorOr<long> sys_sigaction(int signal, const struct sigaction* act, struct sigaction* oact);
|
BAN::ErrorOr<long> sys_sigaction(int signal, const struct sigaction* act, struct sigaction* oact);
|
||||||
BAN::ErrorOr<long> sys_sigpending(sigset_t* set);
|
BAN::ErrorOr<long> sys_sigpending(sigset_t* set);
|
||||||
|
|
@ -290,7 +290,7 @@ namespace Kernel
|
||||||
return m_signal_pending_mask;
|
return m_signal_pending_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_pending_signal(uint8_t signal)
|
void add_pending_signal(uint8_t signal, const siginfo_t& info)
|
||||||
{
|
{
|
||||||
ASSERT(signal >= _SIGMIN);
|
ASSERT(signal >= _SIGMIN);
|
||||||
ASSERT(signal <= _SIGMAX);
|
ASSERT(signal <= _SIGMAX);
|
||||||
|
|
@ -302,6 +302,7 @@ namespace Kernel
|
||||||
if (handler == SIG_DFL && (signal == SIGCHLD || signal == SIGURG))
|
if (handler == SIG_DFL && (signal == SIGCHLD || signal == SIGURG))
|
||||||
return;
|
return;
|
||||||
m_signal_pending_mask |= 1ull << signal;
|
m_signal_pending_mask |= 1ull << signal;
|
||||||
|
m_signal_infos[signal] = info;
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove_pending_signal(uint8_t signal)
|
void remove_pending_signal(uint8_t signal)
|
||||||
|
|
@ -354,6 +355,7 @@ namespace Kernel
|
||||||
uint64_t m_alarm_wake_time_ns { 0 };
|
uint64_t m_alarm_wake_time_ns { 0 };
|
||||||
|
|
||||||
mutable SpinLock m_signal_lock;
|
mutable SpinLock m_signal_lock;
|
||||||
|
siginfo_t m_signal_infos[_SIGMAX + 1] { };
|
||||||
struct sigaction m_signal_handlers[_SIGMAX + 1] { };
|
struct sigaction m_signal_handlers[_SIGMAX + 1] { };
|
||||||
uint64_t m_signal_pending_mask { 0 };
|
uint64_t m_signal_pending_mask { 0 };
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,8 +59,8 @@ namespace Kernel
|
||||||
bool can_add_signal_to_execute() const;
|
bool can_add_signal_to_execute() const;
|
||||||
bool will_execute_signal() const;
|
bool will_execute_signal() const;
|
||||||
// Returns true if handled signal had SA_RESTART
|
// Returns true if handled signal had SA_RESTART
|
||||||
bool handle_signal(int signal = 0);
|
bool handle_signal(int signal = 0, const siginfo_t& signal_info = {});
|
||||||
void add_signal(int signal);
|
void add_signal(int signal, const siginfo_t& info);
|
||||||
void set_suspend_signal_mask(uint64_t sigmask);
|
void set_suspend_signal_mask(uint64_t sigmask);
|
||||||
|
|
||||||
static bool is_stopping_signal(int signal);
|
static bool is_stopping_signal(int signal);
|
||||||
|
|
@ -174,6 +174,7 @@ namespace Kernel
|
||||||
InterruptStack m_interrupt_stack { };
|
InterruptStack m_interrupt_stack { };
|
||||||
InterruptRegisters m_interrupt_registers { };
|
InterruptRegisters m_interrupt_registers { };
|
||||||
|
|
||||||
|
siginfo_t m_signal_infos[_SIGMAX + 1] { };
|
||||||
uint64_t m_signal_pending_mask { 0 };
|
uint64_t m_signal_pending_mask { 0 };
|
||||||
uint64_t m_signal_block_mask { 0 };
|
uint64_t m_signal_block_mask { 0 };
|
||||||
BAN::Optional<uint64_t> m_signal_suspend_mask;
|
BAN::Optional<uint64_t> m_signal_suspend_mask;
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ namespace Kernel::ACPI
|
||||||
EmbeddedController::~EmbeddedController()
|
EmbeddedController::~EmbeddedController()
|
||||||
{
|
{
|
||||||
if (m_thread)
|
if (m_thread)
|
||||||
m_thread->add_signal(SIGKILL);
|
m_thread->add_signal(SIGKILL, {});
|
||||||
m_thread = nullptr;
|
m_thread = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
if (m_reading_count == 0)
|
if (m_reading_count == 0)
|
||||||
{
|
{
|
||||||
Thread::current().add_signal(SIGPIPE);
|
Thread::current().add_signal(SIGPIPE, {});
|
||||||
return BAN::Error::from_errno(EPIPE);
|
return BAN::Error::from_errno(EPIPE);
|
||||||
}
|
}
|
||||||
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex));
|
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex));
|
||||||
|
|
|
||||||
|
|
@ -203,7 +203,7 @@ namespace Kernel
|
||||||
if (result.is_error())
|
if (result.is_error())
|
||||||
{
|
{
|
||||||
dwarnln("Demand paging: {}", result.error());
|
dwarnln("Demand paging: {}", result.error());
|
||||||
Thread::current().handle_signal(SIGKILL);
|
Thread::current().handle_signal(SIGKILL, {});
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -273,30 +273,48 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
// TODO: Confirm and fix the exception to signal mappings
|
// TODO: Confirm and fix the exception to signal mappings
|
||||||
|
|
||||||
int signal = 0;
|
siginfo_t signal_info {};
|
||||||
switch (isr)
|
switch (isr)
|
||||||
{
|
{
|
||||||
case ISR::DivisionError:
|
case ISR::DivisionError:
|
||||||
|
signal_info.si_signo = SIGFPE;
|
||||||
|
signal_info.si_code = FPE_INTDIV;
|
||||||
|
break;
|
||||||
case ISR::SIMDFloatingPointException:
|
case ISR::SIMDFloatingPointException:
|
||||||
case ISR::x87FloatingPointException:
|
case ISR::x87FloatingPointException:
|
||||||
signal = SIGFPE;
|
// FIXME: this is probably not correct?
|
||||||
|
signal_info.si_signo = SIGFPE;
|
||||||
|
signal_info.si_code = FPE_FLTDIV;
|
||||||
break;
|
break;
|
||||||
case ISR::AlignmentCheck:
|
case ISR::AlignmentCheck:
|
||||||
signal = SIGBUS;
|
signal_info.si_signo = SIGBUS;
|
||||||
|
signal_info.si_code = BUS_ADRALN;
|
||||||
|
break;
|
||||||
|
case ISR::GeneralProtectionFault:
|
||||||
|
// TODO: this assumes unaligned operand but GP can be also caused by
|
||||||
|
// a privileged instruction or uncanonical address in which case
|
||||||
|
// the generated signal should be different
|
||||||
|
signal_info.si_signo = SIGBUS;
|
||||||
|
signal_info.si_code = BUS_ADRALN;
|
||||||
break;
|
break;
|
||||||
case ISR::InvalidOpcode:
|
case ISR::InvalidOpcode:
|
||||||
signal = SIGILL;
|
signal_info.si_signo = SIGILL;
|
||||||
|
signal_info.si_code = ILL_ILLOPC;
|
||||||
break;
|
break;
|
||||||
case ISR::PageFault:
|
case ISR::PageFault:
|
||||||
signal = SIGSEGV;
|
signal_info.si_signo = SIGSEGV;
|
||||||
|
if (PageTable::current().get_page_flags(regs->cr2 & PAGE_ADDR_MASK) & PageTable::Flags::Present)
|
||||||
|
signal_info.si_code = SEGV_ACCERR;
|
||||||
|
else
|
||||||
|
signal_info.si_code = SEGV_MAPERR;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dwarnln("Unhandled exception");
|
dwarnln("Unhandled exception");
|
||||||
signal = SIGABRT;
|
signal_info.si_signo = SIGABRT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread::current().handle_signal(signal);
|
Thread::current().handle_signal(signal_info.si_signo, signal_info);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ namespace Kernel
|
||||||
ARPTable::~ARPTable()
|
ARPTable::~ARPTable()
|
||||||
{
|
{
|
||||||
if (m_thread)
|
if (m_thread)
|
||||||
m_thread->add_signal(SIGKILL);
|
m_thread->add_signal(SIGKILL, {});
|
||||||
m_thread = nullptr;
|
m_thread = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ namespace Kernel
|
||||||
IPv4Layer::~IPv4Layer()
|
IPv4Layer::~IPv4Layer()
|
||||||
{
|
{
|
||||||
if (m_thread)
|
if (m_thread)
|
||||||
m_thread->add_signal(SIGKILL);
|
m_thread->add_signal(SIGKILL, {});
|
||||||
m_thread = nullptr;
|
m_thread = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -502,7 +502,7 @@ namespace Kernel
|
||||||
LockGuard _(inode->m_mutex);
|
LockGuard _(inode->m_mutex);
|
||||||
if (inode->has_error())
|
if (inode->has_error())
|
||||||
{
|
{
|
||||||
Thread::current().add_signal(SIGPIPE);
|
Thread::current().add_signal(SIGPIPE, {});
|
||||||
return BAN::Error::from_errno(EPIPE);
|
return BAN::Error::from_errno(EPIPE);
|
||||||
}
|
}
|
||||||
if (is_nonblock && !inode->can_write())
|
if (is_nonblock && !inode->can_write())
|
||||||
|
|
@ -588,7 +588,7 @@ namespace Kernel
|
||||||
LockGuard _(inode->m_mutex);
|
LockGuard _(inode->m_mutex);
|
||||||
if (inode->has_hungup())
|
if (inode->has_hungup())
|
||||||
{
|
{
|
||||||
Thread::current().add_signal(SIGPIPE);
|
Thread::current().add_signal(SIGPIPE, {});
|
||||||
return BAN::Error::from_errno(EPIPE);
|
return BAN::Error::from_errno(EPIPE);
|
||||||
}
|
}
|
||||||
if (is_nonblock && !inode->can_write())
|
if (is_nonblock && !inode->can_write())
|
||||||
|
|
|
||||||
|
|
@ -313,7 +313,17 @@ namespace Kernel
|
||||||
|
|
||||||
child.status = __WGENEXITCODE(status, signal);
|
child.status = __WGENEXITCODE(status, signal);
|
||||||
|
|
||||||
parent_process->add_pending_signal(SIGCHLD);
|
parent_process->add_pending_signal(SIGCHLD, {
|
||||||
|
.si_signo = SIGCHLD,
|
||||||
|
.si_code = signal ? CLD_KILLED : CLD_EXITED,
|
||||||
|
.si_errno = 0,
|
||||||
|
.si_pid = pid(),
|
||||||
|
.si_uid = m_credentials.ruid(),
|
||||||
|
.si_addr = nullptr,
|
||||||
|
.si_status = __WGENEXITCODE(status, signal),
|
||||||
|
.si_band = 0,
|
||||||
|
.si_value = {},
|
||||||
|
});
|
||||||
if (!parent_process->m_threads.empty())
|
if (!parent_process->m_threads.empty())
|
||||||
Processor::scheduler().unblock_thread(parent_process->m_threads.front());
|
Processor::scheduler().unblock_thread(parent_process->m_threads.front());
|
||||||
|
|
||||||
|
|
@ -328,7 +338,7 @@ namespace Kernel
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
for (auto* thread : m_threads)
|
for (auto* thread : m_threads)
|
||||||
if (thread != &Thread::current())
|
if (thread != &Thread::current())
|
||||||
thread->add_signal(SIGKILL);
|
thread->add_signal(SIGKILL, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
while (m_threads.size() > 1)
|
while (m_threads.size() > 1)
|
||||||
|
|
@ -1054,7 +1064,17 @@ namespace Kernel
|
||||||
if (current_ns < process->m_alarm_wake_time_ns)
|
if (current_ns < process->m_alarm_wake_time_ns)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
process->add_pending_signal(SIGALRM);
|
process->add_pending_signal(SIGALRM, {
|
||||||
|
.si_signo = SIGALRM,
|
||||||
|
.si_code = SI_TIMER,
|
||||||
|
.si_errno = 0,
|
||||||
|
.si_pid = 0,
|
||||||
|
.si_uid = 0,
|
||||||
|
.si_addr = nullptr,
|
||||||
|
.si_status = 0,
|
||||||
|
.si_band = 0,
|
||||||
|
.si_value = {},
|
||||||
|
});
|
||||||
|
|
||||||
ASSERT(!process->m_threads.empty());
|
ASSERT(!process->m_threads.empty());
|
||||||
Processor::scheduler().unblock_thread(process->m_threads.front());
|
Processor::scheduler().unblock_thread(process->m_threads.front());
|
||||||
|
|
@ -2765,7 +2785,18 @@ namespace Kernel
|
||||||
|
|
||||||
if (!(m_signal_handlers[SIGCHLD].sa_flags & SA_NOCLDSTOP))
|
if (!(m_signal_handlers[SIGCHLD].sa_flags & SA_NOCLDSTOP))
|
||||||
{
|
{
|
||||||
parent->add_pending_signal(SIGCHLD);
|
parent->add_pending_signal(SIGCHLD, {
|
||||||
|
.si_signo = SIGCHLD,
|
||||||
|
.si_code = stopped ? CLD_STOPPED : CLD_CONTINUED,
|
||||||
|
.si_errno = 0,
|
||||||
|
.si_pid = pid(),
|
||||||
|
.si_uid = m_credentials.ruid(),
|
||||||
|
.si_addr = nullptr,
|
||||||
|
.si_status = __WGENEXITCODE(0, signal),
|
||||||
|
.si_band = 0,
|
||||||
|
.si_value = { .sival_int = 0 },
|
||||||
|
});
|
||||||
|
|
||||||
if (!parent->m_threads.empty())
|
if (!parent->m_threads.empty())
|
||||||
Processor::scheduler().unblock_thread(parent->m_threads.front());
|
Processor::scheduler().unblock_thread(parent->m_threads.front());
|
||||||
}
|
}
|
||||||
|
|
@ -2791,7 +2822,7 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> Process::kill(pid_t pid, int signal)
|
BAN::ErrorOr<void> Process::kill(pid_t pid, int signal, const siginfo_t& signal_info)
|
||||||
{
|
{
|
||||||
if (pid == 0 || pid == -1)
|
if (pid == 0 || pid == -1)
|
||||||
return BAN::Error::from_errno(ENOTSUP);
|
return BAN::Error::from_errno(ENOTSUP);
|
||||||
|
|
@ -2815,7 +2846,7 @@ namespace Kernel
|
||||||
process.set_stopped(false, signal);
|
process.set_stopped(false, signal);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
process.add_pending_signal(signal);
|
process.add_pending_signal(signal, signal_info);
|
||||||
if (!process.m_threads.empty())
|
if (!process.m_threads.empty())
|
||||||
Processor::scheduler().unblock_thread(process.m_threads.front());
|
Processor::scheduler().unblock_thread(process.m_threads.front());
|
||||||
process.m_stop_blocker.unblock();
|
process.m_stop_blocker.unblock();
|
||||||
|
|
@ -2837,6 +2868,18 @@ namespace Kernel
|
||||||
if (signal != 0 && (signal < _SIGMIN || signal > _SIGMAX))
|
if (signal != 0 && (signal < _SIGMIN || signal > _SIGMAX))
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
|
const siginfo_t signal_info {
|
||||||
|
.si_signo = signal,
|
||||||
|
.si_code = SI_USER,
|
||||||
|
.si_errno = 0,
|
||||||
|
.si_pid = this->pid(),
|
||||||
|
.si_uid = m_credentials.ruid(),
|
||||||
|
.si_addr = nullptr,
|
||||||
|
.si_status = 0,
|
||||||
|
.si_band = 0,
|
||||||
|
.si_value = {},
|
||||||
|
};
|
||||||
|
|
||||||
if (pid == m_pid)
|
if (pid == m_pid)
|
||||||
{
|
{
|
||||||
if (signal == 0)
|
if (signal == 0)
|
||||||
|
|
@ -2847,13 +2890,13 @@ namespace Kernel
|
||||||
set_stopped(false, signal);
|
set_stopped(false, signal);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
add_pending_signal(signal);
|
add_pending_signal(signal, signal_info);
|
||||||
m_stop_blocker.unblock();
|
m_stop_blocker.unblock();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRY(kill(pid, signal));
|
TRY(kill(pid, signal, signal_info));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3196,8 +3239,19 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
if (thread->tid() != tid)
|
if (thread->tid() != tid)
|
||||||
continue;
|
continue;
|
||||||
if (signal != 0)
|
if (signal == 0)
|
||||||
thread->add_signal(signal);
|
return 0;
|
||||||
|
thread->add_signal(signal, {
|
||||||
|
.si_signo = signal,
|
||||||
|
.si_code = SI_USER,
|
||||||
|
.si_errno = 0,
|
||||||
|
.si_pid = pid(),
|
||||||
|
.si_uid = m_credentials.ruid(),
|
||||||
|
.si_addr = nullptr,
|
||||||
|
.si_status = 0,
|
||||||
|
.si_band = 0,
|
||||||
|
.si_value = {},
|
||||||
|
});
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -550,12 +550,14 @@ namespace Kernel
|
||||||
vaddr_t signal_handler;
|
vaddr_t signal_handler;
|
||||||
{
|
{
|
||||||
SpinLockGuard _(m_process->m_signal_lock);
|
SpinLockGuard _(m_process->m_signal_lock);
|
||||||
ASSERT(!(m_process->m_signal_handlers[i].sa_flags & SA_SIGINFO));
|
const auto& handler = m_process->m_signal_handlers[i];
|
||||||
signal_handler = (vaddr_t)m_process->m_signal_handlers[i].sa_handler;
|
signal_handler = (handler.sa_flags & SA_SIGINFO)
|
||||||
|
? reinterpret_cast<vaddr_t>(handler.sa_sigaction)
|
||||||
|
: reinterpret_cast<vaddr_t>(handler.sa_handler);
|
||||||
}
|
}
|
||||||
if (signal_handler == (vaddr_t)SIG_IGN)
|
if (signal_handler == reinterpret_cast<vaddr_t>(SIG_IGN))
|
||||||
continue;
|
continue;
|
||||||
if (signal_handler == (vaddr_t)SIG_DFL && is_default_ignored_signal(i))
|
if (signal_handler == reinterpret_cast<vaddr_t>(SIG_DFL) && is_default_ignored_signal(i))
|
||||||
continue;
|
continue;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -586,7 +588,7 @@ namespace Kernel
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Thread::handle_signal(int signal)
|
bool Thread::handle_signal(int signal, const siginfo_t& _signal_info)
|
||||||
{
|
{
|
||||||
ASSERT(&Thread::current() == this);
|
ASSERT(&Thread::current() == this);
|
||||||
ASSERT(is_userspace());
|
ASSERT(is_userspace());
|
||||||
|
|
@ -596,16 +598,23 @@ namespace Kernel
|
||||||
auto& interrupt_stack = *reinterpret_cast<InterruptStack*>(kernel_stack_top() - sizeof(InterruptStack));
|
auto& interrupt_stack = *reinterpret_cast<InterruptStack*>(kernel_stack_top() - sizeof(InterruptStack));
|
||||||
ASSERT(GDT::is_user_segment(interrupt_stack.cs));
|
ASSERT(GDT::is_user_segment(interrupt_stack.cs));
|
||||||
|
|
||||||
|
auto signal_info = _signal_info;
|
||||||
|
|
||||||
if (signal == 0)
|
if (signal == 0)
|
||||||
{
|
{
|
||||||
uint64_t full_pending_mask = m_signal_pending_mask | process().signal_pending_mask();
|
const uint64_t process_signal_pending_mask = process().signal_pending_mask();
|
||||||
|
const uint64_t full_pending_mask = m_signal_pending_mask | process_signal_pending_mask;
|
||||||
for (signal = _SIGMIN; signal <= _SIGMAX; signal++)
|
for (signal = _SIGMIN; signal <= _SIGMAX; signal++)
|
||||||
{
|
{
|
||||||
uint64_t mask = 1ull << signal;
|
const uint64_t mask = 1ull << signal;
|
||||||
if ((full_pending_mask & mask) && !(m_signal_block_mask & mask))
|
if ((full_pending_mask & mask) && !(m_signal_block_mask & mask))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ASSERT(signal <= _SIGMAX);
|
ASSERT(signal <= _SIGMAX);
|
||||||
|
if (process_signal_pending_mask & (1ull << signal))
|
||||||
|
signal_info = process().m_signal_infos[signal];
|
||||||
|
else
|
||||||
|
signal_info = m_signal_infos[signal];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -616,19 +625,20 @@ namespace Kernel
|
||||||
vaddr_t signal_handler;
|
vaddr_t signal_handler;
|
||||||
bool has_sa_restart;
|
bool has_sa_restart;
|
||||||
vaddr_t signal_stack_top = 0;
|
vaddr_t signal_stack_top = 0;
|
||||||
|
|
||||||
{
|
{
|
||||||
SpinLockGuard _(m_process->m_signal_lock);
|
SpinLockGuard _(m_process->m_signal_lock);
|
||||||
|
|
||||||
auto& handler = m_process->m_signal_handlers[signal];
|
auto& handler = m_process->m_signal_handlers[signal];
|
||||||
|
|
||||||
ASSERT(!(handler.sa_flags & SA_SIGINFO));
|
signal_handler = (handler.sa_flags & SA_SIGINFO)
|
||||||
|
? reinterpret_cast<vaddr_t>(handler.sa_sigaction)
|
||||||
signal_handler = reinterpret_cast<vaddr_t>(handler.sa_handler);
|
: reinterpret_cast<vaddr_t>(handler.sa_handler);
|
||||||
if (handler.sa_flags & SA_RESETHAND)
|
|
||||||
handler.sa_handler = SIG_DFL;
|
|
||||||
|
|
||||||
has_sa_restart = !!(handler.sa_flags & SA_RESTART);
|
has_sa_restart = !!(handler.sa_flags & SA_RESTART);
|
||||||
|
|
||||||
|
if (handler.sa_flags & SA_RESETHAND)
|
||||||
|
handler = { .sa_handler = SIG_DFL, .sa_mask = 0, .sa_flags = 0 };
|
||||||
|
|
||||||
const auto& alt_stack = m_signal_alt_stack;
|
const auto& alt_stack = m_signal_alt_stack;
|
||||||
if (alt_stack.ss_flags != SS_DISABLE && (handler.sa_flags & SA_ONSTACK) && !currently_on_alternate_stack())
|
if (alt_stack.ss_flags != SS_DISABLE && (handler.sa_flags & SA_ONSTACK) && !currently_on_alternate_stack())
|
||||||
signal_stack_top = reinterpret_cast<vaddr_t>(alt_stack.ss_sp) + alt_stack.ss_size;
|
signal_stack_top = reinterpret_cast<vaddr_t>(alt_stack.ss_sp) + alt_stack.ss_size;
|
||||||
|
|
@ -663,14 +673,14 @@ namespace Kernel
|
||||||
if (signal_stack_top == 0)
|
if (signal_stack_top == 0)
|
||||||
{
|
{
|
||||||
pages[0] = (interrupt_stack.sp - 1 * sizeof(uintptr_t) ) & PAGE_ADDR_MASK;
|
pages[0] = (interrupt_stack.sp - 1 * sizeof(uintptr_t) ) & PAGE_ADDR_MASK;
|
||||||
pages[1] = (interrupt_stack.sp - 5 * sizeof(uintptr_t)) & PAGE_ADDR_MASK;
|
pages[1] = (interrupt_stack.sp - 5 * sizeof(uintptr_t) - sizeof(siginfo_t)) & PAGE_ADDR_MASK;
|
||||||
page_count = 2;
|
page_count = 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pages[0] = (interrupt_stack.sp - sizeof(uintptr_t)) & PAGE_ADDR_MASK;
|
pages[0] = (interrupt_stack.sp - 1 * sizeof(uintptr_t) ) & PAGE_ADDR_MASK;
|
||||||
pages[1] = (signal_stack_top - 4 * sizeof(uintptr_t)) & PAGE_ADDR_MASK;
|
|
||||||
pages[2] = (signal_stack_top - 1 * sizeof(uintptr_t) ) & PAGE_ADDR_MASK;
|
pages[2] = (signal_stack_top - 1 * sizeof(uintptr_t) ) & PAGE_ADDR_MASK;
|
||||||
|
pages[1] = (signal_stack_top - 4 * sizeof(uintptr_t) - sizeof(siginfo_t)) & PAGE_ADDR_MASK;
|
||||||
page_count = 3;
|
page_count = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -691,6 +701,16 @@ namespace Kernel
|
||||||
interrupt_stack.sp = signal_stack_top;
|
interrupt_stack.sp = signal_stack_top;
|
||||||
write_to_stack(interrupt_stack.sp, old_stack);
|
write_to_stack(interrupt_stack.sp, old_stack);
|
||||||
write_to_stack(interrupt_stack.sp, interrupt_stack.flags);
|
write_to_stack(interrupt_stack.sp, interrupt_stack.flags);
|
||||||
|
|
||||||
|
{
|
||||||
|
signal_info.si_signo = signal;
|
||||||
|
signal_info.si_addr = reinterpret_cast<void*>(interrupt_stack.ip);
|
||||||
|
|
||||||
|
interrupt_stack.sp -= sizeof(siginfo_t);
|
||||||
|
*reinterpret_cast<siginfo_t*>(interrupt_stack.sp) = signal_info;
|
||||||
|
static_assert(sizeof(siginfo_t) % sizeof(uintptr_t) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
write_to_stack(interrupt_stack.sp, signal);
|
write_to_stack(interrupt_stack.sp, signal);
|
||||||
write_to_stack(interrupt_stack.sp, signal_handler);
|
write_to_stack(interrupt_stack.sp, signal_handler);
|
||||||
interrupt_stack.ip = (uintptr_t)signal_trampoline;
|
interrupt_stack.ip = (uintptr_t)signal_trampoline;
|
||||||
|
|
@ -728,25 +748,29 @@ namespace Kernel
|
||||||
return has_sa_restart;
|
return has_sa_restart;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Thread::add_signal(int signal)
|
void Thread::add_signal(int signal, const siginfo_t& info)
|
||||||
{
|
{
|
||||||
SpinLockGuard _(m_signal_lock);
|
SpinLockGuard _(m_signal_lock);
|
||||||
|
|
||||||
if (m_process)
|
if (m_process)
|
||||||
{
|
{
|
||||||
vaddr_t signal_handler;
|
vaddr_t signal_handler;
|
||||||
{
|
{
|
||||||
SpinLockGuard _(m_process->m_signal_lock);
|
SpinLockGuard _(m_process->m_signal_lock);
|
||||||
ASSERT(!(m_process->m_signal_handlers[signal].sa_flags & SA_SIGINFO));
|
const auto& handler = m_process->m_signal_handlers[signal];
|
||||||
signal_handler = (vaddr_t)m_process->m_signal_handlers[signal].sa_handler;
|
signal_handler = (handler.sa_flags & SA_SIGINFO)
|
||||||
|
? reinterpret_cast<vaddr_t>(handler.sa_sigaction)
|
||||||
|
: reinterpret_cast<vaddr_t>(handler.sa_handler);
|
||||||
}
|
}
|
||||||
if (signal_handler == (vaddr_t)SIG_IGN)
|
if (signal_handler == reinterpret_cast<vaddr_t>(SIG_IGN))
|
||||||
return;
|
return;
|
||||||
if (signal_handler == (vaddr_t)SIG_DFL && is_default_ignored_signal(signal))
|
if (signal_handler == reinterpret_cast<vaddr_t>(SIG_DFL) && is_default_ignored_signal(signal))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint64_t mask = 1ull << signal;
|
const uint64_t mask = 1ull << signal;
|
||||||
m_signal_pending_mask |= mask;
|
m_signal_pending_mask |= mask;
|
||||||
|
m_signal_infos[signal] = info;
|
||||||
|
|
||||||
if (this != &Thread::current())
|
if (this != &Thread::current())
|
||||||
Processor::scheduler().unblock_thread(this);
|
Processor::scheduler().unblock_thread(this);
|
||||||
|
|
|
||||||
|
|
@ -152,15 +152,15 @@ typedef struct
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
#if defined(__x86_64__)
|
#if defined(__x86_64__)
|
||||||
|
REG_RIP,
|
||||||
|
REG_RSP,
|
||||||
|
REG_RBP,
|
||||||
REG_RAX,
|
REG_RAX,
|
||||||
REG_RBX,
|
REG_RBX,
|
||||||
REG_RCX,
|
REG_RCX,
|
||||||
REG_RDX,
|
REG_RDX,
|
||||||
REG_RDI,
|
REG_RDI,
|
||||||
REG_RSI,
|
REG_RSI,
|
||||||
REG_RSP,
|
|
||||||
REG_RBP,
|
|
||||||
REG_RIP,
|
|
||||||
REG_R8,
|
REG_R8,
|
||||||
REG_R9,
|
REG_R9,
|
||||||
REG_R10,
|
REG_R10,
|
||||||
|
|
@ -170,15 +170,15 @@ enum
|
||||||
REG_R14,
|
REG_R14,
|
||||||
REG_R15,
|
REG_R15,
|
||||||
#elif defined(__i686__)
|
#elif defined(__i686__)
|
||||||
|
REG_EIP,
|
||||||
|
REG_ESP,
|
||||||
|
REG_EBP,
|
||||||
REG_EAX,
|
REG_EAX,
|
||||||
REG_EBX,
|
REG_EBX,
|
||||||
REG_ECX,
|
REG_ECX,
|
||||||
REG_EDX,
|
REG_EDX,
|
||||||
REG_EDI,
|
REG_EDI,
|
||||||
REG_ESI,
|
REG_ESI,
|
||||||
REG_ESP,
|
|
||||||
REG_EBP,
|
|
||||||
REG_EIP,
|
|
||||||
#else
|
#else
|
||||||
#error
|
#error
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue