diff --git a/SOURCES/0009-logrotate-3.18.0-add-documentation-for-state-dev-null-special-case.patch b/SOURCES/0009-logrotate-3.18.0-add-documentation-for-state-dev-null-special-case.patch new file mode 100644 index 0000000..0a25d62 --- /dev/null +++ b/SOURCES/0009-logrotate-3.18.0-add-documentation-for-state-dev-null-special-case.patch @@ -0,0 +1,30 @@ +From 4ad3d9c362ecd72dd733338d36dde740e5363857 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Posp=C3=AD=C5=A1ek?= + +Date: Thu, 3 Jun 2021 10:37:47 +0200 +Subject: [PATCH 1/2] add documentation for --state /dev/null special case + +This is documentation for the suggested implementation of #395 aka `--state /dev/null` will not write any state file. + +Closes: https://github.com/logrotate/logrotate/pull/396 +(cherry picked from commit ecccf4778695dc5cb3c25bfd13e7a0ab9dc50ec4) +--- + logrotate.8.in | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/logrotate.8.in b/logrotate.8.in +index e0a3ed8..bde2a0e 100644 +--- a/logrotate.8.in ++++ b/logrotate.8.in +@@ -75,6 +75,8 @@ if \fBlogrotate\fR is being run as a different user for various sets of + log files. To prevent parallel execution \fBlogrotate\fR by default + acquires a lock on the state file, if it cannot be acquired \fBlogrotate\fR + will exit with value 3. The default state file is \fI@STATE_FILE_PATH@\fR. ++If \fI/dev/null\fR is given as the state file, then \fBlogrotate\fR will ++not try to write the state file. + + .TP + \fB\-\-skip-state-lock\fR +-- +2.49.0 + diff --git a/SOURCES/0010-logrotate-3.18.0-Do-not-lock-state-file-dev-null.patch b/SOURCES/0010-logrotate-3.18.0-Do-not-lock-state-file-dev-null.patch new file mode 100644 index 0000000..fbe8262 --- /dev/null +++ b/SOURCES/0010-logrotate-3.18.0-Do-not-lock-state-file-dev-null.patch @@ -0,0 +1,52 @@ +From 887287f6b7e7e6bd991d262d71436237617ab696 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Mon, 17 Jan 2022 17:39:08 +0100 +Subject: [PATCH 2/2] Do not lock state file /dev/null + +state file is desired. +lockState() tries to open and lock the state file to avoid issues with +concurrent instances, see #295. +Locking the character file /dev/null might either be not supported, e.g. +on Debian GNU/Hurd (hurd-i386), nor not allowed, e.g. by SELinux. + +(cherry picked from commit c7078c2b393fce376d79317a9a03de8b8e404cde) +--- + logrotate.8.in | 2 +- + logrotate.c | 8 +++++++- + 2 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/logrotate.8.in b/logrotate.8.in +index bde2a0e..c0ac5c4 100644 +--- a/logrotate.8.in ++++ b/logrotate.8.in +@@ -76,7 +76,7 @@ log files. To prevent parallel execution \fBlogrotate\fR by default + acquires a lock on the state file, if it cannot be acquired \fBlogrotate\fR + will exit with value 3. The default state file is \fI@STATE_FILE_PATH@\fR. + If \fI/dev/null\fR is given as the state file, then \fBlogrotate\fR will +-not try to write the state file. ++not try to lock or write the state file. + + .TP + \fB\-\-skip-state-lock\fR +diff --git a/logrotate.c b/logrotate.c +index 819aaed..1bb95b2 100644 +--- a/logrotate.c ++++ b/logrotate.c +@@ -2906,7 +2906,13 @@ static int readState(const char *stateFilename) + static int lockState(const char *stateFilename, int skip_state_lock) + { + struct stat sb; +- int lockFd = open(stateFilename, O_RDWR | O_CLOEXEC); ++ int lockFd; ++ ++ if (!strcmp(stateFilename, "/dev/null")) { ++ return 0; ++ } ++ ++ lockFd = open(stateFilename, O_RDWR | O_CLOEXEC); + if (lockFd == -1) { + if (errno == ENOENT) { + message(MESS_DEBUG, "Creating stub state file: %s\n", +-- +2.49.0 + diff --git a/SOURCES/0011-logrotate-3.18.0-Log-all-glob-errors-in-debug-mode.patch b/SOURCES/0011-logrotate-3.18.0-Log-all-glob-errors-in-debug-mode.patch new file mode 100644 index 0000000..4e0a559 --- /dev/null +++ b/SOURCES/0011-logrotate-3.18.0-Log-all-glob-errors-in-debug-mode.patch @@ -0,0 +1,38 @@ +From 5bbd4c6f55b8ce61953803d05e091897d26a2e7c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Wed, 12 Jul 2023 21:47:45 +0200 +Subject: [PATCH 1/6] Log all glob errors in debug mode + +In case glob(3) returns GLOB_ABORTED always log the error message in +debug mode, since it might be overridden by a further pattern from the +same file statement. + +Also log an OOM message if asprintf(3) fails. + +Reported-by: blu3sh0rk +(cherry picked from commit 7d6ecd67e2c2ab99e26693a0347a2361d11c51e1) +--- + config.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/config.c b/config.c +index e76fad0..96f34f8 100644 +--- a/config.c ++++ b/config.c +@@ -1794,8 +1794,12 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig) + * set, so store the error message for later. */ + rc = asprintf(&globerr_msg, "%s:%d glob failed for %s: %s\n", + configFile, lineNum, argv[argNum], strerror(glob_errno)); +- if (rc == -1) ++ if (rc == -1) { ++ message_OOM(); + globerr_msg = NULL; ++ } else { ++ message(MESS_DEBUG, "%s", globerr_msg); ++ } + + globResult.gl_pathc = 0; + } +-- +2.49.0 + diff --git a/SOURCES/0012-logrotate-3.18.0-Handle-glob-aborts-for-initial-pattern.patch b/SOURCES/0012-logrotate-3.18.0-Handle-glob-aborts-for-initial-pattern.patch new file mode 100644 index 0000000..914520d --- /dev/null +++ b/SOURCES/0012-logrotate-3.18.0-Handle-glob-aborts-for-initial-pattern.patch @@ -0,0 +1,40 @@ +From ff9b66a455b890f86d38dbb772e295fa183733e4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Wed, 12 Jul 2023 21:47:52 +0200 +Subject: [PATCH 2/6] Handle glob aborts for initial pattern + +In case glob(3) fails with GLOB_ABORTED, e.g. due to missing file +permissions, the number of path matches gets set to 0. If the number of +path matches is 0 and there have been no other files matched yet the +following realloc(3) call will be called with a size of 0, free'ing the +array. Since the array gets only assigned to the realloc(3) result in +the non NULL case, the free'd array pointer is retained and any further +access, e.g. by a future glob result, will result in a use-after-free. + +Reported-by: blu3sh0rk +(cherry picked from commit f444a9858e306c94db37f9d7ddbae817530e949e) +--- + config.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/config.c b/config.c +index 96f34f8..33e283c 100644 +--- a/config.c ++++ b/config.c +@@ -1804,6 +1804,13 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig) + globResult.gl_pathc = 0; + } + ++ if (globResult.gl_pathc == 0) { ++ message(MESS_DEBUG, "%s:%d no matches for glob '%s', skipping\n", ++ configFile, lineNum, argv[argNum]); ++ globfree(&globResult); ++ continue; ++ } ++ + tmp = realloc(newlog->files, + sizeof(*newlog->files) * (newlog->numFiles + + globResult. +-- +2.49.0 + diff --git a/SOURCES/0013-logrotate-3.18.0-Handle-non-NUL-terminated-config-files.patch b/SOURCES/0013-logrotate-3.18.0-Handle-non-NUL-terminated-config-files.patch new file mode 100644 index 0000000..195e517 --- /dev/null +++ b/SOURCES/0013-logrotate-3.18.0-Handle-non-NUL-terminated-config-files.patch @@ -0,0 +1,145 @@ +From dd1562ebb0a205f8d47ff85b66a6d5b4e7a9e113 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Wed, 12 Jul 2023 21:47:54 +0200 +Subject: [PATCH 3/6] Handle non NUL terminated config files + +Avoid calling strndup(3) on pointers of the mapped config file in case +the memory is not NUL terminated. + +Validate the current buffer location before dereferencing it if it might +have been advanced after the check in the loop condition. + +Reported-by: blu3sh0rk +(cherry picked from commit 39735f94bed266af08c047aa021d34682ff47433) +--- + config.c | 35 +++++++++++++++++++++++++---------- + 1 file changed, 25 insertions(+), 10 deletions(-) + +diff --git a/config.c b/config.c +index 33e283c..38ef0b0 100644 +--- a/config.c ++++ b/config.c +@@ -159,6 +159,7 @@ static char *isolateLine(char **strt, char **buf, size_t length) { + char *endtag, *start, *tmp; + const char *max = *buf + length; + char *key; ++ size_t llen; + + start = *strt; + endtag = start; +@@ -167,13 +168,19 @@ static char *isolateLine(char **strt, char **buf, size_t length) { + if (max < endtag) + return NULL; + tmp = endtag - 1; +- while (isspace((unsigned char)*endtag)) ++ while (endtag >= start && endtag < max && isspace((unsigned char)*endtag)) + endtag--; +- key = strndup(start, (size_t)(endtag - start + 1)); ++ llen = (size_t)(endtag - start + 1); ++ if (start + llen > max) ++ llen = (size_t)(max - start); ++ /* Avoid strndup(3) since the buffer might not be NUL-terminated. */ ++ key = malloc(llen + 1); + if (key == NULL) { + message_OOM(); + return NULL; + } ++ memcpy(key, start, llen); ++ key[llen] = '\0'; + *strt = tmp; + return key; + } +@@ -182,7 +189,7 @@ static char *isolateValue(const char *fileName, int lineNum, const char *key, + char **startPtr, char **buf, size_t length) + { + char *chptr = *startPtr; +- const char *max = *startPtr + length; ++ const char *max = *buf + length; + + while (chptr < max && isblank((unsigned char)*chptr)) + chptr++; +@@ -206,6 +213,8 @@ static char *isolateWord(char **strt, char **buf, size_t length) { + char *endtag, *start; + const char *max = *buf + length; + char *key; ++ size_t wlen; ++ + start = *strt; + while (start < max && isblank((unsigned char)*start)) + start++; +@@ -214,11 +223,15 @@ static char *isolateWord(char **strt, char **buf, size_t length) { + endtag++;} + if (max < endtag) + return NULL; +- key = strndup(start, (size_t)(endtag - start)); ++ wlen = (size_t)(endtag - start); ++ /* Avoid strndup(3) since the buffer might not be NUL-terminated. */ ++ key = malloc(wlen + 1); + if (key == NULL) { + message_OOM(); + return NULL; + } ++ memcpy(key, start, wlen); ++ key[wlen] = '\0'; + *strt = endtag; + return key; + } +@@ -1091,7 +1104,9 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig) + configFile, lineNum); + RAISE_ERROR(); + } +- if (!isspace((unsigned char)*start) && *start != '=') { ++ if (start < buf + length && ++ !isspace((unsigned char)*start) && ++ *start != '=') { + message(MESS_ERROR, "%s:%d keyword '%s' not properly" + " separated, found %#x\n", + configFile, lineNum, key, *start); +@@ -1709,7 +1724,7 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig) + } else { + message(MESS_ERROR, "%s:%d unknown option '%s' " + "-- ignoring line\n", configFile, lineNum, key); +- if (*start != '\n') ++ if (start < buf + length && *start != '\n') + state = STATE_SKIP_LINE; + } + } else if (*start == '/' || *start == '"' || *start == '\'' +@@ -2048,7 +2063,7 @@ duperror: + } + else { + const char *endtag = start - 9; +- while (*endtag != '\n') ++ while (endtag > scriptStart && *endtag != '\n') + endtag--; + endtag++; + *scriptDest = strndup(scriptStart, (size_t)(endtag - scriptStart)); +@@ -2063,7 +2078,7 @@ duperror: + state = (state & STATE_SKIP_CONFIG) ? STATE_SKIP_CONFIG : STATE_DEFAULT; + } + else { +- state = (*start == '\n' ? 0 : STATE_SKIP_LINE) | ++ state = (start < buf + length && *start == '\n' ? 0 : STATE_SKIP_LINE) | + STATE_LOAD_SCRIPT | + ((state & STATE_SKIP_CONFIG) ? STATE_SKIP_CONFIG : 0); + } +@@ -2103,7 +2118,7 @@ duperror: + * pointer is increased by one and, after this, + * "start" points to the beginning of the next line. + */ +- if (*start != '\n') { ++ if (start < buf + length && *start != '\n') { + state = STATE_SKIP_LINE | STATE_SKIP_CONFIG; + } + } +@@ -2114,7 +2129,7 @@ duperror: + "%s: %d: readConfigFile() unknown state\n", + configFile, lineNum); + } +- if (*start == '\n') { ++ if (start < buf + length && *start == '\n') { + lineNum++; + } + +-- +2.49.0 + diff --git a/SOURCES/0014-logrotate-3.18.0-Limit-glob-length-to-avoid-stack-overflow-in-glob-3.patch b/SOURCES/0014-logrotate-3.18.0-Limit-glob-length-to-avoid-stack-overflow-in-glob-3.patch new file mode 100644 index 0000000..428a082 --- /dev/null +++ b/SOURCES/0014-logrotate-3.18.0-Limit-glob-length-to-avoid-stack-overflow-in-glob-3.patch @@ -0,0 +1,43 @@ +From f9a14b026c5c771a0bc89e204f96d7ca4d112db6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Wed, 12 Jul 2023 21:47:56 +0200 +Subject: [PATCH 4/6] Limit glob length to avoid stack overflow in glob(3) + +Limit the supported length of glob pattern to 2048 to avoid stack +overflows inside glob(3) due to recursion. + +Reported-by: blu3sh0rk +(cherry picked from commit 0271501ae37b1455b98abc00b9bb77096610462b) +--- + config.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/config.c b/config.c +index 38ef0b0..b213b38 100644 +--- a/config.c ++++ b/config.c +@@ -1787,6 +1787,7 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig) + newlog->numFiles = 0; + for (argNum = 0; argNum < argc; argNum++) { + char **tmp; ++ size_t argLen = strlen(argv[argNum]); + int rc; + glob_t globResult; + +@@ -1795,6 +1796,13 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig) + globerr_msg = NULL; + } + ++ if (argLen > 2048) { ++ message(MESS_ERROR, "%s:%d glob too long (%zu > 2048)\n", ++ configFile, lineNum, argLen); ++ logerror = 1; ++ continue; ++ } ++ + rc = glob(argv[argNum], GLOB_NOCHECK + #ifdef GLOB_TILDE + | GLOB_TILDE +-- +2.49.0 + diff --git a/SOURCES/0015-logrotate-3.18.0-Avoid-date-format-overflow-issues.patch b/SOURCES/0015-logrotate-3.18.0-Avoid-date-format-overflow-issues.patch new file mode 100644 index 0000000..3eee414 --- /dev/null +++ b/SOURCES/0015-logrotate-3.18.0-Avoid-date-format-overflow-issues.patch @@ -0,0 +1,110 @@ +From 153ab5af4e48e4cf29a26eec8d0a3fe478c1cc43 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Wed, 12 Jul 2023 21:47:59 +0200 +Subject: [PATCH 5/6] Avoid date format overflow issues + +Prevent overflows on the date format string array. + +Exit early on date format string conversion failures to avoid operating +on wrong files or missing some out. + +Reported-by: blu3sh0rk +(cherry picked from commit 1b45002788b2838fdff32da34a2370f519f7eb51) +--- + logrotate.c | 33 ++++++++++++++++++++------------- + 1 file changed, 20 insertions(+), 13 deletions(-) + +diff --git a/logrotate.c b/logrotate.c +index 1bb95b2..b0f8332 100644 +--- a/logrotate.c ++++ b/logrotate.c +@@ -1542,6 +1542,8 @@ static int prerotateSingleLog(const struct logInfo *log, unsigned logNum, + char dext_str[DATEEXT_LEN]; + char dformat[PATTERN_LEN] = ""; + char dext_pattern[PATTERN_LEN]; ++ const char *final_dformat; ++ size_t ret; + + if (!state->doRotate) + return 0; +@@ -1661,19 +1663,19 @@ static int prerotateSingleLog(const struct logInfo *log, unsigned logNum, + /* Construct the glob pattern corresponding to the date format */ + dext_str[0] = '\0'; + if (log->dateformat) { +- char *dext; ++ const char *dext = log->dateformat; + size_t i = 0, j = 0; ++ + memset(dext_pattern, 0, sizeof(dext_pattern)); +- dext = log->dateformat; + while (*dext == ' ') + dext++; +- while ((*dext != '\0') && (!hasErrors)) { ++ while (*dext != '\0') { + /* Will there be a space for a char and '\0'? */ +- if (j >= (sizeof(dext_pattern) - 1)) { ++ if (j >= (sizeof(dext_pattern) - 1) || ++ i >= (sizeof(dformat) - 1)) { + message(MESS_ERROR, "Date format %s is too long\n", + log->dateformat); +- hasErrors = 1; +- break; ++ return 1; + } + if (*dext == '%') { + switch (*(dext + 1)) { +@@ -1694,8 +1696,7 @@ static int prerotateSingleLog(const struct logInfo *log, unsigned logNum, + if (j >= (sizeof(dext_pattern) - 1)) { + message(MESS_ERROR, "Date format %s is too long\n", + log->dateformat); +- hasErrors = 1; +- break; ++ return 1; + } + dformat[i++] = *(dext++); + dformat[i] = *dext; +@@ -1709,8 +1710,7 @@ static int prerotateSingleLog(const struct logInfo *log, unsigned logNum, + if (j >= (sizeof(dext_pattern) - 1)) { + message(MESS_ERROR, "Date format %s is too long\n", + log->dateformat); +- hasErrors = 1; +- break; ++ return 1; + } + dformat[i++] = *(dext++); + dformat[i] = *dext; +@@ -1730,21 +1730,28 @@ static int prerotateSingleLog(const struct logInfo *log, unsigned logNum, + } + dformat[i] = '\0'; + message(MESS_DEBUG, "Converted '%s' -> '%s'\n", log->dateformat, dformat); +- strftime(dext_str, sizeof(dext_str), dformat, &now); ++ final_dformat = dformat; + } else { + if (log->criterium == ROT_HOURLY) { + /* hourly adds another two digits */ +- strftime(dext_str, sizeof(dext_str), "-%Y%m%d%H", &now); ++ final_dformat = "-%Y%m%d%H"; + strncpy(dext_pattern, "-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]", + sizeof(dext_pattern)); + } else { + /* The default dateformat and glob pattern */ +- strftime(dext_str, sizeof(dext_str), "-%Y%m%d", &now); ++ final_dformat = "-%Y%m%d"; + strncpy(dext_pattern, "-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]", + sizeof(dext_pattern)); + } + dext_pattern[PATTERN_LEN - 1] = '\0'; + } ++ ++ ret = strftime(dext_str, sizeof(dext_str), final_dformat, &now); ++ if (ret == 0) { ++ message(MESS_ERROR, "failed to apply date format '%s'\n", final_dformat); ++ return 1; ++ } ++ + message(MESS_DEBUG, "dateext suffix '%s'\n", dext_str); + message(MESS_DEBUG, "glob pattern '%s'\n", dext_pattern); + +-- +2.49.0 + diff --git a/SOURCES/0016-logrotate-3.18.0-Use-strnlen-in-private-strndup-implementation.patch b/SOURCES/0016-logrotate-3.18.0-Use-strnlen-in-private-strndup-implementation.patch new file mode 100644 index 0000000..782ba28 --- /dev/null +++ b/SOURCES/0016-logrotate-3.18.0-Use-strnlen-in-private-strndup-implementation.patch @@ -0,0 +1,49 @@ +From 83f251b7537cb5da1fb5fa12bee68f22643420dd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= +Date: Thu, 27 Jul 2023 17:42:36 +0200 +Subject: [PATCH 6/6] Use strnlen() in private strndup() implementation + +strndup() might be called on non NUL terminated buffers, thus use +strnlen(). + +Since for this code to be active strndup() has not to be supported by +the standard C library of the system, use a private version of strnlen() +as well. + +(cherry picked from commit 21c614410abe68c894804d0efbae730cb87c14bb) +--- + config.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/config.c b/config.c +index b213b38..2eddcec 100644 +--- a/config.c ++++ b/config.c +@@ -80,15 +80,20 @@ int asprintf(char **string_ptr, const char *format, ...) + #endif + + #if !defined(HAVE_STRNDUP) ++static size_t logr__strnlen(const char *s, size_t n) ++{ ++ const char *p; ++ ++ p = memchr(s, '\0', n); ++ return p ? (size_t)(p - s) : n; ++} ++ + char *strndup(const char *s, size_t n) + { + size_t nAvail; + char *p; + +- /* min() */ +- nAvail = strlen(s) + 1; +- if ( (n + 1) < nAvail) +- nAvail = n + 1; ++ nAvail = logr__strnlen(s, n) + 1; + + p = malloc(nAvail); + if (!p) +-- +2.49.0 + diff --git a/SOURCES/0017-logrotate-3.18.0-writeState-do-nothing-if-state-file-is-dev-null.patch b/SOURCES/0017-logrotate-3.18.0-writeState-do-nothing-if-state-file-is-dev-null.patch new file mode 100644 index 0000000..f25d25a --- /dev/null +++ b/SOURCES/0017-logrotate-3.18.0-writeState-do-nothing-if-state-file-is-dev-null.patch @@ -0,0 +1,80 @@ +From d8e171f36aab41182c2cf52d9a33ba478f090490 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Thu, 3 Jun 2021 10:51:07 +0200 +Subject: [PATCH] writeState: do nothing if state file is /dev/null + +If users do not want to use any state file, they can specify `/dev/null` +as the state file. Without this fix, logrotate would unnecessarily fail +to rename a temporary file to `/dev/null`. + +Fixes: https://github.com/logrotate/logrotate/issues/395 +(cherry picked from commit 456692644cbf5adb6253cb7ed2d169e950a9e348) +--- + logrotate.c | 4 ++++ + test/Makefile.am | 1 + + test/test-0089.sh | 14 ++++++++++++++ + test/test-config.89.in | 4 ++++ + 4 files changed, 23 insertions(+) + create mode 100755 test/test-0089.sh + create mode 100644 test/test-config.89.in + +diff --git a/logrotate.c b/logrotate.c +index b0f8332..df0eb22 100644 +--- a/logrotate.c ++++ b/logrotate.c +@@ -2507,6 +2507,10 @@ static int writeState(const char *stateFilename) + char *prevCtx; + int force_mode = 0; + ++ if (!strcmp(stateFilename, "/dev/null")) ++ /* explicitly asked not to write the state file */ ++ return 0; ++ + localtime_r(&nowSecs, &now); + + tmpFilename = malloc(strlen(stateFilename) + 5 ); +diff --git a/test/Makefile.am b/test/Makefile.am +index 69a5e45..27c3900 100644 +--- a/test/Makefile.am ++++ b/test/Makefile.am +@@ -87,6 +87,7 @@ TEST_CASES = \ + test-0086.sh \ + test-0087.sh \ + test-0088.sh \ ++ test-0089.sh \ + test-0092.sh \ + test-0100.sh \ + test-0101.sh \ +diff --git a/test/test-0089.sh b/test/test-0089.sh +new file mode 100755 +index 0000000..c586690 +--- /dev/null ++++ b/test/test-0089.sh +@@ -0,0 +1,14 @@ ++#!/bin/sh ++ ++. ./test-common.sh ++ ++# skip the test if /dev/null is not readable ++test -r /dev/null || exit 77 ++ ++# we don't want any stuff left from previous runs ++cleanup 89 ++ ++# ------------------------------- Test 89 ------------------------------------ ++# using /dev/null as state file tells logrotate not to write the state file ++preptest test.log 89 2 ++$RLR --state /dev/null test-config.89 +diff --git a/test/test-config.89.in b/test/test-config.89.in +new file mode 100644 +index 0000000..ec41c37 +--- /dev/null ++++ b/test/test-config.89.in +@@ -0,0 +1,4 @@ ++&DIR&/test.log { ++ daily ++ rotate 2 ++} +-- +2.49.0 + diff --git a/SPECS/logrotate.spec b/SPECS/logrotate.spec index d09f857..e76d3a8 100644 --- a/SPECS/logrotate.spec +++ b/SPECS/logrotate.spec @@ -1,7 +1,7 @@ Summary: Rotates, compresses, removes and mails system log files Name: logrotate Version: 3.18.0 -Release: 9%{?dist} +Release: 12%{?dist} License: GPLv2+ URL: https://github.com/logrotate/logrotate Source0: https://github.com/logrotate/logrotate/releases/download/%{version}/logrotate-%{version}.tar.xz @@ -27,6 +27,19 @@ Patch: 0006-logrotate-3.18.0-Ensure-the-type-for-configuration-flags-is-wide-e Patch: 0007-logrotate-3.18.0-config-introduce-ignoreduplicates-configuration-dire.patch Patch: 0008-logrotate-3.18.0-test-0107-cover-the-ignoreduplicates-configuration-d.patch +# allow to disable state management (RHEL-69959) +Patch: 0009-logrotate-3.18.0-add-documentation-for-state-dev-null-special-case.patch +Patch: 0010-logrotate-3.18.0-Do-not-lock-state-file-dev-null.patch +Patch: 0017-logrotate-3.18.0-writeState-do-nothing-if-state-file-is-dev-null.patch + +# fix memory corruption issues in config file parsing +Patch: 0011-logrotate-3.18.0-Log-all-glob-errors-in-debug-mode.patch +Patch: 0012-logrotate-3.18.0-Handle-glob-aborts-for-initial-pattern.patch +Patch: 0013-logrotate-3.18.0-Handle-non-NUL-terminated-config-files.patch +Patch: 0014-logrotate-3.18.0-Limit-glob-length-to-avoid-stack-overflow-in-glob-3.patch +Patch: 0015-logrotate-3.18.0-Avoid-date-format-overflow-issues.patch +Patch: 0016-logrotate-3.18.0-Use-strnlen-in-private-strndup-implementation.patch + BuildRequires: acl BuildRequires: automake BuildRequires: gcc @@ -127,6 +140,15 @@ fi %config(noreplace) %{_sysconfdir}/rwtab.d/logrotate %changelog +* Wed Jun 11 2025 Jan Macku - 3.18.0-12 +- allow to disable state management (RHEL-69959) + +* Fri Jun 06 2025 Jan Macku - 3.18.0-11 +- fix memory corruption issues in config file parsing (RHEL-91449) + +* Fri May 30 2025 Jan Macku - 3.18.0-10 +- allow to disable state management (RHEL-69959) + * Thu Jan 02 2025 Jan Macku - 3.18.0-9 - config: introduce `ignoreduplicates` configuration directive (#RHEL-5711)