Summary
A critical bug was discovered where calling terminate() or sendSignal() on an invalid or moved-from Process object could result in kill(-1, SIGKILL) being called, which kills ALL processes owned by the user.
Root Cause
- boost::process v1 uses
-1 as the default/invalid PID value in child_handle (line 22 of child_handle.hpp)
- When
m_process->id() is called on an invalid process, it returns -1
- The module's
sendSignal() and terminate() functions passed this value directly to kill()
kill(-1, SIGKILL) sends SIGKILL to all processes the user has permission to signal (except init and self)
Impact
- Severity: Critical
- Effect: Can kill all user processes including SSH sessions, IDEs, databases, etc.
- Trigger: Calling terminate() or sendSignal() on a process object after it becomes invalid
Fix
-
Added PID validation (pid <= 0) before all kill() calls in:
-
Added safety check in getChildPids() to reject:
- PID 1 (init) - prevents accidental system-wide operations
- PID 0 and negative PIDs
-
Child processes now run in their own process group (setpgid(0, 0)) to isolate signals
-
Patched boost::process v1 terminate.hpp to add pid <= 0 validation (matching v2 behavior)
Testing
- Added negative tests for invalid PIDs
- Added safety tests to verify terminate doesn't kill unrelated processes
- Verified fix with strace - no more
kill(-1, ...) calls
Files Changed
src/processpriv.cpp - PID validation in sendSignal(), terminate(), getChildPids()
src/processpriv.h - setpgid() in on_exec_setup
3rd_party/boost_1_88_0/.../v1/detail/posix/terminate.hpp - v1 safety patch
test/process.qtest - negative tests
src/process.qpp - release notes
qore-process-module.spec - changelog
Summary
A critical bug was discovered where calling
terminate()orsendSignal()on an invalid or moved-from Process object could result inkill(-1, SIGKILL)being called, which kills ALL processes owned by the user.Root Cause
-1as the default/invalid PID value inchild_handle(line 22 ofchild_handle.hpp)m_process->id()is called on an invalid process, it returns-1sendSignal()andterminate()functions passed this value directly tokill()kill(-1, SIGKILL)sends SIGKILL to all processes the user has permission to signal (except init and self)Impact
Fix
Added PID validation (
pid <= 0) before allkill()calls in:sendSignal()terminate()Added safety check in
getChildPids()to reject:Child processes now run in their own process group (
setpgid(0, 0)) to isolate signalsPatched boost::process v1
terminate.hppto addpid <= 0validation (matching v2 behavior)Testing
kill(-1, ...)callsFiles Changed
src/processpriv.cpp- PID validation in sendSignal(), terminate(), getChildPids()src/processpriv.h- setpgid() in on_exec_setup3rd_party/boost_1_88_0/.../v1/detail/posix/terminate.hpp- v1 safety patchtest/process.qtest- negative testssrc/process.qpp- release notesqore-process-module.spec- changelog