From 518bca17bd39d87a35b9f7c7f186f08dc9e4be15 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Tue, 28 May 2019 15:42:37 -0400 Subject: [PATCH 16/63] Always log to a memfd regardless of loglevel. This writes all debug logs to a memfd, so that they'll always show up in strace. Signed-off-by: Peter Jones --- src/error.c | 88 ++++++++++++++++++++++++++++++++++--- src/include/efivar/efivar.h | 7 +++ src/libefivar.map.in | 1 + src/util.h | 26 +++++------ 4 files changed, 102 insertions(+), 20 deletions(-) diff --git a/src/error.c b/src/error.c index df03d7f45e0..5dc43197c50 100644 --- a/src/error.c +++ b/src/error.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include "efiboot.h" @@ -162,7 +163,58 @@ efi_error_pop(void) clear_error_entry(&error_table[current]); } -void PUBLIC DESTRUCTOR +static int efi_verbose; +static FILE *efi_errlog, *efi_dbglog; +static int efi_dbglog_fd = -1; +static int stashed_log_level; +static char efi_dbglog_buf[4096]; + +void PUBLIC +efi_stash_loglevel_(int level) +{ + stashed_log_level = level; +} + +static ssize_t +dbglog_write(void *cookie UNUSED, const char *buf, size_t size) +{ + FILE *log = efi_errlog ? efi_errlog : stderr; + ssize_t ret = size; + + if (efi_get_verbose() >= stashed_log_level) { + ret = fwrite(buf, 1, size, log); + } else if (efi_dbglog_fd >= 0) { + lseek(efi_dbglog_fd, 0, SEEK_SET); + write(efi_dbglog_fd, buf, size); + } + return ret; +} + +static int +dbglog_seek(void *cookie UNUSED, off64_t *offset, int whence) +{ + FILE *log = efi_errlog ? efi_errlog : stderr; + return fseek(log, *offset, whence); +} + +static int +dbglog_close(void *cookie UNUSED) +{ + if (efi_dbglog_fd >= 0) { + close(efi_dbglog_fd); + efi_dbglog_fd = -1; + } + if (efi_errlog) { + int ret = fclose(efi_errlog); + efi_errlog = NULL; + return ret; + } + + errno = EBADF; + return -1; +} + +void PUBLIC efi_error_clear(void) { if (error_table) { @@ -177,15 +229,39 @@ efi_error_clear(void) current = 0; } -static int efi_verbose; -static FILE *efi_errlog; +void DESTRUCTOR +efi_error_fini(void) +{ + efi_error_clear(); + if (efi_dbglog) { + fclose(efi_dbglog); + efi_dbglog = NULL; + } +} + +static void CONSTRUCTOR +efi_error_init(void) +{ + cookie_io_functions_t io_funcs = { + .write = dbglog_write, + .seek = dbglog_seek, + .close = dbglog_close, + }; + + efi_dbglog_fd = memfd_create("efivar-debug.log", MFD_CLOEXEC); + if (efi_dbglog_fd == -1) + return; + + efi_dbglog = fopencookie(NULL, "a", io_funcs); + if (efi_dbglog) + setvbuf(efi_dbglog, efi_dbglog_buf, _IOLBF, + sizeof(efi_dbglog_buf)); +} FILE PUBLIC * efi_get_logfile(void) { - if (efi_errlog) - return efi_errlog; - return stderr; + return efi_dbglog; } void PUBLIC diff --git a/src/include/efivar/efivar.h b/src/include/efivar/efivar.h index dabf41789e5..343d1c557da 100644 --- a/src/include/efivar/efivar.h +++ b/src/include/efivar/efivar.h @@ -188,6 +188,7 @@ extern int efi_error_set(const char *filename, __attribute__((__format__ (printf, 5, 6))); extern void efi_error_clear(void); extern void efi_error_pop(void); +extern void efi_stash_loglevel_(int level); #else static inline int __attribute__((__nonnull__ (2, 3, 4, 5, 6))) @@ -225,6 +226,12 @@ efi_error_pop(void) { return; } + +static inline void +efi_stash_loglevel_(int level __attribute__((__unused__))) +{ + return; +} #endif #define efi_error_real__(errval, file, function, line, fmt, args...) \ diff --git a/src/libefivar.map.in b/src/libefivar.map.in index 8e50d574f10..8965b729917 100644 --- a/src/libefivar.map.in +++ b/src/libefivar.map.in @@ -133,4 +133,5 @@ LIBEFIVAR_1.37 { LIBEFIVAR_1.38 { global: efi_error_pop; + efi_stash_loglevel_; } LIBEFIVAR_1.37; diff --git a/src/util.h b/src/util.h index a6a80e754ec..337762c9902 100644 --- a/src/util.h +++ b/src/util.h @@ -382,15 +382,14 @@ swizzle_guid_to_uuid(efi_guid_t *guid) #define log_(file, line, func, level, fmt, args...) \ ({ \ - if (efi_get_verbose() >= level) { \ - FILE *logfile_ = efi_get_logfile(); \ - int len_ = strlen(fmt); \ - fprintf(logfile_, "%s:%d %s(): ", \ - file, line, func); \ - fprintf(logfile_, fmt, ## args); \ - if (!len_ || fmt[len_ - 1] != '\n') \ - fprintf(logfile_, "\n"); \ - } \ + efi_stash_loglevel_(level); \ + FILE *logfile_ = efi_get_logfile(); \ + int len_ = strlen(fmt); \ + fprintf(logfile_, "%s:%d %s(): ", \ + file, line, func); \ + fprintf(logfile_, fmt, ## args); \ + if (!len_ || fmt[len_ - 1] != '\n') \ + fprintf(logfile_, "\n"); \ }) #define LOG_VERBOSE 0 @@ -402,11 +401,10 @@ swizzle_guid_to_uuid(efi_guid_t *guid) #define debug(fmt, args...) log(LOG_DEBUG, fmt, ## args) #define log_hex_(file, line, func, level, buf, size) \ ({ \ - if (efi_get_verbose() >= level) { \ - fhexdumpf(efi_get_logfile(), "%s:%d %s(): ", \ - (uint8_t *)buf, size, \ - file, line, func); \ - } \ + efi_stash_loglevel_(level); \ + fhexdumpf(efi_get_logfile(), "%s:%d %s(): ", \ + (uint8_t *)buf, size, \ + file, line, func); \ }) #define log_hex(level, buf, size) log_hex_(__FILE__, __LINE__, __func__, level, buf, size) #define debug_hex(buf, size) log_hex(LOG_DEBUG, buf, size) -- 2.26.2