Files
falco/userspace/engine/logger.cpp
Leonardo Grasso 5e91db569a fix(userspace): replace gmtime/localtime with reentrant variants
gmtime() and localtime() return pointers to a shared static buffer,
making them unsafe in multi-threaded contexts. Replace all call sites
with gmtime_r() and localtime_r() which use caller-provided buffers.

Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2026-04-09 16:56:43 +02:00

139 lines
4.4 KiB
C++

// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <ctime>
#include "logger.h"
#include "falco_common.h"
falco_logger::level falco_logger::current_level = falco_logger::level::INFO;
bool falco_logger::time_format_iso_8601 = false;
static sinsp_logger::severity decode_sinsp_severity(const std::string& s) {
if(s == "trace") {
return sinsp_logger::SEV_TRACE;
} else if(s == "debug") {
return sinsp_logger::SEV_DEBUG;
} else if(s == "info") {
return sinsp_logger::SEV_INFO;
} else if(s == "notice") {
return sinsp_logger::SEV_NOTICE;
} else if(s == "warning") {
return sinsp_logger::SEV_WARNING;
} else if(s == "error") {
return sinsp_logger::SEV_ERROR;
} else if(s == "critical") {
return sinsp_logger::SEV_CRITICAL;
} else if(s == "fatal") {
return sinsp_logger::SEV_FATAL;
}
throw falco_exception("Unknown sinsp log severity " + s);
}
void falco_logger::set_time_format_iso_8601(bool val) {
falco_logger::time_format_iso_8601 = val;
}
void falco_logger::set_level(const std::string& level) {
if(level == "emergency") {
falco_logger::current_level = falco_logger::level::EMERG;
} else if(level == "alert") {
falco_logger::current_level = falco_logger::level::ALERT;
} else if(level == "critical") {
falco_logger::current_level = falco_logger::level::CRIT;
} else if(level == "error") {
falco_logger::current_level = falco_logger::level::ERR;
} else if(level == "warning") {
falco_logger::current_level = falco_logger::level::WARNING;
} else if(level == "notice") {
falco_logger::current_level = falco_logger::level::NOTICE;
} else if(level == "info") {
falco_logger::current_level = falco_logger::level::INFO;
} else if(level == "debug") {
falco_logger::current_level = falco_logger::level::DEBUG;
} else {
throw falco_exception("Unknown log level " + level);
}
}
static std::string s_sinsp_logger_prefix = "";
void falco_logger::set_sinsp_logging(bool enable,
const std::string& severity,
const std::string& prefix) {
if(enable) {
s_sinsp_logger_prefix = prefix;
libsinsp_logger()->set_severity(decode_sinsp_severity(severity));
libsinsp_logger()->disable_timestamps();
libsinsp_logger()->add_callback_log(
[](std::string&& str, const sinsp_logger::severity sev) {
// note: using falco_logger::level ensures that the sinsp
// logs are always printed by the Falco logger. These
// logs are pre-filtered at the sinsp level depending
// on the configured severity
falco_logger::log(falco_logger::current_level, s_sinsp_logger_prefix + str);
});
} else {
libsinsp_logger()->remove_callback_log();
}
}
bool falco_logger::log_stderr = true;
bool falco_logger::log_syslog = true;
void falco_logger::log(falco_logger::level priority, const std::string&& msg) {
if(priority > falco_logger::current_level) {
return;
}
std::string copy = msg;
#ifndef _WIN32
if(falco_logger::log_syslog) {
// Syslog output should not have any trailing newline
if(copy.back() == '\n') {
copy.pop_back();
}
::syslog(static_cast<int>(priority), "%s", copy.c_str());
}
#endif
if(falco_logger::log_stderr) {
// log output should always have a trailing newline
if(copy.back() != '\n') {
copy.push_back('\n');
}
std::time_t result = std::time(nullptr);
if(falco_logger::time_format_iso_8601) {
char buf[sizeof "YYYY-MM-DDTHH:MM:SS-0000"];
struct tm gtm;
if(gmtime_r(&result, &gtm) != NULL &&
(strftime(buf, sizeof(buf), "%FT%T%z", &gtm) != 0)) {
fprintf(stderr, "%s: %s", buf, copy.c_str());
}
} else {
struct tm ltm;
localtime_r(&result, &ltm);
char tstr[std::size("WWW MMM DD HH:mm:ss YYYY")];
std::strftime(std::data(tstr), std::size(tstr), "%a %b %d %H:%M:%S %Y", &ltm);
fprintf(stderr, "%s: %s", tstr, copy.c_str());
}
}
}