commit e56313a0d59b9a396c260ed1ffcf4bc75d6e986a Author: David Goulet dgoulet@torproject.org Date: Fri Apr 20 11:49:58 2018 -0400
log: Avoid crash or file corruption when closing logs
Fixes #24081
Signed-off-by: David Goulet dgoulet@torproject.org --- src/common/log.c | 38 +++++++++++++++++++++++++------------- src/common/log.h | 1 + src/lib/close.c | 6 ++++++ 3 files changed, 32 insertions(+), 13 deletions(-)
diff --git a/src/common/log.c b/src/common/log.c index 8bf8836..60a56f7 100644 --- a/src/common/log.c +++ b/src/common/log.c @@ -145,20 +145,22 @@ int log_init(int level, const char *filepath, enum log_time_status t_status) }
if (filepath) { - logconfig.fp = fopen(filepath, "a"); - if (!logconfig.fp) { - fprintf(stderr, "[tsocks] Unable to open log file %s\n", filepath); + logconfig.filepath = strdup(filepath); + if (!logconfig.filepath) { + perror("[tsocks] log init strdup"); ret = -errno; goto error; }
- logconfig.filepath = strdup(filepath); - if (!logconfig.filepath) { - perror("[tsocks] log init strdup"); + logconfig.fp = fopen(filepath, "a"); + if (!logconfig.fp) { + fprintf(stderr, "[tsocks] Unable to open log file %s\n", filepath); + free(logconfig.filepath); + logconfig.filepath = NULL; ret = -errno; - fclose(logconfig.fp); goto error; } + setbuf(logconfig.fp, NULL); } else { /* The default output is stderr if no filepath is given. */ ret = fileno(stderr); @@ -182,12 +184,22 @@ ATTR_HIDDEN void log_destroy(void) { free(logconfig.filepath); - if (logconfig.fp) { - int ret; + logconfig.filepath = NULL;
- ret = fclose(logconfig.fp); - if (ret) { - perror("[tsocks] fclose log destroy"); - } + /* Don't call fclose() because torsocks fclose() generates log messages and + * so calling it here could cause a loop. Just zero out the fp so it won't + * be used again. */ + logconfig.fp = NULL; +} + +/* + * Clean up if the fd for the log file gets closed. + */ +ATTR_HIDDEN +void log_fd_close_notify(int fd) +{ + if (fd >= 0 && logconfig.fp && (fd == fileno(logconfig.fp))) { + log_print("[tsocks] Log file descriptor closed. Stopping logging.\n"); + log_destroy(); } } diff --git a/src/common/log.h b/src/common/log.h index e3770df..49d7a77 100644 --- a/src/common/log.h +++ b/src/common/log.h @@ -51,6 +51,7 @@ extern int tsocks_loglevel; void log_print(const char *fmt, ...); int log_init(int level, const char *filepath, enum log_time_status t_status); void log_destroy(void); +void log_fd_close_notify(int fd);
#define __tsocks_print(level, fmt, args...) \ do { \ diff --git a/src/lib/close.c b/src/lib/close.c index 4381514..0bf9ea7 100644 --- a/src/lib/close.c +++ b/src/lib/close.c @@ -52,6 +52,12 @@ LIBC_CLOSE_RET_TYPE tsocks_close(LIBC_CLOSE_SIG) connection_put_ref(conn); }
+ /* + * Let the log system detect when the log file fd is about to be + * closed and clean up. + */ + log_fd_close_notify(fd); + /* Return the original libc close. */ return tsocks_libc_close(fd); }
tor-commits@lists.torproject.org