Pass si_pid to all realtime signals.

This commit is contained in:
4lDO2
2024-08-01 19:51:30 +02:00
parent 6fe7c264f6
commit f6761407e5
9 changed files with 64 additions and 31 deletions
+2 -18
View File
@@ -97,11 +97,7 @@ unsafe extern "sysv64" fn fork_impl(initial_rsp: *mut usize) -> usize {
unsafe extern "sysv64" fn child_hook(cur_filetable_fd: usize, new_pid_fd: usize) {
let _ = syscall::close(cur_filetable_fd);
// TODO: Currently pidfd == threadfd, but this will not be the case later.
RtTcb::current()
.thr_fd
.get()
.write(Some(FdGuard::new(new_pid_fd)));
crate::child_hook_common(FdGuard::new(new_pid_fd));
}
asmfunction!(__relibc_internal_fork_wrapper -> usize: ["
@@ -425,11 +421,7 @@ extern "C" {
fn __relibc_internal_sigentry_crit_third();
}
/// Fixes some edge cases, and calculates the value for uc_stack.
pub unsafe fn arch_pre(
stack: &mut SigStack,
area: &mut SigArea,
targeted_thread: bool,
) -> PosixStackt {
pub unsafe fn arch_pre(stack: &mut SigStack, area: &mut SigArea) -> PosixStackt {
// It is impossible to update RSP and RIP atomically on x86_64, without using IRETQ, which is
// almost as slow as calling a SIGRETURN syscall would be. Instead, we abuse the fact that
// signals are disabled in the prologue of the signal trampoline, which allows us to emulate
@@ -451,14 +443,6 @@ pub unsafe fn arch_pre(
stack.regs.rip = area.tmp_rip;
}
stack.sig_code = if (stack.sig_num - 1) / 32 == 1 && !targeted_thread {
area.tmp_inf.code as u32
} else {
// TODO: SIGCHLD information when applicable
0
};
stack.sival = area.tmp_inf.arg;
PosixStackt {
sp: stack.regs.rsp as *mut (),
size: 0, // TODO
+19 -3
View File
@@ -9,7 +9,7 @@
)]
#![forbid(unreachable_patterns)]
use core::cell::UnsafeCell;
use core::cell::{SyncUnsafeCell, UnsafeCell};
use generic_rt::{ExpectTlsFree, GenericTcb};
use syscall::{Sigcontrol, O_CLOEXEC};
@@ -120,13 +120,13 @@ pub unsafe fn tcb_activate(tcb: &RtTcb, tls_end_and_tcb_start: usize, _tls_len:
}
/// Initialize redox-rt in situations where relibc is not used
pub fn initialize_freestanding() {
pub unsafe fn initialize_freestanding() {
// TODO: This code is a hack! Integrate the ld_so TCB code into generic-rt, and then use that
// (this function will need pointers to the ELF structs normally passed in auxvs), so the TCB
// is initialized properly.
// TODO: TLS
let page = unsafe {
let page = {
&mut *(syscall::fmap(
!0,
&syscall::Map {
@@ -155,4 +155,20 @@ pub fn initialize_freestanding() {
let abi_ptr = core::ptr::addr_of_mut!(page.tcb_ptr);
core::arch::asm!("msr tpidr_el0, {}", in(reg) abi_ptr);
}
initialize();
}
pub unsafe fn initialize() {
THIS_PID
.get()
.write(Some(syscall::getpid().unwrap().try_into().unwrap()).unwrap());
}
static THIS_PID: SyncUnsafeCell<u32> = SyncUnsafeCell::new(0);
unsafe fn child_hook_common(new_pid_fd: FdGuard) {
// TODO: Currently pidfd == threadfd, but this will not be the case later.
RtTcb::current().thr_fd.get().write(Some(new_pid_fd));
THIS_PID
.get()
.write(Some(syscall::getpid().unwrap().try_into().unwrap()).unwrap());
}
+18 -4
View File
@@ -81,13 +81,27 @@ unsafe fn inner(stack: &mut SigStack) {
// asm counts from 0
stack.sig_num += 1;
stack.old_stack = arch_pre(stack, &mut *os.arch.get(), targeted_thread_not_process);
let (sender_pid, sender_uid) = {
let area = &mut *os.arch.get();
stack.sival = area.tmp_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)
} else {
// TODO: SIGCHLD information when applicable
stack.sig_code = 0;
(0, 0) // TODO
}
};
let sigaction = {
let guard = SIGACTIONS_LOCK.lock();
let action = convert_old(&PROC_CONTROL_STRUCT.actions[stack.sig_num as usize - 1]);
if action.flags.contains(SigactionFlags::RESETHAND) {
// TODO: other things that must be set
drop(guard);
sigaction(
stack.sig_num as u8,
@@ -159,9 +173,9 @@ unsafe fn inner(stack: &mut SigStack) {
si_addr: core::ptr::null_mut(),
si_code: stack.sig_code as i32,
si_errno: 0,
si_pid: 0, // TODO
si_pid: sender_pid as i32,
si_status: 0,
si_uid: 0, // TODO
si_uid: sender_uid as i32,
si_value: stack.sival,
};
sigaction(
+8 -1
View File
@@ -49,7 +49,9 @@ pub fn posix_kill(pid: usize, sig: usize) -> Result<()> {
pub fn posix_sigqueue(pid: usize, sig: usize, arg: usize) -> Result<()> {
let siginf = RtSigInfo {
arg,
code: usize::wrapping_neg(1), // TODO: SI_QUEUE
code: -1, // TODO: SI_QUEUE constant
uid: 0, // TODO
pid: posix_getpid(),
};
match wrapper(false, || unsafe {
syscall::syscall3(syscall::SYS_SIGENQUEUE, pid, sig, addr_of!(siginf) as usize)
@@ -59,6 +61,11 @@ pub fn posix_sigqueue(pid: usize, sig: usize, arg: usize) -> Result<()> {
}
}
#[inline]
pub fn posix_getpid() -> u32 {
// SAFETY: read-only except during program/fork child initialization
unsafe { crate::THIS_PID.get().read() }
}
#[inline]
pub fn posix_killpg(pgrp: usize, sig: usize) -> Result<()> {
match wrapper(false, || syscall::kill(usize::wrapping_neg(pgrp), sig)) {
Ok(_) | Err(Error { errno: EINTR }) => Ok(()),
+4 -1
View File
@@ -141,6 +141,7 @@ fn resolve_path_name(
}
None
}
// TODO: Make unsafe
#[no_mangle]
pub extern "C" fn relibc_ld_so_start(sp: &'static mut Stack, ld_entry: usize) -> usize {
// We get the arguments, the environment, and the auxilary vector
@@ -184,7 +185,9 @@ pub extern "C" fn relibc_ld_so_start(sp: &'static mut Stack, ld_entry: usize) ->
}
// TODO: Fix memory leak, although minimal.
crate::platform::init(auxv.clone());
unsafe {
crate::platform::init(auxv.clone());
}
// Some variables that will be overridden by environment and auxiliary vectors
let ld_library_path = envs.get("LD_LIBRARY_PATH").map(|s| s.to_owned());
+5 -3
View File
@@ -283,15 +283,17 @@ pub fn get_auxv(auxvs: &[[usize; 2]], key: usize) -> Option<usize> {
#[cold]
#[cfg(target_os = "redox")]
pub fn init(auxvs: Box<[[usize; 2]]>) {
// SAFETY: Must only be called when only one thread exists.
pub unsafe fn init(auxvs: Box<[[usize; 2]]>) {
redox_rt::initialize();
use self::auxv_defs::*;
if let (Some(cwd_ptr), Some(cwd_len)) = (
get_auxv(&auxvs, AT_REDOX_INITIAL_CWD_PTR),
get_auxv(&auxvs, AT_REDOX_INITIAL_CWD_LEN),
) {
let cwd_bytes: &'static [u8] =
unsafe { core::slice::from_raw_parts(cwd_ptr as *const u8, cwd_len) };
let cwd_bytes: &'static [u8] = core::slice::from_raw_parts(cwd_ptr as *const u8, cwd_len);
if let Ok(cwd) = core::str::from_utf8(cwd_bytes) {
self::sys::path::set_cwd_manual(cwd.into());
}
+1 -1
View File
@@ -470,7 +470,7 @@ impl Pal for Sys {
}
fn getpid() -> pid_t {
e(syscall::getpid()) as pid_t
redox_rt::sys::posix_getpid() as pid_t
}
fn getppid() -> pid_t {
+1
View File
@@ -39,6 +39,7 @@ pub struct ucontext_t {
}
const _: () = {
#[track_caller]
const fn assert_eq(a: usize, b: usize) {
if a != b {
panic!("compile-time struct verification failed");
+6
View File
@@ -12,12 +12,15 @@
volatile sig_atomic_t num = 1;
int parent;
void action(int sig, siginfo_t *info, void *context) {
(void)context;
assert(sig == THE_SIG);
assert(info->si_signo == THE_SIG);
assert(info->si_value.sival_int == num);
assert(info->si_code == SI_QUEUE);
assert(info->si_pid == parent);
num++;
write(1, "action\n", 7);
}
@@ -28,6 +31,9 @@ int main(void) {
status = pipe(fds);
ERROR_IF(pipe, status, == -1);
parent = getpid();
assert(parent != 0);
int child = fork();
ERROR_IF(fork, child, == -1);