Compare commits

...

57 Commits

Author SHA1 Message Date
Iacopo Rozzo c348dedcfd
Merge b799abca59 into 082157de78 2025-08-07 01:03:27 -07:00
Angelo Puglisi 082157de78 fix(userspace/libsinsp): sinsp_filter_check_user::extract_single return-stack-address
Address the following warning (we build with -Werror...):
```
/__w/libs/libs/userspace/libsinsp/sinsp_filtercheck_user.cpp:104:26: warning: address of stack memory associated with local variable 'user' returned [-Wreturn-stack-address]
  104 |                         RETURN_EXTRACT_STRING(user);
      |                                               ^~~~
/__w/libs/libs/userspace/libsinsp/sinsp_filtercheck_user.cpp:34:21: note: expanded from macro 'RETURN_EXTRACT_STRING'
   34 |                 return (uint8_t*)(x).c_str(); \
      |                                   ^
```

Signed-off-by: Angelo Puglisi <angelopuglisi86@gmail.com>
2025-08-06 16:39:05 +02:00
Holger Hoffstätte a273f3d05c fix(libsinsp): use proper INET6_ADDRSTRLEN buffer size for inet_ntop
glibc-2.42 added __inet_ntop_chk fortification, which started to fail:

  *** buffer overflow detected ***: terminated
  Program received signal SIGABRT, Aborted.
  0x00007ffff629b0dc in __pthread_kill_implementation () from /lib64/libc.so.6
  (gdb) bt
  #0  0x00007ffff629b0dc in __pthread_kill_implementation () from /lib64/libc.so.6
  #1  0x00007ffff6242572 in raise () from /lib64/libc.so.6
  #2  0x00007ffff6229f3b in abort () from /lib64/libc.so.6
  #3  0x00007ffff622b148 in __libc_message_impl.cold () from /lib64/libc.so.6
  #4  0x00007ffff6327337 in __fortify_fail () from /lib64/libc.so.6
  #5  0x00007ffff6326c92 in __chk_fail () from /lib64/libc.so.6
  #6  0x00007ffff6327a62 in __inet_ntop_chk () from /lib64/libc.so.6
  #7  0x000055555569da3d in inet_ntop (__af=10, __src=0x555555ee0800, __dst=0x7fffffff4f90 "\260P\377\377\377\177", __dst_size=100) at /usr/include/bits/inet-fortified.h:36
  #8  ipv6tuple_to_string[abi:cxx11](ipv6tuple*, bool) (tuple=0x555555ee0800, resolve=false) at /tmp/portage/dev-debug/sysdig-0.40.1/work/libs-0.20.0/userspace/libsinsp/utils.c

Use INET6_ADDRSTRLEN as destination buffer size.

Fixes: https://github.com/falcosecurity/libs/issues/2573
Signed-off-by: Holger Hoffstätte <holger@applied-asynchrony.com>
2025-08-04 12:16:49 +02:00
Federico Di Pierro 8cd5fbf687 fix(userspace/libsinsp): properly check `lastevent_retrieved` value before accessing `enter_evt` in `parse_open_openat_creat_exit` for `PPME_SYSCALL_OPENAT_X`.
Also, fixed a small bug in a test.

Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2025-08-04 10:00:48 +02:00
Federico Di Pierro b530bf90fb cleanup(userspace/libsinsp): drop `sinsp_parser::m_tmp_events_buffer`.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2025-08-04 10:00:48 +02:00
Tero Kauppinen fc31690604 feat(savefile): add empty parameter support for PPME_SETPGID_X
Support for empty parameters was added with
https://github.com/falcosecurity/libs/pull/2550.

This update adds empty parameter support for `PPME_SYSCALL_SETPGID_X`.

Signed-off-by: Tero Kauppinen <tero.kauppinen@est.tech>
2025-08-04 09:46:48 +02:00
Tero Kauppinen 831ed012e0 feat(savefile): add empty parameter support for PPME_SYSCALL_SETNS_X
Support for empty parameters was added with
https://github.com/falcosecurity/libs/pull/2550.

This update adds empty parameter support for `PPME_SYSCALL_SETNS_X`.

Signed-off-by: Tero Kauppinen <tero.kauppinen@est.tech>
2025-08-04 09:46:48 +02:00
Tero Kauppinen 90c9ffecd5 feat(savefile): added empty parameter support for PPME_SYSCALL_FCHDIR_X
Support for empty parameters was added with
https://github.com/falcosecurity/libs/pull/2550.

This update adds empty parameter support for `PPME_SYSCALL_FCHDIR_X`.

Signed-off-by: Tero Kauppinen <tero.kauppinen@est.tech>
2025-08-01 12:39:29 +02:00
Leonardo Di Giovanna 719eeed0bc refactor(userspace/libsinsp): remove timestamp saving custom logic
Remove unused timestamp saving custom logic in parser for
`PPME_SYSCALL_SELECT_E`, `PPME_SYSCALL_POLL_X`,
`PPME_SYSCALL_PPOLL_X` and `PPME_SYSCALL_EPOLLWAIT_X` events

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-08-01 12:11:29 +02:00
Federico Di Pierro 59960f5df1 update(cmake): bumped container plugin to 0.3.4.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2025-08-01 10:19:28 +02:00
Tero Kauppinen b5e18368c5 cleanup(libsinsp): utilize `get_exit_event_fd_location`
The current implementation uses custom code for fetching
the location of fd-related arguments for specific syscalls.

This update removes the custom code and utilizes the
existing `get_exit_event_fd_location` function instead by
expanding it with the location of the `dirfd' argument.

Signed-off-by: Tero Kauppinen <tero.kauppinen@est.tech>
2025-07-31 15:39:24 +02:00
Tero Kauppinen 6685f4a0ec fix: add `EF_USES_FD` flag to events missing it
Some of the events in `g_event_info` structure are not flagged
with `EF_USES_FD` but still use the fd information when parsing.

Add the flag to the following events:

PPME_SYSCALL_SYMLINKAT_X
PPME_SYSCALL_UNLINKAT_2_X
PPME_SYSCALL_MKDIRAT_X
PPME_SYSCALL_FCHMODAT_X
PPME_SYSCALL_FCHOWNAT_X

Signed-off-by: Tero Kauppinen <tero.kauppinen@est.tech>
2025-07-31 15:39:24 +02:00
Leonardo Di Giovanna 7c1aecf4c6 feat: make `PPME_SYSCALL_CLONE3_{E, X}` managed by scap-converter
Make `PPME_SYSCALL_CLONE3_E` and `PPME_SYSCALL_CLONE3_X` managed by
the scap converter and contextually fix some tests using clone3 and
clone events.

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-31 12:08:23 +02:00
Leonardo Di Giovanna 39ab969475 feat: make `PPME_SYSCALL_VFORK_{E, X}` managed by scap-converter
Make both `PPME_SYSCALL_VFORK_E` and `PPME_SYSCALL_VFORK_X` events
managed by the scap-converter. Specifically, convert them to the
corresponding `PPME_SYSCALL_VFORK_17_{E, X}` event types; this allows
userspace code to get rid of special handling code for them.

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-31 12:08:23 +02:00
Leonardo Di Giovanna 870a8a7bc2 feat: make `PPME_SYSCALL_VFORK_17_{E, X}` managed by scap-converter
Make both `PPME_SYSCALL_VFORK_17_E` and `PPME_SYSCALL_VFORK_17_X`
events managed by the scap-converter. Specifically, convert them to
the corresponding `PPME_SYSCALL_VFORK_20_{E, X}` event types; this
allows userspace code to get rid of special handling code for them.

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-31 12:08:23 +02:00
Leonardo Di Giovanna 8808497f1a feat: make `PPME_SYSCALL_VFORK_20_{E, X}` managed by scap-converter
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-31 12:08:23 +02:00
Leonardo Di Giovanna 2618d37a20 feat: make `PPME_SYSCALL_FORK_{E, X}` managed by scap-converter
Make both `PPME_SYSCALL_FORK_E` and `PPME_SYSCALL_FORK_X` events
managed by the scap-converter. Specifically, convert them to the
corresponding `PPME_SYSCALL_FORK_17_{E, X}` event types; this allows
userspace code to get rid of special handling code for them.

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-30 18:34:19 +02:00
Leonardo Di Giovanna 5e0981dc0d feat: make `PPME_SYSCALL_FORK_17_{E, X}` managed by scap-converter
Make both `PPME_SYSCALL_FORK_17_E` and `PPME_SYSCALL_FORK_17_X`
events managed by the scap-converter. Specifically, convert them to
the corresponding `PPME_SYSCALL_FORK_20_{E, X}` event types; this
allows userspace code to get rid of special handling code for them.

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-30 18:34:19 +02:00
Leonardo Di Giovanna 8f3e222d16 feat: make `PPME_SYSCALL_FORK_20_{E, X}` managed by scap-converter
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-30 18:34:19 +02:00
Tero Kauppinen 52d638570a fix(userspace/libsinsp): remove state handling for PPM_SYSCALL_LINK
and PPM_SYSCALL_LINKAT

The new driver does not emit `PPM_SYSCALL_LINK` and
`PPM_SYSCALL_LINKAT` events anymore, and there is no longer need
to handle the old version of the events. This update removes the
state handling and adds conversion rules for the scap files.

Signed-off-by: Tero Kauppinen <tero.kauppinen@est.tech>
2025-07-30 17:40:19 +02:00
Leonardo Di Giovanna 8ad30697ed feat: make `PPME_SYSCALL_CLONE_11_{E, X}` managed by scap-converter
Make both `PPME_SYSCALL_CLONE_11_E` and `PPME_SYSCALL_CLONE_11_X`
events managed by the scap-converter. Specifically, convert them to
the corresponding `PPME_SYSCALL_CLONE_11_{E, X}` event types; this
allows userspace code to get rid of special handling code for them.

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-30 16:01:18 +02:00
Leonardo Di Giovanna fa62300265 feat: make `PPME_SYSCALL_CLONE_16_{E, X}` managed by scap-converter
Make both `PPME_SYSCALL_CLONE_16_E` and `PPME_SYSCALL_CLONE_16_X`
events managed by the scap-converter. Specifically, convert them to
the corresponding `PPME_SYSCALL_CLONE_17_{E, X}` event types; this
allows userspace code to get rid of special handling code for them.

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-30 16:01:18 +02:00
Leonardo Di Giovanna 316fcb2a39 feat: make `PPME_SYSCALL_CLONE_17_{E, X}` managed by scap-converter
Make both `PPME_SYSCALL_CLONE_17_E` and `PPME_SYSCALL_CLONE_17_X`
events managed by the scap-converter. Specifically, convert them to
the corresponding `PPME_SYSCALL_CLONE_20_{E, X}` event types; this
allows userspace code to get rid of special handling code for them.

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-30 16:01:18 +02:00
Leonardo Di Giovanna 6b56ab9ab7 feat: make `PPME_SYSCALL_CLONE_20_{E, X}` managed by scap-converter
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-30 16:01:18 +02:00
Tero Kauppinen a7ba9de555 fix(userspace/libsinsp): remove state handling for PPM_SYSCALL_UNLINK
and PPM_SYSCALL_UNLINKAT

The new driver does not emit `PPM_SYSCALL_UNLINK` and
`PPM_SYSCALL_UNLINKAT` events anymore, and there is no longer need
to handle the old version of the events. This update removes the
state handling and adds conversion rules for the scap files.

Signed-off-by: Tero Kauppinen <tero.kauppinen@est.tech>
2025-07-30 14:03:18 +02:00
Leonardo Di Giovanna 1e35de4388 feat: make `PPME_SYSCALL_EXECVE_8_{E, X}` managed by scap-converter
Make both `PPME_SYSCALL_EXECVE_8_E` and `PPME_SYSCALL_EXECVE_8_X`
events managed by the scap-converter. Specifically, convert them to
the corresponding `PPME_SYSCALL_EXECVE_13_{E, X}` event types; this
allows userspace code to get rid of special handling code for them.

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-30 10:42:56 +02:00
Leonardo Di Giovanna 78acd68141 feat: make `PPME_SYSCALL_EXECVE_13_{E, X}` managed by scap-converter
Make both `PPME_SYSCALL_EXECVE_13_E` and `PPME_SYSCALL_EXECVE_13_X`
events managed by the scap-converter. Specifically, convert them to
the corresponding `PPME_SYSCALL_EXECVE_14_{E, X}` event types; this
allows userspace code to get rid of special handling code for them.

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-30 10:42:56 +02:00
Leonardo Di Giovanna 21e8b0c1c0 feat: make `PPME_SYSCALL_EXECVE_14_{E, X}` managed by scap-converter
Make both `PPME_SYSCALL_EXECVE_14_E` and `PPME_SYSCALL_EXECVE_14_X`
events managed by the scap-converter. Specifically, convert them to
the corresponding `PPME_SYSCALL_EXECVE_15_{E, X}` event types; this
allows userspace code to get rid of special handling code for them.

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-30 10:42:56 +02:00
Leonardo Di Giovanna c3d38df059 feat: make `PPME_SYSCALL_EXECVE_15_{E, X}` managed by scap-converter
Make both `PPME_SYSCALL_EXECVE_15_E` and `PPME_SYSCALL_EXECVE_15_X`
events managed by the scap-converter. Specifically, convert them to
the corresponding `PPME_SYSCALL_EXECVE_16_{E, X}` event types; this
allows userspace code to get rid of special handling code for them.

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-30 10:42:56 +02:00
Leonardo Di Giovanna ebe35459a3 feat: make `PPME_SYSCALL_EXECVE_16_{E, X}` managed by scap-converter
Make both `PPME_SYSCALL_EXECVE_16_E` and `PPME_SYSCALL_EXECVE_16_X`
events managed by the scap-converter. Specifically, convert them to
the corresponding `PPME_SYSCALL_EXECVE_17_{E, X}` event types; this
allows userspace code to get rid of special handling code for them.

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-30 10:42:56 +02:00
Leonardo Di Giovanna 9b991ad442 feat: make `PPME_SYSCALL_EXECVE_17_{E, X}` managed by scap-converter
Make both `PPME_SYSCALL_EXECVE_17_E` and `PPME_SYSCALL_EXECVE_17_X`
events managed by the scap-converter. Specifically, convert them to
the corresponding `PPME_SYSCALL_EXECVE_18_{E, X}` event types; this
allows userspace code to get rid of special handling code for them.

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-30 10:42:56 +02:00
Leonardo Di Giovanna 828935f0e5 feat: make `PPME_SYSCALL_EXECVE_18_{E, X}` managed by scap-converter
Make both `PPME_SYSCALL_EXECVE_18_E` and `PPME_SYSCALL_EXECVE_18_X`
events managed by the scap-converter. Specifically, convert them to
the corresponding `PPME_SYSCALL_EXECVE_19_{E, X}` event types; this
allows userspace code to get rid of special handling code for them.

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-30 10:42:56 +02:00
Leonardo Di Giovanna d021cbfd34 feat: make `PPME_SYSCALL_EXECVEAT_X` "scap converter"-managed
Let the scap converter managing all the possible variation of
`PPME_SYSCALL_EXECVEAT_X` event, adapting the userspace code to
handle possible empty values coming from the conversion.

The `PPME_SYSCALL_EXECVEAT_E` event is stil sent to sinsp, as its
parameters are still used as a fallback if the `trusted_exepath`
parameter is not present in the exit event.

Moreover, fixes some execveat tests.

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-29 14:12:09 +02:00
Leonardo Di Giovanna b8a55f471e test(userspace/libsinsp): add scap conversion test for execve
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-29 14:12:09 +02:00
Leonardo Di Giovanna b4d1072d66 feat(userspace/libsinsp)!: defer sinsp evt params null-encoding logic
In the previous implementation, some specific parameter configurations
(empty or containing '(NULL)', with the type being equal to
`PT_CHARBUF`, `PT_FSPATH` or `PT_FSRELPATH`) were patched at loading
time with the following configuration:
- data: "<NA>"
- len: 5
This made empty parameters indistinguishable from non-empty
parameters.

The new implementation loads the parameters and keeps them untouched:
in this way, it is possible to inspect their original data and
lengths.

Since majority of the userspace space implementation still relies on
the aforementioned particular "null" encoding, a couple of new methods
(i.e. `sinsp_evt_param::used_legacy_null_encoding()` and
`sinsp_evt_param::data_and_len_with_legacy_null_encoding()`),
helping to check or simulate the old behaviour, are provided.
Moreover, parameter conversion methods (e.g.
`sinsp_evt_param::as<T>()`), still return the legacy encoded version.

BREAKING CHANGE: make parameter data and len private

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-29 10:10:09 +02:00
Leonardo Grasso 2a3b01dbb1 fix(userspace/libscap/engine/gvisor): handle read() < 0
Co-authored-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2025-07-28 10:26:05 +02:00
Leonardo Grasso 7d599304a5 fix(userspace/libsinsp): eliminate race condition in plugin async event handler cleanup
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2025-07-28 10:26:05 +02:00
Leonardo Grasso b902665cc3 fix(userspace/libscap/engine/gvisor): proper null termination in runsc output handling
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2025-07-28 10:26:05 +02:00
Leonardo Grasso a81dc05c16 fix(userspace/libsinsp): prevent path traversal in container memory usage reader
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2025-07-28 10:26:05 +02:00
Leonardo Di Giovanna 592217e71c fix(userspace/libsinsp): partially fix filterchecks for empty params
Introduce two fixes:
- turn "NULL" into "<NA>" upon string conversion for parameters that
  couldn't be empty before the introduction of the notion of "empty
  parameters" in the scap-converter
- fix implementation of `exists` operator for `evt.rawarg` by
flagging zero-length parameters as non-existing.

Moreover, introduce a bunch of unit tests for `evt.arg.*` and
`evt.rawarg.*`, and move some of the old one to new locations. Tests
are annotated in order to reflect the expectation of a future good
implementation.

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-25 10:48:44 +02:00
Leonardo Di Giovanna 1f177d0599 fix(userspace/libscap): fix `SCAP_EMPTY_PARAMS_SET` def on Windows
Do not use GCC extension to define `SCAP_EMPTY_PARAMS_SET`. In this
way, it can be used in Windows.

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-25 10:48:44 +02:00
Leonardo Di Giovanna 31673d110d fix(userspace/libscap): populate error in case of failing `stat` on fd
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-24 15:31:41 +02:00
Tero Kauppinen a04a40f95f fix(libscap): add missing fd locations for dup exit events
The function extracting `fd` parameter's location from the
exit event is missing information for the dup syscalls.

Add location of the `fd` parameter in the exit event for
all dup syscalls.

Signed-off-by: Tero Kauppinen <tero.kauppinen@est.tech>
2025-07-24 11:11:40 +02:00
Leonardo Di Giovanna 5afd8eee0e fix: `evt.rawarg.*` raw val eval for pids, uids, gids and socktuples
Add support for `evt.rawarg.*` raw value evaluation for `PT_PID`,
`PT_UID`, `PT_GID` and `PT_SOCKTUPLE`.

Moreover, add support for numerical comparison for `PT_UID` and
`PT_GID`.

Finally, introduce some helpers letting generating execve and connect
events for testing purposes.

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-23 16:01:36 +02:00
Francesco Emmi 7deb173ca5 fix(sinsp_suppress): Fix comm-based suppression to cascade to child processes after /proc scan
Addresses https://github.com/falcosecurity/libs/issues/2546
Ensures that `comm-based` suppression correctly applies not only to processes matching
the configured comm values, but also to their child processes—even when those processes
were already running at the time the library is initialized.
This is achieved by having scap notify sinsp when a `/proc` scan refresh begins and ends.
While the scan is in progress, sinsp builds a temporary `TID` tree to track parent-child relationships.
Once the scan completes, sinsp performs a post-processing step that traverses the tree and suppresses
all children of any process already marked as suppressed by comm.

Signed-off-by: Francesco Emmi <francesco.as@gmail.com>
2025-07-22 09:37:28 +02:00
Leonardo Di Giovanna 9f7c159c49 feat: add support for creating events with empty parameters
Add scap API to create/encode events with empty parameters, as this is
required to easily tests events whose type is managed by the scap
converter.

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-21 15:32:29 +02:00
Tero Kauppinen 398f606986 fix(userspace/libsinsp): remove state handling for PPM_SYSCALL_RMDIR
The new driver does not emit `PPM_SYSCALL_RMDIR` events anymore, and
there is no longer need to handle the old version of the rmdir event.
This update removes the state handling and adds conversion rules for
the scap files.

Signed-off-by: Tero Kauppinen <tero.kauppinen@est.tech>
2025-07-21 13:02:26 +02:00
Tero Kauppinen a8d69fc285 cleanup(libsinsp): removed unused PPME_SYSCALL_MKDIR_X statements
The current implementation does no longer emit PPME_SYSCALL_MKDIR_X
events and these events are also converted to PPME_SYSCALL_MKDIR_2_X
events for older scap files. Remove unused PPME_SYSCALL_MKDIR_X
statements from the codebase.

Added the CIF_FALLBACK_TO_EMPTY flag for parameters copied from
the enter event.

Signed-off-by: Tero Kauppinen <tero.kauppinen@est.tech>
2025-07-21 13:02:26 +02:00
Tero Kauppinen c1cd8e2387 fix(testing): adjust gvisor testing for execve
https://github.com/falcosecurity/libs/pull/2544 implements conversion
of the exceve_x event which increases the number of parameters to 30.

Adjust the number of expected parameters from 27 to 30 for execve_x
events with the gvisor engine.

Signed-off-by: Tero Kauppinen <tero.kauppinen@est.tech>
2025-07-21 10:13:31 +02:00
Leonardo Di Giovanna 17a7da6ceb feat: make `PPME_SYSCALL_EXECVE_19_X` "scap converter"-managed
Let the scap converter managing all the possible variation of
`PPME_SYSCALL_EXECVE_19_X` event, adapting the userspace code to
handle possible empty values coming from the conversion.

The `PPME_SYSCALL_EXECVE_19_E` event is stil sent to sinsp, as its
`filename` parameter value is still used as a fallback if the
`trusted_exepath` parameter is not present in the exit event.

Moreover, fixes some execve and execveat tests and align comments
to the new one-line style in the kernel drivers and tests.

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-16 11:04:54 +02:00
Tero Kauppinen 878d24507b cleanup(libsinsp): retrieve parameters from the prlimit exit events
There is no need to store the prlimit entry event, because all
required parameters are available in the exit event.

Modify the prlimit exit event handler to retrieve information from
the exit event instead of the entry event. Added scap conversion
rules for the exit event with 5 parameters.

Signed-off-by: Tero Kauppinen <tero.kauppinen@est.tech>
2025-07-16 10:36:53 +02:00
Tero Kauppinen 92703f2b42 feat(libscap): support for old PPME_SYSCALL_PTRACE_X events
Old PPME_SYSCALL_PTRACE_X events have zero parameters and they
need conversion support. Add support for converting events
with zero parameters to events with 3 parameters.

Signed-off-by: Tero Kauppinen <tero.kauppinen@est.tech>
2025-07-15 14:28:47 +02:00
Leonardo Di Giovanna 605d8366b7 feat: fall back to empty gid instead of default one in scap converter
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-15 10:57:46 +02:00
Leonardo Di Giovanna d6bf8e983f feat: fall back to empty uid instead of default one in scap converter
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-15 10:57:46 +02:00
Leonardo Di Giovanna 109ef4fd73 feat(userspace/libscap): add scap converter "from empty" instruction
Add `C_INSTR_FROM_EMPTY` converter instruction code. This specify
to generate an empty parameter. In order to keep compatibility with
old scap files, an empty parameter has a parameter length set to 0
but it still have `len` bytes set to 0 as parameter value, where
`len` is determined from the parameter type.
E.g.: a `PT_UINT64` parameter will have the length set to 0 and its
value will occupy 8 bytes, all set to 0.

Contextually, introduce the notion of conversion flags and
particularly, the `CIF_FALLBACK_TO_EMPTY` flag: by default, if a
`C_INSTR_FROM_ENTER` instruction is encountered, and for some reason
the converter is not able to obtain a parameter from the enter event,
it pushes a default parameter; if `CIF_FALLBACK_TO_EMPTY` is
specified, it will fallback to an empty parameter.

This flag is a temporary solution to avoid handling empty parameters
in place of default ones in a single shot.

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-15 10:57:46 +02:00
Leonardo Di Giovanna 7f6e58baaf ci: switch `debian:buster` apt debian repository URL to snapshot URL
As buster reached its EOL, the official debian repo URL doesn't
host anymore buster packages info. For this reason, change the URLs
to point to the `20250630T203427Z` snapshot, which still contains
them.

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-15 09:58:46 +02:00
Iacopo Rozzo b799abca59 fix(libscap): cgroup v2 path discovery fails with empty cgroup2 mountpoint
Fix the cgroup v2 path discovery mechanism in the presence of cgroup2
mount point with no controllers. The issue has been detected in a RKE
node, where the following empty mountpoint is breaking the detection
logic.

```
none on /host/var/run/calico/cgroup type cgroup2 (rw,relatime,nsdelegate,memory_recursiveprot)
```

The fix consists in stopping the iteration as soon as a mountpoint that
has available controllers listed in the `cgroup.controllers` is
detected.

Signed-off-by: Iacopo Rozzo <iacopo@sysdig.com>
2025-05-16 14:56:54 +02:00
94 changed files with 6348 additions and 2237 deletions

View File

@ -36,6 +36,8 @@ jobs:
steps:
- name: Install deps ⛓️
run: |
# Use 20250630T203427Z debian apt snapshot as it still contains support for buster.
printf "deb http://snapshot.debian.org/archive/debian/20250630T203427Z buster main\ndeb http://snapshot.debian.org/archive/debian-security/20250630T203427Z buster/updates main\ndeb http://snapshot.debian.org/archive/debian/20250630T203427Z buster-updates main" > /etc/apt/sources.list
apt update && apt install -y --no-install-recommends curl ca-certificates build-essential git clang llvm pkg-config autoconf automake libtool libelf-dev wget libtbb-dev libjq-dev libjsoncpp-dev protobuf-compiler libgtest-dev libprotobuf-dev linux-headers-${{ matrix.arch }}
- name: Install a recent version of CMake ⛓️

View File

@ -22,13 +22,13 @@ set(CONTAINER_LIBRARY
)
if(NOT CONTAINER_VERSION)
set(CONTAINER_VERSION "0.3.1")
set(CONTAINER_VERSION "0.3.4")
endif()
if(NOT CONTAINER_HASH)
if(${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "x86_64")
set(CONTAINER_HASH "2c8f351448b30044560affd493e7af75dd1207a9ee9c26970e5aa41f1371059a")
set(CONTAINER_HASH "658f96c4b4a56d1bf945a788d60571076f808ae1bcc877c4ba3625b0fd752d8d")
else() # arm64
set(CONTAINER_HASH "8ebe2d7f691ba7fd47534cbffc640fd6830e5057742f185e0fda8fed7ab192a4")
set(CONTAINER_HASH "34a153aca0164843a169193aba092a3063b24bca9ef80fd4f1d1f1919aba3bde")
endif()
endif()
if(NOT TARGET container_plugin)

View File

@ -1 +1 @@
3.65.0
3.69.0

View File

@ -2599,7 +2599,6 @@ FILLER(proc_startupdate, true) {
unsigned long fdlimit;
struct mm_struct *mm;
long total_rss;
char empty = 0;
volatile long args_len;
long retval;
pid_t tgid;
@ -2610,6 +2609,7 @@ FILLER(proc_startupdate, true) {
/*
* Make sure the operation was successful
*/
/* Parameter 1: res (type: PT_ERRNO) */
retval = bpf_syscall_get_retval(data->ctx);
res = bpf_push_s64_to_ring(data, retval);
CHECK_RES(res);
@ -2690,9 +2690,7 @@ FILLER(proc_startupdate, true) {
return PPM_FAILURE_INVALID_USER_MEMORY;
}
/*
* exe
*/
/* Parameter 2: exe (type: PT_CHARBUF) */
if(exe_len == 0) {
res = bpf_push_empty_param(data);
} else {
@ -2703,9 +2701,7 @@ FILLER(proc_startupdate, true) {
args_len -= exe_len;
/*
* Args
*/
/* Parameter 3: args (type: PT_CHARBUFARRAY) */
if(args_len <= 0) {
res = bpf_push_empty_param(data);
CHECK_RES(res);
@ -2715,56 +2711,43 @@ FILLER(proc_startupdate, true) {
CHECK_RES(res);
}
/*
* tid
*/
/* Parameter 4: tid (type: PT_PID) */
/* this is called `tid` but it is the `pid`. */
pid = _READ(task->pid);
res = bpf_push_s64_to_ring(data, pid);
CHECK_RES(res);
/*
* pid
*/
/* Parameter 5: pid (type: PT_PID) */
/* this is called `pid` but it is the `tgid`. */
tgid = _READ(task->tgid);
res = bpf_push_s64_to_ring(data, tgid);
CHECK_RES(res);
/*
* ptid
*/
/* Parameter 6: ptid (type: PT_PID) */
/* this is called `ptid` but it is the `pgid`. */
real_parent = _READ(task->real_parent);
pid_t ptid = _READ(real_parent->pid);
res = bpf_push_s64_to_ring(data, ptid);
CHECK_RES(res);
/*
* cwd, pushed empty to avoid breaking compatibility
* with the older event format
*/
/* Parameter 7: cwd (type: PT_CHARBUF) */
/* Push empty to avoid breaking compatibility with the older event format. */
res = bpf_push_empty_param(data);
CHECK_RES(res);
/*
* fdlimit
*/
/* Parameter 8: fdlimit (type: PT_UINT64) */
signal = _READ(task->signal);
fdlimit = _READ(signal->rlim[RLIMIT_NOFILE].rlim_cur);
res = bpf_push_u64_to_ring(data, fdlimit);
CHECK_RES(res);
/*
* pgft_maj
*/
/* Parameter 9: pgft_maj (type: PT_UINT64) */
maj_flt = _READ(task->maj_flt);
res = bpf_push_u64_to_ring(data, maj_flt);
CHECK_RES(res);
/*
* pgft_min
*/
/* Parameter 10: pgft_min (type: PT_UINT64) */
min_flt = _READ(task->min_flt);
res = bpf_push_u64_to_ring(data, min_flt);
@ -2781,27 +2764,19 @@ FILLER(proc_startupdate, true) {
swap = bpf_get_mm_swap(mm) << (PAGE_SHIFT - 10);
}
/*
* vm_size
*/
/* Parameter 11: vm_size (type: PT_UINT32) */
res = bpf_push_u32_to_ring(data, total_vm);
CHECK_RES(res);
/*
* vm_rss
*/
/* Parameter 12: vm_rss (type: PT_UINT32) */
res = bpf_push_u32_to_ring(data, total_rss);
CHECK_RES(res);
/*
* vm_swap
*/
/* Parameter 13: vm_swap (type: PT_UINT32) */
res = bpf_push_u32_to_ring(data, swap);
CHECK_RES(res);
/*
* comm
*/
/* Parameter 14: comm (type: PT_CHARBUF) */
res = bpf_val_to_ring_type_mem(data, (unsigned long)task->comm, PT_CHARBUF, KERNEL);
CHECK_RES(res);
@ -2817,9 +2792,7 @@ FILLER(proc_startupdate_2, true) {
task = (struct task_struct *)bpf_get_current_task();
/*
* cgroups
*/
/* Parameter 15: cgroups (type: PT_CHARBUFARRAY) */
res = bpf_append_cgroup(task, data->tmp_scratch, &cgroups_len);
CHECK_RES(res);
@ -2976,9 +2949,7 @@ FILLER(proc_startupdate_3, true) {
uint32_t tty;
struct file *exe_file;
/*
* environ
*/
/* Parameter 16: env (type: PT_CHARBUFARRAY) */
if(retval >= 0) {
/*
* Already checked for mm validity
@ -3034,23 +3005,17 @@ FILLER(proc_startupdate_3, true) {
res = __bpf_val_to_ring(data, 0, env_len, PT_BYTEBUF, -1, false, KERNEL);
CHECK_RES(res);
/*
* tty
*/
/* Parameter 17: tty (type: PT_INT32) */
tty = bpf_ppm_get_tty(task);
res = bpf_push_u32_to_ring(data, tty);
CHECK_RES(res);
/*
* pgid
*/
/* Parameter 18: vpgid (type: PT_PID) */
res = bpf_push_s64_to_ring(data, bpf_task_pgrp_vnr(task));
CHECK_RES(res);
/*
* loginuid
*/
/* Parameter 19: loginuid (type: PT_UID) */
/* TODO: implement user namespace support */
#if(LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0) && CONFIG_AUDIT) || \
(LINUX_VERSION_CODE < KERNEL_VERSION(5, 1, 0) && CONFIG_AUDITSYSCALL)
@ -7941,7 +7906,7 @@ FILLER(sched_prog_exec_3, false) {
res = bpf_push_u32_to_ring(data, tty);
CHECK_RES(res);
/* Parameter 18: pgid (type: PT_PID) */
/* Parameter 18: vpgid (type: PT_PID) */
res = bpf_push_s64_to_ring(data, bpf_task_pgrp_vnr(task));
CHECK_RES(res);

View File

@ -117,11 +117,11 @@ const struct ppm_event_info g_event_info[] = {
{"brk", EC_MEMORY | EC_SYSCALL, EF_OLD_VERSION, 1, {{"res", PT_UINT64, PF_HEX}}},
[PPME_SYSCALL_EXECVE_8_E] = {"execve",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_OLD_VERSION,
EF_MODIFIES_STATE | EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
0},
[PPME_SYSCALL_EXECVE_8_X] = {"execve",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_OLD_VERSION,
EF_MODIFIES_STATE | EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
8,
{{"res", PT_ERRNO, PF_DEC},
{"exe", PT_CHARBUF, PF_NA},
@ -133,11 +133,11 @@ const struct ppm_event_info g_event_info[] = {
{"fdlimit", PT_UINT64, PF_DEC}}},
[PPME_SYSCALL_CLONE_11_E] = {"clone",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_OLD_VERSION,
EF_MODIFIES_STATE | EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
0},
[PPME_SYSCALL_CLONE_11_X] = {"clone",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_OLD_VERSION,
EF_MODIFIES_STATE | EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
11,
{{"res", PT_PID, PF_DEC},
{"exe", PT_CHARBUF, PF_NA},
@ -608,10 +608,16 @@ const struct ppm_event_info g_event_info[] = {
EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
1,
{{"res", PT_ERRNO, PF_DEC}}},
[PPME_SYSCALL_RMDIR_E] =
{"rmdir", EC_FILE | EC_SYSCALL, EF_OLD_VERSION, 1, {{"path", PT_FSPATH, PF_NA}}},
[PPME_SYSCALL_RMDIR_X] =
{"rmdir", EC_FILE | EC_SYSCALL, EF_OLD_VERSION, 1, {{"res", PT_ERRNO, PF_DEC}}},
[PPME_SYSCALL_RMDIR_E] = {"rmdir",
EC_FILE | EC_SYSCALL,
EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
1,
{{"path", PT_FSPATH, PF_NA}}},
[PPME_SYSCALL_RMDIR_X] = {"rmdir",
EC_FILE | EC_SYSCALL,
EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
1,
{{"res", PT_ERRNO, PF_DEC}}},
[PPME_SYSCALL_OPENAT_E] = {"openat",
EC_FILE | EC_SYSCALL,
EF_CREATES_FD | EF_MODIFIES_STATE | EF_OLD_VERSION,
@ -627,32 +633,47 @@ const struct ppm_event_info g_event_info[] = {
{{"fd", PT_FD, PF_DEC}}},
[PPME_SYSCALL_LINK_E] = {"link",
EC_FILE | EC_SYSCALL,
EF_OLD_VERSION,
EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
2,
{{"oldpath", PT_FSPATH, PF_NA}, {"newpath", PT_FSPATH, PF_NA}}},
[PPME_SYSCALL_LINK_X] =
{"link", EC_FILE | EC_SYSCALL, EF_OLD_VERSION, 1, {{"res", PT_ERRNO, PF_DEC}}},
[PPME_SYSCALL_LINK_X] = {"link",
EC_FILE | EC_SYSCALL,
EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
1,
{{"res", PT_ERRNO, PF_DEC}}},
[PPME_SYSCALL_LINKAT_E] = {"linkat",
EC_FILE | EC_SYSCALL,
EF_OLD_VERSION,
EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
4,
{{"olddir", PT_FD, PF_DEC},
{"oldpath", PT_CHARBUF, PF_NA},
{"newdir", PT_FD, PF_DEC},
{"newpath", PT_CHARBUF, PF_NA}}},
[PPME_SYSCALL_LINKAT_X] =
{"linkat", EC_FILE | EC_SYSCALL, EF_OLD_VERSION, 1, {{"res", PT_ERRNO, PF_DEC}}},
[PPME_SYSCALL_UNLINK_E] =
{"unlink", EC_FILE | EC_SYSCALL, EF_OLD_VERSION, 1, {{"path", PT_FSPATH, PF_NA}}},
[PPME_SYSCALL_UNLINK_X] =
{"unlink", EC_FILE | EC_SYSCALL, EF_OLD_VERSION, 1, {{"res", PT_ERRNO, PF_DEC}}},
[PPME_SYSCALL_LINKAT_X] = {"linkat",
EC_FILE | EC_SYSCALL,
EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
1,
{{"res", PT_ERRNO, PF_DEC}}},
[PPME_SYSCALL_UNLINK_E] = {"unlink",
EC_FILE | EC_SYSCALL,
EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
1,
{{"path", PT_FSPATH, PF_NA}}},
[PPME_SYSCALL_UNLINK_X] = {"unlink",
EC_FILE | EC_SYSCALL,
EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
1,
{{"res", PT_ERRNO, PF_DEC}}},
[PPME_SYSCALL_UNLINKAT_E] = {"unlinkat",
EC_FILE | EC_SYSCALL,
EF_OLD_VERSION,
EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
2,
{{"dirfd", PT_FD, PF_DEC}, {"name", PT_CHARBUF, PF_NA}}},
[PPME_SYSCALL_UNLINKAT_X] =
{"unlinkat", EC_FILE | EC_SYSCALL, EF_OLD_VERSION, 1, {{"res", PT_ERRNO, PF_DEC}}},
[PPME_SYSCALL_UNLINKAT_X] = {"unlinkat",
EC_FILE | EC_SYSCALL,
EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
1,
{{"res", PT_ERRNO, PF_DEC}}},
[PPME_SYSCALL_PREAD_E] = {"pread",
EC_IO_READ | EC_SYSCALL,
EF_USES_FD | EF_READS_FROM_FD | EF_TMP_CONVERTER_MANAGED,
@ -871,13 +892,13 @@ const struct ppm_event_info g_event_info[] = {
{"resource", PT_ENUMFLAGS8, PF_DEC, rlimit_resources}}},
[PPME_SYSCALL_PRLIMIT_E] = {"prlimit",
EC_PROCESS | EC_SYSCALL,
EF_NONE,
EF_TMP_CONVERTER_MANAGED,
2,
{{"pid", PT_PID, PF_DEC},
{"resource", PT_ENUMFLAGS8, PF_DEC, rlimit_resources}}},
[PPME_SYSCALL_PRLIMIT_X] = {"prlimit",
EC_PROCESS | EC_SYSCALL,
EF_NONE,
EF_TMP_CONVERTER_MANAGED,
7,
{{"res", PT_ERRNO, PF_DEC},
{"newcur", PT_INT64, PF_DEC},
@ -932,11 +953,11 @@ const struct ppm_event_info g_event_info[] = {
[PPME_SCHEDSWITCH_6_X] = {"NA", EC_UNKNOWN, EF_UNUSED, 0},
[PPME_SYSCALL_EXECVE_13_E] = {"execve",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_OLD_VERSION,
EF_MODIFIES_STATE | EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
0},
[PPME_SYSCALL_EXECVE_13_X] = {"execve",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_OLD_VERSION,
EF_MODIFIES_STATE | EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
13,
{{"res", PT_ERRNO, PF_DEC},
{"exe", PT_CHARBUF, PF_NA},
@ -953,11 +974,11 @@ const struct ppm_event_info g_event_info[] = {
{"vm_swap", PT_UINT32, PF_DEC}}},
[PPME_SYSCALL_CLONE_16_E] = {"clone",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_OLD_VERSION,
EF_MODIFIES_STATE | EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
0},
[PPME_SYSCALL_CLONE_16_X] = {"clone",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_OLD_VERSION,
EF_MODIFIES_STATE | EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
16,
{{"res", PT_PID, PF_DEC},
{"exe", PT_CHARBUF, PF_NA},
@ -1102,11 +1123,11 @@ const struct ppm_event_info g_event_info[] = {
{"argument", PT_UINT64, PF_HEX}}},
[PPME_SYSCALL_EXECVE_14_E] = {"execve",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_OLD_VERSION,
EF_MODIFIES_STATE | EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
0},
[PPME_SYSCALL_EXECVE_14_X] = {"execve",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_OLD_VERSION,
EF_MODIFIES_STATE | EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
14,
{{"res", PT_ERRNO, PF_DEC},
{"exe", PT_CHARBUF, PF_NA},
@ -1151,7 +1172,7 @@ const struct ppm_event_info g_event_info[] = {
[PPME_SYSCALL_SYMLINKAT_E] = {"symlinkat", EC_FILE | EC_SYSCALL, EF_NONE, 0},
[PPME_SYSCALL_SYMLINKAT_X] = {"symlinkat",
EC_FILE | EC_SYSCALL,
EF_NONE,
EF_USES_FD,
4,
{{"res", PT_ERRNO, PF_DEC},
{"target", PT_CHARBUF, PF_NA},
@ -1159,11 +1180,11 @@ const struct ppm_event_info g_event_info[] = {
{"linkpath", PT_FSRELPATH, PF_NA, DIRFD_PARAM(2)}}},
[PPME_SYSCALL_FORK_E] = {"fork",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_OLD_VERSION,
EF_MODIFIES_STATE | EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
0},
[PPME_SYSCALL_FORK_X] = {"fork",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_OLD_VERSION,
EF_MODIFIES_STATE | EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
16,
{{"res", PT_PID, PF_DEC},
{"exe", PT_CHARBUF, PF_NA},
@ -1183,11 +1204,11 @@ const struct ppm_event_info g_event_info[] = {
{"gid", PT_UINT32, PF_DEC}}},
[PPME_SYSCALL_VFORK_E] = {"vfork",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_OLD_VERSION,
EF_MODIFIES_STATE | EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
0},
[PPME_SYSCALL_VFORK_X] = {"vfork",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_OLD_VERSION,
EF_MODIFIES_STATE | EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
16,
{{"res", PT_PID, PF_DEC},
{"exe", PT_CHARBUF, PF_NA},
@ -1351,11 +1372,11 @@ const struct ppm_event_info g_event_info[] = {
{"sgid", PT_GID, PF_DEC}}},
[PPME_SYSCALL_EXECVE_15_E] = {"execve",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_OLD_VERSION,
EF_MODIFIES_STATE | EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
0},
[PPME_SYSCALL_EXECVE_15_X] = {"execve",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_OLD_VERSION,
EF_MODIFIES_STATE | EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
15,
{{"res", PT_ERRNO, PF_DEC},
{"exe", PT_CHARBUF, PF_NA},
@ -1374,11 +1395,11 @@ const struct ppm_event_info g_event_info[] = {
{"env", PT_BYTEBUF, PF_NA}}},
[PPME_SYSCALL_CLONE_17_E] = {"clone",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_OLD_VERSION,
EF_MODIFIES_STATE | EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
0},
[PPME_SYSCALL_CLONE_17_X] = {"clone",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_OLD_VERSION,
EF_MODIFIES_STATE | EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
17,
{{"res", PT_PID, PF_DEC},
{"exe", PT_CHARBUF, PF_NA},
@ -1399,11 +1420,11 @@ const struct ppm_event_info g_event_info[] = {
{"gid", PT_UINT32, PF_DEC}}},
[PPME_SYSCALL_FORK_17_E] = {"fork",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_OLD_VERSION,
EF_MODIFIES_STATE | EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
0},
[PPME_SYSCALL_FORK_17_X] = {"fork",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_OLD_VERSION,
EF_MODIFIES_STATE | EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
17,
{{"res", PT_PID, PF_DEC},
{"exe", PT_CHARBUF, PF_NA},
@ -1424,11 +1445,11 @@ const struct ppm_event_info g_event_info[] = {
{"gid", PT_UINT32, PF_DEC}}},
[PPME_SYSCALL_VFORK_17_E] = {"vfork",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_OLD_VERSION,
EF_MODIFIES_STATE | EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
0},
[PPME_SYSCALL_VFORK_17_X] = {"vfork",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_OLD_VERSION,
EF_MODIFIES_STATE | EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
17,
{{"res", PT_PID, PF_DEC},
{"exe", PT_CHARBUF, PF_NA},
@ -1447,10 +1468,13 @@ const struct ppm_event_info g_event_info[] = {
{"flags", PT_FLAGS32, PF_HEX, clone_flags},
{"uid", PT_UINT32, PF_DEC},
{"gid", PT_UINT32, PF_DEC}}},
[PPME_SYSCALL_CLONE_20_E] = {"clone", EC_PROCESS | EC_SYSCALL, EF_MODIFIES_STATE, 0},
[PPME_SYSCALL_CLONE_20_E] = {"clone",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_TMP_CONVERTER_MANAGED,
0},
[PPME_SYSCALL_CLONE_20_X] = {"clone",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE,
EF_MODIFIES_STATE | EF_TMP_CONVERTER_MANAGED,
21,
{{"res", PT_PID, PF_DEC},
{"exe", PT_CHARBUF, PF_NA},
@ -1473,10 +1497,13 @@ const struct ppm_event_info g_event_info[] = {
{"vtid", PT_PID, PF_DEC},
{"vpid", PT_PID, PF_DEC},
{"pidns_init_start_ts", PT_UINT64, PF_DEC}}},
[PPME_SYSCALL_FORK_20_E] = {"fork", EC_PROCESS | EC_SYSCALL, EF_MODIFIES_STATE, 0},
[PPME_SYSCALL_FORK_20_E] = {"fork",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_TMP_CONVERTER_MANAGED,
0},
[PPME_SYSCALL_FORK_20_X] = {"fork",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE,
EF_MODIFIES_STATE | EF_TMP_CONVERTER_MANAGED,
21,
{{"res", PT_PID, PF_DEC},
{"exe", PT_CHARBUF, PF_NA},
@ -1499,10 +1526,13 @@ const struct ppm_event_info g_event_info[] = {
{"vtid", PT_PID, PF_DEC},
{"vpid", PT_PID, PF_DEC},
{"pidns_init_start_ts", PT_UINT64, PF_DEC}}},
[PPME_SYSCALL_VFORK_20_E] = {"vfork", EC_PROCESS | EC_SYSCALL, EF_MODIFIES_STATE, 0},
[PPME_SYSCALL_VFORK_20_E] = {"vfork",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_TMP_CONVERTER_MANAGED,
0},
[PPME_SYSCALL_VFORK_20_X] = {"vfork",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE,
EF_MODIFIES_STATE | EF_TMP_CONVERTER_MANAGED,
21,
{{"res", PT_PID, PF_DEC},
{"exe", PT_CHARBUF, PF_NA},
@ -1536,11 +1566,11 @@ const struct ppm_event_info g_event_info[] = {
[PPME_CONTAINER_X] = {"NA", EC_UNKNOWN, EF_UNUSED | EF_OLD_VERSION, 0},
[PPME_SYSCALL_EXECVE_16_E] = {"execve",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_OLD_VERSION,
EF_MODIFIES_STATE | EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
0},
[PPME_SYSCALL_EXECVE_16_X] = {"execve",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_OLD_VERSION,
EF_MODIFIES_STATE | EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
16,
{{"res", PT_ERRNO, PF_DEC},
{"exe", PT_CHARBUF, PF_NA},
@ -1828,11 +1858,11 @@ const struct ppm_event_info g_event_info[] = {
[PPME_NOTIFICATION_X] = {"NA", EC_UNKNOWN, EF_UNUSED, 0},
[PPME_SYSCALL_EXECVE_17_E] = {"execve",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_OLD_VERSION,
EF_MODIFIES_STATE | EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
0},
[PPME_SYSCALL_EXECVE_17_X] = {"execve",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_OLD_VERSION,
EF_MODIFIES_STATE | EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
17,
{{"res", PT_ERRNO, PF_DEC},
{"exe", PT_CHARBUF, PF_NA},
@ -1873,12 +1903,12 @@ const struct ppm_event_info g_event_info[] = {
[PPME_INFRASTRUCTURE_EVENT_X] = {"NA", EC_UNKNOWN, EF_UNUSED, 0},
[PPME_SYSCALL_EXECVE_18_E] = {"execve",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_OLD_VERSION,
EF_MODIFIES_STATE | EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
1,
{{"filename", PT_FSPATH, PF_NA}}},
[PPME_SYSCALL_EXECVE_18_X] = {"execve",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_OLD_VERSION,
EF_MODIFIES_STATE | EF_OLD_VERSION | EF_TMP_CONVERTER_MANAGED,
17,
{{"res", PT_ERRNO, PF_DEC},
{"exe", PT_CHARBUF, PF_NA},
@ -1912,7 +1942,7 @@ const struct ppm_event_info g_event_info[] = {
{{"filename", PT_FSPATH, PF_NA}}},
[PPME_SYSCALL_EXECVE_19_X] = {"execve",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE,
EF_MODIFIES_STATE | EF_TMP_CONVERTER_MANAGED,
30,
{{"res", PT_ERRNO, PF_DEC},
{"exe", PT_CHARBUF, PF_NA},
@ -1988,7 +2018,7 @@ const struct ppm_event_info g_event_info[] = {
[PPME_SYSCALL_UNLINKAT_2_E] = {"unlinkat", EC_FILE | EC_SYSCALL, EF_NONE, 0},
[PPME_SYSCALL_UNLINKAT_2_X] = {"unlinkat",
EC_FILE | EC_SYSCALL,
EF_NONE,
EF_USES_FD,
4,
{{"res", PT_ERRNO, PF_DEC},
{"dirfd", PT_FD, PF_DEC},
@ -1997,7 +2027,7 @@ const struct ppm_event_info g_event_info[] = {
[PPME_SYSCALL_MKDIRAT_E] = {"mkdirat", EC_FILE | EC_SYSCALL, EF_NONE, 0},
[PPME_SYSCALL_MKDIRAT_X] = {"mkdirat",
EC_FILE | EC_SYSCALL,
EF_NONE,
EF_USES_FD,
4,
{{"res", PT_ERRNO, PF_DEC},
{"dirfd", PT_FD, PF_DEC},
@ -2044,7 +2074,7 @@ const struct ppm_event_info g_event_info[] = {
[PPME_SYSCALL_FCHMODAT_E] = {"fchmodat", EC_FILE | EC_SYSCALL, EF_NONE, 0},
[PPME_SYSCALL_FCHMODAT_X] = {"fchmodat",
EC_FILE | EC_SYSCALL,
EF_NONE,
EF_USES_FD,
4,
{{"res", PT_ERRNO, PF_DEC},
{"dirfd", PT_FD, PF_DEC},
@ -2146,7 +2176,7 @@ const struct ppm_event_info g_event_info[] = {
{"flags", PT_FLAGS32, PF_HEX, execveat_flags}}},
[PPME_SYSCALL_EXECVEAT_X] = {"execveat",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE,
EF_MODIFIES_STATE | EF_TMP_CONVERTER_MANAGED,
30,
{{"res", PT_ERRNO, PF_DEC},
{"exe", PT_CHARBUF, PF_NA},
@ -2197,10 +2227,13 @@ const struct ppm_event_info g_event_info[] = {
{"fdin", PT_FD, PF_DEC},
{"offin", PT_UINT64, PF_DEC},
{"len", PT_UINT64, PF_DEC}}},
[PPME_SYSCALL_CLONE3_E] = {"clone3", EC_PROCESS | EC_SYSCALL, EF_MODIFIES_STATE, 0},
[PPME_SYSCALL_CLONE3_E] = {"clone3",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE | EF_TMP_CONVERTER_MANAGED,
0},
[PPME_SYSCALL_CLONE3_X] = {"clone3",
EC_PROCESS | EC_SYSCALL,
EF_MODIFIES_STATE,
EF_MODIFIES_STATE | EF_TMP_CONVERTER_MANAGED,
21,
{{"res", PT_PID, PF_DEC},
{"exe", PT_CHARBUF, PF_NA},
@ -2471,7 +2504,7 @@ const struct ppm_event_info g_event_info[] = {
[PPME_SYSCALL_FCHOWNAT_E] = {"fchownat", EC_FILE | EC_SYSCALL, EF_NONE, 0},
[PPME_SYSCALL_FCHOWNAT_X] = {"fchownat",
EC_FILE | EC_SYSCALL,
EF_NONE,
EF_USES_FD,
6,
{{"res", PT_ERRNO, PF_DEC},
{"dirfd", PT_FD, PF_DEC},

View File

@ -179,9 +179,9 @@ int BPF_PROG(t1_sched_p_exec, struct task_struct *p, pid_t old_pid, struct linux
uint32_t tty = exctract__tty(task);
auxmap__store_u32_param(auxmap, (uint32_t)tty);
/* Parameter 18: pgid (type: PT_PID) */
pid_t pgid = extract__task_xid_vnr(task, PIDTYPE_PGID);
auxmap__store_s64_param(auxmap, (int64_t)pgid);
/* Parameter 18: vpgid (type: PT_PID) */
pid_t vpgid = extract__task_xid_vnr(task, PIDTYPE_PGID);
auxmap__store_s64_param(auxmap, (int64_t)vpgid);
/* Parameter 19: loginuid (type: PT_UID) */
uint32_t loginuid;

View File

@ -198,9 +198,9 @@ int BPF_PROG(t1_execve_x, struct pt_regs *regs, long ret) {
uint32_t tty = exctract__tty(task);
auxmap__store_u32_param(auxmap, (uint32_t)tty);
/* Parameter 18: pgid (type: PT_PID) */
pid_t pgid = extract__task_xid_vnr(task, PIDTYPE_PGID);
auxmap__store_s64_param(auxmap, (int64_t)pgid);
/* Parameter 18: vpgid (type: PT_PID) */
pid_t vpgid = extract__task_xid_vnr(task, PIDTYPE_PGID);
auxmap__store_s64_param(auxmap, (int64_t)vpgid);
/* Parameter 19: loginuid (type: PT_UID) */
uint32_t loginuid;

View File

@ -977,6 +977,7 @@ int f_proc_startupdate(struct event_filler_arguments *args) {
/*
* Make sure the operation was successful
*/
/* Parameter 1: res (type: PT_ERRNO) */
retval = (int64_t)syscall_get_return_value(current, args->regs);
res = val_to_ring(args, retval, 0, false, 0);
CHECK_RES(res);
@ -987,15 +988,11 @@ int f_proc_startupdate(struct event_filler_arguments *args) {
* anyway, so I report empty ones */
*args->str_storage = 0;
/*
* exe
*/
/* Parameter 2: exe (type: PT_CHARBUF) */
res = val_to_ring(args, (uint64_t)(long)args->str_storage, 0, false, 0);
CHECK_RES(res);
/*
* Args
*/
/* Parameter 3: args (type: PT_CHARBUFARRAY) */
res = val_to_ring(args, (int64_t)(long)args->str_storage, 0, false, 0);
CHECK_RES(res);
} else {
@ -1068,15 +1065,11 @@ int f_proc_startupdate(struct event_filler_arguments *args) {
if(exe_len < args_len)
++exe_len;
/*
* exe
*/
/* Parameter 2: exe (type: PT_CHARBUF) */
res = val_to_ring(args, (uint64_t)(long)args->str_storage, 0, false, 0);
CHECK_RES(res);
/*
* Args
*/
/* Parameter 3: args (type: PT_CHARBUFARRAY) */
res = val_to_ring(args,
(int64_t)(long)args->str_storage + exe_len,
args_len - exe_len,
@ -1085,21 +1078,17 @@ int f_proc_startupdate(struct event_filler_arguments *args) {
CHECK_RES(res);
}
/*
* tid
*/
/* Parameter 4: tid (type: PT_PID) */
res = val_to_ring(args, (int64_t)current->pid, 0, false, 0);
CHECK_RES(res);
/*
* pid
*/
/* Parameter 5: pid (type: PT_PID) */
/* this is called `pid` but it is the `tgid`. */
res = val_to_ring(args, (int64_t)current->tgid, 0, false, 0);
CHECK_RES(res);
/*
* ptid
*/
/* Parameter 6: ptid (type: PT_PID) */
/* this is called `ptid` but it is the `pgid`. */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20)
if(current->real_parent)
ptid = current->real_parent->pid;
@ -1113,16 +1102,12 @@ int f_proc_startupdate(struct event_filler_arguments *args) {
res = val_to_ring(args, (int64_t)ptid, 0, false, 0);
CHECK_RES(res);
/*
* cwd, pushed empty to avoid breaking compatibility
* with the older event format
*/
/* Parameter 7: cwd (type: PT_CHARBUF) */
/* Push empty to avoid breaking compatibility with the older event format. */
res = push_empty_param(args);
CHECK_RES(res);
/*
* fdlimit
*/
/* Parameter 8: fdlimit (type: PT_UINT64) */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20)
res = val_to_ring(args, (int64_t)rlimit(RLIMIT_NOFILE), 0, false, 0);
#else
@ -1130,15 +1115,11 @@ int f_proc_startupdate(struct event_filler_arguments *args) {
#endif
CHECK_RES(res);
/*
* pgft_maj
*/
/* Parameter 9: pgft_maj (type: PT_UINT64) */
res = val_to_ring(args, current->maj_flt, 0, false, 0);
CHECK_RES(res);
/*
* pgft_min
*/
/* Parameter 10: pgft_min (type: PT_UINT64) */
res = val_to_ring(args, current->min_flt, 0, false, 0);
CHECK_RES(res);
@ -1148,33 +1129,23 @@ int f_proc_startupdate(struct event_filler_arguments *args) {
swap = ppm_get_mm_swap(mm) << (PAGE_SHIFT - 10);
}
/*
* vm_size
*/
/* Parameter 11: vm_size (type: PT_UINT32) */
res = val_to_ring(args, total_vm, 0, false, 0);
CHECK_RES(res);
/*
* vm_rss
*/
/* Parameter 12: vm_rss (type: PT_UINT32) */
res = val_to_ring(args, total_rss, 0, false, 0);
CHECK_RES(res);
/*
* vm_swap
*/
/* Parameter 13: vm_swap (type: PT_UINT32) */
res = val_to_ring(args, swap, 0, false, 0);
CHECK_RES(res);
/*
* comm
*/
/* Parameter 14: comm (type: PT_CHARBUF) */
res = val_to_ring(args, (uint64_t)current->comm, 0, false, 0);
CHECK_RES(res);
/*
* cgroups
*/
/* Parameter 15: cgroups (type: PT_CHARBUFARRAY) */
args->str_storage[0] = 0;
#ifdef CONFIG_CGROUPS
rcu_read_lock();
@ -1368,22 +1339,16 @@ cgroups_error:
if(env_len == 0)
*args->str_storage = 0;
/*
* environ
*/
/* Parameter 16: env (type: PT_CHARBUFARRAY) */
res = val_to_ring(args, (int64_t)(long)args->str_storage, env_len, false, 0);
CHECK_RES(res);
/*
* tty
*/
/* Parameter 17: tty (type: PT_INT32) */
tty_nr = ppm_get_tty();
res = val_to_ring(args, tty_nr, 0, false, 0);
CHECK_RES(res);
/*
* pgid
*/
/* Parameter 18: vpgid (type: PT_PID) */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
res = val_to_ring(args,
(int64_t)task_pgrp_nr_ns(current, task_active_pid_ns(current)),
@ -1395,9 +1360,7 @@ cgroups_error:
#endif
CHECK_RES(res);
/*
* loginuid
*/
/* Parameter 19: loginuid (type: PT_UID) */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
loginuid = from_kuid(current_user_ns(), audit_get_loginuid(current));
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
@ -1498,9 +1461,7 @@ cgroups_error:
// write all the additional flags for execve family here...
/*
* flags
*/
/* Parameter 20: flags (type: PT_FLAGS32) */
res = val_to_ring(args, flags, 0, false, 0);
CHECK_RES(res);
@ -1584,12 +1545,10 @@ cgroups_error:
}
int f_sys_execve_e(struct event_filler_arguments *args) {
int res;
unsigned long val;
int res;
/*
* filename
*/
/* Parameter 1: filename (type: PT_FSPATH) */
syscall_get_arguments_deprecated(args, 0, 1, &val);
res = val_to_ring(args, val, 0, true, 0);
CHECK_RES(res);
@ -9425,7 +9384,7 @@ cgroups_error:
res = val_to_ring(args, tty_nr, 0, false, 0);
CHECK_RES(res);
/* Parameter 18: pgid (type: PT_PID) */
/* Parameter 18: vpgid (type: PT_PID) */
res = val_to_ring(args,
(int64_t)task_pgrp_nr_ns(current, task_active_pid_ns(current)),
0,

View File

@ -85,7 +85,7 @@ TEST(GenericTracepoints, sched_proc_exec) {
/* Please note here we cannot assert all the params, we check only the possible ones. */
/* Parameter 1: res (type: PT_ERRNO)*/
/* Parameter 1: res (type: PT_ERRNO) */
evt_test->assert_numeric_param(1, (int64_t)0);
/* Parameter 2: exe (type: PT_CHARBUF) */
@ -230,7 +230,7 @@ TEST(GenericTracepoints, sched_proc_exec_success_memfd) {
/* Please note here we cannot assert all the params, we check only the possible ones. */
/* Parameter 1: res (type: PT_ERRNO)*/
/* Parameter 1: res (type: PT_ERRNO) */
evt_test->assert_numeric_param(1, (int64_t)0);
/* PPM_EXE_WRITABLE is set when the user that executed a process can also write to the

View File

@ -31,7 +31,7 @@ TEST(SyscallEnter, execveE) {
/*=============================== ASSERT PARAMETERS ===========================*/
/* Parameter 1: pathname (type: PT_FSRELPATH) */
/* Parameter 1: filename (type: PT_FSPATH) */
evt_test->assert_charbuf_param(1, pathname);
/*=============================== ASSERT PARAMETERS ===========================*/

View File

@ -190,7 +190,7 @@ TEST(SyscallExit, execveX_failure) {
/*=============================== ASSERT PARAMETERS ===========================*/
/* Parameter 1: res (type: PT_ERRNO)*/
/* Parameter 1: res (type: PT_ERRNO) */
evt_test->assert_numeric_param(1, (int64_t)errno_value);
/* Parameter 2: exe (type: PT_CHARBUF) */
@ -340,7 +340,7 @@ TEST(SyscallExit, execveX_failure_args_env_NULL) {
/*=============================== ASSERT PARAMETERS ===========================*/
/* Parameter 1: res (type: PT_ERRNO)*/
/* Parameter 1: res (type: PT_ERRNO) */
evt_test->assert_numeric_param(1, (int64_t)errno_value);
/* Parameter 2: exe (type: PT_CHARBUF) */
@ -389,7 +389,7 @@ TEST(SyscallExit, execveX_failure_path_NULL_but_not_args) {
/*=============================== ASSERT PARAMETERS ===========================*/
/* Parameter 1: res (type: PT_ERRNO)*/
/* Parameter 1: res (type: PT_ERRNO) */
evt_test->assert_numeric_param(1, (int64_t)errno_value);
/* Parameter 2: exe (type: PT_CHARBUF) */
@ -493,7 +493,7 @@ TEST(SyscallExit, execveX_success) {
/* Please note here we cannot assert all the params, we check only the possible ones. */
/* Parameter 1: res (type: PT_ERRNO)*/
/* Parameter 1: res (type: PT_ERRNO) */
evt_test->assert_numeric_param(1, (int64_t)0);
/* Parameter 2: exe (type: PT_CHARBUF) */
@ -632,7 +632,7 @@ TEST(SyscallExit, execveX_not_upperlayer) {
/* Please note here we cannot assert all the params, we check only the possible ones. */
/* Parameter 1: res (type: PT_ERRNO)*/
/* Parameter 1: res (type: PT_ERRNO) */
evt_test->assert_numeric_param(1, (int64_t)0);
/* Parameter 2: exe (type: PT_CHARBUF) */
@ -762,7 +762,7 @@ TEST(SyscallExit, execveX_upperlayer_success) {
/* Please note here we cannot assert all the params, we check only the possible ones. */
/* Parameter 1: res (type: PT_ERRNO)*/
/* Parameter 1: res (type: PT_ERRNO) */
evt_test->assert_numeric_param(1, (int64_t)0);
/* Parameter 2: exe (type: PT_CHARBUF) */
@ -913,7 +913,7 @@ TEST(SyscallExit, execveX_success_memfd) {
/* Please note here we cannot assert all the params, we check only the possible ones. */
/* Parameter 1: res (type: PT_ERRNO)*/
/* Parameter 1: res (type: PT_ERRNO) */
evt_test->assert_numeric_param(1, (int64_t)0);
/* PPM_EXE_WRITABLE is set when the user that executed a process can also write to the
@ -1013,7 +1013,7 @@ TEST(SyscallExit, execveX_symlink) {
/* Please note here we cannot assert all the params, we check only the possible ones. */
/* Parameter 1: res (type: PT_ERRNO)*/
/* Parameter 1: res (type: PT_ERRNO) */
evt_test->assert_numeric_param(1, (int64_t)0);
/* Parameter 2: exe (type: PT_CHARBUF) */
@ -1087,7 +1087,7 @@ TEST(SyscallExit, execveX_failure_empty_arg) {
/*=============================== ASSERT PARAMETERS ===========================*/
/* Parameter 1: res (type: PT_ERRNO)*/
/* Parameter 1: res (type: PT_ERRNO) */
evt_test->assert_numeric_param(1, (int64_t)errno_value);
/* Parameter 2: exe (type: PT_CHARBUF) */

View File

@ -163,7 +163,7 @@ TEST(gvisor_parsers, parse_execve_x) {
scap_sized_buffer decoded_params[PPM_MAX_EVENT_PARAMS];
uint32_t n = scap_event_decode_params(res.scap_events[0], decoded_params);
EXPECT_EQ(n, 27);
EXPECT_EQ(n, 30);
EXPECT_STREQ(static_cast<const char *>(decoded_params[1].buf), "/usr/bin/ls"); // exe
EXPECT_STREQ(static_cast<const char *>(decoded_params[2].buf), "a"); // args[0] must be argv[1]
EXPECT_STREQ(static_cast<const char *>(decoded_params[6].buf), "/root"); // cwd
@ -190,7 +190,7 @@ TEST(gvisor_parsers, parse_execve_x) {
EXPECT_EQ(res.scap_events.size(), 1);
n = scap_event_decode_params(res.scap_events[0], decoded_params);
EXPECT_EQ(n, 27);
EXPECT_EQ(n, 30);
EXPECT_STREQ(static_cast<const char *>(decoded_params[1].buf), "/usr/bin/ls"); // exe
EXPECT_EQ(strlen(static_cast<const char *>(decoded_params[2].buf)),
0); // there must be no args

View File

@ -27,6 +27,12 @@ class convert_event_test : public testing::Test {
static constexpr uint16_t safe_margin = 100;
protected:
// Return an empty value for the type T.
template<typename T>
constexpr static T empty_value() {
return static_cast<T>(0);
}
virtual void SetUp() {
m_converter_buf = scap_convert_alloc_buffer();
ASSERT_NE(m_converter_buf, nullptr);
@ -34,25 +40,44 @@ protected:
virtual void TearDown() { scap_convert_free_buffer(m_converter_buf); }
safe_scap_evt_t create_safe_scap_event(uint64_t ts,
uint64_t tid,
ppm_event_code event_type,
uint32_t n,
...) {
static safe_scap_evt_t create_safe_scap_event(uint64_t ts,
uint64_t tid,
ppm_event_code event_type,
uint32_t n,
...) {
char error[SCAP_LASTERR_SIZE] = {'\0'};
va_list args;
va_start(args, n);
scap_evt *evt = scap_create_event_v(error, ts, tid, event_type, n, args);
scap_evt *evt = scap_create_event_v(error, ts, tid, event_type, nullptr, n, args);
va_end(args);
if(evt == NULL) {
throw std::runtime_error("Error creating event: " + std::string(error));
}
return new_safe_scap_evt(evt);
}
static safe_scap_evt_t create_safe_scap_event_with_empty_params(
uint64_t ts,
uint64_t tid,
ppm_event_code event_type,
const scap_empty_params_set *empty_params_set,
uint32_t n,
...) {
char error[SCAP_LASTERR_SIZE] = {'\0'};
va_list args;
va_start(args, n);
scap_evt *evt = scap_create_event_v(error, ts, tid, event_type, empty_params_set, n, args);
va_end(args);
if(evt == NULL) {
throw std::runtime_error("Error creating event: " + std::string(error));
}
return new_safe_scap_evt(evt);
}
// The expected result can be either CONVERSION_CONTINUE or CONVERSION_COMPLETED
void assert_single_conversion_success(enum conversion_result expected_res,
safe_scap_evt_t evt_to_convert,
safe_scap_evt_t expected_evt) {
void assert_single_conversion_success(const conversion_result expected_res,
const safe_scap_evt_t &evt_to_convert,
const safe_scap_evt_t &expected_evt) const {
char error[SCAP_LASTERR_SIZE] = {'\0'};
// We assume it's okay to create a new event with the same size as the expected event
auto storage = new_safe_scap_evt((scap_evt *)calloc(1, expected_evt->len));
@ -60,6 +85,7 @@ protected:
ASSERT_EQ(scap_convert_event(m_converter_buf, storage.get(), evt_to_convert.get(), error),
expected_res)
<< "Different conversion results: " << error;
if(!scap_compare_events(storage.get(), expected_evt.get(), error)) {
printf("\nExpected event:\n");
scap_print_event(expected_evt.get(), PRINT_FULL);
@ -68,7 +94,8 @@ protected:
FAIL() << error;
}
}
void assert_single_conversion_failure(safe_scap_evt_t evt_to_convert) {
void assert_single_conversion_failure(const safe_scap_evt_t &evt_to_convert) const {
char error[SCAP_LASTERR_SIZE] = {'\0'};
// We assume it's okay to create a new event with the same size as the expected event
auto storage = new_safe_scap_evt((scap_evt *)calloc(1, evt_to_convert->len));
@ -77,7 +104,7 @@ protected:
CONVERSION_ERROR)
<< "The conversion is not failed: " << error;
}
void assert_single_conversion_skip(safe_scap_evt_t evt_to_convert) {
void assert_single_conversion_skip(const safe_scap_evt_t &evt_to_convert) const {
char error[SCAP_LASTERR_SIZE] = {'\0'};
// We assume it's okay to create a new event with the same size as the expected event
auto storage = new_safe_scap_evt((scap_evt *)calloc(1, evt_to_convert->len));
@ -86,7 +113,8 @@ protected:
CONVERSION_SKIP)
<< "The conversion is not skipped: " << error;
}
void assert_full_conversion(safe_scap_evt_t evt_to_convert, safe_scap_evt_t expected_evt) {
void assert_full_conversion(const safe_scap_evt_t &evt_to_convert,
const safe_scap_evt_t &expected_evt) const {
char error[SCAP_LASTERR_SIZE] = {'\0'};
// Here we need to allocate more space than the expected event because in the middle we
// could have larger events. We could also use `MAX_EVENT_SIZE` but probably it will just
@ -124,6 +152,7 @@ protected:
default:
break;
}
if(!scap_compare_events(new_evt.get(), expected_evt.get(), error)) {
printf("\nExpected event:\n");
scap_print_event(expected_evt.get(), PRINT_FULL);
@ -132,7 +161,7 @@ protected:
FAIL() << error;
}
}
void assert_event_storage_presence(safe_scap_evt_t expected_evt) {
void assert_event_storage_presence(const safe_scap_evt_t &expected_evt) const {
char error[SCAP_LASTERR_SIZE] = {'\0'};
int64_t tid = expected_evt.get()->tid;
auto event = scap_retrieve_evt_from_converter_storage(m_converter_buf, tid);
@ -146,3 +175,13 @@ protected:
struct scap_convert_buffer *m_converter_buf = nullptr;
};
template<>
constexpr scap_const_sized_buffer convert_event_test::empty_value() {
return {nullptr, 0};
}
template<>
constexpr char *convert_event_test::empty_value() {
return nullptr;
}

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@
TEST(event_table, scap_get_syscall_category_from_event) {
ASSERT_EQ(scap_get_syscall_category_from_event(PPME_CONTAINER_JSON_2_E), EC_PROCESS);
ASSERT_EQ(scap_get_syscall_category_from_event(PPME_SYSCALL_EXECVE_17_E), EC_PROCESS);
ASSERT_EQ(scap_get_syscall_category_from_event(PPME_SYSCALL_EXECVE_19_E), EC_PROCESS);
ASSERT_EQ(scap_get_syscall_category_from_event(PPME_MESOS_X), EC_UNKNOWN);
ASSERT_EQ(scap_get_syscall_category_from_event(PPME_TRACER_X), EC_OTHER);
ASSERT_EQ(scap_get_syscall_category_from_event(PPME_PROCINFO_E), EC_INTERNAL);
@ -13,7 +13,7 @@ TEST(event_table, scap_get_syscall_category_from_event) {
TEST(event_table, scap_get_event_category_from_event) {
ASSERT_EQ(scap_get_event_category_from_event(PPME_CONTAINER_JSON_2_E), EC_METAEVENT);
ASSERT_EQ(scap_get_event_category_from_event(PPME_SYSCALL_EXECVE_17_E), EC_SYSCALL);
ASSERT_EQ(scap_get_event_category_from_event(PPME_SYSCALL_EXECVE_19_E), EC_SYSCALL);
ASSERT_EQ(scap_get_event_category_from_event(PPME_MESOS_X), EC_UNKNOWN);
ASSERT_EQ(scap_get_event_category_from_event(PPME_TRACER_X), EC_METAEVENT);
ASSERT_EQ(scap_get_event_category_from_event(PPME_PROCINFO_E), EC_METAEVENT);

View File

@ -54,7 +54,8 @@ static int32_t scap_event_generate(scap_evt **event,
size_t event_size;
va_list args;
va_start(args, n);
int32_t ret = scap_event_encode_params_v(event_buf, &event_size, error, event_type, n, args);
int32_t ret =
scap_event_encode_params_v(event_buf, &event_size, error, event_type, nullptr, n, args);
va_end(args);
if(ret != SCAP_INPUT_TOO_SMALL) {
@ -83,7 +84,7 @@ static int32_t scap_event_generate(scap_evt **event,
}
va_start(args, n);
ret = scap_event_encode_params_v(event_buf, &event_size, error, event_type, n, args);
ret = scap_event_encode_params_v(event_buf, &event_size, error, event_type, nullptr, n, args);
va_end(args);
if(ret != SCAP_SUCCESS) {

View File

@ -767,7 +767,7 @@ TEST_F(sys_call_test, forking_main_thread_exit) {
} else if(param.m_evt->get_type() == PPME_PROCEXIT_1_E && param.m_evt->get_tid() == cpid) {
++callnum;
} else if(param.m_evt->get_type() == PPME_SYSCALL_READ_E) {
if(memcmp(&fd, param.m_evt->get_param(0)->m_val, sizeof(fd)) == 0) {
if(memcmp(&fd, param.m_evt->get_param(0)->data(), sizeof(fd)) == 0) {
EXPECT_EQ("<f>/etc/passwd", param.m_evt->get_param_value_str("fd"));
++callnum;
}
@ -1015,9 +1015,7 @@ TEST_F(sys_call_test, remove_stale_thread_clone_exit) {
sinsp_threadinfo* tinfo = e->get_thread_info();
ASSERT_TRUE((tinfo != NULL));
if((etype == PPME_SYSCALL_CLONE_11_X || etype == PPME_SYSCALL_CLONE_16_X ||
etype == PPME_SYSCALL_CLONE_17_X || etype == PPME_SYSCALL_CLONE_20_X) &&
e->get_direction() == SCAP_ED_OUT) {
if((etype == PPME_SYSCALL_CLONE_20_X) && e->get_direction() == SCAP_ED_OUT) {
++clones_seen;
}

View File

@ -1248,8 +1248,8 @@ TEST_F(sys_call_test, large_read_write) {
if(callnum == 1) {
const sinsp_evt_param* p = e->get_param_by_name("data");
EXPECT_EQ(p->m_len, SNAPLEN_MAX);
EXPECT_EQ(0, memcmp(buf.data(), p->m_val, SNAPLEN_MAX));
EXPECT_EQ(p->len(), SNAPLEN_MAX);
EXPECT_EQ(0, memcmp(buf.data(), p->data(), SNAPLEN_MAX));
callnum++;
}
@ -1262,8 +1262,8 @@ TEST_F(sys_call_test, large_read_write) {
if(callnum == 3) {
const sinsp_evt_param* p = e->get_param_by_name("data");
EXPECT_EQ(p->m_len, SNAPLEN_MAX);
EXPECT_EQ(0, memcmp(buf.data(), p->m_val, SNAPLEN_MAX));
EXPECT_EQ(p->len(), SNAPLEN_MAX);
EXPECT_EQ(0, memcmp(buf.data(), p->data(), SNAPLEN_MAX));
callnum++;
}
@ -1360,11 +1360,11 @@ TEST_F(sys_call_test, large_readv_writev) {
// The driver doesn't have the correct behavior for accumulating
// readv/writev, and it uses a single page as a temporary storage area
//
EXPECT_EQ(p->m_len, max_kmod_buf);
EXPECT_EQ(0, memcmp(buf, p->m_val, max_kmod_buf));
EXPECT_EQ(p->len(), max_kmod_buf);
EXPECT_EQ(0, memcmp(buf, p->data(), max_kmod_buf));
} else {
EXPECT_EQ(p->m_len, SNAPLEN_MAX);
EXPECT_EQ(0, memcmp(buf, p->m_val, SNAPLEN_MAX));
EXPECT_EQ(p->len(), SNAPLEN_MAX);
EXPECT_EQ(0, memcmp(buf, p->data(), SNAPLEN_MAX));
}
EXPECT_EQ(fd, std::stoll(e->get_param_value_str("fd", false)));
@ -1379,11 +1379,11 @@ TEST_F(sys_call_test, large_readv_writev) {
if(callnum == 3) {
const sinsp_evt_param* p = e->get_param_by_name("data");
if(event_capture::s_engine_string == KMOD_ENGINE) {
EXPECT_EQ(p->m_len, max_kmod_buf);
EXPECT_EQ(0, memcmp(buf, p->m_val, max_kmod_buf));
EXPECT_EQ(p->len(), max_kmod_buf);
EXPECT_EQ(0, memcmp(buf, p->data(), max_kmod_buf));
} else {
EXPECT_EQ(p->m_len, SNAPLEN_MAX);
EXPECT_EQ(0, memcmp(buf, p->m_val, SNAPLEN_MAX));
EXPECT_EQ(p->len(), SNAPLEN_MAX);
EXPECT_EQ(0, memcmp(buf, p->data(), SNAPLEN_MAX));
}
EXPECT_EQ(fd, std::stoll(e->get_param_value_str("fd", false)));
@ -1443,14 +1443,14 @@ TEST_F(sys_call_test, large_open) {
const sinsp_evt_param* p = e->get_param_by_name("name");
if(event_capture::s_engine_string == KMOD_ENGINE) {
EXPECT_EQ(p->m_len, PPM_MAX_ARG_SIZE);
EXPECT_EQ(buf.substr(0, PPM_MAX_ARG_SIZE - 1), std::string(p->m_val));
EXPECT_EQ(p->len(), PPM_MAX_ARG_SIZE);
EXPECT_EQ(buf.substr(0, PPM_MAX_ARG_SIZE - 1), std::string(p->data()));
} else if(event_capture::s_engine_string == BPF_ENGINE) {
EXPECT_EQ(p->m_len, SNAPLEN_MAX);
EXPECT_EQ(buf.substr(0, SNAPLEN_MAX - 1), std::string(p->m_val));
EXPECT_EQ(p->len(), SNAPLEN_MAX);
EXPECT_EQ(buf.substr(0, SNAPLEN_MAX - 1), std::string(p->data()));
} else if(event_capture::s_engine_string == MODERN_BPF_ENGINE) {
EXPECT_EQ(p->m_len, PATH_MAX);
EXPECT_EQ(buf.substr(0, PATH_MAX - 1), std::string(p->m_val));
EXPECT_EQ(p->len(), PATH_MAX);
EXPECT_EQ(buf.substr(0, PATH_MAX - 1), std::string(p->data()));
}
callnum++;

View File

@ -960,25 +960,25 @@ TEST_F(sys_call_test, quotactl_ok) {
EXPECT_EQ("/dev/loop0", e->get_param_value_str("special"));
EXPECT_EQ(mydqblk.dqb_bhardlimit,
*reinterpret_cast<const uint64_t*>(
e->get_param_by_name("dqb_bhardlimit")->m_val));
e->get_param_by_name("dqb_bhardlimit")->data()));
EXPECT_EQ(mydqblk.dqb_bsoftlimit,
*reinterpret_cast<const uint64_t*>(
e->get_param_by_name("dqb_bsoftlimit")->m_val));
e->get_param_by_name("dqb_bsoftlimit")->data()));
EXPECT_EQ(mydqblk.dqb_curspace,
*reinterpret_cast<const uint64_t*>(
e->get_param_by_name("dqb_curspace")->m_val));
e->get_param_by_name("dqb_curspace")->data()));
EXPECT_EQ(mydqblk.dqb_ihardlimit,
*reinterpret_cast<const uint64_t*>(
e->get_param_by_name("dqb_ihardlimit")->m_val));
e->get_param_by_name("dqb_ihardlimit")->data()));
EXPECT_EQ(mydqblk.dqb_isoftlimit,
*reinterpret_cast<const uint64_t*>(
e->get_param_by_name("dqb_isoftlimit")->m_val));
e->get_param_by_name("dqb_isoftlimit")->data()));
EXPECT_EQ(mydqblk.dqb_btime,
*reinterpret_cast<const uint64_t*>(
e->get_param_by_name("dqb_btime")->m_val));
e->get_param_by_name("dqb_btime")->data()));
EXPECT_EQ(mydqblk.dqb_itime,
*reinterpret_cast<const uint64_t*>(
e->get_param_by_name("dqb_itime")->m_val));
e->get_param_by_name("dqb_itime")->data()));
EXPECT_EQ("Q_GETQUOTA", e->get_param_value_str("cmd"));
EXPECT_EQ("USRQUOTA", e->get_param_value_str("type"));
EXPECT_EQ("0", e->get_param_value_str("id"));
@ -988,10 +988,10 @@ TEST_F(sys_call_test, quotactl_ok) {
EXPECT_EQ("/dev/loop0", e->get_param_value_str("special"));
EXPECT_EQ(mydqinfo.dqi_bgrace,
*reinterpret_cast<const uint64_t*>(
e->get_param_by_name("dqi_bgrace")->m_val));
e->get_param_by_name("dqi_bgrace")->data()));
EXPECT_EQ(mydqinfo.dqi_igrace,
*reinterpret_cast<const uint64_t*>(
e->get_param_by_name("dqi_igrace")->m_val));
e->get_param_by_name("dqi_igrace")->data()));
EXPECT_EQ("Q_GETINFO", e->get_param_value_str("cmd"));
EXPECT_EQ("USRQUOTA", e->get_param_value_str("type"));
break;
@ -1125,8 +1125,7 @@ TEST_F(sys_call_test32, execve_ia32_emulation) {
sinsp_evt* e = param.m_evt;
uint16_t type = e->get_type();
auto tinfo = e->get_thread_info(true);
if(type == PPME_SYSCALL_EXECVE_19_E || type == PPME_SYSCALL_EXECVE_18_E ||
type == PPME_SYSCALL_EXECVE_17_E) {
if(type == PPME_SYSCALL_EXECVE_19_E) {
++callnum;
switch(callnum) {
case 1:
@ -1142,8 +1141,7 @@ TEST_F(sys_call_test32, execve_ia32_emulation) {
EXPECT_EQ(tinfo->m_comm, "execve");
break;
}
} else if(type == PPME_SYSCALL_EXECVE_19_X || type == PPME_SYSCALL_EXECVE_18_X ||
type == PPME_SYSCALL_EXECVE_17_X) {
} else if(type == PPME_SYSCALL_EXECVE_19_X) {
++callnum;
EXPECT_EQ("0", e->get_param_value_str("res", false));
auto comm = e->get_param_value_str("comm", false);
@ -1355,9 +1353,9 @@ TEST_F(sys_call_test, sendmsg_recvmsg_SCM_RIGHTS) {
sinsp_evt* e = param.m_evt;
if(e->get_num_params() >= 5) {
auto parinfo = e->get_param(4);
if(parinfo->m_len > sizeof(cmsghdr)) {
if(parinfo->len() > sizeof(cmsghdr)) {
cmsghdr cmsg = {};
memcpy(&cmsg, parinfo->m_val, sizeof(cmsghdr));
memcpy(&cmsg, parinfo->data(), sizeof(cmsghdr));
if(cmsg.cmsg_type == SCM_RIGHTS) {
++callnum;
}
@ -1608,12 +1606,12 @@ TEST_F(sys_call_test, failing_execve) {
sinsp_evt* e = param.m_evt;
uint16_t type = e->get_type();
if(type == PPME_SYSCALL_EXECVE_19_E || type == PPME_SYSCALL_EXECVE_18_E) {
if(type == PPME_SYSCALL_EXECVE_19_E) {
++callnum;
string filename = e->get_param_value_str("filename");
EXPECT_EQ(filename, eargv[0]);
} else if(type == PPME_SYSCALL_EXECVE_19_X || type == PPME_SYSCALL_EXECVE_18_X) {
} else if(type == PPME_SYSCALL_EXECVE_19_X) {
++callnum;
string res = e->get_param_value_str("res");
@ -1687,7 +1685,7 @@ TEST_F(sys_call_test, large_execve) {
sinsp_evt* e = param.m_evt;
uint16_t type = e->get_type();
if(type == PPME_SYSCALL_EXECVE_19_E || type == PPME_SYSCALL_EXECVE_18_E) {
if(type == PPME_SYSCALL_EXECVE_19_E) {
++callnum;
string filename = e->get_param_value_str("filename");
@ -1699,7 +1697,7 @@ TEST_F(sys_call_test, large_execve) {
} else {
FAIL();
}
} else if(type == PPME_SYSCALL_EXECVE_19_X || type == PPME_SYSCALL_EXECVE_18_X) {
} else if(type == PPME_SYSCALL_EXECVE_19_X) {
++callnum;
string exe = e->get_param_value_str("exe");
@ -1766,8 +1764,7 @@ TEST_F(sys_call_test32, failing_execve) {
sinsp_evt* e = param.m_evt;
uint16_t type = e->get_type();
auto tinfo = e->get_thread_info(true);
if(type == PPME_SYSCALL_EXECVE_19_E || type == PPME_SYSCALL_EXECVE_18_E ||
type == PPME_SYSCALL_EXECVE_17_E) {
if(type == PPME_SYSCALL_EXECVE_19_E) {
++callnum;
switch(callnum) {
case 1:
@ -1788,8 +1785,7 @@ TEST_F(sys_call_test32, failing_execve) {
default:
FAIL() << "Wrong execve entry callnum (" << callnum << ")";
}
} else if(type == PPME_SYSCALL_EXECVE_19_X || type == PPME_SYSCALL_EXECVE_18_X ||
type == PPME_SYSCALL_EXECVE_17_X) {
} else if(type == PPME_SYSCALL_EXECVE_19_X) {
++callnum;
auto res = e->get_param_value_str("res", false);

View File

@ -481,7 +481,7 @@ TEST_F(sys_call_test, udp_client_server) {
std::string dst_port;
if(type == PPME_SOCKET_RECVFROM_E) {
memcpy(&fd_server_socket, e->get_param(0)->m_val, sizeof(fd_server_socket));
memcpy(&fd_server_socket, e->get_param(0)->data(), sizeof(fd_server_socket));
}
switch(state) {
case 0:

View File

@ -97,6 +97,7 @@ add_library(
scap_event.c
ppm_sc_names.c
scap_print_event.c
scap_empty_params_set.c
${LIBS_DIR}/driver/dynamic_params_table.c
${LIBS_DIR}/driver/event_table.c
${LIBS_DIR}/driver/flags_table.c

View File

@ -20,6 +20,7 @@ limitations under the License.
#include <libscap/scap_log.h>
#include <stdarg.h>
#include <stdio.h>
#define scap_log(HANDLE, sev, ...) scap_log_impl(HANDLE->m_log_fn, sev, __VA_ARGS__)

View File

@ -262,7 +262,7 @@ int32_t fill_event_execve_19_e(scap_sized_buffer scap_buf,
// - F11/vm_rss -- hardcoded to 0
// - F12/vm_swap -- hardcoded to 0
// - F16/tty -- hardcoded to 0
// - F17/pgid -- hardcoded to 0
// - F17/vpgid -- hardcoded to 0
// - F18/loginuid -- hardcoded to UINT32_MAX
// - F19/flags -- hardcoded to 0
// - F20/cap_inheritable -- hardcoded to 0
@ -275,6 +275,7 @@ int32_t fill_event_execve_19_e(scap_sized_buffer scap_buf,
// B) Provided by caller, but caller sometimes specifies a hardcoded value
// due to value not available in native gVisor event:
// - F26/uid -- some callers pass in hardcoded value of 0
// - F29/gid -- some callers pass in hardcoded value of 0
int32_t fill_event_execve_19_x(scap_sized_buffer scap_buf,
size_t* event_size,
char* scap_err,
@ -287,12 +288,13 @@ int32_t fill_event_execve_19_x(scap_sized_buffer scap_buf,
const char* comm,
scap_const_sized_buffer cgroups,
scap_const_sized_buffer env,
uint32_t uid) {
uint32_t uid,
uint32_t gid) {
return scap_event_encode_params(scap_buf,
event_size,
scap_err,
PPME_SYSCALL_EXECVE_19_X,
27,
30,
res,
exe,
args,
@ -310,7 +312,7 @@ int32_t fill_event_execve_19_x(scap_sized_buffer scap_buf,
cgroups,
env,
0, // tty -- INVALID
0, // pgid -- INVALID
0, // vpgid -- INVALID
UINT32_MAX, // loginuid -- INVALID
0, // flags -- INVALID
0, // cap_inheritable -- INVALID
@ -319,7 +321,11 @@ int32_t fill_event_execve_19_x(scap_sized_buffer scap_buf,
0, // exe_ino -- INVALID
0, // exe_ino_ctime -- INVALID
0, // exe_ino_mtime -- INVALID
uid); // uid
uid, // uid
exe, // trusted_exepath
0, // pgid -- INVALID
gid // gid
);
}
// PPME_SYSCALL_EXECVEAT_E
@ -351,7 +357,7 @@ int32_t fill_event_execveat_e(scap_sized_buffer scap_buf,
// - F11/vm_rss -- hardcoded to 0
// - F12/vm_swap -- hardcoded to 0
// - F16/tty -- hardcoded to 0
// - F17/pgid -- hardcoded to 0
// - F17/vpgid -- hardcoded to 0
// - F18/loginuid -- hardcoded to UINT32_MAX
// - F19/flags -- hardcoded to 0
// - F20/cap_inheritable -- hardcoded to 0
@ -364,6 +370,7 @@ int32_t fill_event_execveat_e(scap_sized_buffer scap_buf,
// B) Provided by caller, but caller sometimes specifies a hardcoded value
// due to value not available in native gVisor event:
// - F26/uid -- some callers pass in hardcoded value of 0
// - F29/gid -- some callers pass in hardcoded value of 0
int32_t fill_event_execveat_x(scap_sized_buffer scap_buf,
size_t* event_size,
char* scap_err,
@ -376,12 +383,13 @@ int32_t fill_event_execveat_x(scap_sized_buffer scap_buf,
const char* comm,
scap_const_sized_buffer cgroups,
scap_const_sized_buffer env,
uint32_t uid) {
uint32_t uid,
uint32_t gid) {
return scap_event_encode_params(scap_buf,
event_size,
scap_err,
PPME_SYSCALL_EXECVEAT_X,
27,
30,
res,
exe,
args,
@ -408,7 +416,11 @@ int32_t fill_event_execveat_x(scap_sized_buffer scap_buf,
0, // exe_ino -- INVALID
0, // exe_ino_ctime -- INVALID
0, // exe_ino_mtime -- INVALID
uid); // uid
uid, // uid
exe, // trusted_exepath
0, // pgid -- INVALID
gid // gid
);
}
// PPME_SYSCALL_PROCEXIT_1_E

View File

@ -99,7 +99,8 @@ int32_t fill_event_execve_19_x(scap_sized_buffer scap_buf,
const char* comm,
scap_const_sized_buffer cgroups,
scap_const_sized_buffer env,
uint32_t uid);
uint32_t uid,
uint32_t gid);
int32_t fill_event_execveat_e(scap_sized_buffer scap_buf,
size_t* event_size,
@ -120,7 +121,8 @@ int32_t fill_event_execveat_x(scap_sized_buffer scap_buf,
const char* comm,
scap_const_sized_buffer cgroups,
scap_const_sized_buffer env,
uint32_t uid);
uint32_t uid,
uint32_t gid);
int32_t fill_event_procexit_1_e(scap_sized_buffer scap_buf,
size_t* event_size,

View File

@ -130,12 +130,11 @@ const scap_platform_vtable scap_gvisor_platform_vtable = {
.free_platform = scap_gvisor_free_platform,
};
scap_platform* scap_gvisor_alloc_platform(proc_entry_callback proc_callback,
void* proc_callback_context) {
scap_platform* scap_gvisor_alloc_platform(scap_proc_callbacks callbacks) {
auto platform = new scap_gvisor_platform();
platform->m_generic.m_vtable = &scap_gvisor_platform_vtable;
init_proclist(&platform->m_generic.m_proclist, proc_callback, proc_callback_context);
init_proclist(&platform->m_generic.m_proclist, callbacks);
return &platform->m_generic;
}

View File

@ -34,8 +34,7 @@ struct scap_gvisor_engine_params {
};
struct scap_platform;
struct scap_platform* scap_gvisor_alloc_platform(proc_entry_callback proc_callback,
void* proc_callback_context);
struct scap_platform* scap_gvisor_alloc_platform(scap_proc_callbacks callbacks);
#ifdef __cplusplus
};

View File

@ -209,11 +209,11 @@ static parse_result parse_container_start(uint32_t id,
}
// encode execve entry
ret.status = scap_gvisor::fillers::fill_event_execve_19_e(
event_buf,
&event_size,
scap_err,
gvisor_evt.args(0).c_str()); // TODO actual exe missing
ret.status =
scap_gvisor::fillers::fill_event_execve_19_e(event_buf,
&event_size,
scap_err,
exe.c_str()); // TODO actual exe missing
if(ret.status == SCAP_FAILURE) {
ret.error = scap_err;
@ -248,7 +248,9 @@ static parse_result parse_container_start(uint32_t id,
comm.c_str(),
scap_const_sized_buffer{cgroups.c_str(), cgroups.length() + 1},
scap_const_sized_buffer{env.data(), env.size()},
context_data.credentials().effective_uid()); // uid
context_data.credentials().effective_uid(), // uid
context_data.credentials().effective_gid() // gid
);
if(ret.status == SCAP_FAILURE) {
ret.error = scap_err;
@ -336,7 +338,9 @@ static parse_result parse_execve(uint32_t id,
comm.c_str(), // comm
scap_const_sized_buffer{cgroups.c_str(), cgroups.length() + 1},
scap_const_sized_buffer{env.data(), env.size()},
0); // uid -- INVALID/not available in gVisor evt
0, // uid -- INVALID/not available in gVisor evt
0 // gid -- INVALID/not available in gVisor evt
);
break;
case __NR_execveat:
@ -353,7 +357,9 @@ static parse_result parse_execve(uint32_t id,
comm.c_str(), // comm
scap_const_sized_buffer{cgroups.c_str(), cgroups.length() + 1},
scap_const_sized_buffer{env.data(), env.size()},
0); // uid -- INVALID/not available in gVisor evt
0, // uid -- INVALID/not available in gVisor evt
0 // gid -- INVALID/not available in gVisor evt
);
break;
default:

View File

@ -49,15 +49,21 @@ result runsc(char *argv[]) {
std::string line;
char buf[512]{};
char buf[512];
std::stringstream ss;
size_t len;
ssize_t len;
// Read until EOF
while((len = read(pipefds[0], buf, sizeof(buf) - 1)) != 0) {
while((len = read(pipefds[0], buf, sizeof(buf) - 1)) > 0) {
// Null-terminate the buffer at the exact read length
buf[len] = '\0';
ss << buf;
// Be smart: only reset first len bytes
memset(buf, 0, len);
}
if(len < 0) {
// handle error
res.error = errno;
return res;
}
while(std::getline(ss, line)) {

View File

@ -121,7 +121,7 @@ static char *get_param_ptr(scap_evt *evt, uint8_t num_param) {
return ptr + ptr_off;
}
static uint8_t get_size_bytes_from_type(const ppm_param_type t) {
static uint8_t get_default_value_size_bytes_from_type(const ppm_param_type t) {
switch(t) {
case PT_INT8:
case PT_UINT8:
@ -179,10 +179,11 @@ static uint8_t get_size_bytes_from_type(const ppm_param_type t) {
// `uint64_t` should be enough for all the types considering that types like CHARBUF, BYTEBUF
// have `len==0`. Just remember that the returned value effective content and size should be aligned
// with what is returned by `get_size_bytes_from_type()`
// with what is returned by `get_default_value_size_bytes_from_type()`.
static uint64_t get_default_value_from_type(const ppm_param_type t) {
switch(t) {
case PT_UID:
case PT_GID:
return std::numeric_limits<uint32_t>::max();
case PT_SOCKADDR:
return PPM_AF_UNSPEC;
@ -193,11 +194,11 @@ static uint64_t get_default_value_from_type(const ppm_param_type t) {
// This writes len + the param
static void push_default_parameter(scap_evt *evt, uint16_t *params_offset, uint8_t param_num) {
// Please ensure that `new_evt->type` is already the final type you want to obtain.
// Please ensure that `evt->type` is already the final type you want to obtain.
// Otherwise, we will access the wrong entry in the event table.
const struct ppm_event_info *event_info = &g_event_info[evt->type];
const ppm_event_info *event_info = &g_event_info[evt->type];
const auto param_type = event_info->params[param_num].type;
const uint16_t len = get_size_bytes_from_type(param_type);
const uint16_t len = get_default_value_size_bytes_from_type(param_type);
const uint16_t lens_offset = sizeof(scap_evt) + param_num * sizeof(uint16_t);
PRINT_MESSAGE(
@ -215,6 +216,89 @@ static void push_default_parameter(scap_evt *evt, uint16_t *params_offset, uint8
memcpy((char *)evt + lens_offset, &len, sizeof(uint16_t));
}
static uint8_t get_empty_value_size_bytes_from_type(const ppm_param_type t) {
switch(t) {
case PT_INT8:
case PT_UINT8:
case PT_FLAGS8:
case PT_ENUMFLAGS8:
case PT_SIGTYPE:
return 1;
case PT_INT16:
case PT_UINT16:
case PT_FLAGS16:
case PT_ENUMFLAGS16:
case PT_SYSCALLID:
return 2;
case PT_INT32:
case PT_UINT32:
case PT_FLAGS32:
case PT_ENUMFLAGS32:
case PT_UID:
case PT_GID:
case PT_MODE:
case PT_SIGSET:
return 4;
case PT_INT64:
case PT_UINT64:
case PT_RELTIME:
case PT_ABSTIME:
case PT_ERRNO:
case PT_FD:
case PT_PID:
return 8;
case PT_BYTEBUF:
case PT_CHARBUF:
case PT_SOCKTUPLE:
case PT_FDLIST:
case PT_FSPATH:
case PT_CHARBUFARRAY:
case PT_CHARBUF_PAIR_ARRAY:
case PT_FSRELPATH:
case PT_DYN:
case PT_SOCKADDR:
return 0;
default:
// We forgot to handle something
assert(false);
break;
}
assert(false);
return 0;
}
// This writes len + the param
static void push_empty_parameter(scap_evt *evt, uint16_t *params_offset, uint8_t param_num) {
// Please ensure that `evt->type` is already the final type you want to obtain.
// Otherwise, we will access the wrong entry in the event table.
const ppm_event_info *event_info = &g_event_info[evt->type];
const auto param_type = event_info->params[param_num].type;
const uint16_t len = get_empty_value_size_bytes_from_type(param_type);
const uint16_t lens_offset = sizeof(scap_evt) + param_num * sizeof(uint16_t);
PRINT_MESSAGE(
"push empty param (%d, type: %d) with len (%d) at {params_offset (%d), "
"lens_offset (%d)}\n",
param_num,
param_type,
len,
*params_offset,
lens_offset);
// The empty param value will be always 0 so we just need to copy the right number of 0 bytes.
// `uint64_t` should be enough for all the types considering that types like CHARBUF, BYTEBUF
// have `len==0`. The empty parameter length is always set to 0.
constexpr uint64_t zero = 0;
memcpy((char *)evt + *params_offset, (char *)&zero, len);
*params_offset += len;
memcpy((char *)evt + lens_offset, &zero, sizeof(uint16_t));
}
// This writes len + the param
static void push_parameter(scap_evt *new_evt,
scap_evt *tmp_evt,
@ -227,7 +311,7 @@ static void push_parameter(scap_evt *new_evt,
char *ptr = get_param_ptr(tmp_evt, tmp_evt_param_num);
PRINT_MESSAGE(
"push param (%d, type: %d) with len (%d) at {params_offest: %d, "
"push param (%d, type: %d) with len (%d) at {params_offset: %d, "
"lens_offset: %d} from event type '%d', param '%d'\n",
new_evt_param_num,
g_event_info[tmp_evt->type].params[tmp_evt_param_num].type,
@ -380,7 +464,7 @@ static conversion_result convert_event(std::unordered_map<uint64_t, safe_scap_ev
PRINT_MESSAGE("New event header (the len is still the old one):\n");
PRINT_EVENT(new_evt, PRINT_HEADER);
scap_evt *tmp_evt = NULL;
scap_evt *tmp_evt = nullptr;
// If this is true at the end of the for loop we will free its memory.
bool used_enter_event = false;
@ -388,10 +472,15 @@ static conversion_result convert_event(std::unordered_map<uint64_t, safe_scap_ev
for(size_t i = 0; i < ci.m_instrs.size(); i++, param_to_populate++) {
PRINT_MESSAGE("Instruction n° %d. Param to populate: %d\n", i, param_to_populate);
switch(ci.m_instrs[i].flags) {
auto &instr = ci.m_instrs[i];
switch(instr.code) {
case C_INSTR_FROM_EMPTY:
push_empty_parameter(new_evt, &params_offset, param_to_populate);
continue;
case C_INSTR_FROM_DEFAULT:
tmp_evt = NULL;
break;
push_default_parameter(new_evt, &params_offset, param_to_populate);
continue;
case C_INSTR_FROM_ENTER:
tmp_evt = retrieve_evt(evt_storage, evt_to_convert->tid);
@ -422,7 +511,7 @@ static conversion_result convert_event(std::unordered_map<uint64_t, safe_scap_ev
case C_INSTR_FROM_OLD:
tmp_evt = evt_to_convert;
if(tmp_evt->nparams <= ci.m_instrs[i].param_num) {
if(tmp_evt->nparams <= instr.param_num) {
// todo!: this sounds like an error but let's see in the future. At the moment we
// fail
scap_errprintf(
@ -430,7 +519,7 @@ static conversion_result convert_event(std::unordered_map<uint64_t, safe_scap_ev
0,
"We want to take parameter '%d' from event '%d' but this event has only "
"'%d' parameters!",
ci.m_instrs[i].param_num,
instr.param_num,
tmp_evt->type,
tmp_evt->nparams);
return CONVERSION_ERROR;
@ -440,21 +529,22 @@ static conversion_result convert_event(std::unordered_map<uint64_t, safe_scap_ev
default:
scap_errprintf(error,
0,
"Unknown instruction (flags: %d, param_num: %d).",
ci.m_instrs[i].flags,
ci.m_instrs[i].param_num);
"Unknown instruction (code: %d, param_num: %d).",
instr.code,
instr.param_num);
return CONVERSION_ERROR;
}
if(!tmp_evt) {
push_default_parameter(new_evt, &params_offset, param_to_populate);
} else {
push_parameter(new_evt,
tmp_evt,
&params_offset,
param_to_populate,
ci.m_instrs[i].param_num);
if(instr.flags & CIF_FALLBACK_TO_EMPTY) {
push_empty_parameter(new_evt, &params_offset, param_to_populate);
} else {
push_default_parameter(new_evt, &params_offset, param_to_populate);
}
continue;
}
push_parameter(new_evt, tmp_evt, &params_offset, param_to_populate, instr.param_num);
}
if(used_enter_event) {

View File

@ -32,6 +32,48 @@ const std::unordered_map<conversion_key, conversion_info> g_conversion_table = {
conversion_info()
.action(C_ACTION_ADD_PARAMS)
.instrs({{C_INSTR_FROM_ENTER, 0}, {C_INSTR_FROM_ENTER, 1}})},
/*====================== LINK ======================*/
{conversion_key{PPME_SYSCALL_LINK_E, 2}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SYSCALL_LINK_X, 1},
conversion_info()
.desired_type(PPME_SYSCALL_LINK_2_X)
.action(C_ACTION_CHANGE_TYPE)
.instrs({{C_INSTR_FROM_OLD, 0},
{C_INSTR_FROM_ENTER, 0, CIF_FALLBACK_TO_EMPTY},
{C_INSTR_FROM_ENTER, 1, CIF_FALLBACK_TO_EMPTY}})},
/*====================== LINKAT ======================*/
{conversion_key{PPME_SYSCALL_LINKAT_E, 4}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SYSCALL_LINKAT_X, 1},
conversion_info()
.desired_type(PPME_SYSCALL_LINKAT_2_X)
.action(C_ACTION_CHANGE_TYPE)
.instrs({
{C_INSTR_FROM_OLD, 0}, // res
{C_INSTR_FROM_ENTER, 0, CIF_FALLBACK_TO_EMPTY}, // olddir
{C_INSTR_FROM_ENTER, 1, CIF_FALLBACK_TO_EMPTY}, // oldpath
{C_INSTR_FROM_ENTER, 2, CIF_FALLBACK_TO_EMPTY}, // newdir
{C_INSTR_FROM_ENTER, 3, CIF_FALLBACK_TO_EMPTY}, // newpath
{C_INSTR_FROM_EMPTY, 0}, // flags
})},
/*====================== UNLINK ======================*/
{conversion_key{PPME_SYSCALL_UNLINK_E, 1}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SYSCALL_UNLINK_X, 1},
conversion_info()
.desired_type(PPME_SYSCALL_UNLINK_2_X)
.action(C_ACTION_CHANGE_TYPE)
.instrs({{C_INSTR_FROM_OLD, 0}, {C_INSTR_FROM_ENTER, 0, CIF_FALLBACK_TO_EMPTY}})},
/*====================== UNLINKAT ======================*/
{conversion_key{PPME_SYSCALL_UNLINKAT_E, 2}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SYSCALL_UNLINKAT_X, 1},
conversion_info()
.desired_type(PPME_SYSCALL_UNLINKAT_2_X)
.action(C_ACTION_CHANGE_TYPE)
.instrs({
{C_INSTR_FROM_OLD, 0},
{C_INSTR_FROM_ENTER, 0, CIF_FALLBACK_TO_EMPTY},
{C_INSTR_FROM_ENTER, 1, CIF_FALLBACK_TO_EMPTY},
{C_INSTR_FROM_EMPTY, 0}, // flags
})},
/*====================== PREAD ======================*/
{conversion_key{PPME_SYSCALL_PREAD_E, 3}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SYSCALL_PREAD_X, 2},
@ -91,6 +133,13 @@ const std::unordered_map<conversion_key, conversion_info> g_conversion_table = {
{conversion_key{PPME_SYSCALL_SETRLIMIT_E, 1}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SYSCALL_SETRLIMIT_X, 3},
conversion_info().action(C_ACTION_ADD_PARAMS).instrs({{C_INSTR_FROM_ENTER, 0}})},
/*====================== PRLIMIT ======================*/
{conversion_key{PPME_SYSCALL_PRLIMIT_E, 2}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SYSCALL_PRLIMIT_X, 5},
conversion_info()
.action(C_ACTION_ADD_PARAMS)
.instrs({{C_INSTR_FROM_ENTER, 0, CIF_FALLBACK_TO_EMPTY},
{C_INSTR_FROM_ENTER, 1, CIF_FALLBACK_TO_EMPTY}})},
/*====================== FCNTL ======================*/
{conversion_key{PPME_SYSCALL_FCNTL_E, 2}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SYSCALL_FCNTL_X, 1},
@ -101,6 +150,291 @@ const std::unordered_map<conversion_key, conversion_info> g_conversion_table = {
{conversion_key{PPME_SYSCALL_BRK_4_E, 1}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SYSCALL_BRK_4_X, 4},
conversion_info().action(C_ACTION_ADD_PARAMS).instrs({{C_INSTR_FROM_ENTER, 0}})},
/*====================== EXECVE ======================*/
{conversion_key{PPME_SYSCALL_EXECVE_8_E, 0},
conversion_info().desired_type(PPME_SYSCALL_EXECVE_13_E).action(C_ACTION_CHANGE_TYPE)},
{conversion_key{PPME_SYSCALL_EXECVE_8_X, 8},
conversion_info()
.desired_type(PPME_SYSCALL_EXECVE_13_X)
.action(C_ACTION_CHANGE_TYPE)
.instrs({
{C_INSTR_FROM_OLD, 0}, // res
{C_INSTR_FROM_OLD, 1}, // exe
{C_INSTR_FROM_OLD, 2}, // args
{C_INSTR_FROM_OLD, 3}, // tid
{C_INSTR_FROM_OLD, 4}, // pid
{C_INSTR_FROM_OLD, 5}, // ptid
{C_INSTR_FROM_OLD, 6}, // cwd
{C_INSTR_FROM_OLD, 7}, // fdlimit
{C_INSTR_FROM_EMPTY, 0}, // pgft_maj
{C_INSTR_FROM_EMPTY, 0}, // pgft_min
{C_INSTR_FROM_EMPTY, 0}, // vm_size
{C_INSTR_FROM_EMPTY, 0}, // vm_rss
{C_INSTR_FROM_EMPTY, 0}, // vm_swap
})},
{conversion_key{PPME_SYSCALL_EXECVE_13_E, 0},
conversion_info().desired_type(PPME_SYSCALL_EXECVE_14_E).action(C_ACTION_CHANGE_TYPE)},
{conversion_key{PPME_SYSCALL_EXECVE_13_X, 13},
conversion_info()
.desired_type(PPME_SYSCALL_EXECVE_14_X)
.action(C_ACTION_CHANGE_TYPE)
.instrs({
{C_INSTR_FROM_OLD, 0}, // res
{C_INSTR_FROM_OLD, 1}, // exe
{C_INSTR_FROM_OLD, 2}, // args
{C_INSTR_FROM_OLD, 3}, // tid
{C_INSTR_FROM_OLD, 4}, // pid
{C_INSTR_FROM_OLD, 5}, // ptid
{C_INSTR_FROM_OLD, 6}, // cwd
{C_INSTR_FROM_OLD, 7}, // fdlimit
{C_INSTR_FROM_OLD, 8}, // pgft_maj
{C_INSTR_FROM_OLD, 9}, // pgft_min
{C_INSTR_FROM_OLD, 10}, // vm_size
{C_INSTR_FROM_OLD, 11}, // vm_rss
{C_INSTR_FROM_OLD, 12}, // vm_swap
{C_INSTR_FROM_EMPTY, 0}, // env
})},
{conversion_key{PPME_SYSCALL_EXECVE_14_E, 0},
conversion_info().desired_type(PPME_SYSCALL_EXECVE_15_E).action(C_ACTION_CHANGE_TYPE)},
{conversion_key{PPME_SYSCALL_EXECVE_14_X, 14},
conversion_info()
.desired_type(PPME_SYSCALL_EXECVE_15_X)
.action(C_ACTION_CHANGE_TYPE)
.instrs({
{C_INSTR_FROM_OLD, 0}, // res
{C_INSTR_FROM_OLD, 1}, // exe
{C_INSTR_FROM_OLD, 2}, // args
{C_INSTR_FROM_OLD, 3}, // tid
{C_INSTR_FROM_OLD, 4}, // pid
{C_INSTR_FROM_OLD, 5}, // ptid
{C_INSTR_FROM_OLD, 6}, // cwd
{C_INSTR_FROM_OLD, 7}, // fdlimit
{C_INSTR_FROM_OLD, 8}, // pgft_maj
{C_INSTR_FROM_OLD, 9}, // pgft_min
{C_INSTR_FROM_OLD, 10}, // vm_size
{C_INSTR_FROM_OLD, 11}, // vm_rss
{C_INSTR_FROM_OLD, 12}, // vm_swap
{C_INSTR_FROM_EMPTY, 0}, // comm
{C_INSTR_FROM_OLD, 13}, // env
})},
{conversion_key{PPME_SYSCALL_EXECVE_15_E, 0},
conversion_info().desired_type(PPME_SYSCALL_EXECVE_16_E).action(C_ACTION_CHANGE_TYPE)},
{conversion_key{PPME_SYSCALL_EXECVE_15_X, 15},
conversion_info()
.desired_type(PPME_SYSCALL_EXECVE_16_X)
.action(C_ACTION_CHANGE_TYPE)
.instrs({
{C_INSTR_FROM_OLD, 0}, // res
{C_INSTR_FROM_OLD, 1}, // exe
{C_INSTR_FROM_OLD, 2}, // args
{C_INSTR_FROM_OLD, 3}, // tid
{C_INSTR_FROM_OLD, 4}, // pid
{C_INSTR_FROM_OLD, 5}, // ptid
{C_INSTR_FROM_OLD, 6}, // cwd
{C_INSTR_FROM_OLD, 7}, // fdlimit
{C_INSTR_FROM_OLD, 8}, // pgft_maj
{C_INSTR_FROM_OLD, 9}, // pgft_min
{C_INSTR_FROM_OLD, 10}, // vm_size
{C_INSTR_FROM_OLD, 11}, // vm_rss
{C_INSTR_FROM_OLD, 12}, // vm_swap
{C_INSTR_FROM_OLD, 13}, // comm
{C_INSTR_FROM_EMPTY, 0}, // cgroups
{C_INSTR_FROM_OLD, 14}, // env
})},
{conversion_key{PPME_SYSCALL_EXECVE_16_E, 0},
conversion_info().desired_type(PPME_SYSCALL_EXECVE_17_E).action(C_ACTION_CHANGE_TYPE)},
{conversion_key{PPME_SYSCALL_EXECVE_16_X, 16},
conversion_info()
.desired_type(PPME_SYSCALL_EXECVE_17_X)
.action(C_ACTION_CHANGE_TYPE)
.instrs({
{C_INSTR_FROM_OLD, 0}, // res
{C_INSTR_FROM_OLD, 1}, // exe
{C_INSTR_FROM_OLD, 2}, // args
{C_INSTR_FROM_OLD, 3}, // tid
{C_INSTR_FROM_OLD, 4}, // pid
{C_INSTR_FROM_OLD, 5}, // ptid
{C_INSTR_FROM_OLD, 6}, // cwd
{C_INSTR_FROM_OLD, 7}, // fdlimit
{C_INSTR_FROM_OLD, 8}, // pgft_maj
{C_INSTR_FROM_OLD, 9}, // pgft_min
{C_INSTR_FROM_OLD, 10}, // vm_size
{C_INSTR_FROM_OLD, 11}, // vm_rss
{C_INSTR_FROM_OLD, 12}, // vm_swap
{C_INSTR_FROM_OLD, 13}, // comm
{C_INSTR_FROM_OLD, 14}, // cgroups
{C_INSTR_FROM_OLD, 15}, // env
{C_INSTR_FROM_EMPTY, 0}, // tty
})},
{conversion_key{PPME_SYSCALL_EXECVE_17_E, 0},
conversion_info()
.desired_type(PPME_SYSCALL_EXECVE_18_E)
.action(C_ACTION_CHANGE_TYPE)
.instrs({{C_INSTR_FROM_EMPTY, 0}})}, // filename
{conversion_key{PPME_SYSCALL_EXECVE_17_X, 17},
conversion_info()
.desired_type(PPME_SYSCALL_EXECVE_18_X)
.action(C_ACTION_CHANGE_TYPE)
.instrs({
{C_INSTR_FROM_OLD, 0}, // res
{C_INSTR_FROM_OLD, 1}, // exe
{C_INSTR_FROM_OLD, 2}, // args
{C_INSTR_FROM_OLD, 3}, // tid
{C_INSTR_FROM_OLD, 4}, // pid
{C_INSTR_FROM_OLD, 5}, // ptid
{C_INSTR_FROM_OLD, 6}, // cwd
{C_INSTR_FROM_OLD, 7}, // fdlimit
{C_INSTR_FROM_OLD, 8}, // pgft_maj
{C_INSTR_FROM_OLD, 9}, // pgft_min
{C_INSTR_FROM_OLD, 10}, // vm_size
{C_INSTR_FROM_OLD, 11}, // vm_rss
{C_INSTR_FROM_OLD, 12}, // vm_swap
{C_INSTR_FROM_OLD, 13}, // comm
{C_INSTR_FROM_OLD, 14}, // cgroups
{C_INSTR_FROM_OLD, 15}, // env
{C_INSTR_FROM_OLD, 16}, // tty
})},
{conversion_key{PPME_SYSCALL_EXECVE_18_E, 1},
conversion_info()
.desired_type(PPME_SYSCALL_EXECVE_19_E)
.action(C_ACTION_CHANGE_TYPE)
.instrs({{C_INSTR_FROM_OLD, 0}})}, // filename
{conversion_key{PPME_SYSCALL_EXECVE_18_X, 17},
conversion_info()
.desired_type(PPME_SYSCALL_EXECVE_19_X)
.action(C_ACTION_CHANGE_TYPE)
.instrs({
{C_INSTR_FROM_OLD, 0}, // res
{C_INSTR_FROM_OLD, 1}, // exe
{C_INSTR_FROM_OLD, 2}, // args
{C_INSTR_FROM_OLD, 3}, // tid
{C_INSTR_FROM_OLD, 4}, // pid
{C_INSTR_FROM_OLD, 5}, // ptid
{C_INSTR_FROM_OLD, 6}, // cwd
{C_INSTR_FROM_OLD, 7}, // fdlimit
{C_INSTR_FROM_OLD, 8}, // pgft_maj
{C_INSTR_FROM_OLD, 9}, // pgft_min
{C_INSTR_FROM_OLD, 10}, // vm_size
{C_INSTR_FROM_OLD, 11}, // vm_rss
{C_INSTR_FROM_OLD, 12}, // vm_swap
{C_INSTR_FROM_OLD, 13}, // comm
{C_INSTR_FROM_OLD, 14}, // cgroups
{C_INSTR_FROM_OLD, 15}, // env
{C_INSTR_FROM_OLD, 16}, // tty
{C_INSTR_FROM_EMPTY, 0}, // vpgid
})},
{conversion_key{PPME_SYSCALL_EXECVE_19_X, 18},
conversion_info()
.action(C_ACTION_ADD_PARAMS)
.instrs({{C_INSTR_FROM_EMPTY, 0}})}, // loginuid
{conversion_key{PPME_SYSCALL_EXECVE_19_X, 19},
conversion_info().action(C_ACTION_ADD_PARAMS).instrs({{C_INSTR_FROM_EMPTY, 0}})}, // flags
{conversion_key{PPME_SYSCALL_EXECVE_19_X, 20},
conversion_info()
.action(C_ACTION_ADD_PARAMS)
.instrs({
{C_INSTR_FROM_EMPTY, 0}, // cap_inheritable
{C_INSTR_FROM_EMPTY, 0}, // cap_permitted
{C_INSTR_FROM_EMPTY, 0}, // cap_effective
})},
{conversion_key{PPME_SYSCALL_EXECVE_19_X, 23},
conversion_info()
.action(C_ACTION_ADD_PARAMS)
.instrs({
{C_INSTR_FROM_EMPTY, 0}, // exe_ino
{C_INSTR_FROM_EMPTY, 0}, // exe_ino_ctime
{C_INSTR_FROM_EMPTY, 0}, // exe_ino_mtime
})},
{conversion_key{PPME_SYSCALL_EXECVE_19_X, 26},
conversion_info().action(C_ACTION_ADD_PARAMS).instrs({{C_INSTR_FROM_EMPTY, 0}})}, // uid
{conversion_key{PPME_SYSCALL_EXECVE_19_X, 27},
conversion_info()
.action(C_ACTION_ADD_PARAMS)
.instrs({{C_INSTR_FROM_EMPTY, 0}})}, // trusted_exepath
{conversion_key{PPME_SYSCALL_EXECVE_19_X, 28},
conversion_info().action(C_ACTION_ADD_PARAMS).instrs({{C_INSTR_FROM_EMPTY, 0}})}, // pgid
{conversion_key{PPME_SYSCALL_EXECVE_19_X, 29},
conversion_info().action(C_ACTION_ADD_PARAMS).instrs({{C_INSTR_FROM_EMPTY, 0}})}, // gid
/*====================== CLONE ======================*/
{conversion_key{PPME_SYSCALL_CLONE_11_E, 0}, conversion_info().action(C_ACTION_SKIP)},
{conversion_key{PPME_SYSCALL_CLONE_11_X, 11},
conversion_info()
.desired_type(PPME_SYSCALL_CLONE_16_X)
.action(C_ACTION_CHANGE_TYPE)
.instrs({
{C_INSTR_FROM_OLD, 0}, // res
{C_INSTR_FROM_OLD, 1}, // exe
{C_INSTR_FROM_OLD, 2}, // args
{C_INSTR_FROM_OLD, 3}, // tid
{C_INSTR_FROM_OLD, 4}, // pid
{C_INSTR_FROM_OLD, 5}, // ptid
{C_INSTR_FROM_OLD, 6}, // cwd
{C_INSTR_FROM_OLD, 7}, // fdlimit
{C_INSTR_FROM_EMPTY, 0}, // pgft_maj
{C_INSTR_FROM_EMPTY, 0}, // pgft_min
{C_INSTR_FROM_EMPTY, 0}, // vm_size
{C_INSTR_FROM_EMPTY, 0}, // vm_rss
{C_INSTR_FROM_EMPTY, 0}, // vm_swap
{C_INSTR_FROM_OLD, 8}, // flags
{C_INSTR_FROM_OLD, 9}, // uid
{C_INSTR_FROM_OLD, 10}, // gid
})},
{conversion_key{PPME_SYSCALL_CLONE_16_E, 0}, conversion_info().action(C_ACTION_SKIP)},
{conversion_key{PPME_SYSCALL_CLONE_16_X, 16},
conversion_info()
.desired_type(PPME_SYSCALL_CLONE_17_X)
.action(C_ACTION_CHANGE_TYPE)
.instrs({
{C_INSTR_FROM_OLD, 0}, // res
{C_INSTR_FROM_OLD, 1}, // exe
{C_INSTR_FROM_OLD, 2}, // args
{C_INSTR_FROM_OLD, 3}, // tid
{C_INSTR_FROM_OLD, 4}, // pid
{C_INSTR_FROM_OLD, 5}, // ptid
{C_INSTR_FROM_OLD, 6}, // cwd
{C_INSTR_FROM_OLD, 7}, // fdlimit
{C_INSTR_FROM_OLD, 8}, // pgft_maj
{C_INSTR_FROM_OLD, 9}, // pgft_min
{C_INSTR_FROM_OLD, 10}, // vm_size
{C_INSTR_FROM_OLD, 11}, // vm_rss
{C_INSTR_FROM_OLD, 12}, // vm_swap
{C_INSTR_FROM_EMPTY, 0}, // comm
{C_INSTR_FROM_OLD, 13}, // flags
{C_INSTR_FROM_OLD, 14}, // uid
{C_INSTR_FROM_OLD, 15}, // gid
})},
{conversion_key{PPME_SYSCALL_CLONE_17_E, 0}, conversion_info().action(C_ACTION_SKIP)},
{conversion_key{PPME_SYSCALL_CLONE_17_X, 17},
conversion_info()
.desired_type(PPME_SYSCALL_CLONE_20_X)
.action(C_ACTION_CHANGE_TYPE)
.instrs({
{C_INSTR_FROM_OLD, 0}, // res
{C_INSTR_FROM_OLD, 1}, // exe
{C_INSTR_FROM_OLD, 2}, // args
{C_INSTR_FROM_OLD, 3}, // tid
{C_INSTR_FROM_OLD, 4}, // pid
{C_INSTR_FROM_OLD, 5}, // ptid
{C_INSTR_FROM_OLD, 6}, // cwd
{C_INSTR_FROM_OLD, 7}, // fdlimit
{C_INSTR_FROM_OLD, 8}, // pgft_maj
{C_INSTR_FROM_OLD, 9}, // pgft_min
{C_INSTR_FROM_OLD, 10}, // vm_size
{C_INSTR_FROM_OLD, 11}, // vm_rss
{C_INSTR_FROM_OLD, 12}, // vm_swap
{C_INSTR_FROM_OLD, 13}, // comm
{C_INSTR_FROM_EMPTY, 0}, // cgroups
{C_INSTR_FROM_OLD, 14}, // flags
{C_INSTR_FROM_OLD, 15}, // uid
{C_INSTR_FROM_OLD, 16}, // gid
{C_INSTR_FROM_EMPTY, 0}, // vtid
{C_INSTR_FROM_EMPTY, 0}, // vpid
})},
{conversion_key{PPME_SYSCALL_CLONE_20_E, 0}, conversion_info().action(C_ACTION_SKIP)},
{conversion_key{PPME_SYSCALL_CLONE_20_X, 20},
conversion_info()
.action(C_ACTION_ADD_PARAMS)
.instrs({{C_INSTR_FROM_EMPTY, 0}})}, // pidns_init_start_ts
/*====================== BIND ======================*/
{conversion_key{PPME_SOCKET_BIND_E, 1}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SOCKET_BIND_X, 2},
@ -184,13 +518,15 @@ const std::unordered_map<conversion_key, conversion_info> g_conversion_table = {
{conversion_key{PPME_SYSCALL_SETRESUID_X, 1},
conversion_info()
.action(C_ACTION_ADD_PARAMS)
.instrs({{C_INSTR_FROM_ENTER, 0},
{C_INSTR_FROM_ENTER, 1},
{C_INSTR_FROM_ENTER, 2}})},
.instrs({{C_INSTR_FROM_ENTER, 0, CIF_FALLBACK_TO_EMPTY},
{C_INSTR_FROM_ENTER, 1, CIF_FALLBACK_TO_EMPTY},
{C_INSTR_FROM_ENTER, 2, CIF_FALLBACK_TO_EMPTY}})},
/*====================== SETUID ======================*/
{conversion_key{PPME_SYSCALL_SETUID_E, 1}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SYSCALL_SETUID_X, 1},
conversion_info().action(C_ACTION_ADD_PARAMS).instrs({{C_INSTR_FROM_ENTER, 0}})},
conversion_info()
.action(C_ACTION_ADD_PARAMS)
.instrs({{C_INSTR_FROM_ENTER, 0, CIF_FALLBACK_TO_EMPTY}})},
/*====================== RECV ======================*/
{conversion_key{PPME_SOCKET_RECV_E, 2}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SOCKET_RECV_X, 2},
@ -258,15 +594,24 @@ const std::unordered_map<conversion_key, conversion_info> g_conversion_table = {
/*====================== MKDIR ======================*/
{conversion_key{PPME_SYSCALL_MKDIR_2_E, 1}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SYSCALL_MKDIR_2_X, 2},
conversion_info().action(C_ACTION_ADD_PARAMS).instrs({{C_INSTR_FROM_ENTER, 0}})},
conversion_info()
.action(C_ACTION_ADD_PARAMS)
.instrs({{C_INSTR_FROM_ENTER, 0, CIF_FALLBACK_TO_EMPTY}})},
{conversion_key{PPME_SYSCALL_MKDIR_E, 2}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SYSCALL_MKDIR_X, 1},
conversion_info()
.desired_type(PPME_SYSCALL_MKDIR_2_X)
.action(C_ACTION_CHANGE_TYPE)
.instrs({{C_INSTR_FROM_OLD, 0},
{C_INSTR_FROM_ENTER, 0},
{C_INSTR_FROM_ENTER, 1}})},
{C_INSTR_FROM_ENTER, 0, CIF_FALLBACK_TO_EMPTY},
{C_INSTR_FROM_ENTER, 1, CIF_FALLBACK_TO_EMPTY}})},
/*====================== RMDIR ======================*/
{conversion_key{PPME_SYSCALL_RMDIR_E, 1}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SYSCALL_RMDIR_X, 1},
conversion_info()
.desired_type(PPME_SYSCALL_RMDIR_2_X)
.action(C_ACTION_CHANGE_TYPE)
.instrs({{C_INSTR_FROM_OLD, 0}, {C_INSTR_FROM_ENTER, 0, CIF_FALLBACK_TO_EMPTY}})},
/*====================== UNSHARE ======================*/
{conversion_key{PPME_SYSCALL_UNSHARE_E, 1}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SYSCALL_UNSHARE_X, 1},
@ -354,10 +699,131 @@ const std::unordered_map<conversion_key, conversion_info> g_conversion_table = {
{C_INSTR_FROM_ENTER, 3}})},
/*====================== PTRACE ======================*/
{conversion_key{PPME_SYSCALL_PTRACE_E, 2}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SYSCALL_PTRACE_X, 0},
conversion_info()
.action(C_ACTION_ADD_PARAMS)
.instrs({{C_INSTR_FROM_EMPTY, 0},
{C_INSTR_FROM_EMPTY, 0},
{C_INSTR_FROM_EMPTY, 0}})},
{conversion_key{PPME_SYSCALL_PTRACE_X, 3},
conversion_info()
.action(C_ACTION_ADD_PARAMS)
.instrs({{C_INSTR_FROM_ENTER, 0}, {C_INSTR_FROM_ENTER, 1}})},
.instrs({{C_INSTR_FROM_ENTER, 0, CIF_FALLBACK_TO_EMPTY},
{C_INSTR_FROM_ENTER, 1, CIF_FALLBACK_TO_EMPTY}})},
/*====================== FORK ======================*/
{conversion_key{PPME_SYSCALL_FORK_E, 0}, conversion_info().action(C_ACTION_SKIP)},
{conversion_key{PPME_SYSCALL_FORK_X, 16},
conversion_info()
.desired_type(PPME_SYSCALL_FORK_17_X)
.action(C_ACTION_CHANGE_TYPE)
.instrs({
{C_INSTR_FROM_OLD, 0}, // res
{C_INSTR_FROM_OLD, 1}, // exe
{C_INSTR_FROM_OLD, 2}, // args
{C_INSTR_FROM_OLD, 3}, // tid
{C_INSTR_FROM_OLD, 4}, // pid
{C_INSTR_FROM_OLD, 5}, // ptid
{C_INSTR_FROM_OLD, 6}, // cwd
{C_INSTR_FROM_OLD, 7}, // fdlimit
{C_INSTR_FROM_OLD, 8}, // pgft_maj
{C_INSTR_FROM_OLD, 9}, // pgft_min
{C_INSTR_FROM_OLD, 10}, // vm_size
{C_INSTR_FROM_OLD, 11}, // vm_rss
{C_INSTR_FROM_OLD, 12}, // vm_swap
{C_INSTR_FROM_EMPTY, 0}, // comm
{C_INSTR_FROM_OLD, 13}, // flags
{C_INSTR_FROM_OLD, 14}, // uid
{C_INSTR_FROM_OLD, 15}, // gid
})},
{conversion_key{PPME_SYSCALL_FORK_17_E, 0}, conversion_info().action(C_ACTION_SKIP)},
{conversion_key{PPME_SYSCALL_FORK_17_X, 17},
conversion_info()
.desired_type(PPME_SYSCALL_FORK_20_X)
.action(C_ACTION_CHANGE_TYPE)
.instrs({
{C_INSTR_FROM_OLD, 0}, // res
{C_INSTR_FROM_OLD, 1}, // exe
{C_INSTR_FROM_OLD, 2}, // args
{C_INSTR_FROM_OLD, 3}, // tid
{C_INSTR_FROM_OLD, 4}, // pid
{C_INSTR_FROM_OLD, 5}, // ptid
{C_INSTR_FROM_OLD, 6}, // cwd
{C_INSTR_FROM_OLD, 7}, // fdlimit
{C_INSTR_FROM_OLD, 8}, // pgft_maj
{C_INSTR_FROM_OLD, 9}, // pgft_min
{C_INSTR_FROM_OLD, 10}, // vm_size
{C_INSTR_FROM_OLD, 11}, // vm_rss
{C_INSTR_FROM_OLD, 12}, // vm_swap
{C_INSTR_FROM_OLD, 13}, // comm
{C_INSTR_FROM_EMPTY, 0}, // cgroups
{C_INSTR_FROM_OLD, 14}, // flags
{C_INSTR_FROM_OLD, 15}, // uid
{C_INSTR_FROM_OLD, 16}, // gid
{C_INSTR_FROM_EMPTY, 0}, // vtid
{C_INSTR_FROM_EMPTY, 0}, // vpid
})},
{conversion_key{PPME_SYSCALL_FORK_20_E, 0}, conversion_info().action(C_ACTION_SKIP)},
{conversion_key{PPME_SYSCALL_FORK_20_X, 20},
conversion_info()
.action(C_ACTION_ADD_PARAMS)
.instrs({{C_INSTR_FROM_EMPTY, 0}})}, // pidns_init_start_ts
/*====================== VFORK ======================*/
{conversion_key{PPME_SYSCALL_VFORK_E, 0}, conversion_info().action(C_ACTION_SKIP)},
{conversion_key{PPME_SYSCALL_VFORK_X, 16},
conversion_info()
.desired_type(PPME_SYSCALL_VFORK_17_X)
.action(C_ACTION_CHANGE_TYPE)
.instrs({
{C_INSTR_FROM_OLD, 0}, // res
{C_INSTR_FROM_OLD, 1}, // exe
{C_INSTR_FROM_OLD, 2}, // args
{C_INSTR_FROM_OLD, 3}, // tid
{C_INSTR_FROM_OLD, 4}, // pid
{C_INSTR_FROM_OLD, 5}, // ptid
{C_INSTR_FROM_OLD, 6}, // cwd
{C_INSTR_FROM_OLD, 7}, // fdlimit
{C_INSTR_FROM_OLD, 8}, // pgft_maj
{C_INSTR_FROM_OLD, 9}, // pgft_min
{C_INSTR_FROM_OLD, 10}, // vm_size
{C_INSTR_FROM_OLD, 11}, // vm_rss
{C_INSTR_FROM_OLD, 12}, // vm_swap
{C_INSTR_FROM_EMPTY, 0}, // comm
{C_INSTR_FROM_OLD, 13}, // flags
{C_INSTR_FROM_OLD, 14}, // uid
{C_INSTR_FROM_OLD, 15}, // gid
})},
{conversion_key{PPME_SYSCALL_VFORK_17_E, 0}, conversion_info().action(C_ACTION_SKIP)},
{conversion_key{PPME_SYSCALL_VFORK_17_X, 17},
conversion_info()
.desired_type(PPME_SYSCALL_VFORK_20_X)
.action(C_ACTION_CHANGE_TYPE)
.instrs({
{C_INSTR_FROM_OLD, 0}, // res
{C_INSTR_FROM_OLD, 1}, // exe
{C_INSTR_FROM_OLD, 2}, // args
{C_INSTR_FROM_OLD, 3}, // tid
{C_INSTR_FROM_OLD, 4}, // pid
{C_INSTR_FROM_OLD, 5}, // ptid
{C_INSTR_FROM_OLD, 6}, // cwd
{C_INSTR_FROM_OLD, 7}, // fdlimit
{C_INSTR_FROM_OLD, 8}, // pgft_maj
{C_INSTR_FROM_OLD, 9}, // pgft_min
{C_INSTR_FROM_OLD, 10}, // vm_size
{C_INSTR_FROM_OLD, 11}, // vm_rss
{C_INSTR_FROM_OLD, 12}, // vm_swap
{C_INSTR_FROM_OLD, 13}, // comm
{C_INSTR_FROM_EMPTY, 0}, // cgroups
{C_INSTR_FROM_OLD, 14}, // flags
{C_INSTR_FROM_OLD, 15}, // uid
{C_INSTR_FROM_OLD, 16}, // gid
{C_INSTR_FROM_EMPTY, 0}, // vtid
{C_INSTR_FROM_EMPTY, 0}, // vpid
})},
{conversion_key{PPME_SYSCALL_VFORK_20_E, 0}, conversion_info().action(C_ACTION_SKIP)},
{conversion_key{PPME_SYSCALL_VFORK_20_X, 20},
conversion_info()
.action(C_ACTION_ADD_PARAMS)
.instrs({{C_INSTR_FROM_EMPTY, 0}})}, // pidns_init_start_ts
/*====================== SENDFILE ======================*/
{conversion_key{PPME_SYSCALL_SENDFILE_E, 4}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SYSCALL_SENDFILE_X, 2},
@ -378,7 +844,9 @@ const std::unordered_map<conversion_key, conversion_info> g_conversion_table = {
/*====================== FCHDIR ======================*/
{conversion_key{PPME_SYSCALL_FCHDIR_E, 1}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SYSCALL_FCHDIR_X, 1},
conversion_info().action(C_ACTION_ADD_PARAMS).instrs({{C_INSTR_FROM_ENTER, 0}})},
conversion_info()
.action(C_ACTION_ADD_PARAMS)
.instrs({{C_INSTR_FROM_ENTER, 0, CIF_FALLBACK_TO_EMPTY}})},
/*====================== GETDENTS ======================*/
{conversion_key{PPME_SYSCALL_GETDENTS_E, 1}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SYSCALL_GETDENTS_X, 1},
@ -392,7 +860,8 @@ const std::unordered_map<conversion_key, conversion_info> g_conversion_table = {
{conversion_key{PPME_SYSCALL_SETNS_X, 1},
conversion_info()
.action(C_ACTION_ADD_PARAMS)
.instrs({{C_INSTR_FROM_ENTER, 0}, {C_INSTR_FROM_ENTER, 1}})},
.instrs({{C_INSTR_FROM_ENTER, 0, CIF_FALLBACK_TO_EMPTY},
{C_INSTR_FROM_ENTER, 1, CIF_FALLBACK_TO_EMPTY}})},
/*====================== FLOCK ======================*/
{conversion_key{PPME_SYSCALL_FLOCK_E, 2}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SYSCALL_FLOCK_X, 1},
@ -437,14 +906,17 @@ const std::unordered_map<conversion_key, conversion_info> g_conversion_table = {
/*====================== SETGID ======================*/
{conversion_key{PPME_SYSCALL_SETGID_E, 1}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SYSCALL_SETGID_X, 1},
conversion_info().action(C_ACTION_ADD_PARAMS).instrs({{C_INSTR_FROM_ENTER, 0}})},
conversion_info()
.action(C_ACTION_ADD_PARAMS)
.instrs({{C_INSTR_FROM_ENTER, 0, CIF_FALLBACK_TO_EMPTY}})},
/*====================== SETPGID ======================*/
{conversion_key{PPME_SYSCALL_SETPGID_E, 2}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SYSCALL_SETPGID_E, 2}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SYSCALL_SETPGID_X, 1},
conversion_info()
.action(C_ACTION_ADD_PARAMS)
.instrs({{C_INSTR_FROM_ENTER, 0}, {C_INSTR_FROM_ENTER, 1}})},
.instrs({{C_INSTR_FROM_ENTER, 0, CIF_FALLBACK_TO_EMPTY},
{C_INSTR_FROM_ENTER, 1, CIF_FALLBACK_TO_EMPTY}})},
/*====================== SECCOMP ======================*/
{conversion_key{PPME_SYSCALL_SECCOMP_E, 1},
conversion_info().action(C_ACTION_ADD_PARAMS).instrs({{C_INSTR_FROM_DEFAULT, 0}})},
@ -461,6 +933,35 @@ const std::unordered_map<conversion_key, conversion_info> g_conversion_table = {
.instrs({{C_INSTR_FROM_ENTER, 0},
{C_INSTR_FROM_ENTER, 1},
{C_INSTR_FROM_ENTER, 2}})},
/*====================== EXECVEAT ======================*/
{conversion_key{PPME_SYSCALL_EXECVEAT_X, 19},
conversion_info().action(C_ACTION_ADD_PARAMS).instrs({{C_INSTR_FROM_EMPTY, 0}})}, // flags
{conversion_key{PPME_SYSCALL_EXECVEAT_X, 20},
conversion_info()
.action(C_ACTION_ADD_PARAMS)
.instrs({
{C_INSTR_FROM_EMPTY, 0}, // cap_inheritable
{C_INSTR_FROM_EMPTY, 0}, // cap_permitted
{C_INSTR_FROM_EMPTY, 0}, // cap_effective
})},
{conversion_key{PPME_SYSCALL_EXECVEAT_X, 23},
conversion_info()
.action(C_ACTION_ADD_PARAMS)
.instrs({
{C_INSTR_FROM_EMPTY, 0}, // exe_ino
{C_INSTR_FROM_EMPTY, 0}, // exe_ino_ctime
{C_INSTR_FROM_EMPTY, 0}, // exe_ino_mtime
})},
{conversion_key{PPME_SYSCALL_EXECVEAT_X, 26},
conversion_info().action(C_ACTION_ADD_PARAMS).instrs({{C_INSTR_FROM_EMPTY, 0}})}, // uid
{conversion_key{PPME_SYSCALL_EXECVEAT_X, 27},
conversion_info()
.action(C_ACTION_ADD_PARAMS)
.instrs({{C_INSTR_FROM_EMPTY, 0}})}, // trusted_exepath
{conversion_key{PPME_SYSCALL_EXECVEAT_X, 28},
conversion_info().action(C_ACTION_ADD_PARAMS).instrs({{C_INSTR_FROM_EMPTY, 0}})}, // pgid
{conversion_key{PPME_SYSCALL_EXECVEAT_X, 29},
conversion_info().action(C_ACTION_ADD_PARAMS).instrs({{C_INSTR_FROM_EMPTY, 0}})}, // gid
/*====================== COPY_FILE_RANGE ======================*/
{conversion_key{PPME_SYSCALL_COPY_FILE_RANGE_E, 3},
conversion_info().action(C_ACTION_STORE)},
@ -470,6 +971,12 @@ const std::unordered_map<conversion_key, conversion_info> g_conversion_table = {
.instrs({{C_INSTR_FROM_ENTER, 0},
{C_INSTR_FROM_ENTER, 1},
{C_INSTR_FROM_ENTER, 2}})},
/*====================== CLONE3 ======================*/
{conversion_key{PPME_SYSCALL_CLONE3_E, 0}, conversion_info().action(C_ACTION_SKIP)},
{conversion_key{PPME_SYSCALL_CLONE3_X, 20},
conversion_info()
.action(C_ACTION_ADD_PARAMS)
.instrs({{C_INSTR_FROM_EMPTY, 0}})}, // pidns_init_start_ts
/*====================== EPOLL_CREATE ======================*/
{conversion_key{PPME_SYSCALL_EPOLL_CREATE_E, 1}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SYSCALL_EPOLL_CREATE_X, 1},
@ -483,9 +990,9 @@ const std::unordered_map<conversion_key, conversion_info> g_conversion_table = {
{conversion_key{PPME_SYSCALL_SETRESGID_X, 1},
conversion_info()
.action(C_ACTION_ADD_PARAMS)
.instrs({{C_INSTR_FROM_ENTER, 0},
{C_INSTR_FROM_ENTER, 1},
{C_INSTR_FROM_ENTER, 2}})},
.instrs({{C_INSTR_FROM_ENTER, 0, CIF_FALLBACK_TO_EMPTY},
{C_INSTR_FROM_ENTER, 1, CIF_FALLBACK_TO_EMPTY},
{C_INSTR_FROM_ENTER, 2, CIF_FALLBACK_TO_EMPTY}})},
/*====================== ACCEPT4 ======================*/
{conversion_key{PPME_SOCKET_ACCEPT4_E, 1}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SOCKET_ACCEPT4_X, 3},

View File

@ -20,11 +20,21 @@ limitations under the License.
#include <vector>
#include <cstdint>
enum conversion_instruction_flags {
enum conversion_instruction_code {
C_NO_INSTR = 0, // This should be never called
C_INSTR_FROM_OLD, // Take the parameter from the old event
C_INSTR_FROM_ENTER, // Take the parameter from the enter event
C_INSTR_FROM_DEFAULT, // Generate the default parameter
C_INSTR_FROM_EMPTY, // Generate the empty parameter
};
// TODO(ekoops): remove CIF_FALLBACK_TO_EMPTY and fallback to empty by default once sinsp is able to
// handle empty parameters for all the EF_TMP_CONVERTER_MANAGED entries in the converter table.
enum conversion_instruction_flags {
CIF_NO_FLAGS = 0,
CIF_FALLBACK_TO_EMPTY, // C_INSTR_FROM_ENTER-only flag: fallback to the empty value instead of
// the default one if for some reason the converter is not able to
// obtain the parameter.
};
// Conversion actions
@ -37,8 +47,9 @@ enum conversion_action {
};
struct conversion_instruction {
uint8_t flags = 0;
conversion_instruction_code code = C_NO_INSTR;
uint8_t param_num = 0;
conversion_instruction_flags flags = CIF_NO_FLAGS;
};
struct conversion_key {

View File

@ -35,8 +35,7 @@ struct scap_savefile_engine_params {
struct scap_platform* platform;
};
struct scap_platform* scap_savefile_alloc_platform(proc_entry_callback proc_callback,
void* proc_callback_context);
struct scap_platform* scap_savefile_alloc_platform(scap_proc_callbacks callbacks);
#ifdef __cplusplus
};

View File

@ -690,12 +690,12 @@ static int32_t scap_read_proclist(scap_reader_t *r,
//
// All parsed. Add the entry to the table, or fire the notification callback
//
proclist->m_proc_callback(proclist->m_proc_callback_context,
error,
tinfo.tid,
&tinfo,
NULL,
NULL);
proclist->m_callbacks.m_proc_entry_cb(proclist->m_callbacks.m_callback_context,
error,
tinfo.tid,
&tinfo,
NULL,
NULL);
if(sub_len && subreadsize != sub_len) {
if(subreadsize > sub_len) {
@ -1552,7 +1552,12 @@ static int32_t scap_read_fdlist(scap_reader_t *r,
//
// Add the entry to the table, or fire the notification callback
//
proclist->m_proc_callback(proclist->m_proc_callback_context, error, tid, NULL, &fdi, NULL);
proclist->m_callbacks.m_proc_entry_cb(proclist->m_callbacks.m_callback_context,
error,
tid,
NULL,
&fdi,
NULL);
}
//
@ -2135,8 +2140,7 @@ static const struct scap_platform_vtable scap_savefile_platform_vtable = {
.free_platform = scap_savefile_free_platform,
};
struct scap_platform *scap_savefile_alloc_platform(proc_entry_callback proc_callback,
void *proc_callback_context) {
struct scap_platform *scap_savefile_alloc_platform(scap_proc_callbacks callbacks) {
struct scap_savefile_platform *platform = calloc(1, sizeof(*platform));
if(platform == NULL) {
@ -2146,7 +2150,7 @@ struct scap_platform *scap_savefile_alloc_platform(proc_entry_callback proc_call
platform->m_generic.m_vtable = &scap_savefile_platform_vtable;
platform->m_generic.m_machine_info.num_cpus = (uint32_t)-1;
init_proclist(&platform->m_generic.m_proclist, proc_callback, proc_callback_context);
init_proclist(&platform->m_generic.m_proclist, callbacks);
return &platform->m_generic;
}

View File

@ -88,8 +88,7 @@ static const struct scap_platform_vtable scap_test_input_platform = {
.is_thread_alive = scap_test_input_is_thread_alive,
};
struct scap_platform* scap_test_input_alloc_platform(proc_entry_callback proc_callback,
void* proc_callback_context) {
struct scap_platform* scap_test_input_alloc_platform(scap_proc_callbacks callbacks) {
struct scap_test_input_platform* platform = calloc(1, sizeof(*platform));
if(platform == NULL) {
@ -98,8 +97,7 @@ struct scap_platform* scap_test_input_alloc_platform(proc_entry_callback proc_ca
struct scap_platform* generic = &platform->m_generic;
generic->m_vtable = &scap_test_input_platform;
init_proclist(&platform->m_generic.m_proclist, proc_callback, proc_callback_context);
init_proclist(&platform->m_generic.m_proclist, callbacks);
return generic;
}

View File

@ -29,8 +29,7 @@ struct scap_test_input_engine_params {
};
struct scap_platform;
struct scap_platform* scap_test_input_alloc_platform(proc_entry_callback proc_callback,
void* proc_callback_context);
struct scap_platform* scap_test_input_alloc_platform(scap_proc_callbacks proc_callback);
#ifdef __cplusplus
};
#endif

View File

@ -22,6 +22,7 @@ limitations under the License.
#include <libscap/scap_const.h>
#include <libscap/strerror.h>
#include <libscap/uthash_ext.h>
#include <libscap/debug_log_helpers.h>
#include <dirent.h>
#include <errno.h>
@ -459,13 +460,10 @@ static int32_t get_cgroup_subsystems_v2(struct scap_cgroup_interface* cgi,
char line[SCAP_MAX_PATH_SIZE];
snprintf(line, sizeof(line), "%s/cgroup.controllers", cgroup_mount);
if(access(line, F_OK) == -1) {
// If the file does not exist, return success. Skip
return SCAP_SUCCESS;
}
FILE* cgroup_controllers = fopen(line, "r");
if(!cgroup_controllers) {
scap_debug_log(cgi, "failed to open %s: %s", line, strerror(errno));
return SCAP_FAILURE;
}
@ -520,8 +518,16 @@ static int32_t get_cgroup_subsystems_v2(struct scap_cgroup_interface* cgi,
// Since there is just one, we don't need to do anything fancy here, just glue the pieces together
static int32_t scap_get_cgroup_mount_v2(struct mntent* de,
char* mountpoint,
const char* host_root) {
snprintf(mountpoint, SCAP_MAX_PATH_SIZE, "%s/proc/1/root%s", host_root, de->mnt_dir);
const char* host_root,
char* error) {
int len_needed =
snprintf(mountpoint, SCAP_MAX_PATH_SIZE, "%s/proc/1/root%s", host_root, de->mnt_dir);
if(len_needed < 0) {
return scap_errprintf(error, errno, "cgroup mount path encoding error");
}
if(len_needed >= SCAP_MAX_PATH_SIZE) {
return scap_errprintf(error, 0, "cgroup mount path too long");
}
return SCAP_SUCCESS;
}
@ -641,10 +647,35 @@ int32_t scap_cgroup_interface_init(struct scap_cgroup_interface* cgi,
error);
}
} else if(strcmp(de->mnt_type, "cgroup2") == 0) {
scap_get_cgroup_mount_v2(de, cgi->m_mount_v2, host_root);
get_cgroup_subsystems_v2(cgi, &cgi->m_subsystems_v2, cgi->m_mount_v2);
if(cgi->m_in_cgroupns) {
scap_get_cgroup_self_v2_cgroupns(de, cgi->m_self_v2, host_root, pid_str);
scap_debug_log(cgi, "found cgroup v2 mountpoint %s", de->mnt_dir);
if(scap_get_cgroup_mount_v2(de, cgi->m_mount_v2, host_root, error) == SCAP_SUCCESS) {
if(get_cgroup_subsystems_v2(cgi, &cgi->m_subsystems_v2, cgi->m_mount_v2) ==
SCAP_FAILURE) {
scap_errprintf(error,
0,
"failed to parse %s/cgroup.controllers",
cgi->m_mount_v2);
// Reset the mountpoint as we failed to read the
// controllers
de->mnt_dir[0] = '\0';
continue;
}
if(cgi->m_in_cgroupns) {
scap_get_cgroup_self_v2_cgroupns(de, cgi->m_self_v2, host_root, pid_str);
}
// If we found a cgroup v2 mountpoint with controllers, we can
// stop searching
if(cgi->m_subsystems_v2.len > 0) {
scap_debug_log(cgi,
"found cgroup v2 mountpoint with controllers: %s",
cgi->m_mount_v2);
break;
}
} else {
scap_debug_log(cgi,
"failed to get cgroup mount v2 path for mountpoint %s: %s",
de->mnt_dir,
error);
}
}
}

View File

@ -22,6 +22,7 @@ limitations under the License.
#include <stdint.h>
#include <libscap/scap_cgroup_set.h>
#include <libscap/scap_log.h>
#define FOR_EACH_SUBSYS(cgset, subsys) \
for(const char *subsys = (cgset)->path, *_end = (cgset)->path + (cgset)->len; subsys < _end; \
@ -54,6 +55,8 @@ struct scap_cgroup_interface {
char m_self_v2[SCAP_MAX_PATH_SIZE];
bool m_in_cgroupns;
falcosecurity_log_fn m_log_fn;
};
int32_t scap_cgroup_interface_init(struct scap_cgroup_interface* cgi,

View File

@ -93,12 +93,12 @@ int32_t scap_fd_handle_pipe(struct scap_proclist *proclist,
strlcpy(fdi->info.fname, link_name, sizeof(fdi->info.fname));
fdi->ino = ino;
proclist->m_proc_callback(proclist->m_proc_callback_context,
error,
tinfo->tid,
tinfo,
fdi,
NULL);
proclist->m_callbacks.m_proc_entry_cb(proclist->m_callbacks.m_callback_context,
error,
tinfo->tid,
tinfo,
fdi,
NULL);
return SCAP_SUCCESS;
}
@ -318,12 +318,12 @@ int32_t scap_fd_handle_regular_file(struct scap_proclist *proclist,
strlcpy(fdi->info.fname, link_name, sizeof(fdi->info.fname));
}
proclist->m_proc_callback(proclist->m_proc_callback_context,
error,
tinfo->tid,
tinfo,
fdi,
NULL);
proclist->m_callbacks.m_proc_entry_cb(proclist->m_callbacks.m_callback_context,
error,
tinfo->tid,
tinfo,
fdi,
NULL);
return SCAP_SUCCESS;
}
@ -381,12 +381,12 @@ int32_t scap_fd_handle_socket(struct scap_proclist *proclist,
if(1 != sscanf(link_name, "socket:[%" PRIi64 "]", &ino)) {
// it's a kind of socket, but we don't support it right now
fdi->type = SCAP_FD_UNSUPPORTED;
proclist->m_proc_callback(proclist->m_proc_callback_context,
error,
tinfo->tid,
tinfo,
fdi,
NULL);
proclist->m_callbacks.m_proc_entry_cb(proclist->m_callbacks.m_callback_context,
error,
tinfo->tid,
tinfo,
fdi,
NULL);
return SCAP_SUCCESS;
}
@ -398,12 +398,12 @@ int32_t scap_fd_handle_socket(struct scap_proclist *proclist,
memcpy(&(fdi->info), &(tfdi->info), sizeof(fdi->info));
fdi->ino = ino;
fdi->type = tfdi->type;
proclist->m_proc_callback(proclist->m_proc_callback_context,
error,
tinfo->tid,
tinfo,
fdi,
NULL);
proclist->m_callbacks.m_proc_entry_cb(proclist->m_callbacks.m_callback_context,
error,
tinfo->tid,
tinfo,
fdi,
NULL);
}
return SCAP_SUCCESS;
}
@ -1278,6 +1278,7 @@ int32_t scap_fd_get_fdinfo(struct scap_linux_platform const *const linux_platfor
// Get file descriptor stat.
snprintf(f_name, sizeof(f_name), "%sfd/%d", procdir, fd);
if(stat(f_name, &sb) == -1) {
scap_errprintf(error, 0, "error getting file status for %s", f_name);
return SCAP_NOTFOUND;
}
fdi.fd = fd;

View File

@ -62,6 +62,7 @@ int32_t scap_linux_init_platform(struct scap_platform* platform,
linux_platform->m_proc_scan_timeout_ms = oargs->proc_scan_timeout_ms;
linux_platform->m_proc_scan_log_interval_ms = oargs->proc_scan_log_interval_ms;
linux_platform->m_log_fn = oargs->log_fn;
linux_platform->m_cgroups.m_log_fn = oargs->log_fn;
if(scap_os_get_machine_info(&platform->m_machine_info, lasterr) != SCAP_SUCCESS) {
return SCAP_FAILURE;
@ -124,8 +125,7 @@ static const struct scap_platform_vtable scap_linux_platform_vtable = {
.free_platform = scap_linux_free_platform,
};
struct scap_platform* scap_linux_alloc_platform(proc_entry_callback proc_callback,
void* proc_callback_context) {
struct scap_platform* scap_linux_alloc_platform(scap_proc_callbacks callbacks) {
struct scap_linux_platform* platform = calloc(1, sizeof(*platform));
if(platform == NULL) {
@ -135,7 +135,7 @@ struct scap_platform* scap_linux_alloc_platform(proc_entry_callback proc_callbac
struct scap_platform* generic = &platform->m_generic;
generic->m_vtable = &scap_linux_platform_vtable;
init_proclist(&generic->m_proclist, proc_callback, proc_callback_context);
init_proclist(&generic->m_proclist, callbacks);
return generic;
}

View File

@ -98,8 +98,7 @@ struct scap_linux_platform {
const struct scap_linux_vtable* m_linux_vtable;
};
struct scap_platform* scap_linux_alloc_platform(proc_entry_callback proc_callback,
void* proc_callback_context);
struct scap_platform* scap_linux_alloc_platform(scap_proc_callbacks proc_callbacks);
/**
* @brief A lightweight Linux platform that only collects static host information

View File

@ -781,12 +781,12 @@ static int32_t scap_proc_add_from_proc(struct scap_linux_platform* linux_platfor
//
// Done. Add the entry to the process table, or fire the notification callback
//
proclist->m_proc_callback(proclist->m_proc_callback_context,
error,
tinfo.tid,
&tinfo,
NULL,
&new_tinfo);
proclist->m_callbacks.m_proc_entry_cb(proclist->m_callbacks.m_callback_context,
error,
tinfo.tid,
&tinfo,
NULL,
&new_tinfo);
//
// Only add fds for processes, not threads
@ -829,7 +829,12 @@ int32_t scap_proc_read_thread(struct scap_linux_platform* linux_platform,
char* error,
bool scan_sockets) {
struct scap_proclist single_thread_proclist;
init_proclist(&single_thread_proclist, single_thread_proc_callback, tinfo);
init_proclist(&single_thread_proclist,
(scap_proc_callbacks){default_refresh_start_end_callback,
default_refresh_start_end_callback,
single_thread_proc_callback,
tinfo});
struct scap_ns_socket_list* sockets_by_ns = NULL;
@ -1180,11 +1185,13 @@ int32_t scap_linux_refresh_proc_table(struct scap_platform* platform,
snprintf(procdirname, sizeof(procdirname), "%s/proc", scap_get_host_root());
scap_cgroup_enable_cache(&linux_platform->m_cgroups);
proclist->m_callbacks.m_refresh_start_cb(proclist->m_callbacks.m_callback_context);
int32_t ret = _scap_proc_scan_proc_dir_impl(linux_platform,
proclist,
procdirname,
-1,
linux_platform->m_lasterr);
proclist->m_callbacks.m_refresh_end_cb(proclist->m_callbacks.m_callback_context);
scap_cgroup_clear_cache(&linux_platform->m_cgroups);
return ret;
}

View File

@ -37,8 +37,7 @@ limitations under the License.
// Still, to compile properly on non-Linux, provide implementations
// of scap_linux_alloc_platform() and scap_linux_hostinfo_alloc_platform() that always fail at
// runtime.
struct scap_platform* scap_linux_alloc_platform(proc_entry_callback proc_callback,
void* proc_callback_context) {
struct scap_platform* scap_linux_alloc_platform(scap_proc_callbacks proc_callbacks) {
return NULL;
}
struct scap_platform* scap_linux_hostinfo_alloc_platform() {

View File

@ -102,7 +102,7 @@ struct scap_vtable;
// and handle the result
//
#define SCAP_MINIMUM_DRIVER_API_VERSION PPM_API_VERSION(8, 0, 0)
#define SCAP_MINIMUM_DRIVER_SCHEMA_VERSION PPM_API_VERSION(3, 65, 0)
#define SCAP_MINIMUM_DRIVER_SCHEMA_VERSION PPM_API_VERSION(3, 69, 0)
//
// This is the dimension we used before introducing the variable buffer size.
@ -845,6 +845,19 @@ bool scap_check_current_engine(scap_t* handle, const char* engine_name);
*/
uint32_t scap_event_decode_params(const scap_evt* e, struct scap_sized_buffer* params);
typedef uint64_t scap_empty_params_set;
void scap_empty_params_set_init(scap_empty_params_set* set, int n, ...);
int scap_empty_params_set_is_set(const scap_empty_params_set* set, int index);
#define SCAP_EMPTY_PARAMS_SET(set_name, ...) \
scap_empty_params_set set_name = 0; \
{ /* New scope to hide the following temporary variables. */ \
const int VA_ARGS_INT_ARR[] = {__VA_ARGS__}; \
const int VA_ARGS_NUM = sizeof(VA_ARGS_INT_ARR) / sizeof(const int); \
scap_empty_params_set_init(&set_name, VA_ARGS_NUM, __VA_ARGS__); \
}
/*!
\brief Create an event from the parameters given as arguments.
@ -864,10 +877,12 @@ uint32_t scap_event_decode_params(const scap_evt* e, struct scap_sized_buffer* p
\param error A pointer to a scap error string to be filled in case of error.
\param event_type The event type (normally PPME_*)
\param n The number of parameters for this event. This is required as the number of parameters
used for each event can change between versions. \param ... \return int32_t The error value. If
the event was written successfully, SCAP_SUCCESS is returned. If the supplied buffer is not large
enough for the event SCAP_INPUT_TOO_SMALL is returned and event_size is set with the required size
to contain the entire event. In other error cases, SCAP_FAILURE is returned.
used for each event can change between versions.
\param ... Variadic arguments defining the parameter values.
\return int32_t The error value. If the event was written successfully, SCAP_SUCCESS is returned.
If the supplied buffer is not large enough for the event SCAP_INPUT_TOO_SMALL is returned and
event_size is set with the required size to contain the entire event. In other error cases,
SCAP_FAILURE is returned.
*/
int32_t scap_event_encode_params(struct scap_sized_buffer event_buf,
@ -876,25 +891,60 @@ int32_t scap_event_encode_params(struct scap_sized_buffer event_buf,
ppm_event_code event_type,
uint32_t n,
...);
/*!
\brief Create an event from the parameters given as arguments, setting empty some of them.
Provide a superset of the functionalities of scap_event_encode_params(), allowing to specify a set
of parameters that must be set to empty. The parameter values, provided as variadic arguments
and corresponding to indexes in the empty parameters set, are ignored.
*/
int32_t scap_event_encode_params_with_empty_params(struct scap_sized_buffer event_buf,
size_t* event_size,
char* error,
ppm_event_code event_type,
const scap_empty_params_set* empty_params_set,
uint32_t n,
...);
int32_t scap_event_encode_params_v(struct scap_sized_buffer event_buf,
size_t* event_size,
char* error,
ppm_event_code event_type,
const scap_empty_params_set* empty_params_set,
uint32_t n,
va_list args);
bool scap_compare_events(scap_evt* curr, scap_evt* expected, char* error);
scap_evt* scap_create_event_v(char* error,
uint64_t ts,
uint64_t tid,
ppm_event_code event_type,
uint32_t n,
va_list args);
/*!
\brief Create an event from the parameters given as arguments.
Variant of scap_event_encode_params() allocating a new buffer to store the event.
*/
scap_evt* scap_create_event(char* error,
uint64_t ts,
uint64_t tid,
ppm_event_code event_type,
uint32_t n,
...);
/*!
\brief Create an event from the parameters given as arguments, setting empty some of them.
Provide a superset of the functionalities of scap_create_event(), allowing to specify a set of
parameters that must be set to empty. The parameter values, provided as variadic arguments and
corresponding to indexes in the empty parameters set, are ignored.
*/
scap_evt* scap_create_event_with_empty_params(char* error,
uint64_t ts,
uint64_t tid,
ppm_event_code event_type,
const scap_empty_params_set* empty_params_set,
uint32_t n,
...);
scap_evt* scap_create_event_v(char* error,
uint64_t ts,
uint64_t tid,
ppm_event_code event_type,
const scap_empty_params_set* empty_params_set,
uint32_t n,
va_list args);
typedef enum scap_print_info {
PRINT_HEADER = 0,
PRINT_HEADER_LENGTHS,

View File

@ -0,0 +1,35 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2025 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 <libscap/scap.h>
void scap_empty_params_set_init(scap_empty_params_set* set, const int n, ...) {
if(!set) {
return;
}
va_list args;
va_start(args, n);
for(int i = 0; i < n; i++) {
*set |= 1 << va_arg(args, int);
}
va_end(args);
}
int scap_empty_params_set_is_set(const scap_empty_params_set* set, const int index) {
return set && *set & 1 << index;
}

View File

@ -151,7 +151,29 @@ int32_t scap_event_encode_params(struct scap_sized_buffer event_buf,
...) {
va_list args;
va_start(args, n);
int32_t ret = scap_event_encode_params_v(event_buf, event_size, error, event_type, n, args);
int32_t ret =
scap_event_encode_params_v(event_buf, event_size, error, event_type, NULL, n, args);
va_end(args);
return ret;
}
int32_t scap_event_encode_params_with_empty_params(struct scap_sized_buffer event_buf,
size_t *event_size,
char *error,
ppm_event_code event_type,
const scap_empty_params_set *empty_params_set,
uint32_t n,
...) {
va_list args;
va_start(args, n);
int32_t ret = scap_event_encode_params_v(event_buf,
event_size,
error,
event_type,
empty_params_set,
n,
args);
va_end(args);
return ret;
@ -161,6 +183,7 @@ int32_t scap_event_encode_params_v(const struct scap_sized_buffer event_buf,
size_t *event_size,
char *error,
ppm_event_code event_type,
const scap_empty_params_set *empty_params_set,
uint32_t n,
va_list args) {
scap_evt *event = NULL;
@ -287,19 +310,20 @@ int32_t scap_event_encode_params_v(const struct scap_sized_buffer event_buf,
pi->type);
}
uint16_t param_size_16;
uint32_t param_size_32;
// Write zero as parameter length if the caller specified to set it empty.
const size_t len_to_write =
scap_empty_params_set_is_set(empty_params_set, i) ? 0 : param.size;
switch(len_size) {
case sizeof(uint16_t):
param_size_16 = (uint16_t)(param.size & 0xffff);
if(param_size_16 != param.size) {
case sizeof(uint16_t): {
const uint16_t param_size_16 = len_to_write & 0xffff;
if(param_size_16 != len_to_write) {
return scap_errprintf(
error,
0,
"could not fit event param %d size %zu for event with type %d in %zu bytes",
i,
param.size,
len_to_write,
event_type,
len_size);
}
@ -307,15 +331,16 @@ int32_t scap_event_encode_params_v(const struct scap_sized_buffer event_buf,
scap_event_set_param_length_regular(event, i, param_size_16);
}
break;
case sizeof(uint32_t):
param_size_32 = (uint32_t)(param.size & 0xffffffff);
if(param_size_32 != param.size) {
}
case sizeof(uint32_t): {
const uint32_t param_size_32 = len_to_write & 0xffffffff;
if(param_size_32 != len_to_write) {
return scap_errprintf(
error,
0,
"could not fit event param %d size %zu for event with type %d in %zu bytes",
i,
param.size,
len_to_write,
event_type,
len_size);
}
@ -323,7 +348,8 @@ int32_t scap_event_encode_params_v(const struct scap_sized_buffer event_buf,
scap_event_set_param_length_large(event, i, param_size_32);
}
break;
default:
}
default: {
ASSERT(false);
return scap_errprintf(error,
0,
@ -332,9 +358,13 @@ int32_t scap_event_encode_params_v(const struct scap_sized_buffer event_buf,
len_size,
event_type);
}
}
if(scap_buffer_can_fit(event_buf, len + param.size) && param.size != 0) {
memcpy(((char *)event_buf.buf + len), param.buf, param.size);
// Notice: even if the caller specified to set the parameter as empty, it will always occupy
// a number of bytes determined by its type (i.e.: param.size, not len_to_write).
const size_t value_len = param.size;
if(scap_buffer_can_fit(event_buf, len + value_len) && value_len != 0) {
memcpy(((char *)event_buf.buf + len), param.buf, value_len);
}
len = len + param.size;
}
@ -457,17 +487,52 @@ bool scap_compare_events(scap_evt *curr, scap_evt *expected, char *error) {
return true;
}
// If this returns NULL, check the error message.
scap_evt *scap_create_event(char *error,
uint64_t ts,
uint64_t tid,
ppm_event_code event_type,
uint32_t n,
...) {
va_list args;
va_start(args, n);
scap_evt *ret = scap_create_event_v(error, ts, tid, event_type, NULL, n, args);
va_end(args);
return ret;
}
scap_evt *scap_create_event_with_empty_params(char *error,
uint64_t ts,
uint64_t tid,
ppm_event_code event_type,
const scap_empty_params_set *empty_params_set,
uint32_t n,
...) {
va_list args;
va_start(args, n);
scap_evt *ret = scap_create_event_v(error, ts, tid, event_type, empty_params_set, n, args);
va_end(args);
return ret;
}
scap_evt *scap_create_event_v(char *error,
uint64_t ts,
uint64_t tid,
ppm_event_code event_type,
const scap_empty_params_set *empty_params_set,
uint32_t n,
va_list args) {
struct scap_sized_buffer event_buf = {NULL, 0};
size_t event_size = 0;
va_list args2;
va_copy(args2, args);
int32_t ret = scap_event_encode_params_v(event_buf, &event_size, error, event_type, n, args);
int32_t ret = scap_event_encode_params_v(event_buf,
&event_size,
error,
event_type,
empty_params_set,
n,
args);
if(ret != SCAP_INPUT_TOO_SMALL) {
goto error;
}
@ -477,7 +542,13 @@ scap_evt *scap_create_event_v(char *error,
scap_errprintf(error, 0, "cannot alloc %ld bytes.", event_size);
goto error;
}
ret = scap_event_encode_params_v(event_buf, &event_size, error, event_type, n, args2);
ret = scap_event_encode_params_v(event_buf,
&event_size,
error,
event_type,
empty_params_set,
n,
args2);
if(ret != SCAP_SUCCESS) {
event_buf.size = 0;
free(event_buf.buf);
@ -493,20 +564,6 @@ error:
return NULL;
}
// If this returns NULL, check the error message.
scap_evt *scap_create_event(char *error,
uint64_t ts,
uint64_t tid,
ppm_event_code event_type,
uint32_t n,
...) {
va_list args;
va_start(args, n);
scap_evt *ret = scap_create_event_v(error, ts, tid, event_type, n, args);
va_end(args);
return ret;
}
// Only enter events have a convention on the fd parameter position.
// Should be always the first parameter apart from some exceptions.
int get_enter_event_fd_location(ppm_event_code etype) {
@ -553,6 +610,15 @@ int get_exit_event_fd_location(ppm_event_code etype) {
case PPME_SYSCALL_FLOCK_X:
case PPME_SYSCALL_COPY_FILE_RANGE_X:
case PPME_SYSCALL_FCNTL_X:
case PPME_SYSCALL_DUP_1_X:
case PPME_SYSCALL_DUP2_X:
case PPME_SYSCALL_DUP3_X:
case PPME_SYSCALL_NEWFSTATAT_X:
case PPME_SYSCALL_FCHOWNAT_X:
case PPME_SYSCALL_FCHMODAT_X:
case PPME_SYSCALL_MKDIRAT_X:
case PPME_SYSCALL_UNLINKAT_2_X:
case PPME_SYSCALL_MKNODAT_X:
location = 1;
break;
case PPME_SYSCALL_READ_X:
@ -569,6 +635,7 @@ int get_exit_event_fd_location(ppm_event_code etype) {
case PPME_SYSCALL_WRITEV_X:
case PPME_SYSCALL_PWRITEV_X:
case PPME_SOCKET_CONNECT_X:
case PPME_SYSCALL_SYMLINKAT_X:
location = 2;
break;
case PPME_SOCKET_RECVFROM_X:

View File

@ -65,8 +65,7 @@ struct scap_platform_vtable scap_generic_platform_vtable = {
.free_platform = scap_generic_free_platform,
};
struct scap_platform* scap_generic_alloc_platform(proc_entry_callback proc_callback,
void* proc_callback_context) {
struct scap_platform* scap_generic_alloc_platform(scap_proc_callbacks callbacks) {
struct scap_platform* platform = calloc(1, sizeof(*platform));
if(platform == NULL) {
@ -75,7 +74,7 @@ struct scap_platform* scap_generic_alloc_platform(proc_entry_callback proc_callb
platform->m_vtable = &scap_generic_platform_vtable;
init_proclist(&platform->m_proclist, proc_callback, proc_callback_context);
init_proclist(&platform->m_proclist, callbacks);
return platform;
}

View File

@ -38,8 +38,7 @@ struct scap_platform;
// Note: every platform alloc function needs to set up the proc_callback, since
// this needs to be called before opening the engine; otherwise the proclist callback
// won't be set up in time (for the savefile engine)
struct scap_platform* scap_generic_alloc_platform(proc_entry_callback proc_callback,
void* proc_callback_context);
struct scap_platform* scap_generic_alloc_platform(scap_proc_callbacks proc_callbacks);
// initialize the common part of the platform handle
int32_t scap_generic_init_platform(struct scap_platform* platform,

View File

@ -40,12 +40,12 @@ int32_t scap_proc_scan_vtable(char *error,
//
// Add the entry to the process table, or fire the notification callback
//
proclist->m_proc_callback(proclist->m_proc_callback_context,
error,
new_tinfo.tid,
&new_tinfo,
NULL,
&tinfo);
proclist->m_callbacks.m_proc_entry_cb(proclist->m_callbacks.m_callback_context,
error,
new_tinfo.tid,
&new_tinfo,
NULL,
&tinfo);
if(tinfo->pid != tinfo->tid) {
continue;
@ -62,12 +62,12 @@ int32_t scap_proc_scan_vtable(char *error,
uint64_t j;
for(j = 0; j < n_fdinfos; j++) {
scap_fdinfo fdi = fdinfos[j];
proclist->m_proc_callback(proclist->m_proc_callback_context,
error,
tinfo->tid,
tinfo,
&fdi,
NULL);
proclist->m_callbacks.m_proc_entry_cb(proclist->m_callbacks.m_callback_context,
error,
tinfo->tid,
tinfo,
&fdi,
NULL);
}
}

View File

@ -68,6 +68,8 @@ int32_t scap_fd_add(scap_threadinfo* tinfo, scap_fdinfo* fdinfo) {
}
}
void default_refresh_start_end_callback(void* context) {}
int32_t default_proc_entry_callback(void* context,
char* error,
int64_t tid,
@ -147,17 +149,14 @@ int32_t default_proc_entry_callback(void* context,
return SCAP_SUCCESS;
}
void init_proclist(struct scap_proclist* proclist,
proc_entry_callback callback,
void* callback_context) {
if(callback == NULL) {
proclist->m_proc_callback = default_proc_entry_callback;
proclist->m_proc_callback_context = proclist;
} else {
proclist->m_proc_callback = callback;
proclist->m_proc_callback_context = callback_context;
void init_proclist(struct scap_proclist* proclist, scap_proc_callbacks callbacks) {
if(callbacks.m_proc_entry_cb == NULL) {
callbacks.m_proc_entry_cb = default_proc_entry_callback;
callbacks.m_callback_context = proclist;
}
proclist->m_callbacks = callbacks;
proclist->m_proclist = NULL;
}
bool scap_alloc_proclist_info(struct ppm_proclist_info** proclist_p,

View File

@ -54,6 +54,25 @@ typedef int32_t (*proc_entry_callback)(void* context,
scap_fdinfo* fdinfo,
scap_threadinfo** new_tinfo);
typedef void (*proc_table_refresh_start)(void* context);
typedef void (*proc_table_refresh_end)(void* context);
/*!
@brief Full set of callbacks for proc table refresh
@param refresh_start: callback to be called at the start of the proc table refresh
@param refresh_end: callback to be called at the end of the proc table refresh
@param proc_callback: callback to be called for each thread or fd found
@param callback_context: context to be passed to the proc_callback
*/
typedef struct scap_proc_callbacks {
proc_table_refresh_start m_refresh_start_cb;
proc_table_refresh_end m_refresh_end_cb;
proc_entry_callback m_proc_entry_cb;
void* m_callback_context;
} scap_proc_callbacks;
void default_refresh_start_end_callback(void* context);
int32_t default_proc_entry_callback(void* context,
char* error,
int64_t tid,
@ -62,15 +81,11 @@ int32_t default_proc_entry_callback(void* context,
scap_threadinfo** new_tinfo);
struct scap_proclist {
proc_entry_callback m_proc_callback;
void* m_proc_callback_context;
scap_proc_callbacks m_callbacks;
scap_threadinfo* m_proclist;
};
void init_proclist(struct scap_proclist* proclist,
proc_entry_callback callback,
void* callback_context);
void init_proclist(struct scap_proclist* proclist, scap_proc_callbacks callbacks);
#ifdef __cplusplus
}

View File

@ -726,8 +726,26 @@ const char *sinsp_evt::get_param_as_str(uint32_t id,
const sinsp_evt_param *param = get_param(id);
param_info = param->get_info();
if(param->m_len == 0) {
snprintf(&m_paramstr_storage[0], m_paramstr_storage.size(), "NULL");
if(!param->used_legacy_null_encoding() && param->len() == 0) {
// Ideally, we should always <NA>, but this would break compatibility, so keep pushing NULL
// for parameters that could already be empty before the scap-converter introduced the
// notion of "empty parameters" for all types.
// TODO(ekoops): consistently send the same value.
switch(param_info->type) {
case PT_BYTEBUF:
case PT_SOCKTUPLE:
case PT_FDLIST:
case PT_CHARBUFARRAY:
case PT_CHARBUF_PAIR_ARRAY:
case PT_DYN: {
snprintf(&m_paramstr_storage[0], m_paramstr_storage.size(), "NULL");
break;
}
default: {
snprintf(&m_paramstr_storage[0], m_paramstr_storage.size(), "<NA>");
break;
}
}
*resolved_str = &m_resolved_paramstr_storage[0];
return &m_paramstr_storage[0];
}
@ -736,16 +754,18 @@ const char *sinsp_evt::get_param_as_str(uint32_t id,
// Get the parameter information
//
if(param_info->type == PT_DYN && param_info->info != NULL) {
const auto param_data = param->data();
const auto param_len = param->len();
uint8_t dyn_idx = 0;
memcpy(&dyn_idx, param->m_val, sizeof(uint8_t));
memcpy(&dyn_idx, param_data, sizeof(uint8_t));
if(dyn_idx < param_info->ninfo) {
auto dyn_params = (const ppm_param_info *)param_info->info;
auto dyn_params = static_cast<const ppm_param_info *>(param_info->info);
dyn_param = sinsp_evt_param(param->m_evt,
param->m_idx,
param->m_val + sizeof(uint8_t),
param->m_len - sizeof(uint8_t));
param_data + sizeof(uint8_t),
param_len - sizeof(uint8_t));
param = std::addressof(*dyn_param);
param_info = &dyn_params[dyn_idx];
@ -892,11 +912,13 @@ const char *sinsp_evt::get_param_as_str(uint32_t id,
}
} break;
case PT_BYTEBUF: {
auto param_data = param->data();
auto param_len = param->len();
while(true) {
uint32_t blen = binary_buffer_to_string(&m_paramstr_storage[0],
param->m_val,
param_data,
(uint32_t)m_paramstr_storage.size() - 1,
param->m_len,
param_len,
fmt);
if(blen >= m_paramstr_storage.size() - 1) {
@ -926,15 +948,17 @@ const char *sinsp_evt::get_param_as_str(uint32_t id,
break;
}
} break;
case PT_SOCKADDR:
sockfamily = param->m_val[0];
case PT_SOCKADDR: {
auto param_data = param->data();
auto param_len = param->len();
sockfamily = param_data[0];
if(sockfamily == PPM_AF_UNIX) {
ASSERT(param->m_len > 1);
ASSERT(param->len() > 1);
//
// Sanitize the file string.
//
std::string sanitized_str = param->m_val + 1;
std::string sanitized_str = param_data + 1;
sanitize_string(sanitized_str);
snprintf(&m_paramstr_storage[0],
@ -942,10 +966,10 @@ const char *sinsp_evt::get_param_as_str(uint32_t id,
"%s",
sanitized_str.c_str());
} else if(sockfamily == PPM_AF_INET) {
if(param->m_len == 1 + 4 + 2) {
if(param_len == 1 + 4 + 2) {
ipv4serverinfo addr;
memcpy(&addr.m_ip, param->m_val + 1, sizeof(addr.m_ip));
memcpy(&addr.m_port, param->m_val + 5, sizeof(addr.m_port));
memcpy(&addr.m_ip, param_data + 1, sizeof(addr.m_ip));
memcpy(&addr.m_port, param_data + 5, sizeof(addr.m_port));
addr.m_l4proto = (m_fdinfo != NULL) ? m_fdinfo->get_l4proto() : SCAP_L4_UNKNOWN;
std::string straddr = ipv4serveraddr_to_string(
addr,
@ -956,12 +980,10 @@ const char *sinsp_evt::get_param_as_str(uint32_t id,
snprintf(&m_paramstr_storage[0], m_paramstr_storage.size(), "INVALID IPv4");
}
} else if(sockfamily == PPM_AF_INET6) {
if(param->m_len == 1 + 16 + 2) {
if(param_len == 1 + 16 + 2) {
ipv6serverinfo addr;
memcpy((uint8_t *)addr.m_ip.m_b,
(uint8_t *)param->m_val + 1,
sizeof(addr.m_ip.m_b));
memcpy(&addr.m_port, param->m_val + 17, sizeof(addr.m_port));
memcpy(addr.m_ip.m_b, param_data + 1, sizeof(addr.m_ip.m_b));
memcpy(&addr.m_port, param_data + 17, sizeof(addr.m_port));
addr.m_l4proto = (m_fdinfo != NULL) ? m_fdinfo->get_l4proto() : SCAP_L4_UNKNOWN;
std::string straddr = ipv6serveraddr_to_string(
addr,
@ -975,15 +997,18 @@ const char *sinsp_evt::get_param_as_str(uint32_t id,
snprintf(&m_paramstr_storage[0], m_paramstr_storage.size(), "family %d", sockfamily);
}
break;
case PT_SOCKTUPLE:
sockfamily = param->m_val[0];
}
case PT_SOCKTUPLE: {
const auto param_data = reinterpret_cast<const uint8_t *>(param->data());
const auto param_len = param->len();
sockfamily = param_data[0];
if(sockfamily == PPM_AF_INET) {
if(param->m_len == 1 + 4 + 2 + 4 + 2) {
if(param_len == 1 + 4 + 2 + 4 + 2) {
ipv4tuple addr;
memcpy(&addr.m_fields.m_sip, param->m_val + 1, sizeof(uint32_t));
memcpy(&addr.m_fields.m_sport, param->m_val + 5, sizeof(uint16_t));
memcpy(&addr.m_fields.m_dip, param->m_val + 7, sizeof(uint32_t));
memcpy(&addr.m_fields.m_dport, param->m_val + 11, sizeof(uint16_t));
memcpy(&addr.m_fields.m_sip, param_data + 1, sizeof(uint32_t));
memcpy(&addr.m_fields.m_sport, param_data + 5, sizeof(uint16_t));
memcpy(&addr.m_fields.m_dip, param_data + 7, sizeof(uint32_t));
memcpy(&addr.m_fields.m_dport, param_data + 11, sizeof(uint16_t));
addr.m_fields.m_l4proto =
(m_fdinfo != NULL) ? m_fdinfo->get_l4proto() : SCAP_L4_UNKNOWN;
std::string straddr =
@ -995,19 +1020,19 @@ const char *sinsp_evt::get_param_as_str(uint32_t id,
snprintf(&m_paramstr_storage[0], m_paramstr_storage.size(), "INVALID IPv4");
}
} else if(sockfamily == PPM_AF_INET6) {
if(param->m_len == 1 + 16 + 2 + 16 + 2) {
uint8_t *sip6 = (uint8_t *)param->m_val + 1;
uint8_t *dip6 = (uint8_t *)param->m_val + 19;
uint8_t *sip = (uint8_t *)param->m_val + 13;
uint8_t *dip = (uint8_t *)param->m_val + 31;
if(param_len == 1 + 16 + 2 + 16 + 2) {
const uint8_t *sip6 = param_data + 1;
const uint8_t *dip6 = param_data + 19;
const uint8_t *sip = param_data + 13;
const uint8_t *dip = param_data + 31;
if(sinsp_utils::is_ipv4_mapped_ipv6(sip6) &&
sinsp_utils::is_ipv4_mapped_ipv6(dip6)) {
ipv4tuple addr;
memcpy(&addr.m_fields.m_sip, sip, sizeof(uint32_t));
memcpy(&addr.m_fields.m_sport, param->m_val + 17, sizeof(uint16_t));
memcpy(&addr.m_fields.m_sport, param_data + 17, sizeof(uint16_t));
memcpy(&addr.m_fields.m_dip, dip, sizeof(uint32_t));
memcpy(&addr.m_fields.m_dport, param->m_val + 35, sizeof(uint16_t));
memcpy(&addr.m_fields.m_dport, param_data + 35, sizeof(uint16_t));
addr.m_fields.m_l4proto =
(m_fdinfo != NULL) ? m_fdinfo->get_l4proto() : SCAP_L4_UNKNOWN;
std::string straddr = ipv4tuple_to_string(
@ -1025,8 +1050,8 @@ const char *sinsp_evt::get_param_as_str(uint32_t id,
if(inet_ntop(AF_INET6, sip6, srcstr, sizeof(srcstr)) &&
inet_ntop(AF_INET6, dip6, dststr, sizeof(dststr))) {
uint16_t srcport, dstport;
memcpy(&srcport, param->m_val + 17, sizeof(srcport));
memcpy(&dstport, param->m_val + 35, sizeof(dstport));
memcpy(&srcport, param_data + 17, sizeof(srcport));
memcpy(&dstport, param_data + 35, sizeof(dstport));
snprintf(&m_paramstr_storage[0],
m_paramstr_storage.size(),
"%s:%s->%s:%s",
@ -1052,17 +1077,17 @@ const char *sinsp_evt::get_param_as_str(uint32_t id,
ASSERT(false);
snprintf(&m_paramstr_storage[0], m_paramstr_storage.size(), "INVALID IPv6");
} else if(sockfamily == PPM_AF_UNIX) {
ASSERT(param->m_len > 17);
ASSERT(param->len() > 17);
//
// Sanitize the file string.
//
std::string sanitized_str = param->m_val + 17;
std::string sanitized_str = reinterpret_cast<const char *>(param_data) + 17;
sanitize_string(sanitized_str);
uint64_t src, dst;
memcpy(&src, param->m_val + 1, sizeof(uint64_t));
memcpy(&dst, param->m_val + 9, sizeof(uint64_t));
memcpy(&src, param_data + 1, sizeof(uint64_t));
memcpy(&dst, param_data + 9, sizeof(uint64_t));
snprintf(&m_paramstr_storage[0],
m_paramstr_storage.size(),
@ -1074,14 +1099,16 @@ const char *sinsp_evt::get_param_as_str(uint32_t id,
snprintf(&m_paramstr_storage[0], m_paramstr_storage.size(), "family %d", sockfamily);
}
break;
}
case PT_FDLIST: {
sinsp_threadinfo *tinfo = get_thread_info();
if(!tinfo) {
break;
}
const auto param_data = param->data();
uint16_t nfds = 0;
memcpy(&nfds, param->m_val, sizeof(nfds));
memcpy(&nfds, param_data, sizeof(nfds));
uint32_t pos = 2;
uint32_t spos = 0;
@ -1090,7 +1117,7 @@ const char *sinsp_evt::get_param_as_str(uint32_t id,
for(j = 0; j < nfds; j++) {
char tch;
int64_t fd = 0;
memcpy(&fd, param->m_val + pos, sizeof(uint64_t));
memcpy(&fd, param_data + pos, sizeof(uint64_t));
sinsp_fdinfo *fdinfo = tinfo->get_fd(fd);
if(fdinfo) {
@ -1100,7 +1127,7 @@ const char *sinsp_evt::get_param_as_str(uint32_t id,
}
int16_t p8;
memcpy(&p8, param->m_val + pos + 8, sizeof(int16_t));
memcpy(&p8, param_data + pos + 8, sizeof(int16_t));
int r = snprintf(&m_paramstr_storage[0] + spos,
m_paramstr_storage.size() - spos,
@ -1362,8 +1389,8 @@ const char *sinsp_evt::get_param_as_str(uint32_t id,
break;
}
case PT_CHARBUFARRAY: {
ASSERT(param->m_len == sizeof(uint64_t));
std::vector<char *> *strvect = (std::vector<char *> *)*(uint64_t *)param->m_val;
ASSERT(param->len() == sizeof(uint64_t));
std::vector<char *> *strvect = (std::vector<char *> *)*(uint64_t *)param->data();
m_paramstr_storage[0] = 0;
@ -1411,10 +1438,10 @@ const char *sinsp_evt::get_param_as_str(uint32_t id,
}
} break;
case PT_CHARBUF_PAIR_ARRAY: {
ASSERT(param->m_len == sizeof(uint64_t));
ASSERT(param->len() == sizeof(uint64_t));
std::pair<std::vector<char *> *, std::vector<char *> *> *pairs =
(std::pair<std::vector<char *> *, std::vector<char *> *> *)*(
uint64_t *)param->m_val;
uint64_t *)param->data();
m_paramstr_storage[0] = 0;
@ -1694,40 +1721,16 @@ uint64_t sinsp_evt::get_lastevent_ts() const {
}
void sinsp_evt::save_enter_event_params(sinsp_evt *enter_evt) {
static std::vector<const char *> path_param = {"path"};
static std::vector<const char *> oldpath_newpath_param = {"oldpath", "newpath"};
static std::vector<const char *> name_param = {"name"};
std::vector<const char *> *pnames = NULL;
switch(get_type()) {
case PPME_SYSCALL_MKDIR_X:
case PPME_SYSCALL_RMDIR_X:
case PPME_SYSCALL_UNLINK_X:
pnames = &path_param;
break;
case PPME_SYSCALL_LINK_X:
case PPME_SYSCALL_LINKAT_X:
pnames = &oldpath_newpath_param;
break;
case PPME_SYSCALL_UNLINKAT_X:
case PPME_SYSCALL_OPENAT_X:
pnames = &name_param;
break;
};
if(!pnames) {
if(get_type() != PPME_SYSCALL_OPENAT_X) {
return;
}
for(const char *pname : (*pnames)) {
const sinsp_evt_param *param;
const sinsp_evt_param *param;
param = enter_evt->get_param_by_name(pname);
if(param) {
std::string val = param->as<std::string>();
m_enter_path_param[pname] = val;
}
param = enter_evt->get_param_by_name("name");
if(param) {
std::string val = param->as<std::string>();
m_enter_path_param["name"] = val;
}
}
@ -1743,18 +1746,21 @@ std::optional<std::reference_wrapper<const std::string>> sinsp_evt::get_enter_ev
}
void sinsp_evt_param::throw_invalid_len_error(size_t requested_length) const {
const auto param_data = data();
const auto param_len = len();
const ppm_param_info *parinfo = get_info();
std::stringstream ss;
ss << "could not parse param " << m_idx << " (" << parinfo->name << ") for event "
<< m_evt->get_num() << " of type " << m_evt->get_type() << " (" << m_evt->get_name()
<< "), for tid " << m_evt->get_tid() << ": expected length " << requested_length
<< ", found " << m_len;
<< ", found " << param_len;
std::string error_string = ss.str();
libsinsp_logger()->log(error_string, sinsp_logger::SEV_ERROR);
libsinsp_logger()->log("parameter raw data: \n" + buffer_to_multiline_hex(m_val, m_len),
sinsp_logger::SEV_ERROR);
libsinsp_logger()->log(
"parameter raw data: \n" + buffer_to_multiline_hex(param_data, param_len),
sinsp_logger::SEV_ERROR);
throw sinsp_exception(error_string);
}

View File

@ -69,18 +69,90 @@ inline T get_event_param_as(const class sinsp_evt_param& param);
This class describes an event parameter coming from the driver.
*/
class SINSP_PUBLIC sinsp_evt_param {
const char* m_data; ///< Pointer to the event parameter data.
uint32_t m_len; ///< Length of the parameter pointed by m_data_bufm_data.
public:
const char* data() const { return m_data; }
uint32_t len() const { return m_len; }
/*!
* @return true if the length is equal to zero.
*/
bool empty() const { return len() == 0; }
/*!
* @return a boolean indicating if, for this specific parameter "null" configuration (data and
* len configuration), the legacy null encoding ('<NA>') was used.
*
* Some specific types of parameter used a legacy encoding in specific scenarios. Specifically,
* in the past, the parameters having the following types could be `<NA>` or `(NULL)` or empty:
*
* - PT_CHARBUF
* - PT_FSRELPATH
* - PT_FSPATH
*
* Now they can be only empty (data: nullptr, len: 0)!
*
* The problem is that userspace is not able to manage `NULL` pointers... but it manages `<NA>`,
* so we convert all these cases to `<NA>` when they are empty!
*
* If we read scap-files we could face `(NULL)` params, so also inthis case we convert them to
*`<NA>`.
*
* To be honest there could be other corner cases, but right now we don't have to manage it:
*
* - PT_SOCKADDR
* - PT_SOCKTUPLE
* - PT_FDLIST
*
* Could be empty, so we will have:
* data = "pointer to the next param";
* len = 0;
*
* However, as we said in the previous case, the ideal outcome would be (data: nullptr, len: 0).
*
* The difference with the previous case is that the userspace can manage these params when they
* have `len == 0`, so we don't have to use the `<NA>` workaround! We could also introduce the
*`NULL` and so put in place the ideal solution for this parameter, but before doing this we
* need to be sure that the userspace never tries to deference the pointer otherwise it will
* trigger a segmentation fault at run-time. So as a first step we would keep them as they are.
*/
bool used_legacy_null_encoding() const {
switch(get_info()->type) {
case PT_CHARBUF:
case PT_FSRELPATH:
case PT_FSPATH: {
if(m_len == 0 || (m_len == 7 && strncmp(m_data, "(NULL)", 7) == 0)) {
return true;
}
return false;
}
default:
return false;
}
}
/*!
* \brief A simple helper returning the untouched parameter data and len or a null-encoded
* version of them depending on their values.
*/
std::pair<const char*, uint32_t> data_and_len_with_legacy_null_encoding() const {
if(!used_legacy_null_encoding()) {
return std::make_pair(m_data, m_len);
}
return {"<NA>", 5};
}
const sinsp_evt* m_evt; ///< Pointer to the event that contains this param
uint32_t m_idx; ///< Index of the parameter within the event
const char* m_val; ///< Pointer to the event parameter data.
uint32_t m_len; ///< Length of the parameter pointed by m_val.
sinsp_evt_param(const sinsp_evt* evt, uint32_t idx, const char* val, uint32_t len):
sinsp_evt_param(const sinsp_evt* evt, const uint32_t idx, const char* data, const uint32_t len):
m_data(data),
m_len(len),
m_evt(evt),
m_idx(idx),
m_val(val),
m_len(len) {}
m_idx(idx) {}
/*!
\brief Interpret the parameter as a specific type, like:
@ -119,49 +191,52 @@ inline T get_event_param_as(const sinsp_evt_param& param) {
T ret;
if(param.m_len != sizeof(T)) {
const auto [param_data, param_len] = param.data_and_len_with_legacy_null_encoding();
if(param_len != sizeof(T)) {
// By moving this error string building operation to a separate function
// the compiler is more likely to inline this entire function.
param.throw_invalid_len_error(sizeof(T));
}
memcpy(&ret, param.m_val, sizeof(T));
memcpy(&ret, param_data, sizeof(T));
return ret;
}
template<>
inline std::string_view get_event_param_as<std::string_view>(const sinsp_evt_param& param) {
if(param.m_len == 0) {
const auto [param_data, param_len] = param.data_and_len_with_legacy_null_encoding();
if(param_len == 0) {
return {};
}
size_t string_len = strnlen(param.m_val, param.m_len);
size_t string_len = strnlen(param_data, param_len);
// We expect the parameter to be exactly one null-terminated string
if(param.m_len != string_len + 1) {
if(param_len != string_len + 1) {
// By moving this error string building operation to a separate function
// the compiler is more likely to inline this entire function.
param.throw_invalid_len_error(string_len + 1);
}
return {param.m_val, string_len};
return {param_data, string_len};
}
template<>
inline std::string get_event_param_as<std::string>(const sinsp_evt_param& param) {
if(param.m_len == 0) {
const auto [param_data, param_len] = param.data_and_len_with_legacy_null_encoding();
if(param_len == 0) {
return "";
}
size_t string_len = strnlen(param.m_val, param.m_len);
size_t string_len = strnlen(param_data, param_len);
// We expect the parameter to be exactly one null-terminated string
if(param.m_len != string_len + 1) {
if(param_len != string_len + 1) {
// By moving this error string building operation to a separate function
// the compiler is more likely to inline this entire function.
param.throw_invalid_len_error(string_len + 1);
}
return std::string(param.m_val);
return std::string(param_data);
}
template<>
@ -169,20 +244,23 @@ inline std::vector<std::string> get_event_param_as<std::vector<std::string>>(
const sinsp_evt_param& param) {
// vector string parameters coming from the driver may be NUL-terminated or not. Either way,
// remove the NUL terminator
uint32_t len = param.m_len;
if(len > 0 && param.m_val[param.m_len - 1] == '\0') {
const auto [param_data, param_len] = param.data_and_len_with_legacy_null_encoding();
uint32_t len = param_len;
if(len > 0 && param_data[param_len - 1] == '\0') {
len--;
}
return sinsp_split({param.m_val, static_cast<std::string_view::size_type>(len)}, '\0');
return sinsp_split({param_data, static_cast<std::string_view::size_type>(len)}, '\0');
}
template<>
inline std::vector<uint8_t> get_event_param_as<std::vector<uint8_t>>(const sinsp_evt_param& param) {
const auto [param_data, param_len] = param.data_and_len_with_legacy_null_encoding();
// copy content of the event parameter to a new vector
std::vector<uint8_t> res;
for(size_t i = 0; i < param.m_len; ++i) {
res.push_back(uint8_t(param.m_val[i]));
for(size_t i = 0; i < param_len; ++i) {
res.push_back(uint8_t(param_data[i]));
}
return res;
@ -534,74 +612,14 @@ public:
}
inline void load_params() {
uint32_t j;
struct scap_sized_buffer params[PPM_MAX_EVENT_PARAMS];
m_params.clear();
uint32_t nparams = scap_event_decode_params(m_pevt, params);
/* We need the event info to overwrite some parameters if necessary. */
const struct ppm_event_info* event_info = &m_event_info_table[m_pevt->type];
int param_type = 0;
for(j = 0; j < nparams; j++) {
/* Here we need to manage a particular case:
*
* - PT_CHARBUF
* - PT_FSRELPATH
* - PT_BYTEBUF
* - PT_BYTEBUF
*
* In the past these params could be `<NA>` or `(NULL)` or empty.
* Now they can be only empty! The ideal solution would be:
* params[i].buf = NULL;
* params[i].size = 0;
*
* The problem is that userspace is not
* able to manage `NULL` pointers... but it manages `<NA>` so we
* convert all these cases to `<NA>` when they are empty!
*
* If we read scap-files we could face `(NULL)` params, so also in
* this case we convert them to `<NA>`.
*
* To be honest there could be another corner case, but right now
* we don't have to manage it:
*
* - PT_SOCKADDR
* - PT_SOCKTUPLE
* - PT_FDLIST
*
* Could be empty, so we will have:
* params[i].buf = "pointer to the next param";
* params[i].size = 0;
*
* However, as we said in the previous case, the ideal outcome would be:
* params[i].buf = NULL;
* params[i].size = 0;
*
* The difference with the previous case is that the userspace can manage
* these params when they have `params[i].size == 0`, so we don't have
* to use the `<NA>` workaround! We could also introduce the `NULL` and so
* put in place the ideal solution for this parameter, but before doing this
* we need to be sure that the userspace never tries to deference the pointer
* otherwise it will trigger a segmentation fault at run-time. So as a first
* step we would keep them as they are.
*/
param_type = event_info->params[j].type;
if((param_type == PT_CHARBUF || param_type == PT_FSRELPATH ||
param_type == PT_FSPATH) &&
(params[j].size == 0 ||
(params[j].size == 7 && strncmp((char*)params[j].buf, "(NULL)", 7) == 0))) {
/* Overwrite the value and the size of the param.
* 5 = strlen("<NA>") + `\0`.
*/
params[j].buf = (void*)"<NA>";
params[j].size = 5;
}
m_params.emplace_back(this, j, static_cast<const char*>(params[j].buf), params[j].size);
for(uint32_t i = 0; i < nparams; i++) {
m_params.emplace_back(this, i, static_cast<const char*>(params[i].buf), params[i].size);
}
}
@ -748,7 +766,7 @@ public:
}
// the only return values should be on 32 or 64 bits
switch(p->m_len) {
switch(p->len()) {
case sizeof(int32_t):
return (int64_t)p->as<int32_t>();
case sizeof(int64_t):

View File

@ -937,7 +937,8 @@ void raw_dump(sinsp& inspector, sinsp_evt* ev) {
const sinsp_evt_param* p = ev->get_param(i);
const struct ppm_param_info* pi = ev->get_param_info(i);
cout << ' ' << i << ':' << pi->name << '=';
hexdump((const unsigned char*)p->m_val, p->m_len);
const auto [data, data_len] = p->data_and_len_with_legacy_null_encoding();
hexdump(reinterpret_cast<const unsigned char*>(data), data_len);
}
cout << endl;

View File

@ -214,7 +214,7 @@ public:
inline int64_t get_pid() const { return m_pid; }
inline void set_unix_info(uint8_t* packed_data) {
inline void set_unix_info(const uint8_t* packed_data) {
memcpy(&m_sockinfo.m_unixinfo.m_fields.m_source, packed_data + 1, sizeof(uint64_t));
memcpy(&m_sockinfo.m_unixinfo.m_fields.m_dest, packed_data + 9, sizeof(uint64_t));
}

View File

@ -670,6 +670,8 @@ bool flt_compare(cmpop op,
case PT_FLAGS32:
case PT_ENUMFLAGS32:
case PT_MODE:
case PT_UID:
case PT_GID:
return flt_compare_numeric<uint64_t>(op,
flt_cast<uint32_t, uint64_t>(operand1, op1_len),
flt_cast<uint32_t, uint64_t>(operand2, op2_len));

View File

@ -266,6 +266,12 @@ void linux_resource_utilization::get_container_memory_used() {
// No need for scap_get_host_root since we look at the container pid namespace (if
// applicable) Known collision for VM memory usage, but this default value is configurable
filepath = "/sys/fs/cgroup/memory/memory.usage_in_bytes";
} else {
// Path validation to prevent directory traversal or empty paths
if(strstr(filepath, "..") != nullptr || strlen(filepath) == 0) {
// Fall back to default safe path if validation fails
filepath = "/sys/fs/cgroup/memory/memory.usage_in_bytes";
}
}
FILE* f = fopen(filepath, "r");

File diff suppressed because it is too large Load Diff

View File

@ -115,7 +115,6 @@ private:
void parse_single_param_fd_exit(sinsp_evt& evt, scap_fd_type type) const;
void parse_getrlimit_setrlimit_exit(sinsp_evt& evt) const;
void parse_prlimit_exit(sinsp_evt& evt) const;
void parse_select_poll_ppoll_epollwait(sinsp_evt& evt);
void parse_fcntl_exit(sinsp_evt& evt) const;
static void parse_prctl_exit_event(sinsp_evt& evt);
static void parse_context_switch(sinsp_evt& evt);
@ -135,10 +134,15 @@ private:
static void parse_capset_exit(sinsp_evt& evt);
static void parse_unshare_setns_exit(sinsp_evt& evt);
// Set the event thread user to the user corresponding to the provided effective user id. This
// is no-op if there is no thread associated with the provided event or the effective user id is
// invalid.
void set_evt_thread_user(sinsp_evt& evt, uint32_t euid) const;
// Set the event thread user to the user corresponding to the effective user id taken from the
// provided parameter. This is no-op if there is no thread associated with the provided event
// or the provided parameter is empty.
void set_evt_thread_user(sinsp_evt& evt, const sinsp_evt_param& euid_param) const;
// Set the event thread group to the group corresponding to the effective group id taken from
// the provided parameter. This is no-op if there is no thread associated with the provided
// event or the provided parameter is empty.
void set_evt_thread_group(sinsp_evt& evt, const sinsp_evt_param& egid_param) const;
static inline bool update_ipv4_addresses_and_ports(sinsp_fdinfo& fdinfo,
uint32_t tsip,
@ -147,7 +151,7 @@ private:
uint16_t tdport,
bool overwrite_dest = true);
static inline void fill_client_socket_info(sinsp_evt& evt,
uint8_t* packed_data,
const uint8_t* packed_data,
bool overwrite_dest,
bool can_resolve_hostname_and_port);
inline void add_socket(sinsp_evt& evt,
@ -183,8 +187,6 @@ private:
bool overwrite_dest = true);
static void swap_addresses(sinsp_fdinfo& fdinfo);
uint8_t* reserve_event_buffer();
void free_event_buffer(uint8_t*);
void erase_fd(erase_fd_params& params, sinsp_parser_verdict& verdict) const;
bool is_syscall_plugin_enabled() const {
@ -228,6 +230,4 @@ private:
scap_platform* const& m_scap_platform;
bool m_track_connection_status = false;
std::stack<uint8_t*> m_tmp_events_buffer;
};

View File

@ -923,8 +923,9 @@ std::string sinsp_plugin::event_to_string(sinsp_evt* evt) const {
}
string ret = "";
auto datalen = evt->get_param(1)->m_len;
auto data = (const uint8_t*)evt->get_param(1)->m_val;
const auto data_param = evt->get_param(1);
const auto data = data_param->data();
const auto data_len = data_param->len();
if(m_state && m_handle->api.event_to_string) {
ss_plugin_event_input input;
input.evt = (const ss_plugin_event*)evt->get_scap_evt();
@ -934,16 +935,16 @@ std::string sinsp_plugin::event_to_string(sinsp_evt* evt) const {
}
if(ret.empty()) {
ret += "datalen=";
ret += std::to_string(datalen);
ret += std::to_string(data_len);
ret += " data=";
for(size_t i = 0; i < std::min(datalen, uint32_t(50)); ++i) {
for(size_t i = 0; i < std::min(data_len, uint32_t(50)); ++i) {
if(!std::isprint(data[i])) {
ret += "<binary>";
return ret;
}
}
ret.append((char*)data, std::min(datalen, uint32_t(50)));
if(datalen > 50) {
ret.append((char*)data, std::min(data_len, uint32_t(50)));
if(data_len > 50) {
ret += "...";
}
}
@ -1181,17 +1182,17 @@ bool sinsp_plugin::set_async_event_handler(async_event_handler_t handler) {
if(cur_handler == nullptr && new_handler != nullptr) {
if(rc != SS_PLUGIN_SUCCESS) {
// new handler rejected, restore current one
delete new_handler;
// new handler rejected, restore current one and clean up
m_async_evt_handler.store(cur_handler);
delete new_handler;
}
}
if(cur_handler != nullptr && new_handler == nullptr) {
if(rc == SS_PLUGIN_SUCCESS) {
// new handler accepted, delete current one
delete cur_handler;
m_async_evt_handler.store(new_handler);
delete cur_handler;
}
}

View File

@ -134,6 +134,9 @@ int32_t on_new_entry_from_proc(void* context,
scap_fdinfo* fdinfo,
scap_threadinfo** new_tinfo);
void on_proc_table_refresh_start(void* context);
void on_proc_table_refresh_end(void* context);
///////////////////////////////////////////////////////////////////////////////
// sinsp implementation
///////////////////////////////////////////////////////////////////////////////
@ -559,7 +562,10 @@ void sinsp::open_kmod(unsigned long driver_buffer_bytes_dim,
params.buffer_bytes_dim = driver_buffer_bytes_dim;
oargs.engine_params = &params;
scap_platform* platform = scap_linux_alloc_platform(::on_new_entry_from_proc, this);
scap_platform* platform = scap_linux_alloc_platform({::on_proc_table_refresh_start,
::on_proc_table_refresh_end,
::on_new_entry_from_proc,
this});
if(platform) {
auto linux_plat = (scap_linux_platform*)platform;
linux_plat->m_linux_vtable = &scap_kmod_linux_vtable;
@ -578,7 +584,8 @@ void sinsp::open_bpf(const std::string& bpf_path,
/* Validate the BPF path. */
if(bpf_path.empty()) {
throw sinsp_exception(
"When you use the 'BPF' engine you need to provide a path to the bpf object file.");
"When you use the 'BPF' engine you need to provide a path to the bpf object "
"file.");
}
scap_open_args oargs{};
@ -592,7 +599,10 @@ void sinsp::open_bpf(const std::string& bpf_path,
params.bpf_probe = bpf_path.data();
oargs.engine_params = &params;
scap_platform* platform = scap_linux_alloc_platform(::on_new_entry_from_proc, this);
scap_platform* platform = scap_linux_alloc_platform({::on_proc_table_refresh_start,
::on_proc_table_refresh_end,
::on_new_entry_from_proc,
this});
open_common(&oargs, &scap_bpf_engine, platform, SINSP_MODE_LIVE);
#else
throw sinsp_exception("BPF engine is not supported in this build");
@ -602,7 +612,10 @@ void sinsp::open_bpf(const std::string& bpf_path,
void sinsp::open_nodriver(bool full_proc_scan) {
#ifdef HAS_ENGINE_NODRIVER
scap_open_args oargs{};
scap_platform* platform = scap_linux_alloc_platform(::on_new_entry_from_proc, this);
scap_platform* platform = scap_linux_alloc_platform({::on_proc_table_refresh_start,
::on_proc_table_refresh_end,
::on_new_entry_from_proc,
this});
if(platform) {
if(!full_proc_scan) {
auto linux_plat = (scap_linux_platform*)platform;
@ -610,7 +623,10 @@ void sinsp::open_nodriver(bool full_proc_scan) {
linux_plat->m_minimal_scan = true;
}
} else {
platform = scap_generic_alloc_platform(::on_new_entry_from_proc, this);
platform = scap_generic_alloc_platform({::on_proc_table_refresh_start,
::on_proc_table_refresh_end,
::on_new_entry_from_proc,
this});
}
open_common(&oargs, &scap_nodriver_engine, platform, SINSP_MODE_NODRIVER);
@ -635,7 +651,8 @@ void sinsp::open_savefile(const std::string& filename, int fd) {
} else {
if(filename.empty()) {
throw sinsp_exception(
"When you use the 'savefile' engine you need to provide a path to the file.");
"When you use the 'savefile' engine you need to provide a path to the "
"file.");
}
params.fname = filename.c_str();
@ -652,7 +669,11 @@ void sinsp::open_savefile(const std::string& filename, int fd) {
params.fbuffer_size = 0;
oargs.engine_params = &params;
scap_platform* platform = scap_savefile_alloc_platform(::on_new_entry_from_proc, this);
scap_platform* platform = scap_savefile_alloc_platform({::on_proc_table_refresh_start,
::on_proc_table_refresh_end,
::on_new_entry_from_proc,
this});
;
params.platform = platform;
open_common(&oargs, &scap_savefile_engine, platform, SINSP_MODE_CAPTURE);
#else
@ -676,7 +697,11 @@ void sinsp::open_plugin(const std::string& plugin_name,
switch(platform_type) {
case sinsp_plugin_platform::SINSP_PLATFORM_GENERIC:
mode = SINSP_MODE_PLUGIN;
platform = scap_generic_alloc_platform(::on_new_entry_from_proc, this);
platform = scap_generic_alloc_platform({::on_proc_table_refresh_start,
::on_proc_table_refresh_end,
::on_new_entry_from_proc,
this});
;
break;
case sinsp_plugin_platform::SINSP_PLATFORM_HOSTINFO:
mode = SINSP_MODE_PLUGIN;
@ -684,7 +709,10 @@ void sinsp::open_plugin(const std::string& plugin_name,
break;
case sinsp_plugin_platform::SINSP_PLATFORM_FULL:
mode = SINSP_MODE_LIVE;
platform = scap_linux_alloc_platform(::on_new_entry_from_proc, this);
platform = scap_linux_alloc_platform({::on_proc_table_refresh_start,
::on_proc_table_refresh_end,
::on_new_entry_from_proc,
this});
break;
default:
throw sinsp_exception("Unsupported mode for SOURCE_PLUGIN engine");
@ -702,7 +730,8 @@ void sinsp::open_gvisor(const std::string& config_path,
#ifdef HAS_ENGINE_GVISOR
if(config_path.empty()) {
throw sinsp_exception(
"When you use the 'gvisor' engine you need to provide a path to the config file.");
"When you use the 'gvisor' engine you need to provide a path to the config "
"file.");
}
scap_open_args oargs{};
@ -712,7 +741,11 @@ void sinsp::open_gvisor(const std::string& config_path,
params.no_events = no_events;
params.gvisor_epoll_timeout = epoll_timeout;
scap_platform* platform = scap_gvisor_alloc_platform(::on_new_entry_from_proc, this);
scap_platform* platform = scap_gvisor_alloc_platform({::on_proc_table_refresh_start,
::on_proc_table_refresh_end,
::on_new_entry_from_proc,
this});
;
params.gvisor_platform = reinterpret_cast<scap_gvisor_platform*>(platform);
oargs.engine_params = &params;
@ -742,7 +775,10 @@ void sinsp::open_modern_bpf(unsigned long driver_buffer_bytes_dim,
params.allocate_online_only = online_only;
oargs.engine_params = &params;
scap_platform* platform = scap_linux_alloc_platform(::on_new_entry_from_proc, this);
scap_platform* platform = scap_linux_alloc_platform({::on_proc_table_refresh_start,
::on_proc_table_refresh_end,
::on_new_entry_from_proc,
this});
open_common(&oargs, &scap_modern_bpf_engine, platform, SINSP_MODE_LIVE);
#else
throw sinsp_exception("MODERN_BPF engine is not supported in this build");
@ -759,10 +795,16 @@ void sinsp::open_test_input(scap_test_input_data* data, sinsp_mode_t mode) {
scap_platform* platform;
switch(mode) {
case SINSP_MODE_TEST:
platform = scap_test_input_alloc_platform(::on_new_entry_from_proc, this);
platform = scap_test_input_alloc_platform({default_refresh_start_end_callback,
default_refresh_start_end_callback,
::on_new_entry_from_proc,
this});
break;
case SINSP_MODE_LIVE:
platform = scap_linux_alloc_platform(::on_new_entry_from_proc, this);
platform = scap_linux_alloc_platform({default_refresh_start_end_callback,
default_refresh_start_end_callback,
::on_new_entry_from_proc,
this});
break;
default:
throw sinsp_exception("Unsupported mode for TEST_INPUT engine");
@ -937,7 +979,7 @@ void sinsp::on_new_entry_from_proc(void* context,
}
}
if(tinfo && m_suppress.check_suppressed_comm(tid, tinfo->comm)) {
if(tinfo && m_suppress.check_suppressed_comm(tid, tinfo->ptid, tinfo->comm)) {
return;
}
@ -1088,6 +1130,14 @@ void sinsp::on_new_entry_from_proc(void* context,
}
}
void sinsp::on_proc_table_refresh_start() {
m_suppress.initialize();
}
void sinsp::on_proc_table_refresh_end() {
m_suppress.finalize();
}
int32_t on_new_entry_from_proc(void* context,
char* error,
int64_t tid,
@ -1104,6 +1154,14 @@ int32_t on_new_entry_from_proc(void* context,
return SCAP_SUCCESS;
}
void on_proc_table_refresh_start(void* context) {
static_cast<sinsp*>(context)->on_proc_table_refresh_start();
}
void on_proc_table_refresh_end(void* context) {
static_cast<sinsp*>(context)->on_proc_table_refresh_end();
}
void sinsp::import_ifaddr_list() {
m_network_interfaces.clear();
m_network_interfaces.import_interfaces(scap_get_ifaddr_list(get_scap_platform()));

View File

@ -670,6 +670,8 @@ public:
//
void stop_dropping_mode();
void start_dropping_mode(uint32_t sampling_ratio);
void on_proc_table_refresh_start();
void on_proc_table_refresh_end();
void on_new_entry_from_proc(void* context,
int64_t tid,
scap_threadinfo* tinfo,

View File

@ -117,15 +117,8 @@ int main(int argc, char** argv) {
// Print all interesting events
uint16_t evt_type = ev->get_type();
switch(evt_type) {
case PPME_SYSCALL_CLONE_11_X:
case PPME_SYSCALL_CLONE_16_X:
case PPME_SYSCALL_CLONE_17_X:
case PPME_SYSCALL_CLONE_20_X:
case PPME_SYSCALL_FORK_X:
case PPME_SYSCALL_FORK_17_X:
case PPME_SYSCALL_FORK_20_X:
case PPME_SYSCALL_VFORK_X:
case PPME_SYSCALL_VFORK_17_X:
case PPME_SYSCALL_VFORK_20_X:
case PPME_SYSCALL_CLONE3_X: {
int64_t child_tid = ev->get_syscall_return_value();
@ -139,13 +132,6 @@ int main(int argc, char** argv) {
display_thread_lineage(tinfo);
} break;
case PPME_SYSCALL_EXECVE_8_X:
case PPME_SYSCALL_EXECVE_13_X:
case PPME_SYSCALL_EXECVE_14_X:
case PPME_SYSCALL_EXECVE_15_X:
case PPME_SYSCALL_EXECVE_16_X:
case PPME_SYSCALL_EXECVE_17_X:
case PPME_SYSCALL_EXECVE_18_X:
case PPME_SYSCALL_EXECVE_19_X:
case PPME_SYSCALL_EXECVEAT_X:
printf("🟢 EXECVE EXIT: evt_num(%ld)\n", ev->get_num());

View File

@ -658,17 +658,19 @@ void sinsp_filter_check_event::validate_filter_value(const char* str, uint32_t l
uint8_t* sinsp_filter_check_event::extract_argraw(sinsp_evt* evt,
uint32_t* len,
const char* argname) {
auto pi = evt->get_param_by_name(argname);
if(pi != NULL) {
m_arginfo = pi->get_info();
m_customfield.m_type = m_arginfo->type;
m_customfield.m_print_format = m_arginfo->fmt;
*len = pi->m_len;
return (uint8_t*)pi->m_val;
} else {
return NULL;
const auto pi = evt->get_param_by_name(argname);
if(pi == nullptr) {
return nullptr;
}
m_arginfo = pi->get_info();
m_customfield.m_type = m_arginfo->type;
m_customfield.m_print_format = m_arginfo->fmt;
const auto [data, data_len] = pi->data_and_len_with_legacy_null_encoding();
*len = data_len;
// TODO(ekoops): remove const_cast once we update the signature to return a pointer to a
// constant buffer.
return const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(data));
}
uint8_t* sinsp_filter_check_event::extract_abspath(sinsp_evt* evt, uint32_t* len) {
@ -714,7 +716,7 @@ uint8_t* sinsp_filter_check_event::extract_abspath(sinsp_evt* evt, uint32_t* len
RETURN_EXTRACT_STRING(m_strstorage);
}
} else if(etype == PPME_SYSCALL_LINKAT_E || etype == PPME_SYSCALL_LINKAT_2_X) {
} else if(etype == PPME_SYSCALL_LINKAT_2_X) {
if(m_argid == 0 || m_argid == 1) {
dirfdarg = "olddir";
patharg = "oldpath";
@ -722,7 +724,7 @@ uint8_t* sinsp_filter_check_event::extract_abspath(sinsp_evt* evt, uint32_t* len
dirfdarg = "newdir";
patharg = "newpath";
}
} else if(etype == PPME_SYSCALL_UNLINKAT_E || etype == PPME_SYSCALL_UNLINKAT_2_X) {
} else if(etype == PPME_SYSCALL_UNLINKAT_2_X) {
dirfdarg = "dirfd";
patharg = "name";
} else if(etype == PPME_SYSCALL_MKDIRAT_X) {
@ -756,9 +758,15 @@ uint8_t* sinsp_filter_check_event::extract_abspath(sinsp_evt* evt, uint32_t* len
return 0;
}
int64_t dirfd = evt->get_param(dirfdargidx)->as<int64_t>();
// Make sure that the parameters are not empty.
const auto dirfd_param = evt->get_param(dirfdargidx);
const auto path_param = evt->get_param(pathargidx);
if(dirfd_param->empty() || path_param->empty()) {
return 0;
}
std::string_view path = evt->get_param(pathargidx)->as<std::string_view>();
const auto dirfd = dirfd_param->as<int64_t>();
const auto path = path_param->as<std::string_view>();
string sdir;
@ -1019,7 +1027,7 @@ uint8_t* sinsp_filter_check_event::extract_single(sinsp_evt* evt,
RETURN_EXTRACT_CSTR("<");
}
case TYPE_TYPE: {
uint8_t* evname;
char* evname;
uint16_t etype = evt->get_scap_evt()->type;
if(etype == PPME_GENERIC_E || etype == PPME_GENERIC_X) {
@ -1036,15 +1044,19 @@ uint8_t* sinsp_filter_check_event::extract_single(sinsp_evt* evt,
uint16_t nativeid = evt->get_param(1)->as<uint16_t>();
ppm_sc = scap_native_id_to_ppm_sc(nativeid);
}
evname = (uint8_t*)scap_get_ppm_sc_name((ppm_sc_code)ppm_sc);
evname = (char*)scap_get_ppm_sc_name((ppm_sc_code)ppm_sc);
} else {
// note: for async events, the event name is encoded
// inside the event itself. In this case libsinsp's evt.type
// field acts as an alias of evt.asynctype.
// TODO(ekoops): remove the following const_casts once the method signature is updated
// to return a pointer to a const buffer.
if(etype == PPME_ASYNCEVENT_E) {
evname = (uint8_t*)evt->get_param(1)->m_val;
const auto name_param = evt->get_param(1);
const auto [data, _] = name_param->data_and_len_with_legacy_null_encoding();
evname = const_cast<char*>(data);
} else {
evname = (uint8_t*)evt->get_name();
evname = const_cast<char*>(evt->get_name());
}
}
@ -1692,7 +1704,7 @@ bool sinsp_filter_check_event::compare_nocache(sinsp_evt* evt) {
// class does not support multi-valued extraction
uint8_t* extracted_val = extract_single(evt, &len, sanitize_strings);
if(extracted_val == NULL) {
if(extracted_val == NULL || len == 0) {
return false;
}

View File

@ -107,7 +107,7 @@ uint8_t *sinsp_filter_check_fdlist::extract_single(sinsp_evt *evt,
}
uint32_t j = 0;
const char *payload = parinfo->m_val;
const char *payload = parinfo->data();
uint16_t nfds = *(uint16_t *)payload;
uint32_t pos = 2;
sinsp_threadinfo *tinfo = evt->get_thread_info();

View File

@ -153,23 +153,15 @@ void sinsp_filter_check_fspath::create_fspath_checks() {
std::shared_ptr<sinsp_filter_check> evt_arg_dev = create_event_check("evt.rawarg.dev");
std::shared_ptr<sinsp_filter_check> evt_arg_dir = create_event_check("evt.rawarg.dir");
m_success_checks->emplace(PPME_SYSCALL_MKDIR_X, evt_arg_res_eq_0);
m_path_checks->emplace(PPME_SYSCALL_MKDIR_2_X, evt_arg_path);
m_success_checks->emplace(PPME_SYSCALL_MKDIR_2_X, evt_arg_res_eq_0);
m_path_checks->emplace(PPME_SYSCALL_MKDIRAT_X, evt_arg_path);
m_success_checks->emplace(PPME_SYSCALL_MKDIRAT_X, evt_arg_res_eq_0);
m_success_checks->emplace(PPME_SYSCALL_RMDIR_X, evt_arg_res_eq_0);
m_path_checks->emplace(PPME_SYSCALL_RMDIR_2_X, evt_arg_path);
m_success_checks->emplace(PPME_SYSCALL_RMDIR_2_X, evt_arg_res_eq_0);
m_success_checks->emplace(PPME_SYSCALL_UNLINK_X, evt_arg_res_eq_0);
m_success_checks->emplace(PPME_SYSCALL_UNLINKAT_X, evt_arg_res_eq_0);
m_path_checks->emplace(PPME_SYSCALL_UNLINK_2_X, evt_arg_path);
m_success_checks->emplace(PPME_SYSCALL_UNLINK_2_X, evt_arg_res_eq_0);
@ -223,10 +215,6 @@ void sinsp_filter_check_fspath::create_fspath_checks() {
m_target_checks->emplace(PPME_SYSCALL_RENAMEAT2_X, evt_arg_newpath);
m_success_checks->emplace(PPME_SYSCALL_RENAMEAT2_X, evt_arg_res_eq_0);
m_success_checks->emplace(PPME_SYSCALL_LINK_X, evt_arg_res_eq_0);
m_success_checks->emplace(PPME_SYSCALL_LINKAT_X, evt_arg_res_eq_0);
m_source_checks->emplace(PPME_SYSCALL_LINK_2_X, evt_arg_newpath);
m_target_checks->emplace(PPME_SYSCALL_LINK_2_X, evt_arg_oldpath);
m_success_checks->emplace(PPME_SYSCALL_LINK_2_X, evt_arg_res_eq_0);
@ -319,16 +307,6 @@ uint8_t* sinsp_filter_check_fspath::extract_single(sinsp_evt* evt,
// For some event types we need to get the values from the enter event instead.
switch(evt->get_type()) {
case PPME_SYSCALL_MKDIR_X:
case PPME_SYSCALL_RMDIR_X:
case PPME_SYSCALL_UNLINK_X:
enter_param = evt->get_enter_evt_param("path");
if(!enter_param.has_value()) {
return NULL;
}
m_tstr = enter_param.value();
break;
case PPME_SYSCALL_UNLINKAT_X:
case PPME_SYSCALL_OPENAT_X:
enter_param = evt->get_enter_evt_param("name");
if(!enter_param.has_value()) {
@ -347,44 +325,21 @@ uint8_t* sinsp_filter_check_fspath::extract_single(sinsp_evt* evt,
break;
case TYPE_SOURCE:
case TYPE_SOURCERAW:
// For some event types we need to get the values from the enter event instead.
switch(evt->get_type()) {
case PPME_SYSCALL_LINK_X:
case PPME_SYSCALL_LINKAT_X:
enter_param = evt->get_enter_evt_param("newpath");
if(!enter_param.has_value()) {
return NULL;
}
m_tstr = enter_param.value();
break;
default:
if(!extract_fspath(evt, extract_values, m_source_checks)) {
return NULL;
}
m_tstr.assign((const char*)extract_values[0].ptr,
strnlen((const char*)extract_values[0].ptr, extract_values[0].len));
};
// Extract from the exit event.
if(!extract_fspath(evt, extract_values, m_source_checks)) {
return NULL;
}
m_tstr.assign((const char*)extract_values[0].ptr,
strnlen((const char*)extract_values[0].ptr, extract_values[0].len));
break;
case TYPE_TARGET:
case TYPE_TARGETRAW:
// For some event types we need to get the values from the enter event instead.
switch(evt->get_type()) {
case PPME_SYSCALL_LINK_X:
case PPME_SYSCALL_LINKAT_X:
enter_param = evt->get_enter_evt_param("oldpath");
if(!enter_param.has_value()) {
return NULL;
}
m_tstr = enter_param.value();
break;
default:
if(!extract_fspath(evt, extract_values, m_target_checks)) {
return NULL;
}
m_tstr.assign((const char*)extract_values[0].ptr,
strnlen((const char*)extract_values[0].ptr, extract_values[0].len));
};
// Extract from the exit event.
if(!extract_fspath(evt, extract_values, m_target_checks)) {
return NULL;
}
m_tstr.assign((const char*)extract_values[0].ptr,
strnlen((const char*)extract_values[0].ptr, extract_values[0].len));
break;
default:
return NULL;

View File

@ -276,14 +276,18 @@ uint8_t* sinsp_filter_check_gen_event::extract_single(sinsp_evt* evt,
m_val.u32 = 0;
}
RETURN_EXTRACT_VAR(m_val.u32);
case TYPE_ASYNCTYPE:
case TYPE_ASYNCTYPE: {
if(!libsinsp::events::is_metaevent((ppm_event_code)evt->get_type())) {
return NULL;
}
if(evt->get_type() == PPME_ASYNCEVENT_E) {
RETURN_EXTRACT_CSTR(evt->get_param(1)->m_val);
if(evt->get_type() != PPME_ASYNCEVENT_E) {
RETURN_EXTRACT_CSTR(evt->get_name());
}
RETURN_EXTRACT_CSTR(evt->get_name());
const auto name_param = evt->get_param(1);
const auto [data, _] = name_param->data_and_len_with_legacy_null_encoding();
RETURN_EXTRACT_CSTR(data);
}
case TYPE_HOSTNAME:
minfo = m_inspector->get_machine_info();
if(!minfo) {

View File

@ -99,9 +99,9 @@ uint8_t* sinsp_filter_check_user::extract_single(sinsp_evt* evt,
if(m_field_id == TYPE_NAME &&
(evt->get_type() == PPME_CONTAINER_JSON_E || evt->get_type() == PPME_CONTAINER_JSON_2_E ||
is_container_asyncevent)) {
auto user = tinfo->get_container_user();
if(!user.empty()) {
RETURN_EXTRACT_STRING(user);
m_strval = tinfo->get_container_user();
if(!m_strval.empty()) {
RETURN_EXTRACT_STRING(m_strval);
}
}

View File

@ -20,6 +20,7 @@ limitations under the License.
#include <libsinsp/sinsp_suppress.h>
#include <libsinsp/sinsp_exception.h>
#include <libsinsp/logger.h>
#include <driver/ppm_events_public.h>
#include <libscap/scap_const.h>
#include <libscap/scap_assert.h>
@ -40,7 +41,11 @@ void libsinsp::sinsp_suppress::clear_suppress_tid() {
m_suppressed_tids.clear();
}
bool libsinsp::sinsp_suppress::check_suppressed_comm(uint64_t tid, const std::string &comm) {
bool libsinsp::sinsp_suppress::check_suppressed_comm(uint64_t tid,
uint64_t parent_tid,
const std::string &comm) {
handle_thread(tid, parent_tid, comm);
if(m_suppressed_comms.find(comm) != m_suppressed_comms.end()) {
m_suppressed_tids.insert(tid);
m_num_suppressed_events++;
@ -111,7 +116,7 @@ int32_t libsinsp::sinsp_suppress::process_event(scap_evt *e) {
return SCAP_FILTERED_EVENT;
}
if(check_suppressed_comm(tid, comm)) {
if(check_suppressed_comm(tid, ptid, comm)) {
return SCAP_FILTERED_EVENT;
}
@ -145,3 +150,49 @@ bool libsinsp::sinsp_suppress::is_suppressed_tid(uint64_t tid) const {
}
return m_suppressed_tids.find(tid) != m_suppressed_tids.end();
}
void libsinsp::sinsp_suppress::initialize() {
// Defensive check — we expect m_tids_tree to be a nullptr
if(m_tids_tree == nullptr) {
m_tids_tree = std::make_unique<std::map<uint64_t, tid_tree_node>>();
} else {
m_tids_tree->clear();
}
}
void libsinsp::sinsp_suppress::handle_thread(uint64_t tid,
uint64_t parent_tid,
const std::string &comm) {
if(tid == 0) {
return;
}
// Defensive check — this shouldn't happen under normal conditions.
if(m_tids_tree == nullptr) {
return;
}
// Add the comm to tid
(*m_tids_tree)[tid].m_comm = comm;
(*m_tids_tree)[tid].m_tid = tid;
// Add child to parent
(*m_tids_tree)[parent_tid].m_children.push_back(tid);
}
void libsinsp::sinsp_suppress::finalize() {
// We generate the suppressed tids from the tid tree.
// The tree is built during the /proc scan, so we can
// use it to find all the children of a given tid.
for(auto it = m_tids_tree->begin(); it != m_tids_tree->end(); it++) {
auto &[_, node] = *it;
if(is_suppressed_tid(node.m_tid)) {
for(auto child_tid : node.m_children) {
suppress_tid(child_tid);
}
}
}
// delete the map. We don't need it anymore.
m_tids_tree.reset(nullptr);
}

View File

@ -19,8 +19,11 @@ limitations under the License.
#pragma once
#include <cstdint>
#include <map>
#include <memory>
#include <string>
#include <unordered_set>
#include <vector>
typedef struct ppm_evt_hdr scap_evt;
@ -38,7 +41,7 @@ public:
void clear_suppress_tid();
bool check_suppressed_comm(uint64_t tid, const std::string& comm);
bool check_suppressed_comm(uint64_t tid, uint64_t parent_tid, const std::string& comm);
int32_t process_event(scap_evt* e);
@ -48,11 +51,28 @@ public:
uint64_t get_num_suppressed_tids() const { return m_suppressed_tids.size(); }
void initialize();
void finalize();
protected:
std::unordered_set<std::string> m_suppressed_comms;
std::unordered_set<uint64_t> m_suppressed_tids;
uint64_t m_num_suppressed_events = 0;
private:
struct tid_tree_node {
uint64_t m_tid;
std::string m_comm;
std::vector<uint64_t> m_children;
};
void handle_thread(uint64_t tid, uint64_t parent_tid, const std::string& comm);
// tree representation of /proc filesystem. Used to generate the suppressed tids
// when the proc scan is performed.
std::unique_ptr<std::map<uint64_t, tid_tree_node>> m_tids_tree;
};
} // namespace libsinsp

View File

@ -78,6 +78,7 @@ set(LIBSINSP_UNIT_TESTS_SOURCES
ast_exprs.ut.cpp
test_utils.cpp
sinsp_with_test_input.cpp
filter_eval_test.cpp
events_evt.ut.cpp
events_file.ut.cpp
events_fspath.ut.cpp
@ -108,6 +109,7 @@ set(LIBSINSP_UNIT_TESTS_SOURCES
filter_transformer.ut.cpp
user.ut.cpp
sinsp_utils.ut.cpp
sinsp_suppress.ut.cpp
state.ut.cpp
suppress.ut.cpp
dns_manager.ut.cpp

View File

@ -190,7 +190,7 @@ protected:
void test_enter(ppm_event_code event_type, uint32_t n, ...) {
va_list args;
va_start(args, n);
sinsp_evt *evt = add_event_advance_ts_v(increasing_ts(), 1, event_type, n, args);
sinsp_evt *evt = add_event_advance_ts_v(increasing_ts(), 1, event_type, nullptr, n, args);
va_end(args);
verify_no_fields(evt);
@ -231,7 +231,7 @@ protected:
break;
}
evt = add_event_advance_ts_v(increasing_ts(), 1, event_type, n, args);
evt = add_event_advance_ts_v(increasing_ts(), 1, event_type, nullptr, n, args);
va_end(args);
verify_fields(event_type, evt, expected_name, expected_name_raw, NULL, NULL, NULL, NULL);
@ -270,7 +270,7 @@ protected:
default:
break;
}
evt = add_event_advance_ts_v(increasing_ts(), 1, event_type, n, args);
evt = add_event_advance_ts_v(increasing_ts(), 1, event_type, nullptr, n, args);
va_end(args);
verify_fields(event_type,
@ -286,7 +286,7 @@ protected:
void test_failed_exit(ppm_event_code event_type, uint32_t n, ...) {
va_list args;
va_start(args, n);
sinsp_evt *evt = add_event_advance_ts_v(increasing_ts(), 1, event_type, n, args);
sinsp_evt *evt = add_event_advance_ts_v(increasing_ts(), 1, event_type, nullptr, n, args);
va_end(args);
verify_no_fields(evt);
@ -305,30 +305,12 @@ TEST_F(fspath, mkdirat) {
test_failed_exit(PPME_SYSCALL_MKDIRAT_X, 4, failed_res, evt_dirfd, path, mode);
}
TEST_F(fspath, rmdir) {
test_enter(PPME_SYSCALL_RMDIR_E, 1, path);
test_exit_path(path, path, PPME_SYSCALL_RMDIR_X, 1, res);
test_failed_exit(PPME_SYSCALL_RMDIR_X, 1, failed_res);
}
TEST_F(fspath, rmdir_2) {
test_enter(PPME_SYSCALL_RMDIR_2_E, 0);
test_exit_path(path, path, PPME_SYSCALL_RMDIR_2_X, 2, res, path);
test_failed_exit(PPME_SYSCALL_RMDIR_2_X, 2, failed_res, path);
}
TEST_F(fspath, unlink) {
test_enter(PPME_SYSCALL_UNLINK_E, 1, path);
test_exit_path(path, path, PPME_SYSCALL_UNLINK_X, 1, res);
test_failed_exit(PPME_SYSCALL_UNLINK_X, 1, failed_res);
}
TEST_F(fspath, unlinkat) {
test_enter(PPME_SYSCALL_UNLINKAT_E, 2, evt_dirfd, name);
test_exit_path(resolved_name, name, PPME_SYSCALL_UNLINKAT_X, 1, res);
test_failed_exit(PPME_SYSCALL_UNLINKAT_X, 1, failed_res);
}
TEST_F(fspath, unlink_2) {
test_enter(PPME_SYSCALL_UNLINK_2_E, 0);
test_exit_path(path, path, PPME_SYSCALL_UNLINK_2_X, 2, res, path);
@ -366,7 +348,7 @@ TEST_F(fspath, open) {
TEST_F(fspath, openat) {
test_enter(PPME_SYSCALL_OPENAT_E, 4, evt_dirfd, name, open_flags, mode);
test_exit_path(resolved_name, name, PPME_SYSCALL_OPENAT_X, 1, fd);
test_failed_exit(PPME_SYSCALL_OPENAT_X, 6, failed_res);
test_failed_exit(PPME_SYSCALL_OPENAT_X, 1, failed_res);
}
TEST_F(fspath, openat_2) {
@ -752,40 +734,6 @@ TEST_F(fspath, renameat2_relative) {
flags);
}
TEST_F(fspath, link) {
test_enter(PPME_SYSCALL_LINK_E, 2, oldpath, newpath);
test_exit_source_target(newpath, newpath, oldpath, oldpath, PPME_SYSCALL_LINK_X, 1, res);
test_failed_exit(PPME_SYSCALL_LINK_X, 1, failed_res);
}
TEST_F(fspath, link_relative) {
test_enter(PPME_SYSCALL_LINK_E, 2, rel_oldpath, rel_newpath);
test_exit_source_target(resolved_rel_newpath,
rel_newpath,
resolved_rel_oldpath,
rel_oldpath,
PPME_SYSCALL_LINK_X,
1,
res);
}
TEST_F(fspath, linkat) {
test_enter(PPME_SYSCALL_LINKAT_E, 4, olddirfd, oldpath, newdirfd, newpath);
test_exit_source_target(newpath, newpath, oldpath, oldpath, PPME_SYSCALL_LINKAT_X, 1, res);
test_failed_exit(PPME_SYSCALL_LINKAT_X, 1, failed_res);
}
TEST_F(fspath, linkat_relative) {
test_enter(PPME_SYSCALL_LINKAT_E, 4, olddirfd, rel_oldpath, newdirfd, rel_newpath);
test_exit_source_target(resolved_rel_newpath,
rel_newpath,
resolved_rel_oldpath,
rel_oldpath,
PPME_SYSCALL_LINKAT_X,
1,
res);
}
TEST_F(fspath, link_2) {
test_enter(PPME_SYSCALL_LINK_2_E, 0);
test_exit_source_target(newpath,

View File

@ -131,7 +131,7 @@ TEST_F(sinsp_with_test_input, bytebuf_empty_param) {
ASSERT_EQ(get_field_as_string(evt, "evt.arg.data"),
"NULL"); // "NULL" is the string representation output of the empty buffer
ASSERT_TRUE(evt->get_param(1));
ASSERT_EQ(evt->get_param(1)->m_len, 0);
ASSERT_EQ(evt->get_param(1)->len(), 0);
}
/* Assert that empty (`PT_SOCKADDR`, `PT_SOCKTUPLE`, `PT_FDLIST`) params are NOT converted to `<NA>`
@ -152,7 +152,7 @@ TEST_F(sinsp_with_test_input, sockaddr_empty_param) {
sockaddr_param.size = 0;
evt = add_event_advance_ts(increasing_ts(), 1, PPME_SOCKET_CONNECT_E, 2, fd, sockaddr_param);
param = evt->get_param(1);
ASSERT_EQ(param->m_len, 0);
ASSERT_EQ(param->len(), 0);
/* `PPME_SOCKET_CONNECT_X` is a simple event that uses a `PT_SOCKTUPLE` */
scap_const_sized_buffer socktuple_param;
@ -167,7 +167,7 @@ TEST_F(sinsp_with_test_input, sockaddr_empty_param) {
fd,
sockaddr_param);
param = evt->get_param(1);
ASSERT_EQ(param->m_len, 0);
ASSERT_EQ(param->len(), 0);
/* `PPME_SYSCALL_POLL_X` is a simple event that uses a `PT_FDLIST` */
scap_const_sized_buffer fdlist_param;
@ -175,7 +175,7 @@ TEST_F(sinsp_with_test_input, sockaddr_empty_param) {
fdlist_param.size = 0;
evt = add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_POLL_X, 2, res, fdlist_param);
param = evt->get_param(1);
ASSERT_EQ(param->m_len, 0);
ASSERT_EQ(param->len(), 0);
}
TEST_F(sinsp_with_test_input, filename_toctou) {
@ -370,13 +370,14 @@ TEST_F(sinsp_with_test_input, execve_invalid_path_entry) {
add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_EXECVE_19_E, 1, "<NA>");
const std::string filename{"/bin/test-exe"};
scap_const_sized_buffer empty_bytebuf = {nullptr, 0};
evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SYSCALL_EXECVE_19_X,
23,
30,
(int64_t)0,
"/bin/test-exe",
filename.c_str(),
empty_bytebuf,
(uint64_t)1,
(uint64_t)1,
@ -397,7 +398,14 @@ TEST_F(sinsp_with_test_input, execve_invalid_path_entry) {
0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0);
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint32_t)0,
filename.c_str(),
(int64_t)0,
(uint32_t)0);
ASSERT_EQ(get_field_as_string(evt, "proc.name"), "test-exe");
}

View File

@ -62,35 +62,43 @@ TEST_F(sinsp_with_test_input, execveat_empty_path_flag) {
"<NA>",
PPM_EXVAT_AT_EMPTY_PATH);
/* Please note the exit event for an `execveat` is an `execve` if the syscall succeeds. */
scap_const_sized_buffer empty_bytebuf = {nullptr, 0};
evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SYSCALL_EXECVE_19_X,
23,
(int64_t)0,
"<NA>",
empty_bytebuf,
(uint64_t)1,
(uint64_t)1,
(uint64_t)1,
"<NA>",
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
0,
0,
0,
"<NA>",
empty_bytebuf,
empty_bytebuf,
0,
(uint64_t)0,
0,
0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0);
SCAP_EMPTY_PARAMS_SET(empty_params_set, 27);
evt = add_event_advance_ts_with_empty_params(increasing_ts(),
1,
PPME_SYSCALL_EXECVEAT_X,
&empty_params_set,
30,
(int64_t)0,
"<NA>",
empty_bytebuf,
(uint64_t)1,
(uint64_t)1,
(uint64_t)1,
"<NA>",
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
0,
0,
0,
"<NA>",
empty_bytebuf,
empty_bytebuf,
0,
(uint64_t)0,
0,
0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint32_t)0,
nullptr,
(int64_t)0,
(uint32_t)0);
/* The `exepath` should be the file pointed by the `dirfd` since `execveat` is called with
* `AT_EMPTY_PATH` flag.
@ -137,33 +145,42 @@ TEST_F(sinsp_with_test_input, execveat_relative_path) {
/* Please note the exit event for an `execveat` is an `execve` if the syscall succeeds. */
scap_const_sized_buffer empty_bytebuf = {nullptr, 0};
evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SYSCALL_EXECVE_19_X,
23,
(int64_t)0,
"<NA>",
empty_bytebuf,
(uint64_t)1,
(uint64_t)1,
(uint64_t)1,
"<NA>",
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
0,
0,
0,
"<NA>",
empty_bytebuf,
empty_bytebuf,
0,
(uint64_t)0,
0,
0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0);
SCAP_EMPTY_PARAMS_SET(empty_params_set, 27);
evt = add_event_advance_ts_with_empty_params(increasing_ts(),
1,
PPME_SYSCALL_EXECVEAT_X,
&empty_params_set,
30,
(int64_t)0,
"<NA>",
empty_bytebuf,
(uint64_t)1,
(uint64_t)1,
(uint64_t)1,
"<NA>",
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
0,
0,
0,
"<NA>",
empty_bytebuf,
empty_bytebuf,
0,
(uint64_t)0,
0,
0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint32_t)0,
nullptr,
(int64_t)0,
(uint32_t)0);
/* The `exepath` should be the directory pointed by the `dirfd` + the pathname
* specified in the `execveat` enter event.
@ -213,33 +230,42 @@ TEST_F(sinsp_with_test_input, execveat_invalid_path) {
/* Please note the exit event for an `execveat` is an `execve` if the syscall succeeds. */
scap_const_sized_buffer empty_bytebuf = {nullptr, 0};
evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SYSCALL_EXECVE_19_X,
23,
(int64_t)0,
"<NA>",
empty_bytebuf,
(uint64_t)1,
(uint64_t)1,
(uint64_t)1,
"<NA>",
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
0,
0,
0,
"<NA>",
empty_bytebuf,
empty_bytebuf,
0,
(uint64_t)0,
0,
0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0);
SCAP_EMPTY_PARAMS_SET(empty_params_set, 27);
evt = add_event_advance_ts_with_empty_params(increasing_ts(),
1,
PPME_SYSCALL_EXECVEAT_X,
&empty_params_set,
30,
(int64_t)0,
"<NA>",
empty_bytebuf,
(uint64_t)1,
(uint64_t)1,
(uint64_t)1,
"<NA>",
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
0,
0,
0,
"<NA>",
empty_bytebuf,
empty_bytebuf,
0,
(uint64_t)0,
0,
0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint32_t)0,
nullptr,
(int64_t)0,
(uint32_t)0);
/* The `exepath` should be `<NA>`, sinsp should recognize that the `pathname`
* is invalid and should set `<NA>`.
@ -274,35 +300,43 @@ TEST_F(sinsp_with_test_input, execveat_absolute_path) {
"/tmp/file",
(uint32_t)0);
/* Please note the exit event for an `execveat` is an `execve` if the syscall succeeds. */
scap_const_sized_buffer empty_bytebuf = {nullptr, 0};
evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SYSCALL_EXECVE_19_X,
23,
(int64_t)0,
"<NA>",
empty_bytebuf,
(uint64_t)1,
(uint64_t)1,
(uint64_t)1,
"<NA>",
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
0,
0,
0,
"<NA>",
empty_bytebuf,
empty_bytebuf,
0,
(uint64_t)0,
0,
0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0);
SCAP_EMPTY_PARAMS_SET(empty_params_set, 27);
evt = add_event_advance_ts_with_empty_params(increasing_ts(),
1,
PPME_SYSCALL_EXECVEAT_X,
&empty_params_set,
30,
(int64_t)0,
"<NA>",
empty_bytebuf,
(uint64_t)1,
(uint64_t)1,
(uint64_t)1,
"<NA>",
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
0,
0,
0,
"<NA>",
empty_bytebuf,
empty_bytebuf,
0,
(uint64_t)0,
0,
0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint32_t)0,
nullptr,
(int64_t)0,
(uint32_t)0);
/* The `exepath` should be the absolute file path that we passed in the
* `execveat` enter event.
@ -352,33 +386,42 @@ TEST_F(sinsp_with_test_input, execveat_empty_path_flag_s390) {
PPM_EXVAT_AT_EMPTY_PATH);
scap_const_sized_buffer empty_bytebuf = {nullptr, 0};
evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SYSCALL_EXECVEAT_X,
23,
(int64_t)0,
"<NA>",
empty_bytebuf,
(uint64_t)1,
(uint64_t)1,
(uint64_t)1,
"<NA>",
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
0,
0,
0,
"<NA>",
empty_bytebuf,
empty_bytebuf,
0,
(uint64_t)0,
0,
0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0);
SCAP_EMPTY_PARAMS_SET(empty_params_set, 27);
evt = add_event_advance_ts_with_empty_params(increasing_ts(),
1,
PPME_SYSCALL_EXECVEAT_X,
&empty_params_set,
30,
(int64_t)0,
"<NA>",
empty_bytebuf,
(uint64_t)1,
(uint64_t)1,
(uint64_t)1,
"<NA>",
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
0,
0,
0,
"<NA>",
empty_bytebuf,
empty_bytebuf,
0,
(uint64_t)0,
0,
0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint32_t)0,
nullptr,
(int64_t)0,
(uint32_t)0);
/* The `exepath` should be the file pointed by the `dirfd` since `execveat` is called with
* `AT_EMPTY_PATH` flag.
@ -422,33 +465,42 @@ TEST_F(sinsp_with_test_input, execveat_relative_path_s390) {
add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_EXECVEAT_E, 3, dirfd, "file", 0);
scap_const_sized_buffer empty_bytebuf = {nullptr, 0};
evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SYSCALL_EXECVEAT_X,
23,
(int64_t)0,
"<NA>",
empty_bytebuf,
(uint64_t)1,
(uint64_t)1,
(uint64_t)1,
"<NA>",
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
0,
0,
0,
"<NA>",
empty_bytebuf,
empty_bytebuf,
0,
(uint64_t)0,
0,
0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0);
SCAP_EMPTY_PARAMS_SET(empty_params_set, 27);
evt = add_event_advance_ts_with_empty_params(increasing_ts(),
1,
PPME_SYSCALL_EXECVEAT_X,
&empty_params_set,
30,
(int64_t)0,
"<NA>",
empty_bytebuf,
(uint64_t)1,
(uint64_t)1,
(uint64_t)1,
"<NA>",
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
0,
0,
0,
"<NA>",
empty_bytebuf,
empty_bytebuf,
0,
(uint64_t)0,
0,
0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint32_t)0,
nullptr,
(int64_t)0,
(uint32_t)0);
/* The `exepath` should be the directory pointed by the `dirfd` + the pathname
* specified in the `execveat` enter event.
@ -483,33 +535,42 @@ TEST_F(sinsp_with_test_input, execveat_absolute_path_s390) {
0);
scap_const_sized_buffer empty_bytebuf = {nullptr, 0};
evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SYSCALL_EXECVEAT_X,
23,
(int64_t)0,
"<NA>",
empty_bytebuf,
(uint64_t)1,
(uint64_t)1,
(uint64_t)1,
"<NA>",
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
0,
0,
0,
"<NA>",
empty_bytebuf,
empty_bytebuf,
0,
(uint64_t)0,
0,
0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0);
SCAP_EMPTY_PARAMS_SET(empty_params_set, 27);
evt = add_event_advance_ts_with_empty_params(increasing_ts(),
1,
PPME_SYSCALL_EXECVEAT_X,
&empty_params_set,
30,
(int64_t)0,
"<NA>",
empty_bytebuf,
(uint64_t)1,
(uint64_t)1,
(uint64_t)1,
"<NA>",
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
0,
0,
0,
"<NA>",
empty_bytebuf,
empty_bytebuf,
0,
(uint64_t)0,
0,
0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint32_t)0,
nullptr,
(int64_t)0,
(uint32_t)0);
/* The `exepath` should be the absolute file path that we passed in the
* `execveat` enter event.
@ -553,33 +614,42 @@ TEST_F(sinsp_with_test_input, execveat_invalid_path_s390) {
add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_EXECVEAT_E, 3, dirfd, "<NA>", 0);
scap_const_sized_buffer empty_bytebuf = {nullptr, 0};
evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SYSCALL_EXECVEAT_X,
23,
(int64_t)0,
"<NA>",
empty_bytebuf,
(uint64_t)1,
(uint64_t)1,
(uint64_t)1,
"<NA>",
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
0,
0,
0,
"<NA>",
empty_bytebuf,
empty_bytebuf,
0,
(uint64_t)0,
0,
0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0);
SCAP_EMPTY_PARAMS_SET(empty_params_set, 27);
evt = add_event_advance_ts_with_empty_params(increasing_ts(),
1,
PPME_SYSCALL_EXECVEAT_X,
&empty_params_set,
30,
(int64_t)0,
"<NA>",
empty_bytebuf,
(uint64_t)1,
(uint64_t)1,
(uint64_t)1,
"<NA>",
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
0,
0,
0,
"<NA>",
empty_bytebuf,
empty_bytebuf,
0,
(uint64_t)0,
0,
0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint32_t)0,
nullptr,
(int64_t)0,
(uint32_t)0);
/* The `exepath` should be `<NA>`, sinsp should recognize that the `pathname`
* is invalid and should set `<NA>`.
@ -599,7 +669,8 @@ TEST_F(sinsp_with_test_input, spawn_process) {
uint64_t parent_pid = 1, parent_tid = 1, child_pid = 20, child_tid = 20, null_pid = 0;
uint64_t fdlimit = 1024, pgft_maj = 0, pgft_min = 1;
uint64_t exe_ino = 242048, ctime = 1676262698000004588, mtime = 1676262698000004577;
uint32_t loginuid = UINT32_MAX - 1, euid = 2000U;
uint32_t loginuid = UINT32_MAX - 1, euid = 2000U, egid = 2000U;
uint64_t pidns_init_start_ts = 1234;
scap_const_sized_buffer empty_bytebuf = {.buf = nullptr, .size = 0};
@ -631,7 +702,7 @@ TEST_F(sinsp_with_test_input, spawn_process) {
add_event_advance_ts(increasing_ts(),
parent_tid,
PPME_SYSCALL_CLONE_20_X,
20,
21,
child_tid,
"bash",
empty_bytebuf,
@ -651,13 +722,14 @@ TEST_F(sinsp_with_test_input, spawn_process) {
(uint32_t)1000,
(uint32_t)1000,
parent_pid,
parent_tid);
parent_tid,
pidns_init_start_ts);
/* Child clone exit event */
add_event_advance_ts(increasing_ts(),
child_tid,
PPME_SYSCALL_CLONE_20_X,
20,
21,
(uint64_t)0,
"bash",
empty_bytebuf,
@ -677,7 +749,8 @@ TEST_F(sinsp_with_test_input, spawn_process) {
(uint32_t)1000,
(uint32_t)1000,
child_pid,
child_tid);
child_tid,
pidns_init_start_ts);
/* Execve enter event */
add_event_advance_ts(increasing_ts(), child_tid, PPME_SYSCALL_EXECVE_19_E, 1, "/bin/test-exe");
@ -686,7 +759,7 @@ TEST_F(sinsp_with_test_input, spawn_process) {
evt = add_event_advance_ts(increasing_ts(),
child_tid,
PPME_SYSCALL_EXECVE_19_X,
27,
30,
(int64_t)0,
"/bin/test-exe",
scap_const_sized_buffer{argsv.data(), argsv.size()},
@ -713,7 +786,10 @@ TEST_F(sinsp_with_test_input, spawn_process) {
exe_ino,
ctime,
mtime,
euid);
euid,
"/bin/test-exe",
parent_tid,
egid);
// check that the cwd is inherited from the parent (default process has /root/)
ASSERT_EQ(get_field_as_string(evt, "proc.cwd"), "/root/");
@ -877,6 +953,7 @@ TEST_F(sinsp_with_test_input, pid_over_32bit) {
uint64_t child2_vpid = 3, child2_vtid = 3;
uint64_t fdlimit = 1024, pgft_maj = 0, pgft_min = 1;
scap_const_sized_buffer empty_bytebuf = {.buf = nullptr, .size = 0};
uint64_t pidns_init_start_ts = 1234;
add_event_advance_ts(increasing_ts(), parent_tid, PPME_SYSCALL_CLONE_20_E, 0);
std::vector<std::string> cgroups = {"cpuset=/",
@ -903,7 +980,7 @@ TEST_F(sinsp_with_test_input, pid_over_32bit) {
add_event_advance_ts(increasing_ts(),
parent_tid,
PPME_SYSCALL_CLONE_20_X,
20,
21,
child_tid,
"bash",
empty_bytebuf,
@ -923,13 +1000,14 @@ TEST_F(sinsp_with_test_input, pid_over_32bit) {
(uint32_t)1000,
(uint32_t)1000,
parent_pid,
parent_tid);
parent_tid,
pidns_init_start_ts);
/* Child clone exit event */
add_event_advance_ts(increasing_ts(),
child_tid,
PPME_SYSCALL_CLONE_20_X,
20,
21,
(int64_t)0,
"bash",
empty_bytebuf,
@ -949,7 +1027,8 @@ TEST_F(sinsp_with_test_input, pid_over_32bit) {
(uint32_t)1000,
(uint32_t)1000,
child_vpid,
child_vtid);
child_vtid,
pidns_init_start_ts);
/* Execve enter event */
add_event_advance_ts(increasing_ts(), child_tid, PPME_SYSCALL_EXECVE_19_E, 1, "/bin/test-exe");
@ -958,7 +1037,7 @@ TEST_F(sinsp_with_test_input, pid_over_32bit) {
evt = add_event_advance_ts(increasing_ts(),
child_tid,
PPME_SYSCALL_EXECVE_19_X,
20,
30,
(int64_t)0,
"/bin/test-exe",
scap_const_sized_buffer{argsv.data(), argsv.size()},
@ -978,7 +1057,17 @@ TEST_F(sinsp_with_test_input, pid_over_32bit) {
(uint32_t)34818,
parent_pid,
(int32_t)1000,
(uint32_t)1);
(uint32_t)1,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint32_t)0,
"/bin/test-exe",
(int64_t)0,
(uint32_t)0);
ASSERT_FALSE(field_has_value(evt, "proc.pid"));
ASSERT_FALSE(field_has_value(evt, "thread.tid"));
@ -997,7 +1086,7 @@ TEST_F(sinsp_with_test_input, pid_over_32bit) {
add_event_advance_ts(increasing_ts(),
child2_tid,
PPME_SYSCALL_CLONE_20_X,
20,
21,
(int64_t)0,
"/bin/test-exe",
empty_bytebuf,
@ -1017,13 +1106,14 @@ TEST_F(sinsp_with_test_input, pid_over_32bit) {
(uint32_t)1000,
(uint32_t)1000,
child2_vpid,
child2_vtid);
child2_vtid,
pidns_init_start_ts);
/* Parent clone exit event */
add_event_advance_ts(increasing_ts(),
child_tid,
PPME_SYSCALL_CLONE_20_X,
20,
21,
child2_tid,
"/bin/test-exe",
empty_bytebuf,
@ -1043,7 +1133,8 @@ TEST_F(sinsp_with_test_input, pid_over_32bit) {
(uint32_t)1000,
(uint32_t)1000,
child_vpid,
child_vtid);
child_vtid,
pidns_init_start_ts);
/* Execve enter event */
add_event_advance_ts(increasing_ts(),
@ -1056,7 +1147,7 @@ TEST_F(sinsp_with_test_input, pid_over_32bit) {
evt = add_event_advance_ts(increasing_ts(),
child2_tid,
PPME_SYSCALL_EXECVE_19_X,
20,
30,
(int64_t)0,
"/bin/test-exe2",
scap_const_sized_buffer{argsv.data(), argsv.size()},
@ -1076,7 +1167,17 @@ TEST_F(sinsp_with_test_input, pid_over_32bit) {
(uint32_t)34818,
child_pid,
(int32_t)1000,
(uint32_t)1);
(uint32_t)1,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint32_t)0,
"/bin/test-exe2",
(int64_t)0,
(uint32_t)0);
ASSERT_FALSE(field_has_value(evt, "proc.pid"));
ASSERT_FALSE(field_has_value(evt, "thread.tid"));
@ -1106,6 +1207,7 @@ TEST_F(sinsp_with_test_input, last_exec_ts) {
uint64_t child_pid = 0x0000000100000010, child_tid = 0x0000000100000010;
uint64_t child_vpid = 2, child_vtid = 2;
scap_const_sized_buffer empty_bytebuf = {.buf = nullptr, .size = 0};
uint64_t pidns_init_start_ts = 1234;
add_event_advance_ts(increasing_ts(), parent_tid, PPME_SYSCALL_CLONE_20_E, 0);
std::vector<std::string> cgroups = {"cpuset=/",
@ -1130,7 +1232,7 @@ TEST_F(sinsp_with_test_input, last_exec_ts) {
evt = add_event_advance_ts(increasing_ts(),
parent_tid,
PPME_SYSCALL_CLONE_20_X,
20,
21,
child_tid,
"bash",
empty_bytebuf,
@ -1150,7 +1252,8 @@ TEST_F(sinsp_with_test_input, last_exec_ts) {
(uint32_t)1000,
(uint32_t)1000,
parent_pid,
parent_tid);
parent_tid,
pidns_init_start_ts);
ASSERT_TRUE(evt->get_thread_info());
// Check we initialize lastexec time to zero
@ -1159,7 +1262,7 @@ TEST_F(sinsp_with_test_input, last_exec_ts) {
add_event_advance_ts(increasing_ts(),
child_tid,
PPME_SYSCALL_CLONE_20_X,
20,
21,
(uint64_t)0,
"bash",
empty_bytebuf,
@ -1179,12 +1282,13 @@ TEST_F(sinsp_with_test_input, last_exec_ts) {
(uint32_t)1000,
(uint32_t)1000,
child_vpid,
child_vtid);
child_vtid,
pidns_init_start_ts);
add_event_advance_ts(increasing_ts(), child_tid, PPME_SYSCALL_EXECVE_19_E, 1, "/bin/test-exe");
evt = add_event_advance_ts(increasing_ts(),
child_tid,
PPME_SYSCALL_EXECVE_19_X,
20,
30,
(int64_t)0,
"/bin/test-exe",
scap_const_sized_buffer{argsv.data(), argsv.size()},
@ -1204,7 +1308,17 @@ TEST_F(sinsp_with_test_input, last_exec_ts) {
(uint32_t)34818,
parent_pid,
(uint32_t)1000,
(uint32_t)1);
(uint32_t)1,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint64_t)0,
(uint32_t)0,
"/bin/test-exe",
(int64_t)0,
(uint32_t)0);
// Check last exec was recorded
ASSERT_GT(evt->get_thread_info()->m_lastexec_ts, 0);

View File

@ -0,0 +1,60 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2025 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 <filter_eval_test.h>
TEST_P(filter_eval_test, execve_empty_params) {
const auto tc = GetParam();
add_default_init_thread();
open_inspector();
// Use execve event type as it contains a multitude of parameters (specifically, in the range
// 18-29) that can be set to empty by the scap-converter.
const auto evt = generate_execve_exit_event_with_empty_params(1, "/bin/test-exe", "test-exe");
const auto filter_str = tc.filter_str.c_str();
switch(tc.expected_result) {
case filter_eval_test_case::EXPECT_TRUE: {
EXPECT_TRUE(eval_filter(evt, filter_str));
break;
}
case filter_eval_test_case::EXPECT_FALSE: {
EXPECT_FALSE(eval_filter(evt, filter_str));
break;
}
case filter_eval_test_case::EXPECT_THROW: {
EXPECT_ANY_THROW(eval_filter(evt, filter_str));
break;
}
default:
ASSERT(false);
break;
}
}
/* On windows, the previous TEST_P definition would generate a synthetic failing test.
* The correct solution, would be adding GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST here, but
* this macro generates an error for some reason. Just add a dummy test case to fix the issue. */
INSTANTIATE_TEST_CASE_P(dummy,
filter_eval_test,
testing::ValuesIn(std::vector<filter_eval_test_case>{
{"dummy", "proc.pid exists", filter_eval_test_case::EXPECT_TRUE}}),
filter_eval_test::test_case_name_gen);

View File

@ -0,0 +1,63 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2025 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.
*/
#pragma once
#include <sinsp_with_test_input.h>
/*!
\brief Test case for the filter_eval_test fixture.
*/
struct filter_eval_test_case {
enum expected_filter_result : uint8_t { EXPECT_TRUE, EXPECT_FALSE, EXPECT_THROW };
std::string name;
std::string filter_str;
expected_filter_result expected_result;
std::string expected_result_to_string() const {
switch(expected_result) {
case EXPECT_TRUE:
return "true";
case EXPECT_FALSE:
return "false";
case EXPECT_THROW:
return "throw";
default:
ASSERT(false);
throw std::runtime_error("unexpected filter result: " +
std::to_string(expected_result));
}
}
friend std::ostream& operator<<(std::ostream& os, const filter_eval_test_case& tc) {
return os << "(filter=" << tc.filter_str
<< ", expected_result=" << tc.expected_result_to_string() << ")";
}
};
/*!
\brief Fixture allowing to evaluate filters on events and test the outcomes.
*/
class filter_eval_test : public testing::WithParamInterface<filter_eval_test_case>,
public sinsp_with_test_input {
public:
static std::string test_case_name_gen(const testing::TestParamInfo<ParamType>& info) {
return info.param.name;
}
};

View File

@ -131,34 +131,6 @@ TEST_F(sinsp_with_test_input, EVT_FILTER_is_upper_layer) {
ASSERT_EQ(evt->get_fd_info()->is_overlay_upper(), true);
}
TEST_F(sinsp_with_test_input, EVT_FILTER_rawarg_int) {
add_default_init_thread();
open_inspector();
sinsp_evt* evt =
add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_SETUID_E, 1, (uint32_t)1000);
ASSERT_EQ(get_field_as_string(evt, "evt.rawarg.uid"), "1000");
}
TEST_F(sinsp_with_test_input, EVT_FILTER_rawarg_str) {
add_default_init_thread();
open_inspector();
std::string path = "/home/file.txt";
// In the enter event we don't send the `PPM_O_F_CREATED`
sinsp_evt* evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SYSCALL_OPEN_E,
3,
path.c_str(),
(uint32_t)0,
(uint32_t)0);
ASSERT_EQ(get_field_as_string(evt, "evt.rawarg.name"), path);
}
TEST_F(sinsp_with_test_input, EVT_FILTER_cmd_str) {
add_default_init_thread();
@ -212,77 +184,6 @@ TEST_F(sinsp_with_test_input, EVT_FILTER_check_evt_arg_uid) {
ASSERT_EQ(get_field_as_string(evt, "evt.args"), "uid=5(<NA>)");
}
// Test that for rawarg.X we are correctly retrieving the correct field type/format.
TEST_F(sinsp_with_test_input, EVT_FILTER_rawarg_madness) {
add_default_init_thread();
open_inspector();
// [PPME_SYSCALL_EPOLL_CREATE_E] = {"epoll_create", EC_WAIT | EC_SYSCALL, EF_CREATES_FD |
// EF_MODIFIES_STATE, 1, { {"size", PT_INT32, PF_DEC} } },
sinsp_evt* evt =
add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_EPOLL_CREATE_E, 1, (int32_t)-22);
ASSERT_EQ(get_field_as_string(evt, "evt.rawarg.size"), "-22");
ASSERT_TRUE(eval_filter(evt, "evt.rawarg.size < -20"));
// [PPME_SYSCALL_SIGNALFD4_X] = {"signalfd4", EC_SIGNAL | EC_SYSCALL, EF_CREATES_FD |
// EF_MODIFIES_STATE, 2, {{"res", PT_FD, PF_DEC}, {"flags", PT_FLAGS16, PF_HEX, file_flags}}},
evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SYSCALL_SIGNALFD4_X,
4,
(int64_t)-1,
(uint16_t)512,
(int64_t)9,
(uint32_t)0);
// 512 in hex is 200
ASSERT_EQ(get_field_as_string(evt, "evt.rawarg.flags"), "200");
ASSERT_TRUE(eval_filter(evt, "evt.rawarg.flags < 515"));
ASSERT_EQ(get_field_as_string(evt, "evt.rawarg.fd"), "9");
// [PPME_SYSCALL_TIMERFD_CREATE_E] = {"timerfd_create",EC_TIME | EC_SYSCALL,EF_CREATES_FD |
// EF_MODIFIES_STATE,2,{{"clockid", PT_UINT8, PF_DEC},{"flags", PT_UINT8, PF_HEX}}},
evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SYSCALL_TIMERFD_CREATE_E,
2,
(uint8_t)-1,
(uint8_t)255);
// 255 in hex is FF
ASSERT_EQ(get_field_as_string(evt, "evt.rawarg.flags"), "FF");
ASSERT_TRUE(eval_filter(evt, "evt.rawarg.flags <= 255"));
// [PPME_SYSCALL_BRK_4_E] = {"brk", EC_MEMORY | EC_SYSCALL, EF_NONE, 1, {{"addr", PT_UINT64,
// PF_HEX}}}
uint64_t addr = UINT64_MAX;
evt = add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_BRK_4_E, 1, addr);
// UINT64_MAX is FFFFFFFFFFFFFFFF
ASSERT_EQ(get_field_as_string(evt, "evt.rawarg.addr"), "FFFFFFFFFFFFFFFF");
ASSERT_ANY_THROW(eval_filter(evt, "evt.rawarg.addr > 0")); // PT_SOCKADDR is not comparable
/*
* Now test the bugged case where `find_longest_matching_evt_param` returns a size,
* but then real event has a size that is bigger than that.
* In this case, `find_longest_matching_evt_param` will find `size` param
* from PPME_SYSCALL_READ_E, that is {"size", PT_UINT32, PF_DEC},
* but then we call evt.rawarg.size on a PPME_SYSCALL_SPLICE_E,
* whose `size` param is 64bit: {"size", PT_UINT64, PF_DEC}.
*/
// [PPME_SYSCALL_SPLICE_E] = {"splice", EC_IO_OTHER | EC_SYSCALL, EF_USES_FD, 4, {
// {"fd_in", PT_FD, PF_DEC}, {"fd_out", PT_FD, PF_DEC}, {"size", PT_UINT64, PF_DEC}, {
// "flags", PT_FLAGS32, PF_HEX, splice_flags}}}
evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SYSCALL_SPLICE_E,
4,
(int64_t)-1,
(int64_t)-1,
(uint64_t)512,
(uint32_t)0);
// Size is PF_DEC, 512 is 512
ASSERT_EQ(get_field_as_string(evt, "evt.rawarg.size"), "512");
ASSERT_TRUE(eval_filter(evt, "evt.rawarg.size < 515"));
}
TEST_F(sinsp_with_test_input, EVT_FILTER_thread_proc_info) {
DEFAULT_TREE

View File

@ -0,0 +1,95 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2025 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 <helpers/threads_helpers.h>
#include <filter_eval_test.h>
const auto arg_eq_op_test_cases = testing::ValuesIn(std::vector<filter_eval_test_case>{
{"PT_FLAGS_eq_NA",
"evt.arg.flags = <NA>",
filter_eval_test_case::EXPECT_TRUE}, // Should this always return false?
{"PT_UINT64_eq_NA",
"evt.arg.cap_inheritable = <NA>",
filter_eval_test_case::EXPECT_TRUE}, // Should this always return false?
{"PT_ABSTIME_eq_NA",
"evt.arg.exe_ino_ctime = <NA>",
filter_eval_test_case::EXPECT_TRUE}, // Should this always return false?
{"PT_UID_eq_NA",
"evt.arg.uid = <NA>",
filter_eval_test_case::EXPECT_TRUE}, // Should this always return false?
{"PT_FSPATH_eq_NA",
"evt.arg.trusted_exepath = <NA>",
filter_eval_test_case::EXPECT_TRUE}, // Should this always return false?
{"PT_PID_eq_NA",
"evt.arg.pgid = <NA>",
filter_eval_test_case::EXPECT_TRUE}, // Should this always return false?
{"PT_GID_eq_NA",
"evt.arg.gid = <NA>",
filter_eval_test_case::EXPECT_TRUE}, // Should this always return false?
});
const auto arg_tolower_eq_op_test_cases = testing::ValuesIn(std::vector<filter_eval_test_case>{
{"PT_FLAGS_eq_NA",
"tolower(evt.arg.flags) = <na>",
filter_eval_test_case::EXPECT_TRUE}, // Should this always return false?
{"PT_UINT64_eq_NA",
"tolower(evt.arg.cap_inheritable) = <na>",
filter_eval_test_case::EXPECT_TRUE}, // Should this always return false?
{"PT_ABSTIME_eq_NA",
"tolower(evt.arg.exe_ino_ctime) = <na>",
filter_eval_test_case::EXPECT_TRUE}, // Should this always return false?
{"PT_UID_eq_NA",
"tolower(evt.arg.uid) = <na>",
filter_eval_test_case::EXPECT_TRUE}, // Should this always return false?
{"PT_FSPATH_eq_NA",
"tolower(evt.arg.trusted_exepath) = <na>",
filter_eval_test_case::EXPECT_TRUE}, // Should this always return false?
{"PT_PID_eq_NA",
"tolower(evt.arg.pgid) = <na>",
filter_eval_test_case::EXPECT_TRUE}, // Should this always return false?
{"PT_GID_eq_NA",
"tolower(evt.arg.gid) = <na>",
filter_eval_test_case::EXPECT_TRUE}, // Should this always return false?
});
INSTANTIATE_TEST_CASE_P(arg_eq_op,
filter_eval_test,
arg_eq_op_test_cases,
filter_eval_test::test_case_name_gen);
INSTANTIATE_TEST_CASE_P(arg_tolower_eq_op,
filter_eval_test,
arg_tolower_eq_op_test_cases,
filter_eval_test::test_case_name_gen);
TEST_F(sinsp_with_test_input, EVT_FILTER_arg_empty_params) {
add_default_init_thread();
open_inspector();
// Use execve event type as it contains a multitude of parameters (specifically, in the range
// 18-29) that can be set to empty by the scap-converter.
const auto evt = generate_execve_exit_event_with_empty_params(1, "/bin/test-exe", "test-exe");
ASSERT_EQ(get_field_as_string(evt, "evt.arg.flags"), "<NA>"); // PT_FLAGS32
ASSERT_EQ(get_field_as_string(evt, "evt.arg.cap_inheritable"), "<NA>"); // PT_UINT64
ASSERT_EQ(get_field_as_string(evt, "evt.arg.exe_ino_ctime"), "<NA>"); // PT_ABSTIME
ASSERT_EQ(get_field_as_string(evt, "evt.arg.uid"), "<NA>"); // PT_UID
ASSERT_EQ(get_field_as_string(evt, "evt.arg.trusted_exepath"), "<NA>"); // PT_FSPATH
ASSERT_EQ(get_field_as_string(evt, "evt.arg.pgid"), "<NA>"); // PT_PID
ASSERT_EQ(get_field_as_string(evt, "evt.arg.gid"), "<NA>"); // PT_GID
}

View File

@ -0,0 +1,400 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2025 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 <helpers/threads_helpers.h>
#include <filter_eval_test.h>
// Test that for rawarg.X we are correctly retrieving the correct field type/format.
TEST_F(sinsp_with_test_input, EVT_FILTER_rawarg_madness) {
add_default_init_thread();
open_inspector();
// [PPME_SYSCALL_EPOLL_CREATE_E] = {"epoll_create", EC_WAIT | EC_SYSCALL, EF_CREATES_FD |
// EF_MODIFIES_STATE, 1, { {"size", PT_INT32, PF_DEC} } },
sinsp_evt* evt =
add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_EPOLL_CREATE_E, 1, (int32_t)-22);
ASSERT_EQ(get_field_as_string(evt, "evt.rawarg.size"), "-22");
ASSERT_TRUE(eval_filter(evt, "evt.rawarg.size < -20"));
// [PPME_SYSCALL_SIGNALFD4_X] = {"signalfd4", EC_SIGNAL | EC_SYSCALL, EF_CREATES_FD |
// EF_MODIFIES_STATE, 2, {{"res", PT_FD, PF_DEC}, {"flags", PT_FLAGS16, PF_HEX, file_flags}}},
evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SYSCALL_SIGNALFD4_X,
4,
(int64_t)-1,
(uint16_t)512,
(int64_t)9,
(uint32_t)0);
// 512 in hex is 200
ASSERT_EQ(get_field_as_string(evt, "evt.rawarg.flags"), "200");
ASSERT_TRUE(eval_filter(evt, "evt.rawarg.flags < 515"));
ASSERT_EQ(get_field_as_string(evt, "evt.rawarg.fd"), "9");
// [PPME_SYSCALL_TIMERFD_CREATE_E] = {"timerfd_create",EC_TIME | EC_SYSCALL,EF_CREATES_FD |
// EF_MODIFIES_STATE,2,{{"clockid", PT_UINT8, PF_DEC},{"flags", PT_UINT8, PF_HEX}}},
evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SYSCALL_TIMERFD_CREATE_E,
2,
(uint8_t)-1,
(uint8_t)255);
// 255 in hex is FF
ASSERT_EQ(get_field_as_string(evt, "evt.rawarg.flags"), "FF");
ASSERT_TRUE(eval_filter(evt, "evt.rawarg.flags <= 255"));
// [PPME_SYSCALL_BRK_4_E] = {"brk", EC_MEMORY | EC_SYSCALL, EF_NONE, 1, {{"addr", PT_UINT64,
// PF_HEX}}}
uint64_t addr = UINT64_MAX;
evt = add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_BRK_4_E, 1, addr);
// UINT64_MAX is FFFFFFFFFFFFFFFF
ASSERT_EQ(get_field_as_string(evt, "evt.rawarg.addr"), "FFFFFFFFFFFFFFFF");
ASSERT_ANY_THROW(eval_filter(evt, "evt.rawarg.addr > 0")); // PT_SOCKADDR is not comparable
/*
* Now test the bugged case where `find_longest_matching_evt_param` returns a size,
* but then real event has a size that is bigger than that.
* In this case, `find_longest_matching_evt_param` will find `size` param
* from PPME_SYSCALL_READ_E, that is {"size", PT_UINT32, PF_DEC},
* but then we call evt.rawarg.size on a PPME_SYSCALL_SPLICE_E,
* whose `size` param is 64bit: {"size", PT_UINT64, PF_DEC}.
*/
// [PPME_SYSCALL_SPLICE_E] = {"splice", EC_IO_OTHER | EC_SYSCALL, EF_USES_FD, 4, {
// {"fd_in", PT_FD, PF_DEC}, {"fd_out", PT_FD, PF_DEC}, {"size", PT_UINT64, PF_DEC}, {
// "flags", PT_FLAGS32, PF_HEX, splice_flags}}}
evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SYSCALL_SPLICE_E,
4,
(int64_t)-1,
(int64_t)-1,
(uint64_t)512,
(uint32_t)0);
// Size is PF_DEC, 512 is 512
ASSERT_EQ(get_field_as_string(evt, "evt.rawarg.size"), "512");
ASSERT_TRUE(eval_filter(evt, "evt.rawarg.size < 515"));
evt = generate_execve_exit_event_with_default_params(1, "/bin/test-exe", "test-exe");
ASSERT_TRUE(eval_filter(evt, "evt.rawarg.uid = 0")); // PT_UID
ASSERT_TRUE(eval_filter(evt, "evt.rawarg.pgid = 0")); // PT_PID
ASSERT_TRUE(eval_filter(evt, "evt.rawarg.gid = 0")); // PT_GID
#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && !defined(__APPLE__)
evt = generate_connect_events();
ASSERT_ANY_THROW(eval_filter(evt, "evt.rawarg.addr > 0")); // PT_SOCKADDR is not comparable
ASSERT_ANY_THROW(eval_filter(evt, "evt.rawarg.tuple > 0")); // PT_TUPLE is not comparable
#endif
}
TEST_F(sinsp_with_test_input, EVT_FILTER_rawarg_int) {
add_default_init_thread();
open_inspector();
sinsp_evt* evt =
add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_SETUID_E, 1, (uint32_t)1000);
ASSERT_EQ(get_field_as_string(evt, "evt.rawarg.uid"), "1000");
}
TEST_F(sinsp_with_test_input, EVT_FILTER_rawarg_str) {
add_default_init_thread();
open_inspector();
std::string path = "/home/file.txt";
// In the enter event we don't send the `PPM_O_F_CREATED`
sinsp_evt* evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SYSCALL_OPEN_E,
3,
path.c_str(),
(uint32_t)0,
(uint32_t)0);
ASSERT_EQ(get_field_as_string(evt, "evt.rawarg.name"), path);
}
const auto rawarg_eq_op_test_cases = testing::ValuesIn(std::vector<filter_eval_test_case>{
{"PT_FLAGS_eq_0", "evt.rawarg.flags = 0", filter_eval_test_case::EXPECT_FALSE},
{"PT_UINT64_eq_0", "evt.rawarg.cap_inheritable = 0", filter_eval_test_case::EXPECT_FALSE},
{"PT_ABSTIME_eq_0", "evt.rawarg.exe_ino_ctime = 0", filter_eval_test_case::EXPECT_FALSE},
{"PT_UID_eq_0", "evt.rawarg.uid = 0", filter_eval_test_case::EXPECT_FALSE},
{"PT_FSPATH_eq_NA",
"evt.rawarg.trusted_exepath = <NA>",
filter_eval_test_case::EXPECT_TRUE}, // Should this always return false? Actually,
// trusted_exepath is set to <NA>.
{"PT_PID_eq_0", "evt.rawarg.pgid = 0", filter_eval_test_case::EXPECT_FALSE},
{"PT_GID_eq_0", "evt.rawarg.gid = 0", filter_eval_test_case::EXPECT_FALSE},
});
const auto rawarg_contains_op_test_cases = testing::ValuesIn(std::vector<filter_eval_test_case>{
{"PT_FLAGS_contains_str",
"evt.rawarg.flags contains 'str'",
filter_eval_test_case::EXPECT_THROW},
{"PT_UINT64_contains_str",
"evt.rawarg.cap_inheritable contains 'str'",
filter_eval_test_case::EXPECT_THROW},
{"PT_ABSTIME_contains_str",
"evt.rawarg.exe_ino_ctime contains 'str'",
filter_eval_test_case::EXPECT_THROW},
{"PT_UID_contains_str",
"evt.rawarg.uid contains 'str'",
filter_eval_test_case::EXPECT_THROW},
{"PT_FSPATH_contains_str",
"evt.rawarg.trusted_exepath contains 'str'",
filter_eval_test_case::EXPECT_FALSE}, // Should this always return false?
{"PT_FSPATH_contains_NA",
"evt.rawarg.trusted_exepath contains <NA>",
filter_eval_test_case::EXPECT_TRUE}, // Should this always return false?
{"PT_FSPATH_contains_empty",
"evt.rawarg.trusted_exepath contains ''",
filter_eval_test_case::EXPECT_TRUE}, // Should this always return false?
{"PT_PID_contains_str",
"evt.rawarg.pgid contains 'str'",
filter_eval_test_case::EXPECT_THROW},
{"PT_GID_contains_str",
"evt.rawarg.gid contains 'str'",
filter_eval_test_case::EXPECT_THROW},
});
const auto rawarg_exists_op_test_cases = testing::ValuesIn(std::vector<filter_eval_test_case>{
{"PT_FLAGS_exists", "evt.rawarg.flags exists", filter_eval_test_case::EXPECT_FALSE},
{"PT_UINT64_exists",
"evt.rawarg.cap_inheritable exists",
filter_eval_test_case::EXPECT_FALSE},
{"PT_ABSTIME_exists",
"evt.rawarg.exe_ino_ctime exists",
filter_eval_test_case::EXPECT_FALSE},
{"PT_UID_exists", "evt.rawarg.uid exists", filter_eval_test_case::EXPECT_FALSE},
{"PT_FSPATH_exists",
"evt.rawarg.trusted_exepath exists",
filter_eval_test_case::EXPECT_TRUE}, // Should this always return false? Actually,
// trusted_exepath is set to <NA>, so it exists
{"PT_PID_exists", "evt.rawarg.pgid exists", filter_eval_test_case::EXPECT_FALSE},
{"PT_GID_exists", "evt.rawarg.gid exists", filter_eval_test_case::EXPECT_FALSE},
});
const auto rawarg_glob_op_test_cases = testing::ValuesIn(std::vector<filter_eval_test_case>{
{"PT_FLAGS_glob_path",
"evt.rawarg.flags glob '/path/*'",
filter_eval_test_case::EXPECT_THROW},
{"PT_UINT64_glob_path",
"evt.rawarg.cap_inheritable glob '/path/*'",
filter_eval_test_case::EXPECT_THROW},
{"PT_ABSTIME_glob_path",
"evt.rawarg.exe_ino_ctime glob '/path/*'",
filter_eval_test_case::EXPECT_THROW},
{"PT_UID_glob_path", "evt.rawarg.uid glob '/path/*'", filter_eval_test_case::EXPECT_THROW},
{"PT_FSPATH_glob_path",
"evt.rawarg.trusted_exepath glob '/path/*'",
filter_eval_test_case::EXPECT_FALSE}, // Should this always return false?
{"PT_FSPATH_glob_NA",
"evt.rawarg.trusted_exepath glob '<NA>'",
filter_eval_test_case::EXPECT_TRUE}, // Should this always return false?
{"PT_FSPATH_glob_empty",
"evt.rawarg.trusted_exepath glob ''",
filter_eval_test_case::EXPECT_FALSE},
{"PT_PID_glob_path", "evt.rawarg.pgid glob '/path/*'", filter_eval_test_case::EXPECT_THROW},
{"PT_GID_glob_path", "evt.rawarg.gid glob '/path/*'", filter_eval_test_case::EXPECT_THROW},
});
const auto rawarg_pmatch_op_test_cases = testing::ValuesIn(std::vector<filter_eval_test_case>{
{"PT_FLAGS_pmatch_path",
"evt.rawarg.flags pmatch (/path)",
filter_eval_test_case::EXPECT_THROW},
{"PT_UINT64_pmatch_path",
"evt.rawarg.cap_inheritable pmatch (/path)",
filter_eval_test_case::EXPECT_THROW},
{"PT_ABSTIME_pmatch_path",
"evt.rawarg.exe_ino_ctime pmatch (/path)",
filter_eval_test_case::EXPECT_THROW},
{"PT_UID_pmatch_path",
"evt.rawarg.uid pmatch (/path)",
filter_eval_test_case::EXPECT_THROW},
{"PT_FSPATH_pmatch_NA",
"evt.rawarg.trusted_exepath pmatch (<NA>)",
filter_eval_test_case::EXPECT_TRUE}, // Should this always return false?
{"PT_FSPATH_pmatch_empty_str",
"evt.rawarg.trusted_exepath pmatch ('')",
filter_eval_test_case::EXPECT_TRUE}, // Should this always return false?
{"PT_FSPATH_pmatch_empty",
"evt.rawarg.trusted_exepath pmatch ()",
filter_eval_test_case::EXPECT_FALSE},
{"PT_PID_pmatch_path",
"evt.rawarg.pgid pmatch (/path)",
filter_eval_test_case::EXPECT_THROW},
{"PT_GID_pmatch_path",
"evt.rawarg.gid pmatch (/path)",
filter_eval_test_case::EXPECT_THROW},
});
const auto rawarg_regex_op_test_cases = testing::ValuesIn(std::vector<filter_eval_test_case>{
{"PT_FLAGS_regex", "evt.rawarg.flags regex '[0-9]+'", filter_eval_test_case::EXPECT_THROW},
{"PT_UINT64_regex",
"evt.rawarg.cap_inheritable regex '[0-9]+'",
filter_eval_test_case::EXPECT_THROW},
{"PT_ABSTIME_regex",
"evt.rawarg.exe_ino_ctime regex '[0-9]+'",
filter_eval_test_case::EXPECT_THROW},
{"PT_UID_regex", "evt.rawarg.uid regex '[0-9]+'", filter_eval_test_case::EXPECT_THROW},
{"PT_FSPATH_regex_NA",
"evt.rawarg.trusted_exepath regex '<NA>'",
filter_eval_test_case::EXPECT_TRUE}, // Should this always return false?
{"PT_FSPATH_regex_everything",
"evt.rawarg.trusted_exepath regex '.*'",
filter_eval_test_case::EXPECT_TRUE}, // Should this always return false?
{"PT_FSPATH_regex_empty_str",
"evt.rawarg.trusted_exepath regex ''",
filter_eval_test_case::EXPECT_FALSE},
{"PT_PID_regex", "evt.rawarg.pgid regex '[0-9]+'", filter_eval_test_case::EXPECT_THROW},
{"PT_GID_regex", "evt.rawarg.gid regex '[0-9]+'", filter_eval_test_case::EXPECT_THROW},
});
const auto rawarg_startswith_op_test_cases = testing::ValuesIn(std::vector<filter_eval_test_case>{
{"PT_FLAGS_startswith_0",
"evt.rawarg.flags startswith 0'",
filter_eval_test_case::EXPECT_THROW},
{"PT_UINT64_startswith_0",
"evt.rawarg.cap_inheritable startswith 0'",
filter_eval_test_case::EXPECT_THROW},
{"PT_ABSTIME_startswith_0",
"evt.rawarg.exe_ino_ctime startswith 0'",
filter_eval_test_case::EXPECT_THROW},
{"PT_UID_startswith_0",
"evt.rawarg.uid startswith 0'",
filter_eval_test_case::EXPECT_THROW},
{"PT_FSPATH_startswith_NA",
"evt.rawarg.trusted_exepath startswith '<NA>'",
filter_eval_test_case::EXPECT_TRUE}, // Should this always return false?
{"PT_FSPATH_startswith_empty_str",
"evt.rawarg.trusted_exepath startswith ''",
filter_eval_test_case::EXPECT_TRUE}, // Should this always return false?
{"PT_PID_startswith_0",
"evt.rawarg.pgid startswith 0'",
filter_eval_test_case::EXPECT_THROW},
{"PT_GID_startswith_0",
"evt.rawarg.gid startswith 0'",
filter_eval_test_case::EXPECT_THROW},
});
const auto rawarg_in_op_test_cases = testing::ValuesIn(std::vector<filter_eval_test_case>{
{"PT_FLAGS_in_set_with_0", "evt.rawarg.flags in (0)", filter_eval_test_case::EXPECT_FALSE},
{"PT_UINT64_in_set_with_0",
"evt.rawarg.cap_inheritable in (0)",
filter_eval_test_case::EXPECT_FALSE},
{"PT_ABSTIME_in_set_with_0",
"evt.rawarg.exe_ino_ctime in (0)",
filter_eval_test_case::EXPECT_FALSE},
{"PT_UID_in_set_with_0", "evt.rawarg.uid in (0)", filter_eval_test_case::EXPECT_FALSE},
{"PT_FSPATH_in_set_with_NA",
"evt.rawarg.trusted_exepath in ('<NA>')",
filter_eval_test_case::EXPECT_TRUE}, // Should this always return false?
{"PT_FSPATH_in_set_with_empty_str",
"evt.rawarg.trusted_exepath in ('')",
filter_eval_test_case::EXPECT_FALSE}, // Should this always return false?
{"PT_FSPATH_in_empty_set",
"evt.rawarg.trusted_exepath in ()",
filter_eval_test_case::EXPECT_FALSE},
{"PT_PID_in_set_with_0", "evt.rawarg.pgid in (0)", filter_eval_test_case::EXPECT_FALSE},
{"PT_GID_in_set_with_0", "evt.rawarg.gid in (0)", filter_eval_test_case::EXPECT_FALSE},
});
const auto rawarg_intersects_op_test_cases = testing::ValuesIn(std::vector<filter_eval_test_case>{
{"PT_FLAGS_intersects_set_with_0",
"evt.rawarg.flags intersects (0)",
filter_eval_test_case::EXPECT_FALSE},
{"PT_UINT64_intersects_set_with_0",
"evt.rawarg.cap_inheritable intersects (0)",
filter_eval_test_case::EXPECT_FALSE},
{"PT_ABSTIME_intersects_set_with_0",
"evt.rawarg.exe_ino_ctime intersects (0)",
filter_eval_test_case::EXPECT_FALSE},
{"PT_UID_intersects_set_with_0",
"evt.rawarg.uid intersects (0)",
filter_eval_test_case::EXPECT_FALSE},
{"PT_FSPATH_intersects_set_with_NA",
"evt.rawarg.trusted_exepath intersects ('<NA>')",
filter_eval_test_case::EXPECT_TRUE}, // Should this always return false?
{"PT_FSPATH_intersects_set_with_empty_str",
"evt.rawarg.trusted_exepath intersects ('')",
filter_eval_test_case::EXPECT_FALSE}, // Should this always return false?
{"PT_FSPATH_intersects_empty_set",
"evt.rawarg.trusted_exepath intersects ()",
filter_eval_test_case::EXPECT_FALSE},
{"PT_PID_intersects_set_with_0",
"evt.rawarg.pgid intersects (0)",
filter_eval_test_case::EXPECT_FALSE},
{"PT_GID_intersects_set_with_0",
"evt.rawarg.gid intersects (0)",
filter_eval_test_case::EXPECT_FALSE},
});
INSTANTIATE_TEST_CASE_P(rawarg_eq_op,
filter_eval_test,
rawarg_eq_op_test_cases,
filter_eval_test::test_case_name_gen);
INSTANTIATE_TEST_CASE_P(rawarg_contains_op,
filter_eval_test,
rawarg_contains_op_test_cases,
filter_eval_test::test_case_name_gen);
INSTANTIATE_TEST_CASE_P(rawarg_exists_op,
filter_eval_test,
rawarg_exists_op_test_cases,
filter_eval_test::test_case_name_gen);
INSTANTIATE_TEST_CASE_P(rawarg_glob_op,
filter_eval_test,
rawarg_glob_op_test_cases,
filter_eval_test::test_case_name_gen);
INSTANTIATE_TEST_CASE_P(rawarg_pmatch_op,
filter_eval_test,
rawarg_pmatch_op_test_cases,
filter_eval_test::test_case_name_gen);
INSTANTIATE_TEST_CASE_P(rawarg_regex_op,
filter_eval_test,
rawarg_regex_op_test_cases,
filter_eval_test::test_case_name_gen);
INSTANTIATE_TEST_CASE_P(rawarg_startswith_op,
filter_eval_test,
rawarg_startswith_op_test_cases,
filter_eval_test::test_case_name_gen);
INSTANTIATE_TEST_CASE_P(rawarg_in_op,
filter_eval_test,
rawarg_in_op_test_cases,
filter_eval_test::test_case_name_gen);
INSTANTIATE_TEST_CASE_P(rawarg_intersects_op,
filter_eval_test,
rawarg_intersects_op_test_cases,
filter_eval_test::test_case_name_gen);
TEST_F(sinsp_with_test_input, EVT_FILTER_rawarg_empty_params) {
add_default_init_thread();
open_inspector();
// Use execve event type as it contains a multitude of parameters (specifically, in the range
// 18-29) that can be set to empty by the scap-converter.
const auto evt = generate_execve_exit_event_with_empty_params(1, "/bin/test-exe", "test-exe");
ASSERT_EQ(get_field_as_string(evt, "evt.rawarg.flags"), "0"); // PT_FLAGS32
ASSERT_EQ(get_field_as_string(evt, "evt.rawarg.cap_inheritable"), "0"); // PT_UINT64
ASSERT_EQ(get_field_as_string(evt, "evt.rawarg.exe_ino_ctime"), "0"); // PT_ABSTIME
ASSERT_EQ(get_field_as_string(evt, "evt.rawarg.uid"), "0"); // PT_UID
ASSERT_EQ(get_field_as_string(evt, "evt.rawarg.trusted_exepath"), "<NA>"); // PT_FSPATH
ASSERT_EQ(get_field_as_string(evt, "evt.rawarg.pgid"), "0"); // PT_PID
ASSERT_EQ(get_field_as_string(evt, "evt.rawarg.gid"), "0"); // PT_GID
}

View File

@ -177,88 +177,6 @@ TEST_F(sinsp_with_test_input, EXECVE_exepath_with_trusted_exepath) {
ASSERT_EQ(p7_t1_tinfo->get_comm(), "new-comm");
}
TEST_F(sinsp_with_test_input, EXECVE_exepath_without_trusted_exepath) {
DEFAULT_TREE
/* Now we call an old event version of execve on p6_t1 */
uint64_t not_relevant_64 = 0;
uint32_t not_relevant_32 = 0;
scap_const_sized_buffer empty_bytebuf = {.buf = nullptr, .size = 0};
int64_t retval = 0;
int64_t old_tid = p6_t1_tid;
int64_t new_tid = p6_t1_tid;
int64_t pid = p6_t1_pid;
int64_t ppid = p6_t1_ptid;
std::string pathname = "/bin/test-exe";
std::string comm = "test-exe";
add_event_advance_ts(increasing_ts(), old_tid, PPME_SYSCALL_EXECVE_19_E, 1, pathname.c_str());
add_event_advance_ts(increasing_ts(),
new_tid,
PPME_SYSCALL_EXECVE_19_X,
27,
retval,
pathname.c_str(),
empty_bytebuf,
new_tid,
pid,
ppid,
"",
not_relevant_64,
not_relevant_64,
not_relevant_64,
not_relevant_32,
not_relevant_32,
not_relevant_32,
comm.c_str(),
empty_bytebuf,
empty_bytebuf,
not_relevant_32,
not_relevant_64,
not_relevant_32,
not_relevant_32,
not_relevant_64,
not_relevant_64,
not_relevant_64,
not_relevant_64,
not_relevant_64,
not_relevant_64,
not_relevant_32);
const auto& thread_manager = m_inspector.m_thread_manager;
auto p6_t1_tinfo = thread_manager->get_thread_ref(p6_t1_tid, false).get();
ASSERT_TRUE(p6_t1_tinfo);
/* In the old event version we will use the pathname to reconstruct the exepath through our
* userspace logic */
ASSERT_EQ(p6_t1_tinfo->get_exepath(), pathname.c_str());
ASSERT_EQ(p6_t1_tinfo->get_comm(), comm.c_str());
/* Create a new child of p6_t1 and check if we inerith the exepath */
int64_t p7_t1_tid = 100;
int64_t p7_t1_pid = 100;
int64_t p7_t1_ptid = p6_t1_tid;
int64_t p7_t1_vtid = 20;
int64_t p7_t1_vpid = 20;
generate_clone_x_event(0,
p7_t1_tid,
p7_t1_pid,
p7_t1_ptid,
PPM_CL_CHILD_IN_PIDNS,
p7_t1_vtid,
p7_t1_vpid,
"new-comm");
auto p7_t1_tinfo = thread_manager->get_thread_ref(p7_t1_tid, false).get();
ASSERT_TRUE(p7_t1_tinfo);
ASSERT_EQ(p7_t1_tinfo->get_exepath(), pathname.c_str());
ASSERT_EQ(p7_t1_tinfo->get_comm(), "new-comm");
}
TEST_F(sinsp_with_test_input, EXECVE_check_pgid_population) {
add_default_init_thread();
open_inspector();

View File

@ -0,0 +1,201 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2025 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 <helpers/threads_helpers.h>
/*=============================== EXECVEAT ===========================*/
TEST_F(sinsp_with_test_input, EXECVEAT_from_a_not_leader_thread) {
/* Instantiate the default tree */
DEFAULT_TREE
/* `p2_t2` calls an execveat and `p2_t1` will take control in the exit event */
generate_execveat_enter_and_exit_event(0, p2_t2_tid, p2_t1_tid, p2_t1_pid, p2_t1_ptid);
/* we should have just one thread alive, the leader one */
ASSERT_THREAD_GROUP_INFO(p2_t1_pid, 1, false, 3, 1, p2_t1_tid);
/* we shouldn't be able to find other threads in the thread table */
ASSERT_MISSING_THREAD_INFO(p2_t2_tid, true);
ASSERT_MISSING_THREAD_INFO(p2_t3_tid, true);
}
TEST_F(sinsp_with_test_input, EXECVEAT_from_a_leader_thread) {
/* Instantiate the default tree */
DEFAULT_TREE
/* `p2_t1` calls an execveat */
generate_execveat_enter_and_exit_event(0, p2_t1_tid, p2_t1_tid, p2_t1_pid, p2_t1_ptid);
/* we should have just one thread alive, the leader one */
ASSERT_THREAD_GROUP_INFO(p2_t1_pid, 1, false, 3, 1, p2_t1_tid);
/* we shouldn't be able to find other threads in the thread table */
ASSERT_MISSING_THREAD_INFO(p2_t2_tid, true);
ASSERT_MISSING_THREAD_INFO(p2_t3_tid, true);
}
TEST_F(sinsp_with_test_input, EXECVEAT_from_a_not_leader_thread_with_a_child) {
/* Instantiate the default tree */
DEFAULT_TREE
/* Create a child for `p2_t3` */
int64_t p7_t1_tid = 100;
[[maybe_unused]] int64_t p7_t1_pid = 100;
[[maybe_unused]] int64_t p7_t1_ptid = p2_t3_tid;
generate_clone_x_event(p7_t1_tid, p2_t3_tid, p2_t3_pid, p2_t3_ptid);
ASSERT_THREAD_CHILDREN(p2_t3_tid, 1, 1, p7_t1_tid);
/* Right now `p2_t1` has just one child */
ASSERT_THREAD_CHILDREN(p2_t1_tid, 1, 1, p3_t1_tid);
/* `p2_t2` calls an execveat and `p2_t1` will take control in the exit event */
generate_execveat_enter_and_exit_event(0, p2_t2_tid, p2_t1_tid, p2_t1_pid, p2_t1_ptid);
/* we should have just one thread alive, the leader one */
ASSERT_THREAD_GROUP_INFO(p2_t1_pid, 1, false, 3, 1, p2_t1_tid);
/* we shouldn't be able to find other threads in the thread table */
ASSERT_MISSING_THREAD_INFO(p2_t2_tid, true);
ASSERT_MISSING_THREAD_INFO(p2_t3_tid, true);
/* Now the father of `p7_t1` should be `p2_t1` */
ASSERT_THREAD_CHILDREN(p2_t1_tid, 2, 2, p3_t1_tid, p7_t1_tid);
}
TEST_F(sinsp_with_test_input, EXECVEAT_resurrect_thread) {
/* Instantiate the default tree */
DEFAULT_TREE
/* This is a corner case in which the main thread dies and after it
* a secondary thread of the same thread group will call an execveat.
* This is what stress-ng does.
*/
/* `p2t1` dies, p2t2 is the reaper */
remove_thread(p2_t1_tid, p2_t2_tid);
ASSERT_THREAD_CHILDREN(p2_t2_tid, 1, 1, p3_t1_tid);
ASSERT_THREAD_GROUP_INFO(p2_t2_pid, 2, false, 3, 3);
auto p2_t1_tinfo = m_inspector.m_thread_manager->get_thread_ref(p2_t1_tid).get();
ASSERT_TRUE(p2_t1_tinfo);
/* p2t1 is present but dead */
ASSERT_TRUE(p2_t1_tinfo->is_dead());
/* what happens in the execveat exit parser is that the main thread resurrect
* and it will acquire again its children, and all other threads of the group will die
*/
generate_execveat_enter_and_exit_event(0, p2_t2_tid, p2_t1_tid, p2_t1_pid, p2_t1_ptid);
/* The main thread is no more dead and it has again its children */
ASSERT_FALSE(p2_t1_tinfo->is_dead());
ASSERT_THREAD_CHILDREN(p2_t1_tid, 1, 1, p3_t1_tid);
ASSERT_THREAD_GROUP_INFO(p2_t1_pid, 1, false, 3, 1);
ASSERT_MISSING_THREAD_INFO(p2_t2_tid, true);
ASSERT_MISSING_THREAD_INFO(p2_t3_tid, true);
}
TEST_F(sinsp_with_test_input, EXECVEAT_missing_process_execveat_repair) {
add_default_init_thread();
open_inspector();
/* A process that we don't have in the table calls a random event */
int64_t p1_t1_tid = 24;
int64_t p1_t1_pid = 24;
int64_t p1_t1_ptid = INIT_TID;
/* This event should create invalid thread info for p1_t1 */
generate_random_event(p1_t1_tid);
/* Now we call an execveat on p1_t1 */
generate_execveat_enter_and_exit_event(0, p1_t1_tid, p1_t1_tid, p1_t1_pid, p1_t1_ptid);
/* we should have a valid thread group info and init should have a child now
* we are not in a container but we want to assert also vtid, vpid.
*/
ASSERT_THREAD_INFO_PIDS(p1_t1_tid, p1_t1_pid, p1_t1_ptid);
ASSERT_THREAD_GROUP_INFO(p1_t1_pid, 1, false, 1, 1, p1_t1_tid);
ASSERT_THREAD_CHILDREN(INIT_TID, 1, 1, p1_t1_tid);
}
TEST_F(sinsp_with_test_input, EXECVEAT_exepath_with_trusted_exepath) {
DEFAULT_TREE
/* Now we call an execveat on p6_t1 */
generate_execveat_enter_and_exit_event(0,
p6_t1_tid,
p6_t1_tid,
p6_t1_pid,
p6_t1_ptid,
"/good-exe",
"good-exe",
"/usr/bin/bad-exe");
const auto& thread_manager = m_inspector.m_thread_manager;
auto p6_t1_tinfo = thread_manager->get_thread_ref(p6_t1_tid, false).get();
ASSERT_TRUE(p6_t1_tinfo);
ASSERT_EQ(p6_t1_tinfo->get_exepath(), "/usr/bin/bad-exe");
ASSERT_EQ(p6_t1_tinfo->get_comm(), "good-exe");
/* Create a new child of p6_t1 and check if we inerith the exepath */
int64_t p7_t1_tid = 100;
int64_t p7_t1_pid = 100;
int64_t p7_t1_ptid = p6_t1_tid;
int64_t p7_t1_vtid = 20;
int64_t p7_t1_vpid = 20;
generate_clone_x_event(0,
p7_t1_tid,
p7_t1_pid,
p7_t1_ptid,
PPM_CL_CHILD_IN_PIDNS,
p7_t1_vtid,
p7_t1_vpid,
"new-comm");
auto p7_t1_tinfo = thread_manager->get_thread_ref(p7_t1_tid, false).get();
ASSERT_TRUE(p7_t1_tinfo);
ASSERT_EQ(p7_t1_tinfo->get_exepath(), "/usr/bin/bad-exe");
ASSERT_EQ(p7_t1_tinfo->get_comm(), "new-comm");
}
TEST_F(sinsp_with_test_input, EXECVEAT_check_pgid_population) {
add_default_init_thread();
open_inspector();
int64_t random_pgid = 100;
generate_execveat_enter_and_exit_event(0,
INIT_TID,
INIT_TID,
INIT_PID,
INIT_PTID,
"/usr/bin/bash",
"init",
"/usr/bin/bash",
{},
random_pgid);
auto init_tinfo = m_inspector.m_thread_manager->get_thread_ref(INIT_TID, false).get();
ASSERT_TRUE(init_tinfo);
ASSERT_EQ(init_tinfo->m_pgid, random_pgid);
}
/*=============================== EXECVEAT ===========================*/

View File

@ -59,7 +59,7 @@ TEST_F(sinsp_with_test_input, RECVMSG_success) {
ASSERT_EQ(evt->get_param_value_str("data"), data);
// Check that msgcontrol is empty.
ASSERT_EQ(evt->get_param_by_name("msgcontrol")->m_len, 0);
ASSERT_EQ(evt->get_param_by_name("msgcontrol")->len(), 0);
// Check that fd value is as expected.
ASSERT_EQ(evt->get_param_by_name("fd")->as<int64_t>(), sock_params.fd);

View File

@ -16,7 +16,7 @@ TEST(events, check_unused_events) {
/* Check the `is_old_version_event` API works correctly */
TEST(events, check_old_version_events) {
/* `PPME_SYSCALL_EXECVE_8_E` has only the `EF_OLD_VERSION` flag */
ASSERT_EQ(libsinsp::events::is_old_version_event(PPME_SYSCALL_EXECVE_14_E), true);
ASSERT_EQ(libsinsp::events::is_old_version_event(PPME_SYSCALL_EXECVE_8_E), true);
/* `PPME_SCHEDSWITCH_6_X` has no the `EF_OLD_VERSION` flag */
ASSERT_EQ(libsinsp::events::is_old_version_event(PPME_SCHEDSWITCH_6_X), false);

View File

@ -261,19 +261,21 @@ const libsinsp::events::set<ppm_event_code> expected_unknown_event_set = {
/* Check the `info` API works correctly */
TEST(ppm_sc_API, check_event_info) {
{
auto event_info_pointer = libsinsp::events::info(PPME_GENERIC_E);
const auto event_info_pointer = libsinsp::events::info(PPME_GENERIC_E);
ASSERT_STREQ(event_info_pointer->name, "syscall");
ASSERT_EQ(event_info_pointer->category, ppm_event_category(EC_OTHER | EC_SYSCALL));
ASSERT_EQ(event_info_pointer->category,
static_cast<ppm_event_category>(EC_OTHER | EC_SYSCALL));
ASSERT_EQ(event_info_pointer->flags, EF_NONE);
ASSERT_EQ(event_info_pointer->nparams, 2);
ASSERT_STREQ(event_info_pointer->params[0].name, "ID");
}
{
auto event_info_pointer = libsinsp::events::info(PPME_SYSCALL_CLONE3_X);
const auto event_info_pointer = libsinsp::events::info(PPME_SYSCALL_CLONE3_X);
ASSERT_STREQ(event_info_pointer->name, "clone3");
ASSERT_EQ(event_info_pointer->category, ppm_event_category(EC_PROCESS | EC_SYSCALL));
ASSERT_EQ(event_info_pointer->flags, EF_MODIFIES_STATE);
ASSERT_EQ(event_info_pointer->category,
static_cast<ppm_event_category>(EC_PROCESS | EC_SYSCALL));
ASSERT_EQ(event_info_pointer->flags, EF_MODIFIES_STATE | EF_TMP_CONVERTER_MANAGED);
ASSERT_EQ(event_info_pointer->nparams, 21);
ASSERT_STREQ(event_info_pointer->params[0].name, "res");
}

View File

@ -65,6 +65,8 @@ TEST_F(scap_file_test, same_number_of_events) {
{PPME_SYSCALL_WRITEV_E, 5}, {PPME_SYSCALL_WRITEV_X, 5},
{PPME_SYSCALL_FCNTL_E, 9817}, {PPME_SYSCALL_FCNTL_X, 9817},
{PPME_SOCKET_CONNECT_E, 238}, {PPME_SOCKET_CONNECT_X, 238},
{PPME_SYSCALL_EXECVE_19_E, 202}, {PPME_SYSCALL_EXECVE_19_X, 203},
{PPME_SYSCALL_EXECVEAT_E, 1}, {PPME_SYSCALL_EXECVEAT_X, 0},
// Add further checks regarding the expected number of events in this scap file here.
});
@ -84,6 +86,7 @@ TEST_F(scap_file_test, same_number_of_events) {
{PPME_SYSCALL_MPROTECT_E, 584}, {PPME_SYSCALL_MPROTECT_X, 584},
{PPME_SYSCALL_UMOUNT2_E, 2}, {PPME_SYSCALL_UMOUNT2_X, 2},
{PPME_SYSCALL_INOTIFY_INIT_E, 1}, {PPME_SYSCALL_INOTIFY_INIT_X, 1},
{PPME_SYSCALL_PRLIMIT_E, 173}, {PPME_SYSCALL_PRLIMIT_X, 173},
// Add further checks regarding the expected number of events in this scap file here.
});
@ -430,6 +433,49 @@ TEST_F(scap_file_test, setrlimit_x_check_final_converted_event) {
create_safe_scap_event(ts, tid, PPME_SYSCALL_SETRLIMIT_X, 4, res, cur, max, resource));
}
////////////////////////////
// PRLIMIT
////////////////////////////
TEST_F(scap_file_test, prlimit_x_check_final_converted_event) {
open_filename("kexec_x86.scap");
// Inside the scap-file the event `513076` is the following:
// - type=PPME_SYSCALL_PRLIMIT_X,
// - ts=1687889198695794034
// - tid=107452
// - args=res=0 newcur=-1 newmax=-1 oldcur=8388608 oldmax=-1
//
// And its corresponding enter event `513075` is the following:
// - type=PPME_SYSCALL_PRLIMIT_E
// - ts=1687889198695793141
// - tid=107452
// - args=pid=0 resource=3(RLIMIT_STACK)
//
// Let's see the new PPME_SYSCALL_PRLIMIT_X event!
constexpr uint64_t ts = 1687889198695794034;
constexpr int64_t tid = 107452;
constexpr int64_t res = 0;
constexpr int64_t newcur = -1;
constexpr int64_t newmax = -1;
constexpr int64_t oldcur = 8388608;
constexpr int64_t oldmax = -1;
constexpr int64_t pid = 0;
constexpr uint8_t resource = 3;
assert_event_presence(create_safe_scap_event(ts,
tid,
PPME_SYSCALL_PRLIMIT_X,
7,
res,
newcur,
newmax,
oldcur,
oldmax,
pid,
resource));
}
////////////////////////////
// FCNTL
////////////////////////////
@ -502,6 +548,126 @@ TEST_F(scap_file_test, brk_x_check_final_converted_event) {
addr));
}
////////////////////////////
///// EXECVE
////////////////////////////
TEST_F(scap_file_test, execve_x_check_final_converted_event) {
open_filename("kexec_arm64.scap");
// Inside the scap-file the event `897489` is the following:
// - type=PPME_SYSCALL_EXECVE_19_X,
// - ts=1687966733728778931
// - tid=141707
// - args=res=0 exe=cat args=/proc/129520/stat. tid=141707(cat) pid=141707(cat)
// ptid=141698(cpuUsage.sh) cwd=<NA> fdlimit=1048576 pgft_maj=0 pgft_min=56 vm_size=364 vm_rss=4
// vm_swap=0 comm=cat
// cgroups=cpuset=/user.slice.cpu=/user.slice.cpuacct=/.io=/user.slice.memory=/user.slic...
// env=SHELL=/bin/zsh.VSCODE_VERBOSE_LOGGING=true.LC_ADDRESS=it_IT.UTF-8.LC_NAME=it_... tty=0
// vpgid=118459 loginuid=1000(ubuntu) flags=0 cap_inheritable=0 cap_permitted=0 cap_effective=0
// exe_ino=1522 exe_ino_ctime=2023-03-03 03:16:21.531741984 exe_ino_mtime=2022-02-07
// 17:03:08.000000000 uid=1000(ubuntu)
//
// And its corresponding enter event `897487` is the following:
// - type=PPME_SYSCALL_EXECVE_19_E
// - ts=1687966733728593747
// - tid=141707
// - args=filename=/usr/bin/cat
//
// Let's see the new PPME_SYSCALL_EXECVE_19_X event!
constexpr uint64_t ts = 1687966733728778931;
constexpr int64_t tid_hdr = 141707;
constexpr int64_t res = 0;
constexpr char exe[] = "cat";
constexpr char args_data[] = "/proc/129520/stat";
const scap_const_sized_buffer args{args_data, sizeof(args_data)};
constexpr int64_t tid = 141707;
constexpr int64_t pid = 141707;
constexpr int64_t ptid = 141698;
constexpr auto cwd = empty_value<char *>();
constexpr uint64_t fdlimit = 1048576;
constexpr uint64_t pgft_maj = 0;
constexpr uint64_t pgft_min = 56;
constexpr uint32_t vm_size = 364;
constexpr uint32_t vm_rss = 4;
constexpr uint32_t vm_swap = 0;
constexpr char comm[] = "cat";
constexpr char cgroups_data[] =
"cpuset=/user.slice\0cpu=/user.slice\0cpuacct=/\0io=/user.slice\0memory=/user.slice/"
"user-1000.slice/session-21.scope\0devices=/\0freezer=/\0net_cls=/\0perf_event=/"
"user.slice/user-1000.slice/session-21.scope\0net_prio=/\0hugetlb=/user.slice\0pids=/"
"user.slice/user-1000.slice/session-21.scope\0rdma=/user.slice\0misc=/user.slice";
const scap_const_sized_buffer cgroups{cgroups_data, sizeof(cgroups_data)};
constexpr char env_data[] =
"SHELL=/bin/"
"zsh\0VSCODE_VERBOSE_LOGGING=true\0LC_ADDRESS=it_IT.UTF-8\0LC_NAME=it_IT.UTF-8\0VSCODE_"
"PIPE_LOGGING=true\0LC_MONETARY=it_IT.UTF-8\0VSCODE_AMD_ENTRYPOINT=vs/platform/"
"terminal/node/ptyHostMain\0PWD=/home/"
"ubuntu\0LOGNAME=ubuntu\0XDG_SESSION_TYPE=tty\0MOTD_SHOWN=pam\0HOME=/home/"
"ubuntu\0LC_PAPER=it_IT.UTF-8\0LANG=C.UTF-8\0VSCODE_AGENT_FOLDER=/home/ubuntu/"
".vscode-server\0SSH_CONNECTION=151.38.160.202 36824 172.31.24.0 "
"22\0XDG_SESSION_CLASS=user\0VSCODE_HANDLES_SIGPIPE=true\0LC_IDENTIFICATION=it_IT.UTF-"
"8\0USER=ubuntu\0SHLVL=1\0LC_TELEPHONE=it_IT.UTF-8\0LC_MEASUREMENT=it_IT.UTF-8\0VSCODE_"
"CWD=/home/ubuntu\0XDG_SESSION_ID=21\0VSCODE_PARENT_PID=118516\0XDG_RUNTIME_DIR=/run/"
"user/1000\0SSH_CLIENT=151.38.160.202 36824 "
"22\0LC_TIME=it_IT.UTF-8\0PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/"
"sbin:/bin:/usr/games:/usr/local/games:/snap/bin\0DBUS_SESSION_BUS_ADDRESS=unix:path=/"
"run/user/1000/bus\0LC_NUMERIC=it_IT.UTF-8\0OLDPWD=/home/ubuntu\0_=/usr/bin/cat";
const scap_const_sized_buffer env{env_data, sizeof(env_data)};
constexpr uint32_t tty = 0;
constexpr int64_t vpgid = 118459;
constexpr uint32_t loginuid = 1000;
constexpr uint32_t flags = 0;
constexpr uint64_t cap_inheritable = 0;
constexpr uint64_t cap_permitted = 0;
constexpr uint64_t cap_effective = 0;
constexpr uint64_t exe_ino = 1522;
constexpr int64_t exe_ino_ctime = 1677809781531741984;
constexpr int64_t exe_ino_mtime = 1644249788000000000;
constexpr uint32_t uid = 1000;
constexpr auto trusted_exepath = empty_value<char *>();
constexpr auto pgid = empty_value<int64_t>();
constexpr auto gid = empty_value<uint32_t>();
SCAP_EMPTY_PARAMS_SET(empty_params_set, 6, 27, 28, 29);
assert_event_presence(create_safe_scap_event_with_empty_params(ts,
tid_hdr,
PPME_SYSCALL_EXECVE_19_X,
&empty_params_set,
30,
res,
exe,
args,
tid,
pid,
ptid,
cwd,
fdlimit,
pgft_maj,
pgft_min,
vm_size,
vm_rss,
vm_swap,
comm,
cgroups,
env,
tty,
vpgid,
loginuid,
flags,
cap_inheritable,
cap_permitted,
cap_effective,
exe_ino,
exe_ino_ctime,
exe_ino_mtime,
uid,
trusted_exepath,
pgid,
gid));
}
////////////////////////////
// SOCKET
////////////////////////////
@ -1874,6 +2040,12 @@ TEST_F(scap_file_test, mprotect_x_check_final_converted_event) {
create_safe_scap_event(ts, tid, PPME_SYSCALL_MPROTECT_X, 4, res, addr, len, proto));
}
////////////////////////////
// EXECVEAT
////////////////////////////
// We don't have scap-files with both enter and exit EXECVEAT events. Add it if we face a failure.
////////////////////////////
// COPY_FILE_RANGE
////////////////////////////

View File

@ -93,7 +93,25 @@ protected:
char error[SCAP_LASTERR_SIZE] = {'\0'};
va_list args;
va_start(args, n);
scap_evt* evt = scap_create_event_v(error, ts, tid, event_type, n, args);
scap_evt* evt = scap_create_event_v(error, ts, tid, event_type, nullptr, n, args);
va_end(args);
if(evt == NULL) {
throw std::runtime_error("Error creating event: " + std::string(error));
}
return create_safe_scap_evt(evt);
}
safe_scap_evt_t create_safe_scap_event_with_empty_params(
uint64_t ts,
uint64_t tid,
ppm_event_code event_type,
scap_empty_params_set* empty_params_set,
uint32_t n,
...) {
char error[SCAP_LASTERR_SIZE] = {'\0'};
va_list args;
va_start(args, n);
scap_evt* evt = scap_create_event_v(error, ts, tid, event_type, empty_params_set, n, args);
va_end(args);
if(evt == NULL) {
throw std::runtime_error("Error creating event: " + std::string(error));
@ -150,5 +168,20 @@ protected:
}
}
// Return an empty value for the type T.
template<typename T>
constexpr static T empty_value() {
return static_cast<T>(0);
}
std::unique_ptr<sinsp> m_inspector;
};
template<>
constexpr scap_const_sized_buffer scap_file_test::empty_value() {
return {nullptr, 0};
}
template<>
constexpr char* scap_file_test::empty_value() {
return nullptr;
}

View File

@ -0,0 +1,108 @@
#include "sinsp_suppress.h"
#include <cstdint>
#include <gtest/gtest.h>
#include <algorithm>
struct test_case {
std::string name;
std::vector<std::string> suppressed_comms;
std::vector<std::tuple<uint64_t /*tid*/, uint64_t /*parent_tid*/, std::string /*comm*/>>
entries;
std::vector<uint64_t> expected_suppressed_tids;
};
class suppressed_comm_test : public ::testing::TestWithParam<test_case> {};
TEST_P(suppressed_comm_test, check_suppressed_comm) {
auto test_case = GetParam();
libsinsp::sinsp_suppress suppressor;
for(const auto& comm : test_case.suppressed_comms) {
// Suppress each comm in the test case
suppressor.suppress_comm(comm);
}
// Initialize the suppressor, e.g. a simulate a proc scan
suppressor.initialize();
for(const auto& entry : test_case.entries) {
// Handle each thread entry
suppressor.check_suppressed_comm(std::get<0>(entry),
std::get<1>(entry),
std::get<2>(entry));
}
// Finalize the suppressor, e.g. to clean up or finalize the proc scan
suppressor.finalize();
// Check the number of suppressed tids
EXPECT_EQ(suppressor.get_num_suppressed_tids(), test_case.expected_suppressed_tids.size());
// Check if the expected suppressed tids are recognized
for(const auto& expected_tid : test_case.expected_suppressed_tids) {
EXPECT_TRUE(suppressor.is_suppressed_tid(expected_tid))
<< "Expected tid " << expected_tid << " to be suppressed.";
}
}
INSTANTIATE_TEST_CASE_P(suppressed_comm_tests,
suppressed_comm_test,
::testing::ValuesIn(std::vector<test_case>{
{"single suppressed comm",
{"suppress_me"},
{
{1, 0, "systemd"},
{2, 1, "suppress_me"},
{3, 1, "other_comm"},
},
{2}},
{"multiple suppressed comms",
{"suppress_me", "ignore_me"},
{
{1, 0, "systemd"},
{2, 1, "suppress_me"},
{3, 1, "ignore_me"},
{4, 1, "other_comm"},
},
{2, 3}},
{"hierarchical suppressed comms",
{"suppress_me"},
{
{1, 0, "systemd"},
{2, 1, "suppress_me"},
{3, 2, "child_suppress"},
{4, 1, "other_comm"},
},
{2, 3}},
{"out of order hierarchical suppressed comms",
{"suppress_me"},
{
{1, 0, "systemd"},
{3, 2, "other_comm"}, // child is scanned befor his parent
{2, 1, "suppress_me"},
{4, 1, "another_comm"},
{3, 1, "another_comm"},
},
{3, 2}},
{"child of o child of a suppressed",
{"suppress_me", "destroy_me"},
{{1, 0, "systemd"},
{100, 10, "a_child_to_suppress"},
{200, 20, "another_child_to_suppress"},
{1000, 100, "a_nephew_to_be_suppressed"},
{2000, 200, "another_nephew_to_be_suppressed"},
{10, 1, "suppress_me"},
{20, 1, "destroy_me"},
{1010, 1, "im_fine"}},
{100, 200, 1000, 2000, 10, 20}},
}),
[](testing::TestParamInfo<test_case> info) {
// replace space with underscore for test name
std::string name = info.param.name;
std::replace(name.begin(), name.end(), ' ', '_');
return name;
});

View File

@ -41,19 +41,6 @@ void sinsp_with_test_input::open_inspector(sinsp_mode_t mode) {
m_inspector.open_test_input(&m_test_data, mode);
}
scap_evt* sinsp_with_test_input::_add_event(uint64_t ts,
uint64_t tid,
ppm_event_code event_type,
uint32_t n,
...) {
va_list args;
va_start(args, n);
scap_evt* ret = add_event_v(ts, tid, event_type, n, args);
va_end(args);
return ret;
}
sinsp_evt* sinsp_with_test_input::advance_ts_get_event(uint64_t ts) {
for(sinsp_evt* evt = next_event(); evt != nullptr; evt = next_event()) {
if(evt->get_ts() == ts) {
@ -64,6 +51,34 @@ sinsp_evt* sinsp_with_test_input::advance_ts_get_event(uint64_t ts) {
return nullptr;
}
scap_evt* sinsp_with_test_input::_add_event(uint64_t ts,
uint64_t tid,
ppm_event_code event_type,
uint32_t n,
...) {
va_list args;
va_start(args, n);
scap_evt* ret = add_event_v(ts, tid, event_type, nullptr, n, args);
va_end(args);
return ret;
}
scap_evt* sinsp_with_test_input::_add_event_with_empty_params(
uint64_t ts,
uint64_t tid,
ppm_event_code event_type,
const scap_empty_params_set* empty_params_set,
uint32_t n,
...) {
va_list args;
va_start(args, n);
scap_evt* ret = add_event_v(ts, tid, event_type, empty_params_set, n, args);
va_end(args);
return ret;
}
// adds an event and advances the inspector to the new timestamp
sinsp_evt* sinsp_with_test_input::_add_event_advance_ts(uint64_t ts,
uint64_t tid,
@ -72,18 +87,36 @@ sinsp_evt* sinsp_with_test_input::_add_event_advance_ts(uint64_t ts,
...) {
va_list args;
va_start(args, n);
sinsp_evt* ret = add_event_advance_ts_v(ts, tid, event_type, n, args);
sinsp_evt* ret = add_event_advance_ts_v(ts, tid, event_type, nullptr, n, args);
va_end(args);
return ret;
}
sinsp_evt* sinsp_with_test_input::add_event_advance_ts_v(uint64_t ts,
uint64_t tid,
ppm_event_code event_type,
uint32_t n,
va_list args) {
add_event_v(ts, tid, event_type, n, args);
// adds an event and advances the inspector to the new timestamp
sinsp_evt* sinsp_with_test_input::_add_event_advance_ts_with_empty_params(
uint64_t ts,
uint64_t tid,
ppm_event_code event_type,
const scap_empty_params_set* empty_params_set,
uint32_t n,
...) {
va_list args;
va_start(args, n);
sinsp_evt* ret = add_event_advance_ts_v(ts, tid, event_type, empty_params_set, n, args);
va_end(args);
return ret;
}
sinsp_evt* sinsp_with_test_input::add_event_advance_ts_v(
uint64_t ts,
uint64_t tid,
ppm_event_code event_type,
const scap_empty_params_set* empty_params_set,
uint32_t n,
va_list args) {
add_event_v(ts, tid, event_type, empty_params_set, n, args);
sinsp_evt* evt = advance_ts_get_event(ts);
if(evt != nullptr) {
return evt;
@ -98,6 +131,7 @@ sinsp_evt* sinsp_with_test_input::add_event_advance_ts_v(uint64_t ts,
scap_evt* sinsp_with_test_input::create_event_v(uint64_t ts,
uint64_t tid,
ppm_event_code event_type,
const scap_empty_params_set* empty_params_set,
uint32_t n,
va_list args) {
struct scap_sized_buffer event_buf = {NULL, 0};
@ -106,7 +140,13 @@ scap_evt* sinsp_with_test_input::create_event_v(uint64_t ts,
va_list args2;
va_copy(args2, args);
int32_t ret = scap_event_encode_params_v(event_buf, &event_size, error, event_type, n, args);
int32_t ret = scap_event_encode_params_v(event_buf,
&event_size,
error,
event_type,
empty_params_set,
n,
args);
if(ret != SCAP_INPUT_TOO_SMALL) {
va_end(args2);
@ -121,7 +161,13 @@ scap_evt* sinsp_with_test_input::create_event_v(uint64_t ts,
return nullptr;
}
ret = scap_event_encode_params_v(event_buf, &event_size, error, event_type, n, args2);
ret = scap_event_encode_params_v(event_buf,
&event_size,
error,
event_type,
empty_params_set,
n,
args2);
if(ret != SCAP_SUCCESS) {
free(event_buf.buf);
@ -141,6 +187,7 @@ scap_evt* sinsp_with_test_input::create_event_v(uint64_t ts,
scap_evt* sinsp_with_test_input::add_event_v(uint64_t ts,
uint64_t tid,
ppm_event_code event_type,
const scap_empty_params_set* empty_params_set,
uint32_t n,
va_list args) {
if(ts < m_last_recorded_timestamp) {
@ -149,7 +196,7 @@ scap_evt* sinsp_with_test_input::add_event_v(uint64_t ts,
"timestamps");
}
scap_evt* event = create_event_v(ts, tid, event_type, n, args);
scap_evt* event = create_event_v(ts, tid, event_type, empty_params_set, n, args);
if(event == nullptr) {
std::stringstream ss;
ss << "cannot create event type: " << event_type << ", ts: " << ts << ", tid: " << tid
@ -173,7 +220,7 @@ scap_evt* sinsp_with_test_input::add_async_event(uint64_t ts,
...) {
va_list args;
va_start(args, n);
scap_evt* ret = add_async_event_v(ts, tid, event_type, n, args);
scap_evt* ret = add_async_event_v(ts, tid, event_type, nullptr, n, args);
va_end(args);
return ret;
@ -182,9 +229,10 @@ scap_evt* sinsp_with_test_input::add_async_event(uint64_t ts,
scap_evt* sinsp_with_test_input::add_async_event_v(uint64_t ts,
uint64_t tid,
ppm_event_code event_type,
const scap_empty_params_set* empty_params_set,
uint32_t n,
va_list args) {
scap_evt* scap_event = create_event_v(ts, tid, event_type, n, args);
scap_evt* scap_event = create_event_v(ts, tid, event_type, empty_params_set, n, args);
m_async_events.push_back(scap_event);
auto event = std::make_unique<sinsp_evt>();
@ -234,7 +282,7 @@ sinsp_evt* sinsp_with_test_input::generate_clone_x_event(int64_t retval,
return add_event_advance_ts(increasing_ts(),
tid,
event_type,
20,
21,
retval,
name.c_str(),
empty_bytebuf,
@ -254,7 +302,8 @@ sinsp_evt* sinsp_with_test_input::generate_clone_x_event(int64_t retval,
not_relevant_32,
not_relevant_32,
vtid,
vpid);
vpid,
not_relevant_64);
}
sinsp_evt* sinsp_with_test_input::generate_execve_enter_and_exit_event(
@ -286,7 +335,7 @@ sinsp_evt* sinsp_with_test_input::generate_execve_enter_and_exit_event(
return add_event_advance_ts(increasing_ts(),
new_tid,
PPME_SYSCALL_EXECVE_19_X,
29,
30,
retval,
pathname.c_str(),
empty_bytebuf,
@ -315,7 +364,161 @@ sinsp_evt* sinsp_with_test_input::generate_execve_enter_and_exit_event(
not_relevant_64,
not_relevant_32,
resolved_kernel_path.c_str(),
pgid);
pgid,
not_relevant_32);
}
sinsp_evt* sinsp_with_test_input::generate_execveat_enter_and_exit_event(
int64_t retval,
int64_t old_tid,
int64_t new_tid,
int64_t pid,
int64_t ppid,
const std::string& pathname,
const std::string& comm,
const std::string& resolved_kernel_path,
const std::vector<std::string>& cgroup_vec,
int64_t pgid) {
// Scaffolding needed to call the PPME_SYSCALL_EXECVEAT_X
uint64_t not_relevant_64 = 0;
uint32_t not_relevant_32 = 0;
scap_const_sized_buffer empty_bytebuf = {/*.buf =*/nullptr, /*.size =*/0};
scap_const_sized_buffer cgroup_byte_buf = empty_bytebuf;
std::string cgroupsv = test_utils::to_null_delimited(cgroup_vec);
// If the cgroup vector is not empty overwrite it
if(!cgroup_vec.empty()) {
cgroup_byte_buf = scap_const_sized_buffer{cgroupsv.data(), cgroupsv.size()};
}
int64_t dirfd = 3;
add_event_advance_ts(increasing_ts(),
old_tid,
PPME_SYSCALL_EXECVEAT_E,
3,
dirfd,
pathname.c_str(),
0);
// we have an `old_tid` and a `new_tid` because if a secondary thread calls the execve
// the thread leader will take control so the `tid` between enter and exit event will change
return add_event_advance_ts(increasing_ts(),
new_tid,
PPME_SYSCALL_EXECVEAT_X,
30,
retval,
pathname.c_str(),
empty_bytebuf,
new_tid,
pid,
ppid,
"",
not_relevant_64,
not_relevant_64,
not_relevant_64,
not_relevant_32,
not_relevant_32,
not_relevant_32,
comm.c_str(),
cgroup_byte_buf,
empty_bytebuf,
not_relevant_32,
not_relevant_64,
not_relevant_32,
not_relevant_32,
not_relevant_64,
not_relevant_64,
not_relevant_64,
not_relevant_64,
not_relevant_64,
not_relevant_64,
not_relevant_32,
resolved_kernel_path.c_str(),
pgid,
not_relevant_32);
}
sinsp_evt* sinsp_with_test_input::generate_execve_exit_event_with_default_params(
const int64_t pid,
const std::string& file_to_run,
const std::string& comm) {
return add_event_advance_ts(increasing_ts(),
pid,
PPME_SYSCALL_EXECVE_19_X,
30,
(int64_t)0, /* res */
file_to_run.c_str(), /* exe */
scap_const_sized_buffer{nullptr, 0}, /* args */
(uint64_t)pid, /* tid */
(uint64_t)pid, /* pid */
(uint64_t)pid, /* ptid */
"", /* cwd */
(uint64_t)0, /* fdlimit */
(uint64_t)0, /* pgft_maj */
(uint64_t)0, /* pgft_min */
0, /* vm_size */
0, /* vm_rss */
0, /* vm_swap */
comm.c_str(), /* comm */
scap_const_sized_buffer{nullptr, 0}, /* cgroups */
scap_const_sized_buffer{nullptr, 0}, /* env */
0, /* tty */
(uint64_t)0, /* vpgid */
0, /* loginuid */
0, /* flags */
(uint64_t)0, /* cap_inheritable */
(uint64_t)0, /* cap_permitted */
(uint64_t)0, /* cap_effective */
(uint64_t)0, /* exe_ino */
(uint64_t)0, /* exe_ino_ctime */
(uint64_t)0, /* exe_ino_mtime */
(uint32_t)0, /* uid */
"", /* trusted_exepath */
(uint64_t)0, /* pgid */
(uint32_t)0 /* gid */
);
}
sinsp_evt* sinsp_with_test_input::generate_execve_exit_event_with_empty_params(
const int64_t pid,
const std::string& file_to_run,
const std::string& comm) {
SCAP_EMPTY_PARAMS_SET(empty_params_set, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29);
return add_event_advance_ts_with_empty_params(
increasing_ts(),
1,
PPME_SYSCALL_EXECVE_19_X,
&empty_params_set,
30,
(int64_t)0, /* res */
file_to_run.c_str(), /* exe */
scap_const_sized_buffer{nullptr, 0}, /* args */
(uint64_t)pid, /* tid */
(uint64_t)pid, /* pid */
(uint64_t)pid, /* ptid */
"", /* cwd */
(uint64_t)0, /* fdlimit */
(uint64_t)0, /* pgft_maj */
(uint64_t)0, /* pgft_min */
0, /* vm_size */
0, /* vm_rss */
0, /* vm_swap */
comm.c_str(), /* comm */
empty_value<scap_const_sized_buffer>(), /* cgroups */
empty_value<scap_const_sized_buffer>(), /* env */
0, /* tty */
(uint64_t)0, /* vpgid */
empty_value<uint32_t>(), /* loginuid */
empty_value<uint32_t>(), /* flags */
empty_value<uint64_t>(), /* cap_inheritable */
empty_value<uint64_t>(), /* cap_permitted */
empty_value<uint64_t>(), /* cap_effective */
empty_value<uint64_t>(), /* exe_ino */
empty_value<uint64_t>(), /* exe_ino_ctime */
empty_value<uint64_t>(), /* exe_ino_mtime */
empty_value<uint32_t>(), /* uid */
empty_value<scap_const_sized_buffer>(), /* trusted_exepath */
empty_value<int64_t>(), /* pgid */
empty_value<uint32_t>()); /* gid */
}
void sinsp_with_test_input::remove_thread(int64_t tid_to_remove, int64_t reaper_tid) {
@ -393,6 +596,61 @@ sinsp_evt* sinsp_with_test_input::generate_socket_events(sinsp_test_input::socke
params.type,
params.proto);
}
#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && !defined(__APPLE__)
sinsp_evt* sinsp_with_test_input::generate_connect_events(
const sinsp_test_input::connect_params& params,
const int64_t tid_caller) {
std::vector<uint8_t> server_sockaddr;
std::vector<uint8_t> socktuple;
switch(params.family) {
case AF_INET: {
std::cout << "AF_INET" << std::endl;
sockaddr_in client =
test_utils::fill_sockaddr_in(params.client_in_port, params.client_in_addr_string);
sockaddr_in server =
test_utils::fill_sockaddr_in(params.server_in_port, params.server_in_addr_string);
server_sockaddr = test_utils::pack_sockaddr(reinterpret_cast<sockaddr*>(&server));
socktuple = test_utils::pack_socktuple(reinterpret_cast<sockaddr*>(&client),
reinterpret_cast<sockaddr*>(&server));
break;
}
case AF_INET6: {
sockaddr_in6 client = test_utils::fill_sockaddr_in6(params.client_in6_port,
params.client_in6_addr_string);
sockaddr_in6 server = test_utils::fill_sockaddr_in6(params.server_in6_port,
params.server_in6_addr_string);
server_sockaddr = test_utils::pack_sockaddr(reinterpret_cast<sockaddr*>(&server));
socktuple = test_utils::pack_socktuple(reinterpret_cast<sockaddr*>(&client),
reinterpret_cast<sockaddr*>(&server));
break;
}
case AF_UNIX: {
sockaddr_un server = test_utils::fill_sockaddr_un(params.un_path);
server_sockaddr = test_utils::pack_sockaddr(reinterpret_cast<sockaddr*>(&server));
socktuple = test_utils::pack_unix_socktuple(0x9c758d0f, 0x9c758d0a, params.un_path);
break;
}
default:
throw sinsp_exception("Unsupported socket family " + std::to_string(params.family));
}
add_event_advance_ts(increasing_ts(),
tid_caller,
PPME_SOCKET_CONNECT_E,
2,
params.fd,
scap_const_sized_buffer{server_sockaddr.data(), server_sockaddr.size()});
return add_event_advance_ts(
increasing_ts(),
tid_caller,
PPME_SOCKET_CONNECT_X,
4,
(int64_t)0,
scap_const_sized_buffer{socktuple.data(), socktuple.size()},
params.fd,
scap_const_sized_buffer{server_sockaddr.data(), server_sockaddr.size()});
}
#endif
//=============================== PROCESS GENERATION ===========================

View File

@ -72,6 +72,57 @@ struct socket_params {
};
};
struct connect_params {
static constexpr int64_t default_fd = 4;
static constexpr int64_t default_family = AF_INET;
static constexpr int64_t default_src_pointer = 0xaaaaaaaaaaaaaaaa;
static constexpr int64_t default_dst_pointer = 0xbbbbbbbbbbbbbbbb;
int64_t fd = default_fd;
int family = default_family;
// AF_INET parameters.
uint32_t client_in_port = DEFAULT_CLIENT_PORT;
uint32_t server_in_port = DEFAULT_SERVER_PORT;
const char* client_in_addr_string = DEFAULT_IPV4_CLIENT_STRING;
const char* server_in_addr_string = DEFAULT_IPV4_SERVER_STRING;
// AF_INET6 parameters.
uint32_t client_in6_port = DEFAULT_CLIENT_PORT;
uint32_t server_in6_port = DEFAULT_SERVER_PORT;
const char* client_in6_addr_string = DEFAULT_IPV6_CLIENT_STRING;
const char* server_in6_addr_string = DEFAULT_IPV6_SERVER_STRING;
// AF_UNIX parameters.
uint64_t un_src_pointer = default_src_pointer;
uint64_t un_dst_pointer = default_dst_pointer;
const char* un_path = DEFAULT_UNIX_SOCKET_PATH_STRING;
explicit connect_params(const int family): family{family} {}
connect_params() {
fd = default_fd;
family = default_family;
// AF_INET parameters.
client_in_port = DEFAULT_CLIENT_PORT;
server_in_port = DEFAULT_SERVER_PORT;
client_in_addr_string = DEFAULT_IPV4_CLIENT_STRING;
server_in_addr_string = DEFAULT_IPV4_SERVER_STRING;
// AF_INET6 parameters.
client_in6_port = DEFAULT_CLIENT_PORT;
server_in6_port = DEFAULT_SERVER_PORT;
client_in6_addr_string = DEFAULT_IPV6_CLIENT_STRING;
server_in6_addr_string = DEFAULT_IPV6_SERVER_STRING;
// AF_UNIX parameters.
un_src_pointer = default_src_pointer;
un_dst_pointer = default_dst_pointer;
un_path = DEFAULT_UNIX_SOCKET_PATH_STRING;
}
};
struct fd_info_fields {
std::optional<int64_t> fd_num = std::nullopt;
std::optional<std::string> fd_name = std::nullopt;
@ -189,25 +240,67 @@ protected:
_add_event(ts, tid, code, n, ##__VA_ARGS__); \
_check_event_params(__FILE__, __LINE__, code, n, ##__VA_ARGS__)
scap_evt* _add_event(uint64_t ts, uint64_t tid, ppm_event_code, uint32_t n, ...);
sinsp_evt* advance_ts_get_event(uint64_t ts);
#define add_event_with_empty_params(ts, tid, code, empty_params_set, n, ...) \
_add_event_with_empty_params(ts, tid, code, empty_params_set, n, ##__VA_ARGS__); \
_check_event_params(__FILE__, __LINE__, code, n, ##__VA_ARGS__)
#define add_event_advance_ts(ts, tid, code, n, ...) \
_add_event_advance_ts(ts, tid, code, n, ##__VA_ARGS__); \
_check_event_params(__FILE__, __LINE__, code, n, ##__VA_ARGS__)
sinsp_evt* _add_event_advance_ts(uint64_t ts, uint64_t tid, ppm_event_code, uint32_t n, ...);
#define add_event_advance_ts_with_empty_params(ts, tid, code, empty_params_set, n, ...) \
_add_event_advance_ts_with_empty_params(ts, tid, code, empty_params_set, n, ##__VA_ARGS__); \
_check_event_params(__FILE__, __LINE__, code, n, ##__VA_ARGS__)
sinsp_evt* advance_ts_get_event(uint64_t ts);
scap_evt* _add_event(uint64_t ts, uint64_t tid, ppm_event_code event_type, uint32_t n, ...);
scap_evt* _add_event_with_empty_params(uint64_t ts,
uint64_t tid,
ppm_event_code event_type,
const scap_empty_params_set* empty_params_set,
uint32_t n,
...);
sinsp_evt* _add_event_advance_ts(uint64_t ts,
uint64_t tid,
ppm_event_code event_type,
uint32_t n,
...);
sinsp_evt* _add_event_advance_ts_with_empty_params(
uint64_t ts,
uint64_t tid,
ppm_event_code event_type,
const scap_empty_params_set* empty_params_set,
uint32_t n,
...);
sinsp_evt* add_event_advance_ts_v(uint64_t ts,
uint64_t tid,
ppm_event_code,
ppm_event_code event_type,
const scap_empty_params_set* empty_params_set,
uint32_t n,
va_list args);
scap_evt* create_event_v(uint64_t ts, uint64_t tid, ppm_event_code, uint32_t n, va_list args);
scap_evt* add_event_v(uint64_t ts, uint64_t tid, ppm_event_code, uint32_t n, va_list args);
scap_evt* add_async_event(uint64_t ts, uint64_t tid, ppm_event_code, uint32_t n, ...);
scap_evt* create_event_v(uint64_t ts,
uint64_t tid,
ppm_event_code event_type,
const scap_empty_params_set* empty_params_set,
uint32_t n,
va_list args);
scap_evt* add_event_v(uint64_t ts,
uint64_t tid,
ppm_event_code event_type,
const scap_empty_params_set* empty_params_set,
uint32_t n,
va_list args);
scap_evt* add_async_event(uint64_t ts,
uint64_t tid,
ppm_event_code event_type,
uint32_t n,
...);
scap_evt* add_async_event_v(uint64_t ts,
uint64_t tid,
ppm_event_code,
ppm_event_code event_type,
const scap_empty_params_set* empty_params_set,
uint32_t n,
va_list args);
@ -236,6 +329,26 @@ protected:
const std::string& resolved_kernel_path = "/bin/test-exe",
const std::vector<std::string>& cgroup_vec = {},
int64_t pgid = 0);
sinsp_evt* generate_execveat_enter_and_exit_event(
int64_t retval,
int64_t old_tid,
int64_t new_tid,
int64_t pid,
int64_t ppid,
const std::string& pathname = "/bin/test-exe",
const std::string& comm = "test-exe",
const std::string& resolved_kernel_path = "/bin/test-exe",
const std::vector<std::string>& cgroup_vec = {},
int64_t pgid = 0);
sinsp_evt* generate_execve_exit_event_with_default_params(int64_t pid,
const std::string& file_to_run,
const std::string& comm);
// Generate a PPME_SYSCALL_EXECVE_19_X event with empty parameters in the range 18-29.
sinsp_evt* generate_execve_exit_event_with_empty_params(int64_t pid,
const std::string& file_to_run,
const std::string& comm);
void remove_thread(int64_t tid_to_remove, int64_t reaper_tid);
sinsp_evt* generate_proc_exit_event(int64_t tid_to_remove, int64_t reaper_tid);
sinsp_evt* generate_random_event(int64_t tid_caller = INIT_TID);
@ -245,6 +358,11 @@ protected:
sinsp_evt* generate_socket_events(sinsp_test_input::socket_params params = {},
int64_t tid_caller = INIT_TID);
#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && !defined(__APPLE__)
sinsp_evt* generate_connect_events(const sinsp_test_input::connect_params& params = {},
int64_t tid_caller = INIT_TID);
#endif
//=============================== PROCESS GENERATION ===========================
void add_thread(const scap_threadinfo&, const std::vector<scap_fdinfo>&);
@ -331,6 +449,12 @@ protected:
sinsp_evt* next_event();
// Return an empty value for the type T.
template<typename T>
constexpr static T empty_value() {
return static_cast<T>(0);
}
scap_test_input_data m_test_data;
std::vector<scap_evt*> m_events;
std::vector<scap_evt*> m_async_events;
@ -343,3 +467,13 @@ protected:
uint64_t m_test_timestamp = 1566230400000000000;
uint64_t m_last_recorded_timestamp = 0;
};
template<>
constexpr scap_const_sized_buffer sinsp_with_test_input::empty_value() {
return {nullptr, 0};
}
template<>
constexpr char* sinsp_with_test_input::empty_value() {
return nullptr;
}

View File

@ -22,41 +22,6 @@ limitations under the License.
#include <sinsp_with_test_input.h>
#include <test_utils.h>
#define generate_execve_x(pid, file_to_run, comm) \
add_event_advance_ts(increasing_ts(), \
pid, \
PPME_SYSCALL_EXECVE_19_X, \
29, \
(int64_t)0, /* res */ \
file_to_run, /* exe */ \
scap_const_sized_buffer{nullptr, 0}, /* args */ \
(uint64_t)pid, /* tid */ \
(uint64_t)pid, /* pid */ \
(uint64_t)pid, /* ptid */ \
"", /* cwd */ \
(uint64_t)0, /* fdlimit */ \
(uint64_t)0, /* pgft_maj */ \
(uint64_t)0, /* pgft_min */ \
0, /* vm_size */ \
0, /* vm_rss */ \
0, /* vm_swap */ \
comm, /* comm */ \
scap_const_sized_buffer{nullptr, 0}, /* cgroups */ \
scap_const_sized_buffer{nullptr, 0}, /* env */ \
0, /* tty */ \
(uint64_t)0, /* vpgid */ \
0, /* loginuid */ \
0, /* flags */ \
(uint64_t)0, /* cap_inheritable */ \
(uint64_t)0, /* cap_permitted */ \
(uint64_t)0, /* cap_effective */ \
(uint64_t)0, /* exe_ino */ \
(uint64_t)0, /* exe_ino_ctime */ \
(uint64_t)0, /* exe_ino_mtime */ \
(uint32_t)0, /* uid */ \
"", /* trusted_exepath */ \
(uint64_t)0) /* pgid */
TEST_F(sinsp_with_test_input, suppress_comm) {
//
// init (pid 1)
@ -79,7 +44,7 @@ TEST_F(sinsp_with_test_input, suppress_comm) {
// Whenever we try to add an event to sinsp_with_test_input, if
// the event is suppressed we get an exception.
EXPECT_ANY_THROW(generate_execve_x(pid, file_to_run, "sh"));
EXPECT_ANY_THROW(generate_execve_exit_event_with_default_params(pid, file_to_run, "sh"));
const auto& thread_manager = m_inspector.m_thread_manager;
@ -124,14 +89,15 @@ TEST_F(sinsp_with_test_input, suppress_comm_execve) {
// Whenever we try to add an event to sinsp_with_test_input, if
// the event is suppressed we get an exception.
EXPECT_ANY_THROW(generate_execve_x(pid, file_to_run, "sh"));
EXPECT_ANY_THROW(generate_execve_exit_event_with_default_params(pid, file_to_run, "sh"));
EXPECT_ANY_THROW(add_event_advance_ts(increasing_ts(),
pid,
PPME_SYSCALL_EXECVE_19_E,
1,
"/bin/test-exe"));
EXPECT_ANY_THROW(generate_execve_x(pid, "/bin/test-exe", "test-exe"));
EXPECT_ANY_THROW(
generate_execve_exit_event_with_default_params(pid, "/bin/test-exe", "test-exe"));
const auto& thread_manager = m_inspector.m_thread_manager;

View File

@ -40,6 +40,8 @@ limitations under the License.
#define DEFAULT_IPV4_FDNAME "172.40.111.222:54321->142.251.111.147:443"
#define DEFAULT_IPV6_FDNAME "::1:54321->2001:4860:4860::8888:443"
#define DEFAULT_UNIX_SOCKET_PATH_STRING "/tmp/socket.sock"
#define DEFAULT_IP_STRING_SIZE 100
#if defined(__linux__)

View File

@ -216,24 +216,10 @@ struct user_group_updater {
case PPME_PROCEXIT_1_E:
m_check_cleanup = true;
// falltrough
case PPME_SYSCALL_CLONE_11_X:
case PPME_SYSCALL_CLONE_16_X:
case PPME_SYSCALL_CLONE_17_X:
case PPME_SYSCALL_CLONE_20_X:
case PPME_SYSCALL_FORK_X:
case PPME_SYSCALL_FORK_17_X:
case PPME_SYSCALL_FORK_20_X:
case PPME_SYSCALL_VFORK_X:
case PPME_SYSCALL_VFORK_17_X:
case PPME_SYSCALL_VFORK_20_X:
case PPME_SYSCALL_CLONE3_X:
case PPME_SYSCALL_EXECVE_8_X:
case PPME_SYSCALL_EXECVE_13_X:
case PPME_SYSCALL_EXECVE_14_X:
case PPME_SYSCALL_EXECVE_15_X:
case PPME_SYSCALL_EXECVE_16_X:
case PPME_SYSCALL_EXECVE_17_X:
case PPME_SYSCALL_EXECVE_18_X:
case PPME_SYSCALL_EXECVE_19_X:
case PPME_SYSCALL_EXECVEAT_X:
case PPME_SYSCALL_CHROOT_X:

View File

@ -737,7 +737,7 @@ std::string sinsp_utils::concatenate_paths(std::string_view path1, std::string_v
return std::string(fullpath);
}
bool sinsp_utils::is_ipv4_mapped_ipv6(uint8_t* paddr) {
bool sinsp_utils::is_ipv4_mapped_ipv6(const uint8_t* paddr) {
if(paddr[0] == 0 && paddr[1] == 0 && paddr[2] == 0 && paddr[3] == 0 && paddr[4] == 0 &&
paddr[5] == 0 && paddr[6] == 0 && paddr[7] == 0 && paddr[8] == 0 && paddr[9] == 0 &&
((paddr[10] == 0xff && paddr[11] == 0xff) || // A real IPv4 address
@ -1042,8 +1042,8 @@ std::string ipv4tuple_to_string(const ipv4tuple& tuple, const bool resolve) {
}
std::string ipv6serveraddr_to_string(const ipv6serverinfo& addr, const bool resolve) {
char address[100];
if(!inet_ntop(AF_INET6, addr.m_ip.m_b, address, 100)) {
char address[INET6_ADDRSTRLEN];
if(!inet_ntop(AF_INET6, addr.m_ip.m_b, address, INET6_ADDRSTRLEN)) {
return std::string();
}
@ -1058,12 +1058,12 @@ std::string ipv6serveraddr_to_string(const ipv6serverinfo& addr, const bool reso
std::string ipv6tuple_to_string(const ipv6tuple& tuple, const bool resolve) {
char source_address[INET6_ADDRSTRLEN];
if(!inet_ntop(AF_INET6, tuple.m_fields.m_sip.m_b, source_address, 100)) {
if(!inet_ntop(AF_INET6, tuple.m_fields.m_sip.m_b, source_address, INET6_ADDRSTRLEN)) {
return std::string();
}
char destination_address[INET6_ADDRSTRLEN];
if(!inet_ntop(AF_INET6, tuple.m_fields.m_dip.m_b, destination_address, 100)) {
if(!inet_ntop(AF_INET6, tuple.m_fields.m_dip.m_b, destination_address, INET6_ADDRSTRLEN)) {
return std::string();
}

View File

@ -120,7 +120,7 @@ public:
//
// Determines if an IPv6 address is IPv4-mapped
//
static bool is_ipv4_mapped_ipv6(uint8_t* paddr);
static bool is_ipv4_mapped_ipv6(const uint8_t* paddr);
//
// Given a string, scan the event list and find the longest argument that the input string

View File

@ -62,6 +62,7 @@ size_t sinsp_filter_value_parser::string_to_rawval(const char* str,
case PT_INT64:
case PT_FD:
case PT_ERRNO:
case PT_PID:
check_storage_size(str, max_len, sizeof(int64_t));
*(int64_t*)storage = sinsp_numparser::parsed64(str);
parsed_len = sizeof(int64_t);
@ -109,6 +110,8 @@ size_t sinsp_filter_value_parser::string_to_rawval(const char* str,
case PT_UINT32:
case PT_MODE:
case PT_ENUMFLAGS32:
case PT_UID:
case PT_GID:
check_storage_size(str, max_len, sizeof(uint32_t));
*(uint32_t*)storage = sinsp_numparser::parseu32(str);
parsed_len = sizeof(uint32_t);
@ -126,6 +129,7 @@ size_t sinsp_filter_value_parser::string_to_rawval(const char* str,
break;
case PT_CHARBUF:
case PT_SOCKADDR:
case PT_SOCKTUPLE:
case PT_SOCKFAMILY:
case PT_FSPATH:
case PT_FSRELPATH: {