commit e56313a0d59b9a396c260ed1ffcf4bc75d6e986a
Author: David Goulet <dgou...@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 <dgou...@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 mailing list
tor-commits@lists.torproject.org
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits

Reply via email to