Old gcc versions (e.g. 4.8.3) won't allow move elision
but newer versions (e.g. 10.2.1) would complain about
the redundant move.
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
* prefix counters and stats belonging to kernel space w/ `k.` else `u.` for userspace
* add n_drops_perc from old stats writer schema
* revert one change: file output shall reflect exact same "output_fields" key as rule output, note that src is already part of the "output_fields" schema.
Co-authored-by: Jason Dellaluce <jasondellaluce@gmail.com>
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
- avoiding inspector to be allocated for each rule
- use two boolean values for expecting macros and lists
- move items of lists alongside name, under info
- use snake case for json output, like we do for e.g alerts
- correctly retrieve evt names
- consider two levels of lists for exception operators
Signed-off-by: Lorenzo Susini <susinilorenzo1@gmail.com>
* address reviewers feedback
* improve clarity around new -A and -i behavior
* additional cleanup (e.g. use generic set operations only)
* extend unit tests
Note: sinsp ppm sc API is undergoing a refactor, therefore current lookups are interim
and will subsequently be refactored as well.
Co-authored-by: Jason Dellaluce <jasondellaluce@gmail.com>
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
In the copy constructor and assignment operator for falco_source, also
copy the ruleset along with factories/name.
Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
Now that ASTs contain parse positions, use them when reporting errors
about unknown macros.
When doing the first pass to find all macro references, save macros as
a map<macro name,parse position> instead of a set<macro name>. While
making that change, change the visitor struct to use references
instead of pointers.
In the second pass, when reporting any unresolved macro references,
also report the parse position.
The unit tests also check that the positions of macros are properly
returned in the resolved/unresolved maps.
Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
Now that ASTs have parse positions and the compiler will return the
position of the last error, use that in falco rules to return errors
within condition strings instead of reporting the position as the
beginning of the condition.
This led to a change in the filter_ruleset interface--now, an ast is
compiled to a filter before being passed to the filter_ruleset
object. That avoids polluting the interface with a lot of details
about rule_loader contexts, errors, etc. The ast is still provided in
case the filter_ruleset wants to do indexing/analysis of the filter.
Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
The optimization in https://github.com/falcosecurity/falco/pull/2210
had a bug when the engine uses multiple sources at the same
time--m_syscall_source is a pointer to an entry in the indexed vector
m_sources, but if add_source is called multiple times, the vector is
resized, which copies the structs but invalidates any pointer to the
vector entries.
So instead of caching m_syscall_source in add_source(), cache it in
process_events(). m_sources won't change once processing events starts.
Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
Instead of using a falco_rule struct on the stack, use a single value
inside the falco_source struct. It's mutable as find_source returns a
const struct.
At very high event volumes (> 1M syscalls/second), even the tiny time
it takes to create/destroy the struct starts to add up, and this
switch has some small cpu savings.
Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
When doing some testing of falco on very high event volumes (> 1.5M
events/second), I found that the time taken to look up a falco_source
struct had a non-negligible contribution to cpu usage.
So instead of looking up the source from the source_idx every time,
separately save the source for syscalls in the falco_engine object
directly. The separately saved copy is only used once someone calls
add_source with source="syscall".
Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
Use an enum instead of a string for the item_type aka "parts of a
rules file" field of contexts.
The set of values is mostly defined by the contexts that were already
created. There are a couple of forward-looking values for rule
outputs/macro conditions/etc. that may be useful for later.
Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
In #2098 and #2158, we reworked how rules loading errors/warnings were
returned to provide a richer set of information, including
locations/context for the errors/warnings.
That did *not* include locations within condition expressions,
though. When parsing a condition expression resulted in a
warning/error, the location simply pointed to the condition property
of the rule.
This commit improves this to handle parse errors:
- When libsinsp::filter::parser::parse() throws an exception, use
get_pos() to get the position within the condition string.
- Add a new context() constructor that takes a filter pos_info instead
of a YAML::Mark.
Now that positions aren't always related to the location of yaml
nodes, Make up a generic "position" struct for locations and convert
YAML::Mark and parser positions to a position struct.
Also allow a context to contain an alternate content string which is
used to build the snippet. For contexts related to condition strings,
the content is the condition.
Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
In outputs it could be confusing to see a line:
<filename>: Ok
followed by a set of warnings.
To differentiate this, add a top level status "Ok, with warnings" when
rule loading was successful but had warnings.
Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
The methods that throw exceptions from stringified results need to
additionally pass a rules_contents_t struct. This also meant that they
need to call the filename + content version of load_rules.
To avoid some duplicate code between the two load_rules_file methods,
move the work of opening the file into a private method
read_file(). It can throw an exception, which is passed through for
the void return method and caught + converted into a load_result error
for the method that returns a load_result.
Also, to avoid duplicate code between the void load_rules and
load_rules_file methods, add a private method interpret_load_result()
which throws an exception if the result has an error and prints
warnings otherwise if verbose is true.
Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
The old version of rules_result assumed that all errors/warnings were
related to a single file. That was generally correct for errors, as
rules parsing always stopped at the first error, so there is only one
relevant file.
However, for warnings that was not the case. When reading multiple
files A and B, you might get a warning from file A *only* after
reading file B. For example, B might redefine a rule in such a way
that you could get unused list/macro warnings from file A.
To properly address this, make some changes to how contexts are
managed:
- Instead of creating snippets at the time the error/warning was
generated, create snippets at the time the error/warning is
converted into a string. This requires passing all rules contents to
as_string()/as_json(), so define a
falco::load_result::rules_contents_t map from filename to rules
content (reference) and pass it in as_string/as_json(). Snippets are
now generated from the rules content matching the filename in the
context.
- When creating warnings/errors, there's no need to pass along the
rules content. This is only used when converting an error into a
string/json.
Also change snippet() to handle potentially very long lines. Instead
of always printing the entire line matching a location, print up to
snippet_width(param, with default 160 chars)/2 characters surrounding
the column from the location.
Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
Changes to the rule loader to support result objects:
- Instead of throwing falco_exception on internal error, throw a
rule_load_exception instead, which contains distinct
error/message/context information.
- A context object contains a chain of location structs chaining from
the document root to the object where the error occurred. Each
location has a file position (as a YAML::Mark), an item
type (e.g. "rule", "list", "exception"), and an item name (e.g. "Write
Below Etc"). This will allow showing the exact location of an
error (e.g. list item/exception field) while also remembering the item
that contained it.
- All the _info structs now contain a context so errors that occur
after yaml parsing can still point to the original location in the
yaml file.
- rule_loader::result is an implementation of the abstract class
defined in falco_load_result. The implementation keeps track of a
list of errors/warnigns that used to be in the configuration object,
- Clean up compile_ methods to just throw rule_load_exceptions or
return nothing, and ensure that all rule_load_exceptions are caught in
compile(). When caught, errors are added to the result object.
Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
Modify rule reader to use a result struct for errors and warnings:
- Instead of throwing a falco_exception to pass back errors, use a
rule_load_exception, which contains distinct error codes, messages,
and a context that points to the location of the error.
- The static method context_yaml_get_context() has moved to a method
of the rule_loader context object + the result as_string() method.
- As objects are parsed, create relevant context objects as reading
drills down into the contents of a rule/list/exception. This will
enable for specific errors in, say, the middle of an exception/list
while remembering the object that contains it.
- Modify decode_val()/decode_seq() to always return errors as
exceptions. Previously, it was a mix of a bool return + some
exceptions.
- decode_val()/decode_seq() are now more consistent about returning
distinct errors for the property not existing, the property existing
but not being a scalar/sequence value, and not being convertable to
the templated value.
- Combine the two nearly identical decode_seq() functions into a
single one that uses a lambda to perform the final step of adding to
the vector/set.
- There are some item-specific decode_xxx functions for specific
item properties like tags, exceptions fields/comps/values, etc.
that call the above functions.
These changes simplify the calls to decode_seq()/decode_val() as they
don't need to add their own errors when returning false. Also some
calls weren't checking the return value.
Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
Now that we have a result struct and set of warning codes, change the
filter_warning_resolver to use them. This involves populating a set of
warning codes instead of strings.
Also, the methods to format warnings into human-readable strings is
now in the falco_load_result static methods, so move the text there
and remove the methods here.
Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
Add new load_rules methods that return a result object instead of
throwing exceptions on error. The existing load_rules methods call the
new methods internally and continue to throw exceptions on
error/return individual values on success.
The result is returned as a unique_ptr so it can be populated while
loading rules (as a part of the configuration object) and then move()d
to the return value.
Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
Define a falco_load_result abstract class for use in new load_rules
methods. It's abstract so the implementation details in
rule_loader/rule_reader can be hidden from someone who wants to use
the API to load rules and work with a result.
The class defines a set of error codes/warning codes and has static
methods to get a short and long description of each error/warning.
There are virtual methods to access the important parts of a result:
- successful or not
- a string representation of the result, suitable for display to
users. Takes a verbose argument. When verbose is true, the string is
multi-line and has full details, including locations, item names,
etc. When verbose is false, the string is single-line and just
returns error codes.
- a json representation of the result, suitable for automated
parsing/interpretation later.
Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
The only use of it was to include in --support output, which is
redundant as the support output already includes the full contents of
each rules file.
Additionally, it wasn't even being updated after the switch from lua
rules loading to c++ rules
loading (https://github.com/falcosecurity/falco/pull/1966/ or
surrounding PRs).
This will simplify follow-on changes to add a real "result" to rules
loading methods, as there will be fewer API variants to support.
Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
This updates the engine to comply and work properly with the newly-introduced
interface design.
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
The filter_ruleset interface its implementation evt_type_index_ruleset
have been modified as follows:
- Only keep track of ruleset ids and not names. The falco engine will take
care of mapping easy-to-remember ruleset names to ruleset ids.
To emphasize this, use ruleset_id everywhere and not ruleset.
Also, make it non-optional.
- Have explicit separate functions to enable/disable rules, instead of a single enable() method combined with a boolean flag.
This does *not* change the falco_engine interface, which has
similar methods, to avoid breaking API changes.
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
Co-authored-by: Mark Stemm <mark.stemm@gmail.com>
This also fixes a couple of bugs. With the current implementation, the multi-ruleset feature is broken with multiple sources.
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
This interface will allow us to use different ruleset implementations inside the same engine.
The goal is to define API boundaries that will allow swapping the current evttype-index
ruleset implementation more easily. Key benefits include: smaller component with less responsibilities,
easier substituibility, more testable design, opportunity to adopt different index strategies
depending on the ruleset implementation.
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
When adding an implied "in" comparison to an exception using the
single value form, add it to item, not items.
This fixes#1984.
Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
This include making a coherent use of const, remove private inheritance, and adding virtual destructors.
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
Some objects used by falco (falco outputs, falco_formats, etc) were
using raw pointer references, which isn't great.
So convert use of raw pointers (originally passed from falco_init or
functions it called) with shared_ptr, as they are now held in
application state.
Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
The first warnings we support involve the unsafe comparisons with <NA>, which were present
in the legacy regression tests for PSPs.
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>