Document unsafe contracts and stop reusing poisoned state
This commit is contained in:
1 parent
a7fcd69897
commit
f2e728b503
46 files changed
+377
-45
No files matched your search
@@ -247,8 +247,9 @@ pub fn command(action: &Action, socket: &Path, json_output: bool) -> Result<(),
|
||||
static CHILD: std::sync::atomic::AtomicI32 = std::sync::atomic::AtomicI32::new(0);
|
||||
extern "C" fn terminate(signal: i32) {
|
||||
let pid = CHILD.load(std::sync::atomic::Ordering::Relaxed);
|
||||
// SAFETY: kill is async-signal-safe; the PID belongs to this wrapper's child.
|
||||
if pid > 0 {
|
||||
// SAFETY: kill is async-signal-safe and has no pointer arguments; pid names the wrapper
|
||||
// child.
|
||||
unsafe {
|
||||
libc::kill(pid, signal);
|
||||
}
|
||||
@@ -325,6 +326,8 @@ pub fn run(
|
||||
// Terminal-generated signals reach both processes in the shell's job group.
|
||||
// The wrapper waits for the actual child result; the child resets inherited
|
||||
// dispositions before exec. SIGTSTP/SIGCONT retain normal job control.
|
||||
// SAFETY: The handler only loads an atomic PID and calls kill. The pre_exec hook only resets
|
||||
// signal dispositions, without allocation or locks.
|
||||
unsafe {
|
||||
libc::signal(libc::SIGINT, libc::SIG_IGN);
|
||||
libc::signal(libc::SIGQUIT, libc::SIG_IGN);
|
||||
@@ -442,6 +445,8 @@ pub fn run(
|
||||
}
|
||||
if let Some(signal) = status.signal() {
|
||||
// Preserve signal termination as well as the conventional shell status.
|
||||
// SAFETY: signal and raise use a signal obtained from the child exit status and have no
|
||||
// borrowed memory.
|
||||
unsafe {
|
||||
libc::signal(signal, libc::SIG_DFL);
|
||||
libc::raise(signal);
|
||||
|
||||
@@ -32,6 +32,7 @@ impl Read for Output {
|
||||
};
|
||||
// The pipe has exactly one reader. Once readable (or hung up), a
|
||||
// pipe read returns available bytes (or EOF) without filling bytes.
|
||||
// SAFETY: fd is a live pollfd and the count of one matches its writable storage.
|
||||
let result = unsafe { libc::poll(&mut fd, 1, 20) };
|
||||
if result > 0 {
|
||||
return self.pipe.read(bytes);
|
||||
|
||||
@@ -13,6 +13,8 @@ pub(crate) fn run() -> Result<(), Box<dyn std::error::Error>> {
|
||||
.filter(|fd| *fd >= 3)
|
||||
{
|
||||
// These session-helper descriptors must never reach ordinary startup apps.
|
||||
// SAFETY: fcntl receives integer descriptor flags, without pointer arguments; invalid
|
||||
// descriptors return an error.
|
||||
unsafe {
|
||||
let flags = libc::fcntl(fd, libc::F_GETFD);
|
||||
if flags < 0 || libc::fcntl(fd, libc::F_SETFD, flags | libc::FD_CLOEXEC) < 0 {
|
||||
@@ -76,6 +78,8 @@ pub(crate) fn run() -> Result<(), Box<dyn std::error::Error>> {
|
||||
.env_remove("FERESE_PUBLIC_WAYLAND_DISPLAY");
|
||||
// Only signal-safe calls run in the child before exec. A pending launcher
|
||||
// dies with this helper, while apps already launched by GIO remain independent.
|
||||
// SAFETY: The child hook uses only async-signal-safe prctl, getppid and _exit before
|
||||
// exec.
|
||||
unsafe {
|
||||
command.pre_exec(move || {
|
||||
if libc::prctl(libc::PR_SET_PDEATHSIG, libc::SIGTERM) != 0 {
|
||||
|
||||
Reference in new issue
Block a user