Set siginfo_t.si_{pid,uid} from kill signals too.
This commit is contained in:
@@ -7,6 +7,8 @@
|
||||
|
||||
typedef struct siginfo siginfo_t;
|
||||
typedef unsigned long long sigset_t;
|
||||
typedef struct ucontext ucontext_t;
|
||||
typedef struct mcontext mcontext_t;
|
||||
|
||||
struct sigaction {
|
||||
union {
|
||||
|
||||
@@ -29,7 +29,8 @@ pub struct SigArea {
|
||||
pub tmp_rdx: usize,
|
||||
pub tmp_rdi: usize,
|
||||
pub tmp_rsi: usize,
|
||||
pub tmp_inf: RtSigInfo,
|
||||
pub tmp_rt_inf: RtSigInfo,
|
||||
pub tmp_id_inf: u64,
|
||||
|
||||
pub altstack_top: usize,
|
||||
pub altstack_bottom: usize,
|
||||
@@ -192,7 +193,10 @@ asmfunction!(__relibc_internal_sigentry: ["
|
||||
and eax, edx
|
||||
bsf eax, eax
|
||||
jz 8f
|
||||
lea rdi, [rip + {pctl} + {pctl_off_sender_infos}]
|
||||
mov rdi, [rdi + rax * 8]
|
||||
lock btr [rip + {pctl} + {pctl_off_pending}], eax
|
||||
mov fs:[{tcb_sa_off} + {sa_tmp_id_inf}], rdi
|
||||
jc 9f
|
||||
8:
|
||||
// Read second signal word - both process and thread simultaneously.
|
||||
@@ -211,7 +215,7 @@ asmfunction!(__relibc_internal_sigentry: ["
|
||||
mov esi, eax
|
||||
mov eax, {SYS_SIGDEQUEUE}
|
||||
mov rdi, fs:[0]
|
||||
add rdi, {tcb_sa_off} + {sa_tmp_inf} // out pointer of dequeued realtime sig
|
||||
add rdi, {tcb_sa_off} + {sa_tmp_rt_inf} // out pointer of dequeued realtime sig
|
||||
syscall
|
||||
test eax, eax
|
||||
jnz 1b // assumes error can only be EAGAIN
|
||||
@@ -220,7 +224,9 @@ asmfunction!(__relibc_internal_sigentry: ["
|
||||
2:
|
||||
mov edx, eax
|
||||
shr edx, 5
|
||||
mov rdi, fs:[{tcb_sc_off} + {sc_sender_infos} + eax * 8]
|
||||
lock btr fs:[{tcb_sc_off} + {sc_word} + edx * 4], eax
|
||||
mov fs:[{tcb_sa_off} + {sa_tmp_id_inf}], rdi
|
||||
add eax, 64 // indicate signal was targeted at thread
|
||||
9:
|
||||
sub rsp, {REDZONE_SIZE}
|
||||
@@ -396,17 +402,20 @@ __relibc_internal_sigentry_crit_third:
|
||||
sa_tmp_rdx = const offset_of!(SigArea, tmp_rdx),
|
||||
sa_tmp_rdi = const offset_of!(SigArea, tmp_rdi),
|
||||
sa_tmp_rsi = const offset_of!(SigArea, tmp_rsi),
|
||||
sa_tmp_inf = const offset_of!(SigArea, tmp_inf),
|
||||
sa_tmp_rt_inf = const offset_of!(SigArea, tmp_rt_inf),
|
||||
sa_tmp_id_inf = const offset_of!(SigArea, tmp_id_inf),
|
||||
sa_altstack_top = const offset_of!(SigArea, altstack_top),
|
||||
sa_altstack_bottom = const offset_of!(SigArea, altstack_bottom),
|
||||
sc_saved_rflags = const offset_of!(Sigcontrol, saved_archdep_reg),
|
||||
sc_saved_rip = const offset_of!(Sigcontrol, saved_ip),
|
||||
sc_word = const offset_of!(Sigcontrol, word),
|
||||
sc_sender_infos = const offset_of!(Sigcontrol, sender_infos),
|
||||
sc_control = const offset_of!(Sigcontrol, control_flags),
|
||||
tcb_sa_off = const offset_of!(crate::Tcb, os_specific) + offset_of!(RtSigarea, arch),
|
||||
tcb_sc_off = const offset_of!(crate::Tcb, os_specific) + offset_of!(RtSigarea, control),
|
||||
pctl_off_actions = const offset_of!(SigProcControl, actions),
|
||||
pctl_off_pending = const offset_of!(SigProcControl, pending),
|
||||
pctl_off_sender_infos = const offset_of!(SigProcControl, sender_infos),
|
||||
pctl = sym PROC_CONTROL_STRUCT,
|
||||
supports_avx = sym SUPPORTS_AVX,
|
||||
REDZONE_SIZE = const 128,
|
||||
|
||||
+27
-23
@@ -6,10 +6,10 @@ use core::{
|
||||
};
|
||||
|
||||
use syscall::{
|
||||
data::AtomicU64, Error, NonatomicUsize, RawAction, Result, SetSighandlerData, SigProcControl,
|
||||
Sigcontrol, SigcontrolFlags, EINVAL, ENOMEM, EPERM, SIGABRT, SIGBUS, SIGCHLD, SIGCONT, SIGFPE,
|
||||
SIGILL, SIGKILL, SIGQUIT, SIGSEGV, SIGSTOP, SIGSYS, SIGTRAP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG,
|
||||
SIGWINCH, SIGXCPU, SIGXFSZ,
|
||||
data::AtomicU64, Error, NonatomicUsize, RawAction, Result, SenderInfo, SetSighandlerData,
|
||||
SigProcControl, Sigcontrol, SigcontrolFlags, EINVAL, ENOMEM, EPERM, SIGABRT, SIGBUS, SIGCHLD,
|
||||
SIGCONT, SIGFPE, SIGILL, SIGKILL, SIGQUIT, SIGSEGV, SIGSTOP, SIGSYS, SIGTRAP, SIGTSTP, SIGTTIN,
|
||||
SIGTTOU, SIGURG, SIGWINCH, SIGXCPU, SIGXFSZ,
|
||||
};
|
||||
|
||||
use crate::{arch::*, proc::FdGuard, sync::Mutex, RtTcb, Tcb};
|
||||
@@ -85,16 +85,19 @@ unsafe fn inner(stack: &mut SigStack) {
|
||||
let (sender_pid, sender_uid) = {
|
||||
let area = &mut *os.arch.get();
|
||||
|
||||
stack.sival = area.tmp_inf.arg;
|
||||
// Undefined if the signal was not realtime
|
||||
stack.sival = area.tmp_rt_inf.arg;
|
||||
|
||||
stack.old_stack = arch_pre(stack, area);
|
||||
|
||||
if (stack.sig_num - 1) / 32 == 1 && !targeted_thread_not_process {
|
||||
stack.sig_code = area.tmp_inf.code as u32;
|
||||
(area.tmp_inf.pid, area.tmp_inf.uid)
|
||||
stack.sig_code = area.tmp_rt_inf.code as u32;
|
||||
(area.tmp_rt_inf.pid, area.tmp_rt_inf.uid)
|
||||
} else {
|
||||
// TODO: SIGCHLD information when applicable
|
||||
stack.sig_code = 0;
|
||||
(0, 0) // TODO
|
||||
stack.sig_code = 0; // TODO: SI_USER constant?
|
||||
// TODO: Handle SIGCHLD. Maybe that should always be queued though?
|
||||
let inf = SenderInfo::from_raw(area.tmp_id_inf);
|
||||
(inf.pid, inf.ruid)
|
||||
}
|
||||
};
|
||||
|
||||
@@ -140,7 +143,6 @@ unsafe fn inner(stack: &mut SigStack) {
|
||||
let sigallow_inside_lo = sigallow_inside & 0xffff_ffff;
|
||||
let sigallow_inside_hi = sigallow_inside >> 32;
|
||||
|
||||
//let _ = syscall::write(1, &alloc::format!("WORD0 {:x?}\n", os.control.word).as_bytes());
|
||||
let prev_w0 = os.control.word[0].fetch_add(
|
||||
(sigallow_inside_lo << 32).wrapping_sub(prev_sigallow_lo << 32),
|
||||
Ordering::Relaxed,
|
||||
@@ -149,7 +151,6 @@ unsafe fn inner(stack: &mut SigStack) {
|
||||
(sigallow_inside_hi << 32).wrapping_sub(prev_sigallow_hi << 32),
|
||||
Ordering::Relaxed,
|
||||
);
|
||||
//let _ = syscall::write(1, &alloc::format!("WORD1 {:x?}\n", os.control.word).as_bytes());
|
||||
|
||||
// TODO: If sa_mask caused signals to be unblocked, deliver one or all of those first?
|
||||
|
||||
@@ -161,13 +162,12 @@ unsafe fn inner(stack: &mut SigStack) {
|
||||
);
|
||||
core::sync::atomic::compiler_fence(Ordering::Acquire);
|
||||
|
||||
stack.old_mask = ((prev_w1 >> 32) << 32) | (prev_w0 >> 32);
|
||||
|
||||
// Call handler, either sa_handler or sa_siginfo depending on flag.
|
||||
if sigaction.flags.contains(SigactionFlags::SIGINFO)
|
||||
&& let Some(sigaction) = handler.sigaction
|
||||
{
|
||||
stack.old_mask = ((prev_w1 >> 32) << 32) | (prev_w0 >> 32);
|
||||
|
||||
//let _ = syscall::write(1, alloc::format!("SIGACTION {:p}\n", sigaction).as_bytes());
|
||||
let info = SiginfoAbi {
|
||||
si_signo: stack.sig_num as c_int,
|
||||
si_addr: core::ptr::null_mut(),
|
||||
@@ -184,10 +184,8 @@ unsafe fn inner(stack: &mut SigStack) {
|
||||
stack as *mut SigStack as *mut (),
|
||||
);
|
||||
} else if let Some(handler) = handler.handler {
|
||||
//let _ = syscall::write(1, alloc::format!("HANDLER {:p}\n", handler).as_bytes());
|
||||
handler(stack.sig_num as c_int);
|
||||
}
|
||||
//let _ = syscall::write(1, alloc::format!("RETURNED HANDLER\n").as_bytes());
|
||||
|
||||
// Disable signals while we modify the sigmask again
|
||||
control_flags.store(
|
||||
@@ -197,25 +195,30 @@ unsafe fn inner(stack: &mut SigStack) {
|
||||
core::sync::atomic::compiler_fence(Ordering::Acquire);
|
||||
|
||||
// Update allowset again.
|
||||
//let _ = syscall::write(1, &alloc::format!("WORD2 {:x?}\n", os.control.word).as_bytes());
|
||||
|
||||
let new_mask = stack.old_mask;
|
||||
let old_mask = (os.control.word[0].load(Ordering::Relaxed) >> 32)
|
||||
| ((os.control.word[1].load(Ordering::Relaxed) >> 32) << 32);
|
||||
|
||||
let _prev_w0 = os.control.word[0].fetch_add(
|
||||
(prev_sigallow_lo << 32).wrapping_sub(sigallow_inside_lo << 32),
|
||||
((new_mask & 0xffff_ffff) << 32).wrapping_sub((old_mask & 0xffff_ffff) << 32),
|
||||
Ordering::Relaxed,
|
||||
);
|
||||
let _prev_w1 = os.control.word[1].fetch_add(
|
||||
(prev_sigallow_hi << 32).wrapping_sub(sigallow_inside_hi << 32),
|
||||
((new_mask >> 32) << 32).wrapping_sub((old_mask >> 32) << 32),
|
||||
Ordering::Relaxed,
|
||||
);
|
||||
//let _ = syscall::write(1, &alloc::format!("WORD3 {:x?}\n", os.control.word).as_bytes());
|
||||
|
||||
// TODO: If resetting the sigmask caused signals to be unblocked, then should they be delivered
|
||||
// here? And would it be possible to tail-call-optimize that?
|
||||
|
||||
//let _ = syscall::write(1, alloc::format!("will return to {:x?}\n", stack.regs.eip).as_bytes());
|
||||
|
||||
(*os.arch.get()).last_sig_was_restart = shall_restart;
|
||||
|
||||
// TODO: Support setting uc_link to jump back to a different context?
|
||||
(*os.arch.get()).last_sigstack = NonNull::new(stack.link);
|
||||
|
||||
// TODO: Support restoring uc_stack?
|
||||
|
||||
// And re-enable them again
|
||||
if !signals_were_disabled {
|
||||
core::sync::atomic::compiler_fence(Ordering::Release);
|
||||
@@ -502,6 +505,7 @@ pub(crate) static PROC_CONTROL_STRUCT: SigProcControl = SigProcControl {
|
||||
user_data: AtomicU64::new(0),
|
||||
}
|
||||
}; 64],
|
||||
sender_infos: [const { AtomicU64::new(0) }; 32],
|
||||
};
|
||||
|
||||
fn combine_allowset([lo, hi]: [u64; 2]) -> u64 {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
use core::arch::global_asm;
|
||||
|
||||
use super::{sigset_t, stack_t};
|
||||
|
||||
pub const SIGHUP: usize = 1;
|
||||
pub const SIGINT: usize = 2;
|
||||
pub const SIGQUIT: usize = 3;
|
||||
@@ -54,3 +56,39 @@ pub const SIGSTKSZ: usize = 8096;
|
||||
|
||||
pub const SI_QUEUE: i32 = -1;
|
||||
pub const SI_USER: i32 = 0;
|
||||
|
||||
pub(crate) type ucontext_t = ucontext;
|
||||
pub(crate) type mcontext_t = mcontext;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct ucontext {
|
||||
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
|
||||
_pad: [usize; 1], // pad from 7*8 to 64
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
_pad: [usize; 3], // pad from 9*4 to 12*4
|
||||
|
||||
pub uc_link: *mut ucontext_t,
|
||||
pub uc_stack: stack_t,
|
||||
pub uc_sigmask: sigset_t,
|
||||
_sival: usize,
|
||||
_sigcode: u32,
|
||||
_signum: u32,
|
||||
pub uc_mcontext: mcontext_t,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct mcontext {
|
||||
#[cfg(target_arch = "x86")]
|
||||
_opaque: [u8; 512],
|
||||
#[cfg(target_arch = "x86-64")]
|
||||
_opaque: [u8; 864],
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
_opaque: [u8; 272],
|
||||
}
|
||||
#[no_mangle]
|
||||
pub extern "C" fn __completely_unused_cbindgen_workaround_fn_ucontext_mcontext(
|
||||
a: *const ucontext_t,
|
||||
b: *const mcontext_t,
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ use crate::{
|
||||
header::{
|
||||
errno::{EINVAL, ENOSYS},
|
||||
signal::{
|
||||
sigaction, siginfo_t, sigset_t, sigval, stack_t, SA_SIGINFO, SIG_BLOCK, SIG_DFL,
|
||||
SIG_IGN, SIG_SETMASK, SIG_UNBLOCK, SS_DISABLE, SS_ONSTACK,
|
||||
sigaction, siginfo_t, sigset_t, sigval, stack_t, ucontext_t, SA_SIGINFO, SIG_BLOCK,
|
||||
SIG_DFL, SIG_IGN, SIG_SETMASK, SIG_UNBLOCK, SS_DISABLE, SS_ONSTACK,
|
||||
},
|
||||
sys_time::{itimerval, ITIMER_REAL},
|
||||
time::timespec,
|
||||
@@ -22,23 +22,6 @@ use crate::{
|
||||
platform::ERRNO,
|
||||
};
|
||||
|
||||
#[repr(C)]
|
||||
pub struct ucontext_t {
|
||||
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
|
||||
_pad: [usize; 1], // pad from 7*8 to 64
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
_pad: [usize; 3], // pad from 9*4 to 12*4
|
||||
|
||||
pub uc_link: *mut ucontext_t,
|
||||
pub uc_stack: stack_t,
|
||||
pub uc_sigmask: sigset_t,
|
||||
_sival: usize,
|
||||
_sigcode: u32,
|
||||
_signum: u32,
|
||||
pub uc_mcontext: mcontext_t,
|
||||
}
|
||||
|
||||
const _: () = {
|
||||
#[track_caller]
|
||||
const fn assert_eq(a: usize, b: usize) {
|
||||
@@ -61,16 +44,6 @@ const _: () = {
|
||||
);
|
||||
};
|
||||
|
||||
#[repr(C)]
|
||||
pub struct mcontext_t {
|
||||
#[cfg(target_arch = "x86")]
|
||||
_opaque: [u8; 512],
|
||||
#[cfg(target_arch = "x86-64")]
|
||||
_opaque: [u8; 864],
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
_opaque: [u8; 272],
|
||||
}
|
||||
|
||||
impl PalSignal for Sys {
|
||||
unsafe fn getitimer(which: c_int, out: *mut itimerval) -> c_int {
|
||||
let path = match which {
|
||||
|
||||
+26
-6
@@ -1,4 +1,6 @@
|
||||
#include <assert.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
@@ -7,23 +9,41 @@
|
||||
#include "test_helpers.h"
|
||||
|
||||
void handler1(int sig) {
|
||||
ERROR_IF(handler, sig, != SIGUSR1);
|
||||
puts("Signal handler1 called!");
|
||||
assert(sig == SIGUSR1);
|
||||
char *str = "Signal handler1 called!\n";
|
||||
write(STDOUT_FILENO, str, strlen(str));
|
||||
}
|
||||
|
||||
void handler2(int sig) {
|
||||
ERROR_IF(handler, sig, != SIGUSR1);
|
||||
puts("Signal handler2 called!");
|
||||
sigset_t the_set = { 0 };
|
||||
|
||||
void handler2(int sig, siginfo_t *info, void *context_raw) {
|
||||
assert(sig == SIGUSR1);
|
||||
char *str = "Signal handler2 called!\n";
|
||||
write(STDOUT_FILENO, str, strlen(str));
|
||||
|
||||
assert(info != NULL);
|
||||
assert(info->si_signo == SIGUSR1);
|
||||
assert(info->si_code == SI_USER);
|
||||
assert(info->si_pid == getpid());
|
||||
assert(info->si_uid == getuid());
|
||||
|
||||
ucontext_t *context = context_raw;
|
||||
assert(context != NULL);
|
||||
assert(memcmp(&context->uc_sigmask, &the_set, sizeof(sigset_t)));
|
||||
assert(context->uc_link == NULL);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
struct sigaction sa1 = { .sa_handler = handler1 };
|
||||
struct sigaction sa2 = { .sa_handler = handler2 };
|
||||
struct sigaction sa2 = { .sa_sigaction = handler2, .sa_flags = SA_SIGINFO };
|
||||
struct sigaction saold = {0};
|
||||
|
||||
sigemptyset(&sa1.sa_mask);
|
||||
sigemptyset(&sa2.sa_mask);
|
||||
|
||||
int status = sigprocmask(SIG_SETMASK, NULL, &the_set);
|
||||
ERROR_IF(sigprocmask, status, == -1);
|
||||
|
||||
int rcode = sigaction(SIGUSR1, &sa1, NULL);
|
||||
ERROR_IF(signal, rcode, != 0);
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@ int parent;
|
||||
void action(int sig, siginfo_t *info, void *context) {
|
||||
(void)context;
|
||||
assert(sig == THE_SIG);
|
||||
assert(info != NULL);
|
||||
assert(context != NULL);
|
||||
assert(info->si_signo == THE_SIG);
|
||||
assert(info->si_value.sival_int == num);
|
||||
assert(info->si_code == SI_QUEUE);
|
||||
|
||||
Reference in New Issue
Block a user