From: Christian Goeschel Ndjomouo Date: Sun, 5 Apr 2026 02:15:04 +0000 (-0400) Subject: lib: (pidutils.c) allow zero and negative numbers for PIDs X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=938b0668fff01daf299713e29a9ecc1cc99875f4;p=thirdparty%2Futil-linux.git lib: (pidutils.c) allow zero and negative numbers for PIDs kill(1) and kill(2) man pages clearly state that 0 and negative numbers can be used. Therefore let us adapt the internal helper function ul_parse_pid_str() to permit this value range, as the previous behavior regressed the kill(1) PID parsing behavior. The uncommon value range can be controlled with two new flags UL_PID_ZERO and UL_PID_NEGATIVE, ORed together they will allow 0 and negative values down to INT_MIN. Otherwise they can be passed individually to only allow either. If 0 is passed only 1 upto INT_MAX values are allowed. Closes: #4194 Closes: #4195 Signed-off-by: Christian Goeschel Ndjomouo --- diff --git a/include/c.h b/include/c.h index 991048dbd..49616389b 100644 --- a/include/c.h +++ b/include/c.h @@ -652,6 +652,7 @@ static inline int fputsln(const char *s, FILE *stream) { #endif #define SINT_MAX(t) (((t)1 << (sizeof(t) * 8 - 2)) - (t)1 + ((t)1 << (sizeof(t) * 8 - 2))) +#define SINT_MIN(t) (-SINT_MAX(t) - (t)1) #define MAX_OF_UINT_TYPE(t) ~((t)0) #ifndef HAVE_REALLOCARRAY diff --git a/include/pidutils.h b/include/pidutils.h index 979ec0590..633dd049b 100644 --- a/include/pidutils.h +++ b/include/pidutils.h @@ -9,7 +9,10 @@ #include -extern int ul_parse_pid_str(char *pidstr, pid_t *pid_num, uint64_t *pfd_ino); -extern void ul_parse_pid_str_or_err(char *pidstr, pid_t *pid_num, uint64_t *pfd_ino); +#define UL_PID_ZERO (1 << 1) +#define UL_PID_NEGATIVE (1 << 2) + +extern int ul_parse_pid_str(char *pidstr, pid_t *pid_num, uint64_t *pfd_ino, int flags); +extern void ul_parse_pid_str_or_err(char *pidstr, pid_t *pid_num, uint64_t *pfd_ino, int flags); #endif /* UTIL_LINUX_PIDUTILS_H */ diff --git a/lib/pidutils.c b/lib/pidutils.c index e1a474d96..ea4156cfa 100644 --- a/lib/pidutils.c +++ b/lib/pidutils.c @@ -13,11 +13,14 @@ #include "pidutils.h" /* - * ul_parse_pid_str() - Parse a string and store the found pid and/or pidfd inode. + * ul_parse_pid_str() - Parse a string and store the found pid and pidfd inode. * - * @pidstr: string in format `pid:pidfd_inode` that is to be parsed - * @pid_num: stores pid number - * @pfd_ino: stores pidfd inode number + * @pidstr: string in format `pid[:pidfd_inode]` that is to be parsed + * @pid_num: stores pid number + * @pfd_ino: stores pidfd inode number + * @flags: uncommon values that are accepted as PIDs + * (e.g.: zero = UL_PID_ZERO, negative = UL_PID_NEGATIVE) + * the flag values can be ORed * * If @pfd_ino is not destined to be set, pass it as NULL. * @@ -25,7 +28,7 @@ * On failure, a negative errno number is returned * and errno is set to indicate the issue. */ -int ul_parse_pid_str(char *pidstr, pid_t *pid_num, uint64_t *pfd_ino) +int ul_parse_pid_str(char *pidstr, pid_t *pid_num, uint64_t *pfd_ino, int flags) { int rc; char *end = NULL; @@ -38,12 +41,18 @@ int ul_parse_pid_str(char *pidstr, pid_t *pid_num, uint64_t *pfd_ino) if (num == 0 && end == pidstr) return -(errno = EINVAL); - if (errno == ERANGE || (num <= 0 || num > SINT_MAX(pid_t))) + if (errno == ERANGE || num < SINT_MIN(pid_t) || num > SINT_MAX(pid_t)) + return -(errno = ERANGE); + + if (num == 0 && !(flags & UL_PID_ZERO)) + return -(errno = ERANGE); + + if (num < 0 && !(flags & UL_PID_NEGATIVE)) return -(errno = ERANGE); *pid_num = (pid_t) num; - if (*end == ':' && pfd_ino) { + if (*end == ':' && pfd_ino && num > 0) { rc = ul_strtou64(++end, pfd_ino, 10); if (rc < 0) return rc; @@ -65,14 +74,17 @@ int ul_parse_pid_str(char *pidstr, pid_t *pid_num, uint64_t *pfd_ino) * @pidstr: string in format `pid[:pidfd_inode]` that is to be parsed * @pid_num: stores pid number * @pfd_ino: stores pidfd inode number + * @flags: uncommon values that are accepted as PIDs + * (e.g.: zero = UL_PID_ZERO, negative = UL_PID_NEGATIVE) + * the flag values can be ORed * * If @pfd_ino is not destined to be set, pass it as NULL. * * On failure, err() is called with an error message to indicate the issue. */ -void ul_parse_pid_str_or_err(char *pidstr, pid_t *pid_num, uint64_t *pfd_ino) +void ul_parse_pid_str_or_err(char *pidstr, pid_t *pid_num, uint64_t *pfd_ino, int flags) { - if (ul_parse_pid_str(pidstr, pid_num, pfd_ino) < 0) { + if (ul_parse_pid_str(pidstr, pid_num, pfd_ino, flags) < 0) { err(EXIT_FAILURE, N_("failed to parse PID argument '%s'"), pidstr); } } diff --git a/misc-utils/getino.c b/misc-utils/getino.c index 161f2fe2e..22328c182 100644 --- a/misc-utils/getino.c +++ b/misc-utils/getino.c @@ -238,7 +238,7 @@ int main(int argc, char **argv) argv += optind - 1; while (*++argv) { - rc = ul_parse_pid_str(*argv, &ctx.pid, &ctx.pidfd_ino); + rc = ul_parse_pid_str(*argv, &ctx.pid, &ctx.pidfd_ino, 0); if (rc) err(EXIT_FAILURE, _("invalid PID argument '%s'"), *argv); print_inode(&ctx); diff --git a/misc-utils/kill.c b/misc-utils/kill.c index 4fe11d02b..dd6eab938 100644 --- a/misc-utils/kill.c +++ b/misc-utils/kill.c @@ -645,7 +645,7 @@ int main(int argc, char **argv) for ( ; (ctl.arg = *argv) != NULL; argv++) { errno = 0; - rc = ul_parse_pid_str(ctl.arg, &ctl.pid, &ctl.pidfd_ino); + rc = ul_parse_pid_str(ctl.arg, &ctl.pid, &ctl.pidfd_ino, UL_PID_ZERO | UL_PID_NEGATIVE); if(errno == 0 && rc == 0) { if (check_signal_handler(&ctl) <= 0) continue; diff --git a/misc-utils/waitpid.c b/misc-utils/waitpid.c index d77a41c5e..b89c54bc4 100644 --- a/misc-utils/waitpid.c +++ b/misc-utils/waitpid.c @@ -63,7 +63,7 @@ static void parse_pids_or_err(struct process_info *pinfos, size_t n_strings, cha { for (size_t i = 0; i < n_strings; i++) { struct process_info *pi = &pinfos[i]; - ul_parse_pid_str_or_err(strings[i], &pi->pid, &pi->pidfd_ino); + ul_parse_pid_str_or_err(strings[i], &pi->pid, &pi->pidfd_ino, 0); } } diff --git a/sys-utils/nsenter.c b/sys-utils/nsenter.c index 2bbfe79ce..0ddf8cd9f 100644 --- a/sys-utils/nsenter.c +++ b/sys-utils/nsenter.c @@ -579,7 +579,7 @@ static int parse_pid_str(char *pidstr, pid_t *ns_target_pid) int pfd = -1; uint64_t pidfd_ino = 0; - ul_parse_pid_str_or_err(pidstr, ns_target_pid, &pidfd_ino); + ul_parse_pid_str_or_err(pidstr, ns_target_pid, &pidfd_ino, 0); if (pidfd_ino) pfd = ul_get_valid_pidfd_or_err(*ns_target_pid, pidfd_ino); return pfd; diff --git a/sys-utils/prlimit.c b/sys-utils/prlimit.c index 8d118a8f5..b92db2c3f 100644 --- a/sys-utils/prlimit.c +++ b/sys-utils/prlimit.c @@ -519,7 +519,7 @@ static int parse_pid_str(char *pidstr, pid_t *pidnum) int pfd = -1; uint64_t pidfd_ino = 0; - ul_parse_pid_str_or_err(pidstr, pidnum, &pidfd_ino); + ul_parse_pid_str_or_err(pidstr, pidnum, &pidfd_ino, 0); if (pidfd_ino) pfd = ul_get_valid_pidfd_or_err(*pidnum, pidfd_ino);