[tor-commits] [torsocks/master] log: Avoid crash or file corruption when closing logs

dgoulet at torproject.org dgoulet at torproject.org
Fri Apr 20 16:10:45 UTC 2018


commit e56313a0d59b9a396c260ed1ffcf4bc75d6e986a
Author: David Goulet <dgoulet at 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 at 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);
 }





More information about the tor-commits mailing list