Compare commits

...

2 Commits

Author SHA1 Message Date
f9003d7a58
kernel: Mask away unsafe bits in rflags when restoring state after a signal
All checks were successful
continuous-integration/drone/push Build is passing
2023-07-15 11:54:48 +02:00
89786d8be2
kernel: Save/restore the SSE/FPU state when executing signal handlers 2023-07-15 11:53:50 +02:00
2 changed files with 19 additions and 2 deletions

View File

@ -18,6 +18,16 @@ struct FPData
void save();
void restore();
void* data()
{
return (void*)m_data;
}
usize size() const
{
return 512;
}
private:
char m_data[512] alignas(16);
bool m_already_saved;

View File

@ -111,8 +111,11 @@ bool Thread::deliver_signal(int signo, Registers* current_regs)
regs.rsp -= 128; // Skip the red zone
fp_data.save();
if (push_mem_on_stack((u8*)current_regs, sizeof(*current_regs)).has_error()) return false;
if (push_mem_on_stack((u8*)&signal_mask, sizeof(signal_mask)).has_error()) return false;
if (push_mem_on_stack((u8*)fp_data.data(), fp_data.size()).has_error()) return false;
u64 rsp = regs.rsp;
@ -147,16 +150,20 @@ void Thread::sigreturn(Registers* current_regs)
{
memcpy(&regs, current_regs, sizeof(regs));
u64 rflags = current_regs->rflags;
u64 rsp;
pop_mem_from_stack((u8*)&rsp, sizeof(rsp));
regs.rsp = rsp;
pop_mem_from_stack((u8*)fp_data.data(), fp_data.size());
pop_mem_from_stack((u8*)&signal_mask, sizeof(signal_mask));
pop_mem_from_stack((u8*)current_regs, sizeof(*current_regs));
memcpy(&regs, current_regs, sizeof(regs));
regs.cs = 0x18 | 3;
regs.ss = 0x20 | 3;
// FIXME: Using this, a program can craft a special RFLAGS that gives them a higher IOPL or other stuff. Find out
// exactly what bits to block from modifying.
regs.rflags = (rflags & ~0xdff) | (regs.rflags & 0xdff);
fp_data.restore();
kinfoln("sigreturn: restored program state, sp=%p, ip=%p", (void*)regs.rsp, (void*)regs.rip);