diff options
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-.patch | 275 |
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 + |