Compare commits

...

19 Commits

Author SHA1 Message Date
Andrea Terzolo
9763809cd9 update(ci): enable gh actions jobs on 'maintainers/*' branches
Signed-off-by: Andrea Terzolo <andrea.terzolo@polito.it>
2022-12-13 16:29:00 +01:00
Jason Dellaluce
5552bcab76 chore: fix typo
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2022-12-13 15:06:10 +01:00
Jason Dellaluce
cb58ea9c57 test: add regression tests for ref loops in lists and macros
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2022-12-13 15:06:10 +01:00
Jason Dellaluce
0a6db28783 fix(test/engine): solve compilation issues with macro resolver
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2022-12-13 15:06:10 +01:00
Jason Dellaluce
25ddc3c6a2 update(userspace/engine): broader err catching support in macro resolver
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2022-12-13 15:06:10 +01:00
Jason Dellaluce
35dd0fc153 fix(userspace/engine): implement loop detection in macro resolver
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2022-12-13 15:06:10 +01:00
Federico Di Pierro
0c39776557 chore(ci): properly checkout pull request HEAD instead of merge commit in gh actions.
See https://github.com/actions/checkout#checkout-pull-request-head-commit-instead-of-merge-commit.

Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2022-12-12 11:11:44 +01:00
Federico Di Pierro
4696948754 fix(cmake): properly fetch dev version by appending latest Falco tag, delta between master and tag, and hash.
`describe` can no more be used as tags are now made on release branches.

Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2022-12-12 11:11:44 +01:00
dependabot[bot]
ec04b758e6 chore(deps): Bump certifi from 2020.4.5.1 to 2022.12.7 in /test
Bumps [certifi](https://github.com/certifi/python-certifi) from 2020.4.5.1 to 2022.12.7.
- [Release notes](https://github.com/certifi/python-certifi/releases)
- [Commits](https://github.com/certifi/python-certifi/compare/2020.04.05.1...2022.12.07)

---
updated-dependencies:
- dependency-name: certifi
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-12 11:01:44 +01:00
Andrea Terzolo
52ee61b800 chore(userspace): add njson lib as a dependency for falco_engine
Signed-off-by: Andrea Terzolo <andrea.terzolo@polito.it>
2022-12-10 17:07:06 +01:00
gentooise
70dfdb2e75 support older rhel distros in falco-driver-loader
Tested on RHEL 6

Signed-off-by: gentooise <andrea.genuise@ibm.com>
2022-12-09 12:03:13 +01:00
Federico Di Pierro
1b227cf90b update(cmake): bumped libs and driver to latest RC.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2022-12-06 12:59:50 +01:00
Andrea Terzolo
ff3a38415d fix: remove conflicting helper methods
Signed-off-by: Andrea Terzolo <andrea.terzolo@polito.it>
2022-12-06 12:59:50 +01:00
Andrea Terzolo
94ed56df95 chore: bump libs
Signed-off-by: Andrea Terzolo <andrea.terzolo@polito.it>
2022-12-06 12:59:50 +01:00
Andrea Terzolo
6a972272c0 update: the capture will be stopped in the inspector destructor
Signed-off-by: Andrea Terzolo <andrea.terzolo@polito.it>
2022-12-06 12:59:50 +01:00
Andrea Terzolo
55deb452d8 update: start/stop capture inside do_inspect
Signed-off-by: Andrea Terzolo <andrea.terzolo@polito.it>
2022-12-06 12:59:50 +01:00
Federico Di Pierro
87371492c5 update(userspace/engine): updated checksum.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2022-12-06 12:59:50 +01:00
Federico Di Pierro
17dfe4f55d fix(userspace/falco): properly start/stop capture.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2022-12-06 12:59:50 +01:00
Federico Di Pierro
928ad6625b update(cmake): update libs to 8eef2e445364d892dba12564d20f9651232eba7c
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2022-12-06 12:59:50 +01:00
18 changed files with 304 additions and 96 deletions

View File

@@ -3,7 +3,9 @@ on:
pull_request:
branches: [master]
push:
branches: [master]
branches:
- master
- 'maintainers/**'
workflow_dispatch:
jobs:
@@ -14,6 +16,7 @@ jobs:
uses: actions/checkout@v3
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
- name: Update base image
run: sudo apt update -y
@@ -47,6 +50,7 @@ jobs:
uses: actions/checkout@v3
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
- name: Update base image
run: sudo apt update -y
@@ -80,6 +84,7 @@ jobs:
uses: actions/checkout@v3
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
- name: Update base image
run: sudo apt update -y
@@ -113,6 +118,7 @@ jobs:
uses: actions/checkout@v3
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
- name: Update base image
run: sudo apt update -y
@@ -151,6 +157,7 @@ jobs:
with:
fetch-depth: 0
path: falco
ref: ${{ github.event.pull_request.head.sha }}
- name: Link falco repo to /source/falco
run: |
@@ -167,4 +174,4 @@ jobs:
run: /usr/bin/entrypoint tests
- name: Build packages
run: /usr/bin/entrypoint package
run: /usr/bin/entrypoint package

View File

@@ -16,18 +16,32 @@ include(GetGitRevisionDescription)
# Create the falco version variable according to git index
if(NOT FALCO_VERSION)
string(STRIP "${FALCO_HASH}" FALCO_HASH)
# Try to obtain the exact git tag
git_get_exact_tag(FALCO_TAG)
if(NOT FALCO_TAG)
# Obtain the closest tag
git_describe(FALCO_VERSION "--always" "--tags" "--abbrev=7")
# Fallback version
if(FALCO_VERSION MATCHES "NOTFOUND$")
set(FALCO_VERSION "0.0.0")
endif()
# Format FALCO_VERSION to be semver with prerelease and build part
string(REPLACE "-g" "+" FALCO_VERSION "${FALCO_VERSION}")
# Fetch current hash
get_git_head_revision(refspec FALCO_HASH)
if(NOT FALCO_HASH OR FALCO_HASH MATCHES "NOTFOUND$")
set(FALCO_VERSION "0.0.0")
else()
# Obtain the closest tag
git_get_latest_tag(FALCO_LATEST_TAG)
if(NOT FALCO_LATEST_TAG OR FALCO_LATEST_TAG MATCHES "NOTFOUND$")
set(FALCO_VERSION "0.0.0")
else()
# Compute commit delta since tag
git_get_delta_from_tag(FALCO_DELTA ${FALCO_LATEST_TAG} ${FALCO_HASH})
if(NOT FALCO_DELTA OR FALCO_DELTA MATCHES "NOTFOUND$")
set(FALCO_VERSION "0.0.0")
else()
# Cut hash to 7 bytes
string(SUBSTRING ${FALCO_HASH} 0 7 FALCO_HASH)
# Format FALCO_VERSION to be semver with prerelease and build part
set(FALCO_VERSION
"${FALCO_LATEST_TAG}-${FALCO_DELTA}+${FALCO_HASH}")
endif()
endif()
endif()
else()
# A tag has been found: use it as the Falco version
set(FALCO_VERSION "${FALCO_TAG}")

View File

@@ -86,29 +86,36 @@ function(get_git_head_revision _refspecvar _hashvar)
PARENT_SCOPE)
endfunction()
function(git_describe _var)
function(git_get_latest_tag _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
get_git_head_revision(refspec hash)
if(NOT GIT_FOUND)
set(${_var}
"GIT-NOTFOUND"
PARENT_SCOPE)
return()
endif()
if(NOT hash)
set(${_var}
"HEAD-HASH-NOTFOUND"
PARENT_SCOPE)
# We use git describe --tags `git rev-list --tags --max-count=1`
execute_process(COMMAND
"${GIT_EXECUTABLE}"
rev-list
--tags
--max-count=1
WORKING_DIRECTORY
"${CMAKE_CURRENT_SOURCE_DIR}"
COMMAND tail -n1
RESULT_VARIABLE
res
OUTPUT_VARIABLE
tag_hash
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT res EQUAL 0)
set(out "${tag_hash}-${res}-NOTFOUND" PARENT_SCOPE)
return()
endif()
execute_process(COMMAND
"${GIT_EXECUTABLE}"
describe
${hash}
${ARGN}
--tags
${tag_hash}
WORKING_DIRECTORY
"${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE
@@ -120,10 +127,108 @@ function(git_describe _var)
if(NOT res EQUAL 0)
set(out "${out}-${res}-NOTFOUND")
endif()
set(${_var} "${out}" PARENT_SCOPE)
endfunction()
function(git_get_delta_from_tag _var tag hash)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
# Count commits in HEAD
execute_process(COMMAND
"${GIT_EXECUTABLE}"
rev-list
--count
${hash}
WORKING_DIRECTORY
"${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE
res
OUTPUT_VARIABLE
out_counter_head
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT res EQUAL 0)
set(${_var} "HEADCOUNT-NOTFOUND" PARENT_SCOPE)
return()
endif()
# Count commits in latest tag
execute_process(COMMAND
"${GIT_EXECUTABLE}"
rev-list
--count
${tag}
WORKING_DIRECTORY
"${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE
res
OUTPUT_VARIABLE
out_counter_tag
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT res EQUAL 0)
set(${_var} "TAGCOUNT-NOTFOUND" PARENT_SCOPE)
return()
endif()
execute_process(COMMAND
expr
${out_counter_head} - ${out_counter_tag}
WORKING_DIRECTORY
"${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE
res
OUTPUT_VARIABLE
out_delta
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT res EQUAL 0)
set(${_var} "DELTA-NOTFOUND" PARENT_SCOPE)
return()
endif()
set(${_var} "${out_delta}" PARENT_SCOPE)
endfunction()
function(git_describe _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
get_git_head_revision(refspec hash)
if(NOT GIT_FOUND)
set(${_var}
"GIT-NOTFOUND"
PARENT_SCOPE)
return()
endif()
if(NOT hash)
set(${_var}
"HEAD-HASH-NOTFOUND"
PARENT_SCOPE)
return()
endif()
execute_process(COMMAND
"${GIT_EXECUTABLE}"
describe
${hash}
${ARGN}
WORKING_DIRECTORY
"${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE
res
OUTPUT_VARIABLE
out
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT res EQUAL 0)
set(out "${out}-${res}-NOTFOUND")
endif()
set(${_var}
"${out}"
PARENT_SCOPE)
"${out}"
PARENT_SCOPE)
endfunction()
function(git_get_exact_tag _var)

View File

@@ -26,8 +26,8 @@ else()
# In case you want to test against another driver version (or branch, or commit) just pass the variable -
# ie., `cmake -DDRIVER_VERSION=dev ..`
if(NOT DRIVER_VERSION)
set(DRIVER_VERSION "dd443b67c6b04464cb8ee2771af8ada8777e7fac")
set(DRIVER_CHECKSUM "SHA256=df373099d0f4cd4417a0103bb57f26c7412ffa86cde2bb2d579c6feba841626d")
set(DRIVER_VERSION "4.0.0-rc1+driver")
set(DRIVER_CHECKSUM "SHA256=82d18ca00d245e5b7195c420b00a4c895190b6de77be0feb13b98861d749f257")
endif()
# cd /path/to/build && cmake /path/to/source

View File

@@ -27,8 +27,8 @@ else()
# In case you want to test against another falcosecurity/libs version (or branch, or commit) just pass the variable -
# ie., `cmake -DFALCOSECURITY_LIBS_VERSION=dev ..`
if(NOT FALCOSECURITY_LIBS_VERSION)
set(FALCOSECURITY_LIBS_VERSION "dd443b67c6b04464cb8ee2771af8ada8777e7fac")
set(FALCOSECURITY_LIBS_CHECKSUM "SHA256=df373099d0f4cd4417a0103bb57f26c7412ffa86cde2bb2d579c6feba841626d")
set(FALCOSECURITY_LIBS_VERSION "0.10.0-rc1")
set(FALCOSECURITY_LIBS_CHECKSUM "SHA256=af2fcd9017d1611d3c5068405632eb3aa5cd578514ed8f06cb02ebca5556fd1d")
endif()
# cd /path/to/build && cmake /path/to/source

View File

@@ -113,6 +113,9 @@ get_target_id() {
elif [ -f "${HOST_ROOT}/etc/centos-release" ]; then
# Older CentOS distros
OS_ID=centos
elif [ -f "${HOST_ROOT}/etc/redhat-release" ]; then
# Older RHEL distros
OS_ID=rhel
else
return 1
fi

View File

@@ -358,6 +358,16 @@ trace_files: !mux
validate_rules_file:
- rules/invalid_macro_without_condition.yaml
trace_file: trace_files/cat_write.scap
invalid_macro_loop:
exit_status: 1
validate_errors:
- item_type: macro
item_name: macro_a
code: LOAD_ERR_VALIDATE
message_contains: "reference loop in macro"
validate_rules_file:
- rules/invalid_macro_loop.yaml
invalid_rule_without_output:
exit_status: 1
@@ -403,6 +413,16 @@ trace_files: !mux
- rules/list_append_failure.yaml
trace_file: trace_files/cat_write.scap
invalid_list_loop:
exit_status: 1
validate_errors:
- item_type: rule
item_name: sample rule
code: LOAD_ERR_COMPILE_CONDITION
message: "unknown event type list_a"
validate_rules_file:
- rules/invalid_list_loop.yaml
invalid_rule_append_dangling:
exit_status: 1
validate_errors:

View File

@@ -1,6 +1,6 @@
avocado-framework==69.0
avocado-framework-plugin-varianter-yaml-to-mux==69.0
certifi==2020.4.5.1
certifi==2022.12.7
chardet==3.0.4
idna==2.9
pathtools==0.1.2

View File

@@ -0,0 +1,17 @@
- list: list_a
items: [open]
- list: list_b
items: [list_a]
- list: list_a
items: [list_b]
- macro: macro_a
condition: evt.type in (list_a)
- rule: sample rule
priority: WARNING
output: test
desc: testdesc
condition: macro_a

View File

@@ -0,0 +1,8 @@
- macro: macro_a
condition: evt.type=open
- macro: macro_b
condition: macro_a
- macro: macro_a
condition: macro_b

View File

@@ -20,27 +20,20 @@ limitations under the License.
using namespace std;
using namespace libsinsp::filter::ast;
static pos_info create_pos(uint32_t idx, uint32_t line, uint32_t col)
static std::vector<filter_macro_resolver::value_info>::const_iterator find_value(
const std::vector<filter_macro_resolver::value_info>& values,
const std::string& ref)
{
pos_info ret;
ret.idx = idx;
ret.line = line;
ret.col = col;
return ret;
}
static bool operator==(const pos_info& p1, const pos_info& p2)
{
return (p1.idx == p2.idx) &&
(p1.line == p2.line) &&
(p1.col == p2.col);
return std::find_if(
values.begin(),
values.end(),
[&ref](const filter_macro_resolver::value_info& v) { return v.first == ref; });
}
TEST_CASE("Should resolve macros on a filter AST", "[rule_loader]")
{
string macro_name = "test_macro";
pos_info macro_pos = create_pos(12, 85, 27);
pos_info macro_pos(12, 85, 27);
SECTION("in the general case")
{
@@ -109,8 +102,8 @@ TEST_CASE("Should resolve macros on a filter AST", "[rule_loader]")
string a_macro_name = macro_name + "_1";
string b_macro_name = macro_name + "_2";
pos_info a_macro_pos = create_pos(11, 75, 43);
pos_info b_macro_pos = create_pos(91, 21, 9);
pos_info a_macro_pos(11, 75, 43);
pos_info b_macro_pos(91, 21, 9);
std::shared_ptr<expr> a_macro = std::move(
unary_check_expr::create("one.field", "", "exists"));
@@ -134,12 +127,12 @@ TEST_CASE("Should resolve macros on a filter AST", "[rule_loader]")
// first run
REQUIRE(resolver.run(filter) == true);
REQUIRE(resolver.get_resolved_macros().size() == 2);
auto a_resolved_itr = resolver.get_resolved_macros().find(a_macro_name);
auto a_resolved_itr = find_value(resolver.get_resolved_macros(), a_macro_name);
REQUIRE(a_resolved_itr != resolver.get_resolved_macros().end());
REQUIRE(a_resolved_itr->first == a_macro_name);
REQUIRE(a_resolved_itr->second == a_macro_pos);
auto b_resolved_itr = resolver.get_resolved_macros().find(b_macro_name);
auto b_resolved_itr = find_value(resolver.get_resolved_macros(), b_macro_name);
REQUIRE(b_resolved_itr != resolver.get_resolved_macros().end());
REQUIRE(resolver.get_unknown_macros().empty());
REQUIRE(b_resolved_itr->first == b_macro_name);
@@ -158,8 +151,8 @@ TEST_CASE("Should resolve macros on a filter AST", "[rule_loader]")
string a_macro_name = macro_name + "_1";
string b_macro_name = macro_name + "_2";
pos_info a_macro_pos = create_pos(47, 1, 76);
pos_info b_macro_pos = create_pos(111, 65, 2);
pos_info a_macro_pos(47, 1, 76);
pos_info b_macro_pos(111, 65, 2);
std::vector<std::unique_ptr<expr>> a_macro_and;
a_macro_and.push_back(unary_check_expr::create("one.field", "", "exists"));
@@ -183,12 +176,12 @@ TEST_CASE("Should resolve macros on a filter AST", "[rule_loader]")
// first run
REQUIRE(resolver.run(filter) == true);
REQUIRE(resolver.get_resolved_macros().size() == 2);
auto a_resolved_itr = resolver.get_resolved_macros().find(a_macro_name);
auto a_resolved_itr = find_value(resolver.get_resolved_macros(), a_macro_name);
REQUIRE(a_resolved_itr != resolver.get_resolved_macros().end());
REQUIRE(a_resolved_itr->first == a_macro_name);
REQUIRE(a_resolved_itr->second == a_macro_pos);
auto b_resolved_itr = resolver.get_resolved_macros().find(b_macro_name);
auto b_resolved_itr = find_value(resolver.get_resolved_macros(), b_macro_name);
REQUIRE(b_resolved_itr != resolver.get_resolved_macros().end());
REQUIRE(resolver.get_unknown_macros().empty());
REQUIRE(b_resolved_itr->first == b_macro_name);
@@ -208,7 +201,7 @@ TEST_CASE("Should resolve macros on a filter AST", "[rule_loader]")
TEST_CASE("Should find unknown macros", "[rule_loader]")
{
string macro_name = "test_macro";
pos_info macro_pos = create_pos(9, 4, 2);
pos_info macro_pos(9, 4, 2);
SECTION("in the general case")
{
@@ -230,8 +223,8 @@ TEST_CASE("Should find unknown macros", "[rule_loader]")
string a_macro_name = macro_name + "_1";
string b_macro_name = macro_name + "_2";
pos_info a_macro_pos = create_pos(32, 84, 9);
pos_info b_macro_pos = create_pos(1, 0, 5);
pos_info a_macro_pos(32, 84, 9);
pos_info b_macro_pos(1, 0, 5);
std::vector<std::unique_ptr<expr>> a_macro_and;
a_macro_and.push_back(unary_check_expr::create("one.field", "", "exists"));
@@ -259,8 +252,8 @@ TEST_CASE("Should find unknown macros", "[rule_loader]")
TEST_CASE("Should undefine macro", "[rule_loader]")
{
string macro_name = "test_macro";
pos_info macro_pos_1 = create_pos(12, 9, 3);
pos_info macro_pos_2 = create_pos(9, 6, 3);
pos_info macro_pos_1(12, 9, 3);
pos_info macro_pos_2(9, 6, 3);
std::shared_ptr<expr> macro = std::move(unary_check_expr::create("test.field", "", "exists"));
std::shared_ptr<expr> a_filter = std::move(value_expr::create(macro_name, macro_pos_1));
@@ -287,7 +280,7 @@ TEST_CASE("Should undefine macro", "[rule_loader]")
TEST_CASE("Should clone macro AST", "[rule_loader]")
{
string macro_name = "test_macro";
pos_info macro_pos = create_pos(5, 2, 8888);
pos_info macro_pos(5, 2, 8888);
std::shared_ptr<unary_check_expr> macro = std::move(unary_check_expr::create("test.field", "", "exists"));
std::shared_ptr<expr> filter = std::move(value_expr::create(macro_name, macro_pos));
filter_macro_resolver resolver;

View File

@@ -30,7 +30,7 @@ set(FALCO_ENGINE_SOURCE_FILES
add_library(falco_engine STATIC ${FALCO_ENGINE_SOURCE_FILES})
if(USE_BUNDLED_DEPS)
add_dependencies(falco_engine yamlcpp)
add_dependencies(falco_engine yamlcpp njson)
endif()
if(MINIMAL_BUILD)

View File

@@ -21,4 +21,4 @@ limitations under the License.
// This is the result of running "falco --list -N | sha256sum" and
// represents the fields supported by this version of Falco. It's used
// at build time to detect a changed set of fields.
#define FALCO_FIELDS_CHECKSUM "674c6cf2bc1c105038c8676f018fa3d1431d86597df428453441f5d859cad284"
#define FALCO_FIELDS_CHECKSUM "cc9d32916c719ce5aea164cdadb56207cbeff20033e278b99101964be7aa77a1"

View File

@@ -15,6 +15,7 @@ limitations under the License.
*/
#include "filter_macro_resolver.h"
#include "falco_common.h"
using namespace std;
using namespace libsinsp::filter;
@@ -23,8 +24,9 @@ bool filter_macro_resolver::run(libsinsp::filter::ast::expr*& filter)
{
m_unknown_macros.clear();
m_resolved_macros.clear();
m_errors.clear();
visitor v(m_unknown_macros, m_resolved_macros, m_macros);
visitor v(m_errors, m_unknown_macros, m_resolved_macros, m_macros);
v.m_node_substitute = nullptr;
filter->accept(&v);
if (v.m_node_substitute)
@@ -39,8 +41,9 @@ bool filter_macro_resolver::run(std::shared_ptr<libsinsp::filter::ast::expr>& fi
{
m_unknown_macros.clear();
m_resolved_macros.clear();
m_errors.clear();
visitor v(m_unknown_macros, m_resolved_macros, m_macros);
visitor v(m_errors, m_unknown_macros, m_resolved_macros, m_macros);
v.m_node_substitute = nullptr;
filter->accept(&v);
if (v.m_node_substitute)
@@ -57,12 +60,17 @@ void filter_macro_resolver::set_macro(
m_macros[name] = macro;
}
const filter_macro_resolver::macro_info_map& filter_macro_resolver::get_unknown_macros() const
const std::vector<filter_macro_resolver::value_info>& filter_macro_resolver::get_unknown_macros() const
{
return m_unknown_macros;
}
const filter_macro_resolver::macro_info_map& filter_macro_resolver::get_resolved_macros() const
const std::vector<filter_macro_resolver::value_info>& filter_macro_resolver::get_errors() const
{
return m_errors;
}
const std::vector<filter_macro_resolver::value_info>& filter_macro_resolver::get_resolved_macros() const
{
return m_resolved_macros;
}
@@ -125,9 +133,21 @@ void filter_macro_resolver::visitor::visit(ast::value_expr* e)
// we are supposed to get here only in case
// of identier-only children from either a 'not',
// an 'and' or an 'or'.
auto macro = m_macros.find(e->value);
const auto& macro = m_macros.find(e->value);
if (macro != m_macros.end() && macro->second) // skip null-ptr macros
{
// note: checks for loop detection
const auto& prevref = std::find(m_macros_path.begin(), m_macros_path.end(), macro->first);
if (prevref != m_macros_path.end())
{
auto msg = "reference loop in macro '" + macro->first + "'";
m_errors.push_back({msg, e->get_pos()});
m_node_substitute = nullptr;
m_unknown_macros.push_back({e->value, e->get_pos()});
return;
}
m_macros_path.push_back(macro->first);
m_node_substitute = nullptr;
auto new_node = ast::clone(macro->second.get());
new_node->accept(this);
@@ -137,11 +157,12 @@ void filter_macro_resolver::visitor::visit(ast::value_expr* e)
{
m_node_substitute = std::move(new_node);
}
m_resolved_macros[e->value] = e->get_pos();
m_resolved_macros.push_back({e->value, e->get_pos()});
m_macros_path.pop_back();
}
else
{
m_node_substitute = nullptr;
m_unknown_macros[e->value] = e->get_pos();
m_unknown_macros.push_back({e->value, e->get_pos()});
}
}

View File

@@ -59,16 +59,17 @@ class filter_macro_resolver
std::shared_ptr<libsinsp::filter::ast::expr> macro);
/*!
\brief used in get_{resolved,unknown}_macros
\brief used in get_{resolved,unknown}_macros and get_errors
to represent an identifier/string value along with an AST position.
*/
typedef std::unordered_map<std::string,libsinsp::filter::ast::pos_info> macro_info_map;
typedef std::pair<std::string,libsinsp::filter::ast::pos_info> value_info;
/*!
\brief Returns a set containing the names of all the macros
substituted during the last invocation of run(). Should be
non-empty if the last invocation of run() returned true.
*/
const macro_info_map& get_resolved_macros() const;
const std::vector<value_info>& get_resolved_macros() const;
/*!
\brief Returns a set containing the names of all the macros
@@ -76,7 +77,13 @@ class filter_macro_resolver
A macro remains unresolved if it is found inside the processed
filter but it was not defined with set_macro();
*/
const macro_info_map& get_unknown_macros() const;
const std::vector<value_info>& get_unknown_macros() const;
/*!
\brief Returns a list of errors occurred during
the latest invocation of run().
*/
const std::vector<value_info>& get_errors() const;
private:
typedef std::unordered_map<
@@ -86,17 +93,25 @@ class filter_macro_resolver
struct visitor : public libsinsp::filter::ast::expr_visitor
{
visitor(macro_info_map& unknown_macros, macro_info_map& resolved_macros, macro_defs& macros)
: m_unknown_macros(unknown_macros), m_resolved_macros(resolved_macros), m_macros(macros) {}
visitor(
std::vector<value_info>& errors,
std::vector<value_info>& unknown_macros,
std::vector<value_info>& resolved_macros,
macro_defs& macros):
m_errors(errors),
m_unknown_macros(unknown_macros),
m_resolved_macros(resolved_macros),
m_macros(macros) {}
visitor(visitor&&) = default;
visitor& operator = (visitor&&) = default;
visitor(const visitor&) = delete;
visitor& operator = (const visitor&) = delete;
std::vector<std::string> m_macros_path;
std::unique_ptr<libsinsp::filter::ast::expr> m_node_substitute;
macro_info_map& m_unknown_macros;
macro_info_map& m_resolved_macros;
std::vector<value_info>& m_errors;
std::vector<value_info>& m_unknown_macros;
std::vector<value_info>& m_resolved_macros;
macro_defs& m_macros;
void visit(libsinsp::filter::ast::and_expr* e) override;
@@ -108,7 +123,8 @@ class filter_macro_resolver
void visit(libsinsp::filter::ast::binary_check_expr* e) override;
};
macro_info_map m_unknown_macros;
macro_info_map m_resolved_macros;
std::vector<value_info> m_errors;
std::vector<value_info> m_unknown_macros;
std::vector<value_info> m_resolved_macros;
macro_defs m_macros;
};

View File

@@ -248,18 +248,19 @@ static void resolve_macros(
}
macro_resolver.run(ast);
// Note: only complaining about the first unknown macro
const filter_macro_resolver::macro_info_map& unresolved_macros = macro_resolver.get_unknown_macros();
if(!unresolved_macros.empty())
// Note: only complaining about the first error or unknown macro
const auto& errors_macros = macro_resolver.get_errors();
const auto& unresolved_macros = macro_resolver.get_unknown_macros();
if(!errors_macros.empty() || !unresolved_macros.empty())
{
auto it = unresolved_macros.begin();
const rule_loader::context cond_ctx(it->second, condition, ctx);
THROW(true,
std::string("Undefined macro '")
+ it->first
+ "' used in filter.",
cond_ctx);
auto errpos = !errors_macros.empty()
? errors_macros.begin()->second
: unresolved_macros.begin()->second;
std::string errmsg = !errors_macros.empty()
? errors_macros.begin()->first
: ("Undefined macro '" + unresolved_macros.begin()->first + "' used in filter.");
const rule_loader::context cond_ctx(errpos, condition, ctx);
THROW(true, errmsg, cond_ctx);
}
for (auto &it : macro_resolver.get_resolved_macros())

View File

@@ -50,8 +50,8 @@ application::run_result application::do_inspect(
uint64_t duration_to_tot_ns,
uint64_t &num_evts)
{
int32_t rc;
sinsp_evt* ev;
int32_t rc = 0;
sinsp_evt* ev = NULL;
stats_writer::collector stats_collector(statsw);
uint64_t duration_start = 0;
uint32_t timeouts_since_last_success_or_msg = 0;
@@ -91,6 +91,11 @@ application::run_result application::do_inspect(
m_state->config->m_syscall_evt_simulate_drops);
}
//
// Start capture
//
inspector->start_capture();
//
// Loop through the events
//

View File

@@ -16,8 +16,6 @@ limitations under the License.
#pragma once
#define FALCO_BRANCH "@FALCO_REF@"
#define FALCO_HASH "@FALCO_HASH@"
#define FALCO_VERSION "@FALCO_VERSION@"
#define FALCO_VERSION_MAJOR @FALCO_VERSION_MAJOR@
#define FALCO_VERSION_MINOR @FALCO_VERSION_MINOR@