From 5c9eb30727331780e01cd34293801efd38aa787d Mon Sep 17 00:00:00 2001 From: huyubiao Date: Fri, 16 Jun 2023 15:32:28 +0800 Subject: [PATCH] fix: init uses SIGABRT to reexec sysmaster, increase signal permissions --- core/bin/main.rs | 46 ++++++++++++++++---------------- core/bin/manager/mod.rs | 9 ++++++- exts/init/Cargo.toml | 1 - exts/init/src/runtime/mod.rs | 33 +++++++++-------------- exts/init/src/runtime/signals.rs | 19 +++++++------ libs/constants/src/lib.rs | 2 -- 7 files changed, 60 insertions(+), 62 deletions(-) diff --git a/core/bin/main.rs b/core/bin/main.rs index 0239ce9..7f163c7 100644 --- a/core/bin/main.rs +++ b/core/bin/main.rs @@ -39,7 +39,7 @@ use crate::mount::setup; use basic::logger::{self}; use basic::process_util; use clap::Parser; -use libc::{c_int, getppid, prctl, PR_SET_CHILD_SUBREAPER}; +use libc::{c_int, getpid, getppid, prctl, PR_SET_CHILD_SUBREAPER}; use log::{self}; use manager::signals::EVENT_SIGNALS; use nix::sys::resource::{self, Resource}; @@ -52,7 +52,6 @@ use std::rc::Rc; use sysmaster::error::*; use sysmaster::rel; -use constants::SIG_MANAGER_REEXEC_OFFSET; use constants::SIG_SWITCH_ROOT_OFFSET; /// parse program arguments @@ -106,21 +105,17 @@ fn main() -> Result<()> { setup::mount_setup()?; rel::reli_dir_prepare()?; - let switch = rel::reli_debug_get_switch(); - log::info!("sysmaster initialize with switch: {}.", switch); + let self_recovery_enable = rel::reli_debug_get_switch(); + log::info!("sysmaster self_recovery_enable: {}.", self_recovery_enable); - initialize_runtime(switch)?; + initialize_runtime(self_recovery_enable)?; let manager = Manager::new(Mode::System, Action::Run, manager_config); - // enable clear, mutex with install_crash_handler - if !switch { - if !args.deserialize { - manager.debug_clear_restore(); - log::info!("debug: clear data restored."); - } - // if switch is false unregister init's reexec signal. - register_reexec_signal(false); + // enable clear + if !self_recovery_enable && !args.deserialize { + manager.debug_clear_restore(); + log::info!("debug: clear data restored."); } manager.setup_cgroup()?; @@ -144,10 +139,13 @@ fn main() -> Result<()> { Ok(()) } -fn initialize_runtime(switch: bool) -> Result<()> { - if switch { +fn initialize_runtime(self_recovery_enable: bool) -> Result<()> { + if self_recovery_enable { install_crash_handler(); log::info!("install crash handler."); + } else { + // if self_recovery_enable is false unregister init's reexec signal. + register_reexec_signal(false); } #[cfg(feature = "linux")] @@ -222,7 +220,7 @@ fn install_crash_handler() { Signal::SIGABRT, Signal::SIGSYS, ]; - let handler = SigHandler::Handler(crash); + let handler = SigHandler::SigAction(crash); let flags = SaFlags::SA_NODEFER; let action = SigAction::new(handler, flags, SigSet::empty()); for &signal in signals.iter() { @@ -232,11 +230,14 @@ fn install_crash_handler() { } } -extern "C" fn crash(signo: c_int) { - let _signal = Signal::try_from(signo).unwrap(); // debug - - let args: Vec = env::args().collect(); - do_reexecute(&args, false); +extern "C" fn crash(signo: c_int, siginfo: *mut libc::siginfo_t, _con: *mut libc::c_void) { + let signal = Signal::try_from(signo).unwrap(); // debug + if (signal == Signal::SIGABRT && unsafe { (*siginfo).si_pid() == getppid() }) + || unsafe { (*siginfo).si_pid() == getpid() } + { + let args: Vec = env::args().collect(); + do_reexecute(&args, false); + } } fn execarg_build_default() -> (String, Vec) { @@ -265,8 +266,7 @@ extern "C" fn crash_none(_signo: c_int, _siginfo: *mut libc::siginfo_t, _con: *m } fn register_reexec_signal(enable: bool) { - let manager_signal: signal::Signal = - unsafe { std::mem::transmute(libc::SIGRTMIN() + SIG_MANAGER_REEXEC_OFFSET) }; + let manager_signal: Signal = Signal::SIGABRT; let handler = match enable { true => SigHandler::SigAction(crash_reexec), false => SigHandler::SigAction(crash_none), diff --git a/core/bin/manager/mod.rs b/core/bin/manager/mod.rs index e972cc7..7bd16e0 100644 --- a/core/bin/manager/mod.rs +++ b/core/bin/manager/mod.rs @@ -59,6 +59,12 @@ impl SignalMgr { SignalMgr { um: Rc::clone(&um) } } fn reexec(&self) -> Result { + self.um.set_state(State::ReExecute); + Ok(1) + } + + fn reload(&self) -> Result { + self.um.set_state(State::ReLoad); Ok(1) } } @@ -70,7 +76,8 @@ impl SignalDispatcher for SignalMgr { return Ok(1); } match signal.ssi_signo as libc::c_int { - libc::SIGHUP | libc::SIGTERM => self.reexec(), + libc::SIGHUP => self.reload(), + libc::SIGTERM => self.reexec(), libc::SIGCHLD => Ok(self.um.child_sigchld_enable(true)), /* Kernel will send SIGINT to PID1 when users press ctrl-alt-del, * init should forward SIGINT to sysmaster. */ diff --git a/exts/init/Cargo.toml b/exts/init/Cargo.toml index e3c0198..e351b61 100644 --- a/exts/init/Cargo.toml +++ b/exts/init/Cargo.toml @@ -9,4 +9,3 @@ edition = "2021" constants = { version = "0.1.0", path = "../../libs/constants" } libc = "0.2.*" nix = "0.24" -signal-hook-registry = "1.4.0" diff --git a/exts/init/src/runtime/mod.rs b/exts/init/src/runtime/mod.rs index e37ff01..d11d8f2 100644 --- a/exts/init/src/runtime/mod.rs +++ b/exts/init/src/runtime/mod.rs @@ -33,7 +33,6 @@ use std::rc::Rc; use constants::SIG_SWITCH_ROOT_OFFSET; const INVALID_PID: i32 = -1; -const MANAGER_SIG_OFFSET: i32 = 7; const SYSMASTER_PATH: &str = "/usr/lib/sysmaster/sysmaster"; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd)] @@ -152,12 +151,7 @@ impl RunTime { self.comm.finish(); - unsafe { - libc::kill( - self.sysmaster_pid.into(), - libc::SIGRTMIN() + MANAGER_SIG_OFFSET, - ) - }; + unsafe { libc::kill(self.sysmaster_pid.into(), libc::SIGABRT) }; } fn reexec_comm_dispatch(&mut self, event: EpollEvent) -> Result<(), Errno> { @@ -187,11 +181,10 @@ impl RunTime { fn reexec_signal_dispatch(&mut self, event: EpollEvent) -> Result<(), Errno> { if let Some(siginfo) = self.signals.read(event)? { - let signo = siginfo.ssi_signo as i32; - match signo { - _x if self.signals.is_zombie(signo) => self.do_recycle(), - _x if self.signals.is_restart(signo) => self.do_reexec(), - _x if self.signals.is_unrecover(signo) => self.change_to_unrecover(), + match siginfo { + _x if self.signals.is_zombie(siginfo) => self.do_recycle(), + _x if self.signals.is_restart(siginfo) => self.do_reexec(), + _x if self.signals.is_unrecover(siginfo) => self.change_to_unrecover(), _ => {} } } @@ -200,11 +193,10 @@ impl RunTime { fn run_signal_dispatch(&mut self, event: EpollEvent) -> Result<(), Errno> { if let Some(siginfo) = self.signals.read(event)? { - let signo = siginfo.ssi_signo as i32; - match signo { - _x if self.signals.is_zombie(signo) => self.do_recycle(), - _x if self.signals.is_restart(signo) => self.do_reexec(), - _x if self.signals.is_switch_root(signo) => self.send_switch_root_signal(), + match siginfo { + _x if self.signals.is_zombie(siginfo) => self.do_recycle(), + _x if self.signals.is_restart(siginfo) => self.do_reexec(), + _x if self.signals.is_switch_root(siginfo) => self.send_switch_root_signal(), _ => {} } } @@ -213,15 +205,14 @@ impl RunTime { fn unrecover_signal_dispatch(&mut self, event: EpollEvent) -> Result<(), Errno> { if let Some(siginfo) = self.signals.read(event)? { - let signo = siginfo.ssi_signo as i32; - match signo { - _x if self.signals.is_zombie(signo) => { + match siginfo { + _x if self.signals.is_zombie(siginfo) => { self.signals.recycle_zombie(); if self.is_sysmaster(siginfo.ssi_pid as i32) && self.switching { self.reexec_self() } } - _x if self.signals.is_restart(signo) => self.do_recreate(), + _x if self.signals.is_restart(siginfo) => self.do_recreate(), _ => {} } } diff --git a/exts/init/src/runtime/signals.rs b/exts/init/src/runtime/signals.rs index eee088c..1c3059c 100644 --- a/exts/init/src/runtime/signals.rs +++ b/exts/init/src/runtime/signals.rs @@ -81,20 +81,23 @@ impl Signals { } } - pub fn is_zombie(&self, signo: i32) -> bool { - self.zombie_signal == signo + pub fn is_zombie(&self, siginfo: libc::signalfd_siginfo) -> bool { + self.zombie_signal as u32 == siginfo.ssi_signo } - pub fn is_restart(&self, signo: i32) -> bool { - self.restart_signal == signo + pub fn is_restart(&self, siginfo: libc::signalfd_siginfo) -> bool { + self.restart_signal as u32 == siginfo.ssi_signo } - pub fn is_unrecover(&self, signo: i32) -> bool { - self.unrecover_signal == signo + pub fn is_unrecover(&self, siginfo: libc::signalfd_siginfo) -> bool { + if 0 == siginfo.ssi_uid { + return self.unrecover_signal as u32 == siginfo.ssi_signo; + } + false } - pub fn is_switch_root(&self, signo: i32) -> bool { - self.switch_root_signal == signo + pub fn is_switch_root(&self, siginfo: libc::signalfd_siginfo) -> bool { + self.switch_root_signal as u32 == siginfo.ssi_signo } pub fn create_signals_epoll(&mut self) -> Result<(), Errno> { diff --git a/libs/constants/src/lib.rs b/libs/constants/src/lib.rs index 7c918aa..b1db27c 100644 --- a/libs/constants/src/lib.rs +++ b/libs/constants/src/lib.rs @@ -12,8 +12,6 @@ //! Common used constants by init, sysmaster and other extensions. -/// Signal used to reexecute sysmaster, SIGRTMIN+7 -pub const SIG_MANAGER_REEXEC_OFFSET: i32 = 7; /// Signal used run unrecover, SIGRTMIN+8 pub const SIG_RUN_UNRECOVER_OFFSET: i32 = 8; /// Signal used to restart the manager, SIGRTMIN+9 -- 2.33.0