From d366043876555ffedd1b620882f829f05cf1427d Mon Sep 17 00:00:00 2001 From: jiangjianfeng Date: Fri, 14 Mar 2025 06:53:00 +0000 Subject: [PATCH] Enable sig_action test from gVisor test --- kernel/src/process/signal/sig_action.rs | 28 +++++++----- kernel/src/syscall/rt_sigaction.rs | 59 +++++++++++++++++++++++-- test/syscall_test/Makefile | 1 + 3 files changed, 75 insertions(+), 13 deletions(-) diff --git a/kernel/src/process/signal/sig_action.rs b/kernel/src/process/signal/sig_action.rs index 2704ac7e4..1e9bb1f33 100644 --- a/kernel/src/process/signal/sig_action.rs +++ b/kernel/src/process/signal/sig_action.rs @@ -2,7 +2,12 @@ use bitflags::bitflags; -use super::{c_types::sigaction_t, constants::*, sig_mask::SigMask, sig_num::SigNum}; +use super::{ + c_types::sigaction_t, + constants::*, + sig_mask::{SigMask, SigSet}, + sig_num::SigNum, +}; use crate::prelude::*; #[derive(Debug, Copy, Clone, PartialEq, Eq, Default)] @@ -19,16 +24,20 @@ pub enum SigAction { }, } -impl TryFrom for SigAction { - type Error = Error; - - fn try_from(input: sigaction_t) -> Result { - let action = match input.handler_ptr { +impl From for SigAction { + fn from(input: sigaction_t) -> Self { + match input.handler_ptr { SIG_DFL => SigAction::Dfl, SIG_IGN => SigAction::Ign, _ => { let flags = SigActionFlags::from_bits_truncate(input.flags); - let mask = input.mask.into(); + let mask = { + let mut sigset = SigSet::from(input.mask); + // SIGSTOP and SIGKILL cannot be masked + sigset -= SIGSTOP; + sigset -= SIGKILL; + sigset + }; SigAction::User { handler_addr: input.handler_ptr, flags, @@ -36,8 +45,7 @@ impl TryFrom for SigAction { mask, } } - }; - Ok(action) + } } } @@ -105,7 +113,7 @@ impl SigActionFlags { } /// The default action to signals -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum SigDefaultAction { Term, // Default action is to terminate the process. Ign, // Default action is to ignore the signal. diff --git a/kernel/src/syscall/rt_sigaction.rs b/kernel/src/syscall/rt_sigaction.rs index 8f9757c81..5aceffcba 100644 --- a/kernel/src/syscall/rt_sigaction.rs +++ b/kernel/src/syscall/rt_sigaction.rs @@ -3,7 +3,16 @@ use super::SyscallReturn; use crate::{ prelude::*, - process::signal::{c_types::sigaction_t, sig_action::SigAction, sig_num::SigNum}, + process::{ + posix_thread::AsPosixThread, + signal::{ + c_types::sigaction_t, + constants::{SIGKILL, SIGSTOP}, + sig_action::{SigAction, SigDefaultAction}, + sig_mask::SigSet, + sig_num::SigNum, + }, + }, }; pub fn sys_rt_sigaction( @@ -29,10 +38,18 @@ pub fn sys_rt_sigaction( let mut sig_dispositions = ctx.process.sig_dispositions().lock(); let old_action = if sig_action_addr != 0 { + if sig_num == SIGKILL || sig_num == SIGSTOP { + return_errno_with_message!( + Errno::EINVAL, + "cannot set a new signal action for SIGKILL and SIGSTOP" + ); + } + let sig_action_c = ctx.user_space().read_val::(sig_action_addr)?; - let sig_action = SigAction::try_from(sig_action_c).unwrap(); + let sig_action = SigAction::from(sig_action_c); trace!("sig action = {:?}", sig_action); - sig_dispositions.set(sig_num, sig_action) + discard_signals_if_ignored(ctx, sig_num, &sig_action); + sig_dispositions.set(sig_num, sig_action)? } else { sig_dispositions.get(sig_num) }; @@ -45,3 +62,39 @@ pub fn sys_rt_sigaction( Ok(SyscallReturn::Return(0)) } + +/// Discard signals if the new action is to ignore the signal. +/// +/// Ref: +// +// POSIX 3.3.1.3: +// Setting a signal action to SIG_IGN for a signal that is +// pending shall cause the pending signal to be discarded, +// whether or not it is blocked. +// +// Setting a signal action to SIG_DFL for a signal that is +// pending and whose default action is to ignore the signal +// (for example, SIGCHLD), shall cause the pending signal to +// be discarded, whether or not it is blocked +fn discard_signals_if_ignored(ctx: &Context, signum: SigNum, sig_action: &SigAction) { + match sig_action { + SigAction::Dfl => { + let default_action = SigDefaultAction::from_signum(signum); + if default_action != SigDefaultAction::Ign { + return; + } + } + SigAction::Ign => {} + SigAction::User { .. } => return, + } + + let mask = SigSet::new_full() - signum; + + for task in ctx.process.tasks().lock().as_slice() { + let Some(posix_thread) = task.as_posix_thread() else { + continue; + }; + + posix_thread.dequeue_signal(&mask); + } +} diff --git a/test/syscall_test/Makefile b/test/syscall_test/Makefile index e95686f7d..84476946b 100644 --- a/test/syscall_test/Makefile +++ b/test/syscall_test/Makefile @@ -42,6 +42,7 @@ TESTS ?= \ sched_yield_test \ semaphore_test \ sendfile_test \ + sigaction_test \ sigaltstack_test \ stat_test \ stat_times_test \