Skip to content

distrib-compat 0.1-5: Backport upstream killproc fixes from bitstreamout/killproc#1637

Open
dcasota wants to merge 1 commit intovmware:5.0from
dcasota:distrib-compat-0.1-5-upstream-backports
Open

distrib-compat 0.1-5: Backport upstream killproc fixes from bitstreamout/killproc#1637
dcasota wants to merge 1 commit intovmware:5.0from
dcasota:distrib-compat-0.1-5-upstream-backports

Conversation

@dcasota
Copy link
Contributor

@dcasota dcasota commented Feb 21, 2026

Summary

Backport critical bug fixes and robustness improvements from Werner Fink's upstream killproc v2.23 into distrib-compat 0.1. This update bumps the release from 0.1-4 to 0.1-5 by adding a single new patch file (Patch1) while preserving the unmodified Source0 tarball and its SHA-512 checksum.

Motivation

Photon OS's distrib-compat package (providing startproc, killproc, checkproc) is a simplified fork of Werner Fink's killproc suite, originally developed for SUSE/openSUSE. The upstream project has accumulated several important fixes since the fork point that address real-world failure scenarios:

  • Process name matching failures for binaries with names longer than 15 characters
  • Race conditions during daemon startup
  • Incorrect SIGKILL escalation behavior
  • Permission errors for non-root users and NFS-mounted executables

Source Provenance and Upstream Attribution

All backported code originates from Werner Fink's bitstreamout/killproc repository. The original source files carry the following copyright headers:

Copyright 1994-2000 Werner Fink, 1996-2000 SuSE GmbH Nuernberg, Germany.
Copyright 2005 Werner Fink, 2005 SUSE LINUX Products GmbH, Germany.
Author: Werner Fink <werner@suse.de>

The distrib-compat package was created by Ankit Jain (VMware) in 2021 as a simplified multicall-binary adaptation of Werner Fink's killproc suite for Photon OS compatibility.

License Compliance

Component License SPDX Identifier
Upstream killproc (bitstreamout/killproc) GNU GPL v2 "or any later version" GPL-2.0-or-later
distrib-compat source (COPYING) GNU GPL v2 "or any later version" GPL-2.0-or-later
distrib-compat package metadata (license.txt) GPL-2.0-only AND GPL-2.0-or-later GPL-2.0-only AND GPL-2.0-or-later
config.yaml SPDX license_concluded: GPL-2.0-or-later AND GPL-2.0-only --

The backported code is licensed under GPL-2.0-or-later (per upstream source file headers), which is fully compatible with the existing distrib-compat license declaration. All modifications are derivative works under the same GPL-2.0 terms. No license change is required.

Changes

High Priority -- Correctness Fixes

  1. COMM_LEN process name truncation (libinit.h): Added COMM_LEN constant (15 chars) and rewrote swap_name() to use strncat() with proper truncation. The Linux kernel truncates /proc/<pid>/stat comm field to 15 characters; without this fix, killproc/checkproc fail to match processes whose binary name exceeds 15 characters (e.g., NetworkManager, systemd-resolved).

  2. sig_forced flag (killproc.c): Added a boolean flag that prevents unwanted SIGKILL escalation when the user explicitly specifies a signal (e.g., killproc -SIGTERM /path/to/daemon). Previously, killproc would always escalate to SIGKILL after timeout, even when SIGTERM was explicitly requested.

  3. pipe2() parent-child synchronization (startproc.c): Replaced the previous fork/exec sequence with pipe-based synchronization using pipe2(O_CLOEXEC) (with pipe()+fcntl() fallback). This eliminates a race condition where the parent would check /proc/<pid>/exe before the child had completed execve(), causing spurious "start of ... failed" errors, particularly under system load.

