From fd0c8c5101ab3db637db0da45cc8e1f72f65e8c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Poho=C5=99elsk=C3=BD?= Date: Fri, 11 Apr 2025 11:01:16 +0200 Subject: [PATCH] Fix range parsing Adds patch from this PR: https://github.com/cronie-crond/cronie/pull/200 And additional support patches from this PR: https://github.com/cronie-crond/cronie/pull/154 Also adds `-n option: wait on finnishing grandchild process`, to sync the behaviour of cronie in c9s and c10s: https://gitlab.com/redhat/centos-stream/rpms/cronie/-/merge_requests/16 Resolves: RHEL-82795 --- cronie.spec | 22 +++++- fix-range-parsing.patch | 26 +++++++ n_option_wait_on_finnish.patch | 25 ++++++ rename-variables-in-get_range.patch | 117 ++++++++++++++++++++++++++++ set-size-out-of-bounds.patch | 26 +++++++ 5 files changed, 214 insertions(+), 2 deletions(-) create mode 100644 fix-range-parsing.patch create mode 100644 n_option_wait_on_finnish.patch create mode 100644 rename-variables-in-get_range.patch create mode 100644 set-size-out-of-bounds.patch diff --git a/cronie.spec b/cronie.spec index c8c3c09..6273b32 100644 --- a/cronie.spec +++ b/cronie.spec @@ -6,7 +6,7 @@ Summary: Cron daemon for executing programs at set times Name: cronie Version: 1.5.7 -Release: 13%{?dist} +Release: 14%{?dist} License: MIT and BSD and ISC and GPLv2+ URL: https://github.com/cronie-crond/cronie Source0: https://github.com/cronie-crond/cronie/releases/download/cronie-%{version}/cronie-%{version}.tar.gz @@ -17,15 +17,27 @@ Patch: 0002-Add-random-within-range-operator.patch Patch: 0003-get_number-Add-missing-NUL-termination-for-the-scann.patch Patch: 0004-Fix-regression-in-handling-x-crontab-entries.patch Patch: 0005-Fix-regression-in-handling-1-5-crontab-entries.patch + # Add support for `-n` option in crontab entries # https://github.com/cronie-crond/cronie/commit/ce7d5bf0a43d147f8502e6424cd523b56adf5599 Patch: n_option.patch +# -n option: wait on finnishing grandchild process +# https://github.com/cronie-crond/cronie/commit/5cf85f8cbb816ff1df5b317d6f8559b67e1993dd +Patch: n_option_wait_on_finnish.patch # Optimization to close fds from /proc/self/fd in case of high nofile limit after fork # https://github.com/cronie-crond/cronie/commit/e3682c7135b9176b60d226c60ee4e78cf1ab711b Patch: optimization_to_close_fds.patch # Increase the maximum number of crontab entries # https://github.com/cronie-crond/cronie/pull/92/commits/36bb94cceda71c83ca01be22a959d8bf3e59b37b Patch: increase_max_crontabs.patch +# Rename variables in get_range() +# Step size out fo bound handling +# https://github.com/cronie-crond/cronie/pull/154 +Patch: rename-variables-in-get_range.patch +Patch: set-size-out-of-bounds.patch +# Fix range parsing +# https://github.com/cronie-crond/cronie/pull/200 +Patch: fix-range-parsing.patch Requires: dailyjobs @@ -43,7 +55,7 @@ Buildrequires: audit-libs-devel >= 1.4.1 BuildRequires: gcc BuildRequires: systemd -BuildRequires: make +BuildRequires: make Obsoletes: %{name}-sysvinit Requires(post): coreutils sed @@ -220,6 +232,12 @@ exit 0 %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/cron.d/dailyjobs %changelog +* Fri Apr 11 2025 Ondřej Pohořelský - 1.5.7-14 +- Rename variables in get_range() +- Step size out fo bound handling +- Fix range parsing +- Resolves: RHEL-82795 + * Wed Dec 11 2024 Ondřej Pohořelský - 1.5.7-13 - Create anacron timestamp files with correct permissions - Resolves: RHEL-5376 diff --git a/fix-range-parsing.patch b/fix-range-parsing.patch new file mode 100644 index 0000000..81e07c5 --- /dev/null +++ b/fix-range-parsing.patch @@ -0,0 +1,26 @@ +From d037042129eacdd9d7760d74437842ee5a2d116e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Poho=C5=99elsk=C3=BD?= +Date: Tue, 11 Mar 2025 15:12:38 +0100 +Subject: [PATCH] get_range() fix range parsing for Sunday as 0 or 7 + +In fc8b0e5, we changed how the ranges are parsed. This created a +regression for parsing Sunday at the end of the range. This commit adds +the logic to correctly handle Sunday as the end of the range. +--- + src/entry.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/entry.c b/src/entry.c +index a2077e8..30bedb3 100644 +--- a/src/entry.c ++++ b/src/entry.c +@@ -642,6 +642,9 @@ get_range(bitstr_t * bits, int low, int high, const char *names[], + state = R_FINISH; + break; + } ++ if (low_ > high_ && high_ == 0) { ++ high_ = 7; ++ } + return (EOF); + + case R_RANDOM: diff --git a/n_option_wait_on_finnish.patch b/n_option_wait_on_finnish.patch new file mode 100644 index 0000000..b01c6f5 --- /dev/null +++ b/n_option_wait_on_finnish.patch @@ -0,0 +1,25 @@ +From 5cf85f8cbb816ff1df5b317d6f8559b67e1993dd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Poho=C5=99elsk=C3=BD?= +Date: Wed, 25 Oct 2023 10:58:46 +0200 +Subject: [PATCH] -n option: wait on finnishing grandchild process + +With `WNOHANG` we skip sending the email when waitpid() returns 0, +which happens if the process is still running. Instead, using `0` +parameter will wait for the process to actually stop running. +--- + src/do_command.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/do_command.c b/src/do_command.c +index d7ca840..2ada913 100644 +--- a/src/do_command.c ++++ b/src/do_command.c +@@ -579,7 +579,7 @@ static int child_process(entry * e, char **jobenv) { + if (mail && e->flags & MAIL_WHEN_ERR) { + int jobstatus = -1; + if (jobpid > 0) { +- while (waitpid(jobpid, &jobstatus, WNOHANG) == -1) { ++ while (waitpid(jobpid, &jobstatus, 0) == -1) { + if (errno == EINTR) continue; + log_it("CRON", getpid(), "error", "invalid job pid", errno); + break; diff --git a/rename-variables-in-get_range.patch b/rename-variables-in-get_range.patch new file mode 100644 index 0000000..a52757a --- /dev/null +++ b/rename-variables-in-get_range.patch @@ -0,0 +1,117 @@ +From 023c03333d184b0c2feb9b703db5af242f58a578 Mon Sep 17 00:00:00 2001 +From: Alexander Schwinn +Date: Thu, 28 Sep 2023 08:08:01 +0200 +Subject: [PATCH] Rename variables in 'get_range' to make code more readable + +--- + src/entry.c | 32 ++++++++++++++++---------------- + 1 file changed, 16 insertions(+), 16 deletions(-) + +diff --git a/src/entry.c b/src/entry.c +index 9f6d72b..388bca8 100644 +--- a/src/entry.c ++++ b/src/entry.c +@@ -554,29 +554,29 @@ get_range(bitstr_t * bits, int low, int high, const char *names[], + * | [number] "~" [number] + */ + +- int ch, i, num1, num2, num3; ++ int ch, i, low_, high_, step; + + /* default value for step + */ +- num3 = 1; ++ step = 1; + range_state_t state = R_START; + + while (state != R_FINISH && ((ch = get_char(file)) != EOF)) { + switch (state) { + case R_START: + if (ch == '*') { +- num1 = low; +- num2 = high; ++ low_ = low; ++ high_ = high; + state = R_AST; + break; + } + if (ch == '~') { +- num1 = low; ++ low_ = low; + state = R_RANDOM; + break; + } + unget_char(ch, file); +- if (get_number(&num1, low, names, file) != EOF) { ++ if (get_number(&low_, low, names, file) != EOF) { + state = R_NUM1; + break; + } +@@ -595,8 +595,8 @@ get_range(bitstr_t * bits, int low, int high, const char *names[], + + case R_STEP: + unget_char(ch, file); +- if (get_number(&num3, 0, PPC_NULL, file) != EOF +- && num3 != 0) { ++ if (get_number(&step, 0, PPC_NULL, file) != EOF ++ && step != 0) { + state = R_TERMS; + break; + } +@@ -619,7 +619,7 @@ get_range(bitstr_t * bits, int low, int high, const char *names[], + break; + } + if (is_separator(ch)) { +- num2 = num1; ++ high_ = low_; + state = R_FINISH; + break; + } +@@ -627,7 +627,7 @@ get_range(bitstr_t * bits, int low, int high, const char *names[], + + case R_RANGE: + unget_char(ch, file); +- if (get_number(&num2, low, names, file) != EOF) { ++ if (get_number(&high_, low, names, file) != EOF) { + state = R_RANGE_NUM2; + break; + } +@@ -646,11 +646,11 @@ get_range(bitstr_t * bits, int low, int high, const char *names[], + + case R_RANDOM: + if (is_separator(ch)) { +- num2 = high; ++ high_ = high; + state = R_FINISH; + } + else if (unget_char(ch, file), +- get_number(&num2, low, names, file) != EOF) { ++ get_number(&high_, low, names, file) != EOF) { + state = R_TERMS; + } + /* fail if couldn't find match on previous term +@@ -659,12 +659,12 @@ get_range(bitstr_t * bits, int low, int high, const char *names[], + return (EOF); + + /* if invalid random range was selected */ +- if (num1 > num2) ++ if (low_ > high_) + return (EOF); + +- /* select random number in range ++ /* select random number in range + */ +- num1 = num2 = random() % (num2 - num1 + 1) + num1; ++ low_ = high_ = random() % (high_ - low_ + 1) + low_; + break; + + +@@ -677,7 +677,7 @@ get_range(bitstr_t * bits, int low, int high, const char *names[], + if (state != R_FINISH || ch == EOF) + return (EOF); + +- for (i = num1; i <= num2; i += num3) ++ for (i = low_; i <= high_; i += step) + if (EOF == set_element(bits, low, high, i)) { + unget_char(ch, file); + return (EOF); diff --git a/set-size-out-of-bounds.patch b/set-size-out-of-bounds.patch new file mode 100644 index 0000000..d375297 --- /dev/null +++ b/set-size-out-of-bounds.patch @@ -0,0 +1,26 @@ +From d6bb0384975ac179bca7b9d8c5a967880d73415e Mon Sep 17 00:00:00 2001 +From: Alexander Schwinn +Date: Thu, 28 Sep 2023 08:25:05 +0200 +Subject: [PATCH] Show error when step size is out of bound + +--- + src/entry.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/entry.c b/src/entry.c +index 388bca8..586eb9d 100644 +--- a/src/entry.c ++++ b/src/entry.c +@@ -677,6 +677,12 @@ get_range(bitstr_t * bits, int low, int high, const char *names[], + if (state != R_FINISH || ch == EOF) + return (EOF); + ++ /* Make sure the step size makes any sense */ ++ if (step > 1 && step > (high_ - low_)) { ++ int max = high_ - low_ > 0 ? high_ - low_ : 1; ++ fprintf(stderr, "Warning: Step size %i higher than possible maximum of %i\n", step, max); ++ } ++ + for (i = low_; i <= high_; i += step) + if (EOF == set_element(bits, low, high, i)) { + unget_char(ch, file);