Files
falco/userspace/engine/falco_load_result.cpp
irozzo-1A 5b53681d2f chore(engine): add deprecation warning for evt.latency when used in conditions
Emit a deprecation warning when `evt.latency` is detected in a rule
condition.

Signed-off-by: irozzo-1A <iacopo@sysdig.com>
2025-12-01 12:54:18 +01:00

193 lines
10 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 "falco_load_result.h"
static const std::string error_codes[] = {"LOAD_ERR_FILE_READ",
"LOAD_ERR_YAML_PARSE",
"LOAD_ERR_YAML_VALIDATE",
"LOAD_ERR_COMPILE_CONDITION",
"LOAD_ERR_COMPILE_OUTPUT",
"LOAD_ERR_VALIDATE",
"LOAD_ERR_EXTENSION"};
const std::string& falco::load_result::error_code_str(error_code ec) {
return error_codes[ec];
}
static const std::string error_strings[] = {"File read error",
"YAML parse error",
"Error validating internal structure of YAML file",
"Error compiling condition",
"Error compiling output",
"Error validating rule/macro/list/exception objects",
"Error in extension item"};
const std::string& falco::load_result::error_str(error_code ec) {
return error_strings[ec];
}
static const std::string error_descs[] = {
"This occurs when falco can not read a given file. Check permissions and whether the file "
"exists.",
"This occurs when the rules content is not valid YAML.",
"This occurs when the internal structure of the YAML file is incorrect. Examples include "
"not consisting of a sequence of maps, a given rule/macro/list item not having required "
"keys, values not having the right type (e.g. the items property of a list not being a "
"sequence), etc.",
"This occurs when a condition string can not be compiled to a filter object.",
"This occurs when an output string can not be compiled to an output object.",
"This occurs when a rule/macro/list item is incorrect. Examples include a condition field "
"referring to an undefined macro, falco engine/plugin version mismatches, items with "
"append without any existing item, exception fields/comps having different lengths, etc.",
"This occurs when there is an error in an extension item"};
const std::string& falco::load_result::error_desc(error_code ec) {
return error_strings[ec];
}
static const std::string warning_codes[] = {"LOAD_UNKNOWN_SOURCE",
"LOAD_UNSAFE_NA_CHECK",
"LOAD_NO_EVTTYPE",
"LOAD_UNKNOWN_FILTER",
"LOAD_UNUSED_MACRO",
"LOAD_UNUSED_LIST",
"LOAD_UNKNOWN_ITEM",
"LOAD_DEPRECATED_ITEM",
"LOAD_WARNING_EXTENSION",
"LOAD_APPEND_NO_VALUES",
"LOAD_EXCEPTION_NAME_NOT_UNIQUE",
"LOAD_INVALID_MACRO_NAME",
"LOAD_INVALID_LIST_NAME",
"LOAD_COMPILE_CONDITION"};
// Compile-time check to ensure warning_codes array has the correct size
static_assert(std::size(warning_codes) ==
static_cast<int>(falco::load_result::warning_code::LOAD_COMPILE_CONDITION) +
1,
"warning_codes array size must match the last warning_code enum value + 1");
const std::string& falco::load_result::warning_code_str(warning_code wc) {
return warning_codes[static_cast<int>(wc)];
}
static const std::string warning_strings[] = {"Unknown event source",
"Unsafe <NA> comparison in condition",
"Condition has no event-type restriction",
"Unknown field or event-type in condition or output",
"Unused macro",
"Unused list",
"Unknown rules file item",
"Used deprecated item",
"Warning in extension item",
"Overriding/appending with no values",
"Multiple exceptions defined with the same name",
"Invalid macro name",
"Invalid list name",
"Warning in rule condition"};
// Compile-time check to ensure warning_strings array has the correct size
static_assert(std::size(warning_strings) ==
static_cast<int>(falco::load_result::warning_code::LOAD_COMPILE_CONDITION) +
1,
"warning_strings array size must match the last warning_code enum value + 1");
const std::string& falco::load_result::warning_str(warning_code wc) {
return warning_strings[static_cast<int>(wc)];
}
static const std::string warning_descs[] = {
"A rule has a unknown event source. This can occur when reading rules content without "
"having a corresponding plugin loaded, etc. The rule will be silently ignored.",
"Comparing a field value with <NA> is unsafe and can lead to unpredictable behavior of the "
"rule condition. If you need to check for the existence of a field, consider using the "
"'exists' operator instead.",
"A rule condition matches too many evt.type values. This has a significant performance "
"penalty. Make the condition more specific by adding an evt.type field or further "
"restricting the number of evt.type values in the condition.",
"A rule condition or output refers to a field or evt.type that does not exist. This is "
"normally an error, but if a rule has a skip-if-unknown-filter property, the error is "
"downgraded to a warning.",
"A macro is defined in the rules content but is not used by any other macro or rule.",
"A list is defined in the rules content but is not used by any other list, macro, or rule.",
"An unknown top-level object is in the rules content. It will be ignored.",
"A deprecated item is employed by lists, macros, or rules.",
"An extension item has a warning",
"A rule exception is overriding/appending with no values",
"A rule is defining multiple exceptions with the same name",
"A macro is defined with an invalid name",
"A list is defined with an invalid name",
"A rule condition or output have been parsed with a warning"};
// Compile-time check to ensure warning_descs array has the correct size
static_assert(std::size(warning_descs) ==
static_cast<int>(falco::load_result::warning_code::LOAD_COMPILE_CONDITION) +
1,
"warning_descs array size must match the last warning_code enum value + 1");
const std::string& falco::load_result::warning_desc(warning_code wc) {
return warning_descs[static_cast<int>(wc)];
}
static const std::string deprecated_fields[] = {"evt.dir",
"evt.latency",
"evt.latency.s",
"evt.latency.ns",
"evt.latency.human",
"evt.wait_latency"};
// Compile-time check to ensure deprecated_fields array has the correct size
static_assert(
std::size(deprecated_fields) ==
static_cast<int>(falco::load_result::deprecated_field::DEPRECATED_FIELD_NOT_FOUND),
"deprecated_fields array size must match DEPRECATED_FIELD_NOT_FOUND enum value");
const std::string& falco::load_result::deprecated_field_str(deprecated_field df) {
return deprecated_fields[static_cast<int>(df)];
}
// Shared description suffix for latency fields
static const std::string latency_field_desc_suffix =
"field is not available due to the drop of enter events.";
static const std::string deprecated_field_descs[] = {
"due to the drop of enter events, 'evt.dir = <' always evaluates to true, and 'evt.dir = "
">' always evaluates to false. The rule expression can be simplified by removing the "
"condition on 'evt.dir'",
latency_field_desc_suffix,
latency_field_desc_suffix,
latency_field_desc_suffix,
latency_field_desc_suffix,
latency_field_desc_suffix};
// Compile-time check to ensure deprecated_field_descs array has the correct size
static_assert(
std::size(deprecated_field_descs) ==
static_cast<int>(falco::load_result::deprecated_field::DEPRECATED_FIELD_NOT_FOUND),
"deprecated_field_descs array size must match DEPRECATED_FIELD_NOT_FOUND enum value");
const std::string& falco::load_result::deprecated_field_desc(deprecated_field df) {
return deprecated_field_descs[static_cast<int>(df)];
}
falco::load_result::deprecated_field falco::load_result::deprecated_field_from_str(
const std::string& f) {
return falco::load_result::deprecated_field(
std::find(std::begin(deprecated_fields), std::end(deprecated_fields), f) -
std::begin(deprecated_fields));
}