Medium Priority -- Robustness Improvements

  1. UID-based fallback (libinit.c): In pidof(), verify_pidfile(), and check_pids(), added fallback logic for non-root users when readlink(/proc/<pid>/exe) returns EACCES. Falls back to stat-based name matching using the caller's UID, enabling process checks by service users without elevated privileges.

  2. expandpath() function (libinit.c, libinit.h): Added a 96-line realpath() alternative that avoids lstat() calls which can hang indefinitely on unresponsive NFS mounts. Used in pidof(), verify_pidfile(), and check_pids() for safe path resolution.

  3. O_CLOEXEC on script open (libinit.c): Added O_CLOEXEC flag to the open() call in isscript() to prevent file descriptor leaks to child processes.

  4. atexit(undo_proc) cleanup (libinit.c): Added automatic /proc unmount on exit if the tool had to mount it, preventing stale mounts.

  5. Bonus: Fixed uninitialized variable p warning in waiton() (startproc.c) -- a pre-existing issue not related to the backport but resolved to achieve a warning-free build.

Files Changed

  • SPECS/distrib-compat/distrib-compat.spec -- Release bump 4 -> 5, added Patch1, changelog entry
  • SPECS/distrib-compat/distrib-compat-upstream-backports.patch -- New 580-line unified diff (Patch1)

The patch modifies 4 source files within the tarball:

  • libinit.h -- COMM_LEN constant, swap_name() rewrite, expandpath() declaration
  • libinit.c -- expandpath(), UID fallback, O_CLOEXEC, atexit cleanup
  • killproc.c -- sig_forced flag
  • startproc.c -- pipe2() sync, waiton() fix

Testing

Build Verification

  • Platform: VMware Photon OS 5.0 (PHOTON_BUILD_NUMBER=b9d98344d)
  • Compiler: GCC 12.2.0
  • Result: Zero errors, zero warnings
  • Binary: ELF 64-bit LSB PIE executable, x86-64, dynamically linked, with debug_info

Patch Application

  • Both Patch0 (distrib-compat-gen-debuginfo.patch) and Patch1 (distrib-compat-upstream-backports.patch) apply cleanly in sequence to an unmodified extraction of distrib-compat-0.1.tar.bz2
  • Source0 tarball and SHA-512 checksum are unchanged

Smoke Tests

Test Command Result
Signal listing killproc -l All 64 signals listed correctly
Running process check checkproc -v /usr/bin/bash Exit 0, PIDs listed
Missing binary check checkproc -v /usr/bin/nonexistent Exit 5 (LSB_NOENTR)
Symlink dispatch ls -la /sbin/{killproc,checkproc,startproc} All symlinks to proctools

Fork Verification

Build and tests were additionally verified using the dcasota/photon fork's 5.0 branch, confirming that the spec and patch files from the fork's SPECS/distrib-compat/ directory are identical to vmware/photon:5.0 and that the changes apply cleanly.

Reviewer Guidance

Suggested test scenarios for extended validation:

  1. COMM_LEN fix: Test checkproc / killproc with daemons whose binary names exceed 15 characters (e.g., NetworkManager, systemd-resolved, systemd-timesyncd)
  2. sig_forced: Verify killproc -SIGTERM /path/to/daemon does not escalate to SIGKILL
  3. Non-root: Run checkproc as a non-root user against a process owned by that user
  4. NFS: If applicable, test on systems with NFS-mounted /usr or /opt

Backport critical and robustness improvements from Werner Fink's
killproc v2.23 (https://github.com/bitstreamout/killproc):

High priority (correctness):
- COMM_LEN: fix process name truncation in swap_name() for names >15 chars
- sig_forced: prevent unwanted SIGKILL escalation on explicit -SIGTERM
- pipe2(): eliminate startproc fork/exec race condition with pipe-based sync

Medium priority (robustness):
- UID-based fallback: non-root users can check owned processes on EACCES
- expandpath(): avoid lstat() hangs on unresponsive NFS mounts
- O_CLOEXEC: prevent fd leak to child processes in isscript()
- atexit(undo_proc): auto-unmount /proc if mounted by the tool
- Fix uninitialized variable warning in waiton()

Tested: Photon OS 5.0, GCC 12.2.0 - zero errors, zero warnings.
Smoke tests pass (killproc -l, checkproc on running/missing binaries).

Signed-off-by: Daniel Casota <daniel@casota.ch>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant