From 26daebb1a9002676093bcd6a9b30705294bc1d53 Mon Sep 17 00:00:00 2001 From: Leonardo Grasso Date: Thu, 9 Apr 2026 11:41:37 +0200 Subject: [PATCH] fix(userspace): replace strerror() with thread-safe strerror_r() strerror() returns a pointer to a shared static buffer, making it unsafe when called concurrently from different threads. Replace all call sites with strerror_r() using stack-local buffers, consistent with the existing pattern in create_signal_handlers.cpp. Signed-off-by: Leonardo Grasso --- .../app/actions/print_kernel_version.cpp | 11 +++++---- userspace/falco/app/actions/print_support.cpp | 4 +++- userspace/falco/outputs_program.cpp | 6 +++-- userspace/falco/stats_writer.cpp | 24 ++++++++++++++----- 4 files changed, 32 insertions(+), 13 deletions(-) diff --git a/userspace/falco/app/actions/print_kernel_version.cpp b/userspace/falco/app/actions/print_kernel_version.cpp index d65e3579..c31a2c73 100644 --- a/userspace/falco/app/actions/print_kernel_version.cpp +++ b/userspace/falco/app/actions/print_kernel_version.cpp @@ -36,10 +36,13 @@ falco::app::run_result falco::app::actions::print_kernel_version(const falco::ap std::ifstream input_file("/proc/version"); if(!input_file.is_open()) { // We don't want to fail, we just need to log something - falco_logger::log( - falco_logger::level::INFO, - "Cannot read under '/proc/version' (err_message: '" + std::string(strerror(errno)) + - "', err_code: " + std::to_string(errno) + "). No info provided, go on."); + int saved_errno = errno; + char errbuf[256]; + const char* errstr = strerror_r(saved_errno, errbuf, sizeof(errbuf)); + falco_logger::log(falco_logger::level::INFO, + "Cannot read under '/proc/version' (err_message: '" + + std::string(errstr) + "', err_code: " + + std::to_string(saved_errno) + "). No info provided, go on."); return run_result::ok(); } diff --git a/userspace/falco/app/actions/print_support.cpp b/userspace/falco/app/actions/print_support.cpp index 96ab2abb..be0f8509 100644 --- a/userspace/falco/app/actions/print_support.cpp +++ b/userspace/falco/app/actions/print_support.cpp @@ -95,7 +95,9 @@ falco::app::run_result falco::app::actions::print_support(falco::app::state& s) nlohmann::json support; if(get_sysinfo(support) != 0) { - return run_result::fatal(std::string("Could not get system info: ") + strerror(errno)); + char errbuf[256]; + const char* errstr = strerror_r(errno, errbuf, sizeof(errbuf)); + return run_result::fatal(std::string("Could not get system info: ") + errstr); } const falco::versions_info infos(s.offline_inspector); diff --git a/userspace/falco/outputs_program.cpp b/userspace/falco/outputs_program.cpp index 811f94af..855c9440 100644 --- a/userspace/falco/outputs_program.cpp +++ b/userspace/falco/outputs_program.cpp @@ -26,9 +26,11 @@ void falco::outputs::output_program::open_pfile() { m_pfile = popen(m_oc.options["program"].c_str(), "w"); if(m_pfile == nullptr) { + char errbuf[256]; + const char* errstr = strerror_r(errno, errbuf, sizeof(errbuf)); falco_logger::log(falco_logger::level::ERR, "Failed to open program output: " + m_oc.options["program"] + - " (error: " + std::string(std::strerror(errno)) + ")"); + " (error: " + errstr + ")"); return; } @@ -38,7 +40,7 @@ void falco::outputs::output_program::open_pfile() { } } -void falco::outputs::output_program::output(const message *msg) { +void falco::outputs::output_program::output(const message* msg) { open_pfile(); if(m_pfile != nullptr) { diff --git a/userspace/falco/stats_writer.cpp b/userspace/falco/stats_writer.cpp index e19c6765..54e54fc2 100644 --- a/userspace/falco/stats_writer.cpp +++ b/userspace/falco/stats_writer.cpp @@ -71,7 +71,9 @@ bool stats_writer::init_ticker(uint32_t interval_msec, std::string& err) { memset(&handler, 0, sizeof(handler)); handler.sa_handler = &timer_handler; if(sigaction(SIGALRM, &handler, NULL) == -1) { - err = std::string("Could not set up signal handler for periodic timer: ") + strerror(errno); + char errbuf[256]; + const char* errstr = strerror_r(errno, errbuf, sizeof(errbuf)); + err = std::string("Could not set up signal handler for periodic timer: ") + errstr; return false; } @@ -93,7 +95,9 @@ bool stats_writer::init_ticker(uint32_t interval_msec, std::string& err) { memset(&handler, 0, sizeof(handler)); handler.sa_handler = &timer_handler; if(sigaction(SIGALRM, &handler, NULL) == -1) { - err = std::string("Could not set up signal handler for periodic timer: ") + strerror(errno); + char errbuf[256]; + const char* errstr = strerror_r(errno, errbuf, sizeof(errbuf)); + err = std::string("Could not set up signal handler for periodic timer: ") + errstr; return false; } @@ -119,7 +123,9 @@ bool stats_writer::init_ticker(uint32_t interval_msec, std::string& err) { memset(&handler, 0, sizeof(handler)); handler.sa_handler = &timer_handler; if(sigaction(SIGALRM, &handler, NULL) == -1) { - err = std::string("Could not set up signal handler for periodic timer: ") + strerror(errno); + char errbuf[256]; + const char* errstr = strerror_r(errno, errbuf, sizeof(errbuf)); + err = std::string("Could not set up signal handler for periodic timer: ") + errstr; return false; } @@ -131,14 +137,18 @@ bool stats_writer::init_ticker(uint32_t interval_msec, std::string& err) { // delete any previously set timer if(s_timerid_exists) { if(timer_delete(s_timerid) == -1) { - err = std::string("Could not delete previous timer: ") + strerror(errno); + char errbuf[256]; + const char* errstr = strerror_r(errno, errbuf, sizeof(errbuf)); + err = std::string("Could not delete previous timer: ") + errstr; return false; } s_timerid_exists = false; } if(timer_create(CLOCK_MONOTONIC, &sev, &s_timerid) == -1) { - err = std::string("Could not create periodic timer: ") + strerror(errno); + char errbuf[256]; + const char* errstr = strerror_r(errno, errbuf, sizeof(errbuf)); + err = std::string("Could not create periodic timer: ") + errstr; return false; } s_timerid_exists = true; @@ -148,7 +158,9 @@ bool stats_writer::init_ticker(uint32_t interval_msec, std::string& err) { timer.it_interval = timer.it_value; if(timer_settime(s_timerid, 0, &timer, NULL) == -1) { - err = std::string("Could not set up periodic timer: ") + strerror(errno); + char errbuf[256]; + const char* errstr = strerror_r(errno, errbuf, sizeof(errbuf)); + err = std::string("Could not set up periodic timer: ") + errstr; return false; }