summaryrefslogtreecommitdiffstats
path: root/debian/patches/75_27_Fix-logging-with-empty-element-in-log_file_path-Bug-.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/75_27_Fix-logging-with-empty-element-in-log_file_path-Bug-.patch')
-rw-r--r--debian/patches/75_27_Fix-logging-with-empty-element-in-log_file_path-Bug-.patch275
1 files changed, 275 insertions, 0 deletions
diff --git a/debian/patches/75_27_Fix-logging-with-empty-element-in-log_file_path-Bug-.patch b/debian/patches/75_27_Fix-logging-with-empty-element-in-log_file_path-Bug-.patch
new file mode 100644
index 0000000..58da37c
--- /dev/null
+++ b/debian/patches/75_27_Fix-logging-with-empty-element-in-log_file_path-Bug-.patch
@@ -0,0 +1,275 @@
+From e19790f7707cc901435849e78d20f249056c16b5 Mon Sep 17 00:00:00 2001
+From: Jeremy Harris <jgh146exb@wizmail.org>
+Date: Sat, 15 May 2021 13:37:04 +0200
+Subject: [PATCH 3/4] Fix logging with empty element in log_file_path (Bug
+ 2733)
+
+---
+ src/log.c | 84 +++++++++++++++++++++++++++++++++------------------
+ 1 file changed, 55 insertions(+), 29 deletions(-)
+
+diff --git a/src/log.c b/src/log.c
+index 2108ed46f..716bec553 100644
+--- a/src/log.c
++++ b/src/log.c
+@@ -283,16 +283,19 @@ problem. */
+
+ if (fd < 0 && errno == ENOENT)
+ {
+ BOOL created;
+ uschar *lastslash = Ustrrchr(name, '/');
+ *lastslash = 0;
+ created = directory_make(NULL, name, LOG_DIRECTORY_MODE, FALSE);
+- DEBUG(D_any) debug_printf("%s log directory %s\n",
+- created ? "created" : "failed to create", name);
++ DEBUG(D_any)
++ if (created)
++ debug_printf("created log directory %s\n", name);
++ else
++ debug_printf("failed to create log directory %s: %s\n", name, strerror(errno));
+ *lastslash = '/';
+ if (created) fd = Uopen(name, flags, LOG_MODE);
+ }
+
+ return fd;
+ }
+
+@@ -390,17 +393,15 @@ Returns: a file descriptor, or < 0 on failure (errno set)
+ int
+ log_open_as_exim(uschar * const name)
+ {
+ int fd = -1;
+ const uid_t euid = geteuid();
+
+ if (euid == exim_uid)
+- {
+ fd = log_open_already_exim(name);
+- }
+ else if (euid == root_uid)
+ {
+ int sock[2];
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sock) == 0)
+ {
+ const pid_t pid = exim_fork(US"logfile-open");
+ if (pid == 0)
+@@ -495,38 +496,48 @@ ok = string_format(buffer, sizeof(buffer), CS file_path, log_names[type]);
+ switch (type)
+ {
+ case lt_main:
+ /* Save the name of the mainlog for rollover processing. Without a datestamp,
+ it gets statted to see if it has been cycled. With a datestamp, the datestamp
+ will be compared. The static slot for saving it is the same size as buffer,
+ and the text has been checked above to fit, so this use of strcpy() is OK. */
++
+ Ustrcpy(mainlog_name, buffer);
+ if (string_datestamp_offset > 0)
+ mainlog_datestamp = mainlog_name + string_datestamp_offset;
++ break;
++
+ case lt_reject:
+ /* Ditto for the reject log */
++
+ Ustrcpy(rejectlog_name, buffer);
+ if (string_datestamp_offset > 0)
+ rejectlog_datestamp = rejectlog_name + string_datestamp_offset;
++ break;
++
+ case lt_debug:
+ /* and deal with the debug log (which keeps the datestamp, but does not
+ update it) */
++
+ Ustrcpy(debuglog_name, buffer);
+ if (tag)
+ {
+ /* this won't change the offset of the datestamp */
+ ok2 = string_format(buffer, sizeof(buffer), "%s%s",
+ debuglog_name, tag);
+ if (ok2)
+ Ustrcpy(debuglog_name, buffer);
+ }
++ break;
++
+ default:
+ /* Remove any datestamp if this is the panic log. This is rare, so there's no
+ need to optimize getting the datestamp length. We remove one non-alphanumeric
+ char afterwards if at the start, otherwise one before. */
++
+ if (string_datestamp_offset >= 0)
+ {
+ uschar * from = buffer + string_datestamp_offset;
+ uschar * to = from + string_datestamp_length;
+
+ if (from == buffer || from[-1] == '/')
+ {
+@@ -535,30 +546,29 @@ switch (type)
+ else
+ if (!isalnum(from[-1])) from--;
+
+ /* This copy is ok, because we know that to is a substring of from. But
+ due to overlap we must use memmove() not Ustrcpy(). */
+ memmove(from, to, Ustrlen(to)+1);
+ }
++ break;
+ }
+
+ /* If the file name is too long, it is an unrecoverable disaster */
+
+ if (!ok)
+ die(US"exim: log file path too long: aborting",
+ US"Logging failure; please try later");
+
+ /* We now have the file name. After a successful open, return. */
+
+ *fd = log_open_as_exim(buffer);
+
+ if (*fd >= 0)
+- {
+ return;
+- }
+
+ euid = geteuid();
+
+ /* Creation failed. There are some circumstances in which we get here when
+ the effective uid is not root or exim, which is the problem. (For example, a
+ non-setuid binary with log_arguments set, called in certain ways.) Rather than
+ just bombing out, force the log to stderr and carry on if stderr is available.
+@@ -702,45 +712,61 @@ while (1)
+ left -= wrote;
+ }
+ }
+ return total_written;
+ }
+
+
++/* Pull the file out of the configured or the compiled-in list.
++Called for an empty log_file_path element, for debug logging activation
++when file_path has not previously been set, and from the appenfile transport setup. */
++
+ void
+ set_file_path(BOOL *multiple)
+ {
+ uschar *s;
+ int sep = ':'; /* Fixed separator - outside use */
+ const uschar *ss = *log_file_path ? log_file_path : US LOG_FILE_PATH;
+
+-logging_mode = 0;
+-while ((s = string_nextinlist(&ss, &sep, log_buffer, LOG_BUFFER_SIZE)))
+- {
+- if (Ustrcmp(s, "syslog") == 0)
+- logging_mode |= LOG_MODE_SYSLOG;
+- else if (logging_mode & LOG_MODE_FILE) /* we know a file already */
++if (*ss)
++ for (logging_mode = 0;
++ s = string_nextinlist(&ss, &sep, log_buffer, LOG_BUFFER_SIZE); )
+ {
+- if (multiple) *multiple = TRUE;
+- }
+- else
+- {
+- logging_mode |= LOG_MODE_FILE;
++ if (Ustrcmp(s, "syslog") == 0)
++ logging_mode |= LOG_MODE_SYSLOG;
++ else if (!(logging_mode & LOG_MODE_FILE)) /* no file yet */
++ {
++ /* If a non-empty path is given, use it */
+
+- /* If a non-empty path is given, use it */
++ if (*s)
++ file_path = string_copy(s);
+
+- if (*s)
+- file_path = string_copy(s);
++ /* If handling the config option, and the element is empty, we want to use
++ the first non-empty, non-syslog item in LOG_FILE_PATH, if there is one,
++ since the value of log_file_path may have been set at runtime. If there is
++ no such item, use the ultimate default in the spool directory. */
+
+- /* If the path is empty, we want to use the first non-empty, non-
+- syslog item in LOG_FILE_PATH, if there is one, since the value of
+- log_file_path may have been set at runtime. If there is no such item,
+- use the ultimate default in the spool directory. */
++ else if (*log_file_path && LOG_FILE_PATH[0])
++ {
++ ss = US LOG_FILE_PATH;
++ continue;
++ }
++
++ logging_mode |= LOG_MODE_FILE;
++ }
++ else
++ if (multiple) *multiple = TRUE;
+ }
+- }
++ else
++ logging_mode = LOG_MODE_FILE;
++
++/* Set up the ultimate default if necessary. */
++
++if (logging_mode & LOG_MODE_FILE && !*file_path)
++ file_path = string_sprintf("%s/log/%%slog", spool_directory);
+ }
+
+
+ void
+ mainlog_close(void)
+ {
+ /* avoid closing it if it is closed already or if we do not see a chance
+@@ -866,19 +892,16 @@ if (!path_inspected)
+
+ /* If no modes have been selected, it is a major disaster */
+
+ if (logging_mode == 0)
+ die(US"Neither syslog nor file logging set in log_file_path",
+ US"Unexpected logging failure");
+
+- /* Set up the ultimate default if necessary. Then revert to the old store
+- pool, and record that we've sorted out the path. */
++ /* Revert to the old store pool, and record that we've sorted out the path. */
+
+- if (logging_mode & LOG_MODE_FILE && !file_path[0])
+- file_path = string_sprintf("%s/log/%%slog", spool_directory);
+ store_pool = old_pool;
+ path_inspected = TRUE;
+
+ /* If more than one file path was given, log a complaint. This recursive call
+ should work since we have now set up the routing. */
+
+ if (multiple)
+@@ -1224,14 +1247,15 @@ if (flags & LOG_PANIC)
+ write_syslog(LOG_ALERT, log_buffer);
+
+ /* If this panic logging was caused by a failure to open the main log,
+ the original log line is in panic_save_buffer. Make an attempt to write it. */
+
+ if (logging_mode & LOG_MODE_FILE)
+ {
++ if (!*file_path) set_file_path(NULL);
+ panic_recurseflag = TRUE;
+ open_log(&paniclogfd, lt_panic, NULL); /* Won't return on failure */
+ panic_recurseflag = FALSE;
+
+ if (panic_save_buffer)
+ {
+ int i = write(paniclogfd, panic_save_buffer, Ustrlen(panic_save_buffer));
+@@ -1501,16 +1525,18 @@ if (!debug_file || !debuglog_name[0]) return;
+
+ debug_selector = 0;
+ fclose(debug_file);
+ debug_file = NULL;
+ unlink_log(lt_debug);
+ }
+
++/* Called from the appendfile transport setup. */
+ void
+ open_logs(void)
+ {
+ set_file_path(NULL);
++if (!(logging_mode & LOG_MODE_FILE)) return;
+ open_log(&mainlogfd, lt_main, 0);
+ open_log(&rejectlogfd, lt_reject, 0);
+ }
+
+ /* End of log.c */
+--
+2.30.2
+