logging: Add string validation to detect %p misuse

Logging shall not use character pointers with %p because in
certain configurations it may lead to memory faults. A compile
time detection is added. If faulty usage is detected then
message is replaced with error message which indicates which
message failed and what shall be done (casting to a pointer
of different type).

Validation is enabled only for configurations which remove
strings from binary as otherwise it may impact CI execution
time.

Signed-off-by: Krzysztof Chruściński <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
Krzysztof Chruściński 2023-11-21 09:50:52 +01:00 committed by Carles Cufí
parent aa2e315ab0
commit 465446e5aa
2 changed files with 39 additions and 0 deletions

View file

@ -190,6 +190,30 @@ static inline char z_log_minimal_level_to_char(int level)
#define Z_LOG_INST(_inst) COND_CODE_1(CONFIG_LOG, (_inst), NULL) #define Z_LOG_INST(_inst) COND_CODE_1(CONFIG_LOG, (_inst), NULL)
/* If strings are removed from the binary then there is a risk of creating invalid
* cbprintf package if %p is used with character pointer which is interpreted as
* string. A compile time check is performed (since format string is known at
* compile time) and check fails logging message is not created but error is
* emitted instead. String check may increase compilation time so it is not
* always performed (could significantly increase CI time).
*/
#if CONFIG_LOG_FMT_STRING_VALIDATE
#define LOG_STRING_WARNING(_mode, _src, ...) \
Z_LOG_MSG_CREATE(UTIL_NOT(IS_ENABLED(CONFIG_USERSPACE)), _mode, \
Z_LOG_LOCAL_DOMAIN_ID, _src, LOG_LEVEL_ERR, NULL, 0, \
"char pointer used for %%p, cast to void *:\"%s\"", \
GET_ARG_N(1, __VA_ARGS__))
#define LOG_POINTERS_VALIDATE(string_ok, ...) \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wpointer-arith\"") \
string_ok = Z_CBPRINTF_POINTERS_VALIDATE(__VA_ARGS__); \
_Pragma("GCC diagnostic pop")
#else
#define LOG_POINTERS_VALIDATE(string_ok, ...) string_ok = true
#define LOG_STRING_WARNING(_mode, _src, ...)
#endif
/*****************************************************************************/ /*****************************************************************************/
/****************** Macros for standard logging ******************************/ /****************** Macros for standard logging ******************************/
/*****************************************************************************/ /*****************************************************************************/
@ -234,6 +258,12 @@ static inline char z_log_minimal_level_to_char(int level)
int _mode; \ int _mode; \
void *_src = IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING) ? \ void *_src = IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING) ? \
(void *)_dsource : (void *)_source; \ (void *)_dsource : (void *)_source; \
bool string_ok; \
LOG_POINTERS_VALIDATE(string_ok, __VA_ARGS__); \
if (!string_ok) { \
LOG_STRING_WARNING(_mode, _src, __VA_ARGS__); \
break; \
} \
Z_LOG_MSG_CREATE(UTIL_NOT(IS_ENABLED(CONFIG_USERSPACE)), _mode, \ Z_LOG_MSG_CREATE(UTIL_NOT(IS_ENABLED(CONFIG_USERSPACE)), _mode, \
Z_LOG_LOCAL_DOMAIN_ID, _src, _level, NULL,\ Z_LOG_LOCAL_DOMAIN_ID, _src, _level, NULL,\
0, __VA_ARGS__); \ 0, __VA_ARGS__); \

View file

@ -70,6 +70,15 @@ config LOG_FMT_SECTION_STRIP
depends on LOG_FMT_SECTION depends on LOG_FMT_SECTION
depends on LINKER_DEVNULL_SUPPORT depends on LINKER_DEVNULL_SUPPORT
imply LINKER_DEVNULL_MEMORY imply LINKER_DEVNULL_MEMORY
imply LOG_FMT_STRING_VALIDATE
config LOG_FMT_STRING_VALIDATE
bool "Validate logging strings"
help
Logging strings cannot use %p with character pointers. They should be
casted to the pointer of another type (e.g. void *). With this feature
enabled, at compile time, the preprocessor detects strings with %p
without casting and reports an error at runtime.
config LOG_USE_TAGGED_ARGUMENTS config LOG_USE_TAGGED_ARGUMENTS
bool "Using tagged arguments for packaging" bool "Using tagged arguments for packaging"