feat(core): add automatic logging in TSH_CHECK macros
What changed, and why it matters
This commit adds automatic error logging to internal Trezor firmware macros that handle failed security and status checks. It is a diagnostic/debugging improvement, not a fix for a security vulnerability. The change only affects what information is logged when errors already occur; it does not change how errors are handled or what code is allowed to run.
No security action required. Treat as normal diagnostic-quality improvement. If concerned about information leakage via debug logs, verify that USE_DBG_CONSOLE is disabled in release builds and that syslog output is not accessible to untrusted hosts.
Security signals we found
No security fix: change is purely additive logging instrumentation
No change to error-handling control flow or trust boundary enforcement
New macro TSH_LOG_ expands to empty block when USE_DBG_CONSOLE is undefined, so no runtime effect in production builds without debug console
Logging may expose path/file names and status codes, but only to an already-present debug console facility
Evidence from the diff
The patch instruments TSH_CHECK, TSH_CHECK_ARG, and TSH_CHECK_SEC macros in core/embed/rtl/inc/rtl/error_handling.h so they call a new TSH_LOG_ helper when a check fails. TSH_LOG_ is defined as a no-op unless USE_DBG_CONSOLE is set; when enabled, it calls syslog_tsh_error() in core/embed/sys/dbg/syslog.c to emit the ts_t status string plus file/line. core/embed/sys/inc/sys/logging.h also overrides TSH_LOG_ to use LOG_ERR with the current module name. No control-flow, privilege, or validation behavior is changed; the goto cleanup paths remain identical.
Changed components
core/embed/rtl/inc/rtl/error_handling.hcore/embed/sys/dbg/syslog.ccore/embed/sys/inc/sys/logging.hInspect captured patch +44 / −0
diff --git a/core/embed/rtl/inc/rtl/error_handling.h b/core/embed/rtl/inc/rtl/error_handling.h
index 79e88b4b..3d8fbc00 100644
--- a/core/embed/rtl/inc/rtl/error_handling.h
+++ b/core/embed/rtl/inc/rtl/error_handling.h
@@ -237,6 +237,7 @@ __fatal_error(const char *msg, const char *file, int line);
do { \
ts_t _status = status; \
if (ts_error(_status)) { \
+ TSH_LOG_((status)); \
__status = _status; \
goto cleanup; \
} \
@@ -252,6 +253,7 @@ __fatal_error(const char *msg, const char *file, int line);
#define TSH_CHECK(cond, status) \
do { \
if (!(cond)) { \
+ TSH_LOG_((status)); \
__status = status; \
goto cleanup; \
} \
@@ -266,6 +268,7 @@ __fatal_error(const char *msg, const char *file, int line);
#define TSH_CHECK_ARG(cond) \
do { \
if (!(cond)) { \
+ TSH_LOG_(TS_EINVAL); \
__status = TS_EINVAL; \
goto cleanup; \
} \
@@ -281,7 +284,28 @@ __fatal_error(const char *msg, const char *file, int line);
#define TSH_CHECK_SEC(seccond, status) \
do { \
if ((seccond) != sectrue) { \
+ TSH_LOG_((status)); \
__status = status; \
goto cleanup; \
} \
} while (0)
+
+#ifdef USE_DBG_CONSOLE
+
+// defined in /sys/dbg/syslog.c
+extern void syslog_tsh_error(ts_t status, const char *file, int line);
+
+// Helper macro for logging within TSH_CHECK_xxx macros.
+// Do not use directly.
+#define TSH_LOG_(status) \
+ do { \
+ syslog_tsh_error(status, __FILE_NAME__, __LINE__); \
+ } while (0)
+
+#else
+
+#define TSH_LOG_(status) \
+ do { \
+ } while (0)
+
+#endif
diff --git a/core/embed/sys/dbg/syslog.c b/core/embed/sys/dbg/syslog.c
index 6990964e..bfb33edc 100644
--- a/core/embed/sys/dbg/syslog.c
+++ b/core/embed/sys/dbg/syslog.c
@@ -256,6 +256,17 @@ void syslog_print_hex(const log_source_t* source, log_level_t level,
}
}
+// declared in rtl/error_handling.h
+void syslog_tsh_error(ts_t status, const char* file, int line) {
+ log_source_t source = {
+ .name = "tsh",
+ .name_len = sizeof("tsh") - 1,
+ };
+
+ syslog_printf(&source, LOG_LEVEL_ERR, "%s at %s:%d", ts_string(status), file,
+ line);
+}
+
#ifdef TREZOR_PRODTEST
#include <rtl/cli.h>
diff --git a/core/embed/sys/inc/sys/logging.h b/core/embed/sys/inc/sys/logging.h
index d048e35d..63a62a80 100644
--- a/core/embed/sys/inc/sys/logging.h
+++ b/core/embed/sys/inc/sys/logging.h
@@ -19,6 +19,8 @@
#pragma once
+#include <trezor_types.h>
+
typedef enum {
LOG_LEVEL_OFF = 0,
LOG_LEVEL_ERR = 1,
@@ -51,6 +53,13 @@ typedef struct {
#define LOG_HEXDUMP_DBG(prefix, data, data_size) \
SYSLOG_LOG_HEXDUMP_DBG(prefix, data, data_size)
+// Override TSH_LOG_ macro to log error with the current module name
+#undef TSH_LOG_
+#define TSH_LOG_(status) \
+ do { \
+ LOG_ERR("%s at %s:%d", ts_string(status), __FILE_NAME__, __LINE__); \
+ } while (0)
+
#else
#define LOG_DECLARE(source_name)
Why this scored 12/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.