torerr: Close sigsafe fds on shutdown

And clear the list of error fds.

Part of 31594.
This commit is contained in:
teor 2019-09-04 14:54:08 +10:00
parent 896a1ac50b
commit d02ced4caf
No known key found for this signature in database
GPG Key ID: 10FEAA0E7075672A
3 changed files with 45 additions and 3 deletions

View File

@ -110,6 +110,8 @@ tor_log_get_sigsafe_err_fds(const int **out)
* Update the list of fds that get errors from inside a signal handler or * Update the list of fds that get errors from inside a signal handler or
* other emergency condition. Ignore any beyond the first * other emergency condition. Ignore any beyond the first
* TOR_SIGSAFE_LOG_MAX_FDS. * TOR_SIGSAFE_LOG_MAX_FDS.
*
* If fds is NULL or n is 0, clears the list of error fds.
*/ */
void void
tor_log_set_sigsafe_err_fds(const int *fds, int n) tor_log_set_sigsafe_err_fds(const int *fds, int n)
@ -118,8 +120,18 @@ tor_log_set_sigsafe_err_fds(const int *fds, int n)
n = TOR_SIGSAFE_LOG_MAX_FDS; n = TOR_SIGSAFE_LOG_MAX_FDS;
} }
memcpy(sigsafe_log_fds, fds, n * sizeof(int)); /* Clear the entire array. This code mitigates against some race conditions,
n_sigsafe_log_fds = n; * but there are still some races here:
* - err logs are disabled while the array is cleared, and
* - a thread can read the old value of n_sigsafe_log_fds, then read a
* partially written array.
* We could fix these races using atomics, but atomics use the err module. */
n_sigsafe_log_fds = 0;
memset(sigsafe_log_fds, 0, sizeof(sigsafe_log_fds));
if (fds && n > 0) {
memcpy(sigsafe_log_fds, fds, n * sizeof(int));
n_sigsafe_log_fds = n;
}
} }
/** /**
@ -132,6 +144,32 @@ tor_log_reset_sigsafe_err_fds(void)
tor_log_set_sigsafe_err_fds(fds, 1); tor_log_set_sigsafe_err_fds(fds, 1);
} }
/**
* Close the list of fds that get errors from inside a signal handler or
* other emergency condition. These fds are shared with the logging code:
* closing them flushes the log buffers, and prevents any further logging.
*
* This function closes stderr, so it should only be called immediately before
* process shutdown.
*/
void
tor_log_close_sigsafe_err_fds(void)
{
int n_fds, i;
const int *fds = NULL;
n_fds = tor_log_get_sigsafe_err_fds(&fds);
for (i = 0; i < n_fds; ++i) {
/* tor_log_close_sigsafe_err_fds_on_error() is called on error and on
* shutdown, so we can't log or take any useful action if close()
* fails. */
(void)close(fds[i]);
}
/* Don't even try logging, we've closed all the log fds. */
tor_log_set_sigsafe_err_fds(NULL, 0);
}
/** /**
* Set the granularity (in ms) to use when reporting fatal errors outside * Set the granularity (in ms) to use when reporting fatal errors outside
* the logging system. * the logging system.

View File

@ -40,6 +40,7 @@ void tor_log_err_sigsafe(const char *m, ...);
int tor_log_get_sigsafe_err_fds(const int **out); int tor_log_get_sigsafe_err_fds(const int **out);
void tor_log_set_sigsafe_err_fds(const int *fds, int n); void tor_log_set_sigsafe_err_fds(const int *fds, int n);
void tor_log_reset_sigsafe_err_fds(void); void tor_log_reset_sigsafe_err_fds(void);
void tor_log_close_sigsafe_err_fds(void);
void tor_log_sigsafe_err_set_granularity(int ms); void tor_log_sigsafe_err_set_granularity(int ms);
int format_hex_number_sigsafe(unsigned long x, char *buf, int max_len); int format_hex_number_sigsafe(unsigned long x, char *buf, int max_len);

View File

@ -27,8 +27,11 @@ subsys_torerr_initialize(void)
static void static void
subsys_torerr_shutdown(void) subsys_torerr_shutdown(void)
{ {
tor_log_reset_sigsafe_err_fds(); /* Stop handling signals with backtraces, then close the logs. */
clean_up_backtrace_handler(); clean_up_backtrace_handler();
/* We can't log any log messages after this point: we've closed all the log
* fds, including stdio. */
tor_log_close_sigsafe_err_fds();
} }
const subsys_fns_t sys_torerr = { const subsys_fns_t sys_torerr = {