Compare commits

...

69 Commits

Author SHA1 Message Date
Angelo Puglisi 9120d29691
Merge ee14b3e328 into a273f3d05c 2025-08-05 01:53:48 +01: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
Leonardo Di Giovanna 0394af7612 fix(userspace/libsinsp): fix recv data buffer index
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-11 18:21:24 +02:00
Leonardo Di Giovanna 45952bf4c7 fix: fix scap converter `PT_UID` parameters default value
Fix the scap converter `PT_UID` parameters default value by setting it
to `UINT32_MAX`. Moreover, fix scap converter tests and sinsp parser
code to correctly account for the default value.

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-10 20:09:18 +02:00
Leonardo Di Giovanna e8d3b78fff fix(userspace/libsinsp): fix threadinfo ctor params forward decl
`sinsp_threadinfo_ctor_params` is declared as struct but
forward-declared as class. Fix forward declaration by declaring it
as struct.

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-10 14:53:17 +02:00
Leonardo Di Giovanna c658df0835 refactor: clean scap converter tests
Constify wherever possible and remove redundant qualifiers.

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-10 12:38:16 +02:00
Leonardo Di Giovanna 25159de410 feat: add `PPME_SYSCALL_CONNECT_E` params to `PPME_SYSCALL_CONNECT_X`
Add `PPME_SYSCALL_CONNECT_E` parameters to` PPME_SYSCALL_CONNECT_X`
event definition and align all 3 kernel drivers to it.

Add new rules to scap file converter table to convert events in old
scap files to the new layout.

Add/update connect-related drivers, scap converter and sinsp parser
tests to account the new layout.

For the moment, do not touch userspace connect "enter event"-related
logic as it requires additional work to be done on driver's tuple
generation logic.

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-10 12:08:17 +02:00
Angelo Puglisi a320519189 feat(userspace/libsinsp/example): print tables entries
Introduced an optional argument to -T, to output the tables entries in a
json format.

Signed-off-by: Angelo Puglisi <angelopuglisi86@gmail.com>
2025-07-09 19:16:10 +02:00
Angelo Puglisi 9494d6f0c5 feat(libsinsp/state): introduce table_input_adapter
Helper class to access subtables

Signed-off-by: Angelo Puglisi <angelopuglisi86@gmail.com>
2025-07-09 19:16:10 +02:00
Angelo Puglisi 3797e18e31 feat(libsinsp/state): typeinfo::from
Introduce typeinfo::from convenience function, to create a typeinfo
object from ss_plugin_state_type

Signed-off-by: Angelo Puglisi <angelopuglisi86@gmail.com>
2025-07-09 19:16:10 +02:00
Leonardo Di Giovanna 0f6ea5c6f2 fix(driver/bpf): fix `sched_process_exec_args` conditional definition
The current `sched_process_exec_args` raw tracepoint definition is
actually the tracepoint one; similarly, the current tracepoint
defintion is actually the raw tracepoint one. Swap them to give the
correct definition on each context.

Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-07-09 17:12:10 +02:00
Tero Kauppinen 94b471887f feat(libscap/libsinsp): fcntl scap conversion
This update adds scap event conversion for the fcntl syscall exit
events and it eliminates the need to store the entry event in
libsinsp.

Signed-off-by: Tero Kauppinen <tero.kauppinen@est.tech>
2025-07-09 15:25:09 +02:00
Angelo Puglisi 4d572b21b9 chore(libsinsp): clean "detect container id" comments
Missed from https://github.com/falcosecurity/libs/pull/2207, the comment
makes no sense now. Drop it.

Signed-off-by: Angelo Puglisi <angelopuglisi86@gmail.com>
2025-07-09 14:06:08 +02:00
Super User 2a5b4c7347 fix(test/drivers): correctly handle accept socketcalls on s390x
Revise the socketcall test case for accept for modern BPF and
other drivers.

On s390x, there is no direct accept syscall and for modern BPF
accept4 is used instead.

The BPF and kernel drivers handle socketcalls internally and, thus,
can handle accept. There was only special handling for setting up
the event.  This commit also adds handling for the argument assertions.

Solving these test case failures:

````
Expected: (m_current_param) <= (m_event_header->nparams), actual: 6 vs 5
>>>>> The param id '6' is too big.

/root/git/libs/test/drivers/event_class/event_class.cpp:1457: Failure
Expected equality of these values:
  size
    Which is: 0
  expected_size
    Which is: 4
>>>>> length of the param is not correct. Param id = 6

[  FAILED  ] SyscallExit.socketcall_acceptX_INET
[  FAILED  ] SyscallExit.socketcall_acceptX_INET6
[  FAILED  ] SyscallExit.socketcall_acceptX_UNIX
[  FAILED  ] SyscallExit.socketcall_acceptX_failure
````

Signed-off-by: Hendrik Brueckner <brueckner@linux.ibm.com>
2025-07-08 15:50:01 +02:00
Super User 52ddeb4950 chore(test/libsinsp_e2e): add climits header file
Recent compilers complain about missing climits header file:

libs/test/libsinsp_e2e/sys_call_test.cpp: In lambda function:
/root/git/libs/test/libsinsp_e2e/sys_call_test.cpp:266:23: error: ‘INT_MAX’ was not declared in this scope
  266 |                 close(INT_MAX);
      |                       ^~~~~~~
libs/test/libsinsp_e2e/sys_call_test.cpp:266:23: note: ‘INT_MAX’ is defined in header ‘<climits>’; this is probably fixable by adding ‘#include <climits>’

Signed-off-by: Hendrik Brueckner <brueckner@linux.ibm.com>
2025-07-08 15:50:01 +02:00
Angelo Puglisi ee14b3e328 update(libsinsp): get_dynamic_field constness
Signed-off-by: Angelo Puglisi <angelopuglisi86@gmail.com>
2025-06-26 15:48:03 +02:00
109 changed files with 7922 additions and 3293 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.64.0
3.69.0

View File

@ -1436,57 +1436,60 @@ FILLER(sys_connect_x, true) {
int res = bpf_push_s64_to_ring(data, retval);
CHECK_RES(res);
/* Get socket file descriptor, sockaddr pointer and length. */
int64_t fd = (int64_t)(int32_t)bpf_syscall_get_argument(data, 0);
if(retval != 0 && retval != -EINPROGRESS) {
/* Parameter 2: tuple (type: PT_SOCKTUPLE) */
res = bpf_push_empty_param(data);
CHECK_RES(res);
/* Parameter 3: fd (type: PT_FD) */
return bpf_push_s64_to_ring(data, fd);
}
/* Get the sockaddr pointer and length. */
struct sockaddr __user *usrsockaddr =
(struct sockaddr __user *)bpf_syscall_get_argument(data, 1);
unsigned long usrsockaddr_len = bpf_syscall_get_argument(data, 2);
/* Evaluate socktuple, leveraging the user-provided sockaddr if possible */
/* Copy the user-provided sockaddr into kernel memory, if possible. */
struct sockaddr *ksockaddr = (struct sockaddr *)data->tmp_scratch;
bool use_sockaddr_user_data = false;
bool can_use_sockaddr_data = false;
bool push_socktuple = true;
if(usrsockaddr != NULL && usrsockaddr_len != 0) {
/* Copy the address into kernel memory. */
res = bpf_addr_to_kernel(usrsockaddr, usrsockaddr_len, ksockaddr);
if(likely(res >= 0)) {
/* Convert the fd into socket endpoint information. */
use_sockaddr_user_data = true;
can_use_sockaddr_data = true;
} else {
/* Do not send any socket endpoint information. */
push_socktuple = false;
}
}
uint32_t tuple_size = 0;
if(push_socktuple) {
/* Convert the fd into socket endpoint information */
tuple_size = bpf_fd_to_socktuple(data,
fd,
ksockaddr,
usrsockaddr_len,
use_sockaddr_user_data,
false,
data->tmp_scratch + sizeof(struct sockaddr_storage));
}
/* Parameter 2: tuple (type: PT_SOCKTUPLE) */
data->curarg_already_on_frame = true;
res = bpf_val_to_ring_len(data, 0, tuple_size);
if(retval != 0 && retval != -EINPROGRESS) {
res = bpf_push_empty_param(data);
} else {
uint32_t tuple_size = 0;
if(push_socktuple) {
/* Use the file descriptor (and possibly the sockaddr) to obtain the socket tuple.
* The socket tuple is stored into the provided temp area. */
tuple_size = bpf_fd_to_socktuple(data,
fd,
ksockaddr,
usrsockaddr_len,
can_use_sockaddr_data,
false,
data->tmp_scratch + sizeof(struct sockaddr_storage));
}
data->curarg_already_on_frame = true;
res = bpf_val_to_ring_len(data, 0, tuple_size);
}
CHECK_RES(res);
/* Parameter 3: fd (type: PT_FD) */
return bpf_push_s64_to_ring(data, fd);
res = bpf_push_s64_to_ring(data, fd);
CHECK_RES(res);
long addr_size = 0;
if(can_use_sockaddr_data) {
/* Convert the fd into socket endpoint information. */
addr_size = bpf_pack_addr(data, ksockaddr, usrsockaddr_len);
}
/* Parameter 4: addr (type: PT_SOCKADDR) */
data->curarg_already_on_frame = true;
return bpf_val_to_ring_len(data, 0, addr_size);
}
FILLER(sys_socketpair_x, true) {
@ -2596,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;
@ -2607,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);
@ -2687,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 {
@ -2700,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);
@ -2712,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);
@ -2778,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);
@ -2814,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);
@ -2973,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
@ -3031,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)
@ -7938,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

@ -143,6 +143,16 @@ struct sys_stash_args {
#ifdef CAPTURE_SCHED_PROC_EXEC
#ifndef BPF_SUPPORTS_RAW_TRACEPOINTS
struct sched_process_exec_args {
unsigned short common_type;
unsigned char common_flags;
unsigned char common_preempt_count;
int common_pid;
__u32 filename; // This is actually defined as "__data_loc char[] filename;".
pid_t pid;
pid_t old_pid;
};
#else
/* TP_PROTO(struct task_struct *p, pid_t old_pid, struct linux_binprm *bprm)
* Taken from `/include/trace/events/sched.h`
*/
@ -151,16 +161,6 @@ struct sched_process_exec_args {
pid_t old_pid;
struct linux_binprm *bprm;
};
#else
struct sched_process_exec_args {
unsigned short common_type;
unsigned char common_flags;
unsigned char common_preempt_count;
int common_pid;
int filename;
pid_t pid;
pid_t old_pid;
};
#endif /* BPF_SUPPORTS_RAW_TRACEPOINTS */
#endif /* CAPTURE_SCHED_PROC_EXEC */

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},
@ -184,16 +184,17 @@ const struct ppm_event_info g_event_info[] = {
{"fd", PT_FD, PF_DEC}}},
[PPME_SOCKET_CONNECT_E] = {"connect",
EC_NET | EC_SYSCALL,
EF_USES_FD | EF_MODIFIES_STATE,
EF_USES_FD | EF_MODIFIES_STATE | EF_TMP_CONVERTER_MANAGED,
2,
{{"fd", PT_FD, PF_DEC}, {"addr", PT_SOCKADDR, PF_NA}}},
[PPME_SOCKET_CONNECT_X] = {"connect",
EC_NET | EC_SYSCALL,
EF_USES_FD | EF_MODIFIES_STATE,
3,
EF_USES_FD | EF_MODIFIES_STATE | EF_TMP_CONVERTER_MANAGED,
4,
{{"res", PT_ERRNO, PF_DEC},
{"tuple", PT_SOCKTUPLE, PF_NA},
{"fd", PT_FD, PF_DEC}}},
{"fd", PT_FD, PF_DEC},
{"addr", PT_SOCKADDR, PF_NA}}},
[PPME_SOCKET_LISTEN_E] = {"listen",
EC_NET | EC_SYSCALL,
EF_USES_FD | EF_TMP_CONVERTER_MANAGED,
@ -607,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,
@ -626,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,
@ -870,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},
@ -906,13 +928,13 @@ const struct ppm_event_info g_event_info[] = {
{{"ratio", PT_UINT32, PF_DEC}}},
[PPME_SYSCALL_FCNTL_E] = {"fcntl",
EC_IO_OTHER | EC_SYSCALL,
EF_USES_FD | EF_MODIFIES_STATE,
EF_USES_FD | EF_MODIFIES_STATE | EF_TMP_CONVERTER_MANAGED,
2,
{{"fd", PT_FD, PF_DEC},
{"cmd", PT_ENUMFLAGS8, PF_DEC, fcntl_commands}}},
[PPME_SYSCALL_FCNTL_X] = {"fcntl",
EC_IO_OTHER | EC_SYSCALL,
EF_USES_FD | EF_MODIFIES_STATE,
EF_USES_FD | EF_MODIFIES_STATE | EF_TMP_CONVERTER_MANAGED,
3,
{{"res", PT_FD, PF_DEC},
{"fd", PT_FD, PF_DEC},
@ -931,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},
@ -952,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},
@ -1101,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},
@ -1150,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},
@ -1158,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},
@ -1182,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},
@ -1350,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},
@ -1373,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},
@ -1398,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},
@ -1423,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},
@ -1446,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},
@ -1472,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},
@ -1498,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},
@ -1535,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},
@ -1827,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},
@ -1872,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},
@ -1911,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},
@ -1987,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},
@ -1996,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},
@ -2043,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},
@ -2145,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},
@ -2196,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},
@ -2470,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

@ -29,9 +29,9 @@ int BPF_PROG(connect_e, struct pt_regs *regs, long id) {
auxmap__store_s64_param(auxmap, socket_fd);
/* Parameter 2: addr (type: PT_SOCKADDR) */
unsigned long sockaddr_ptr = args[1];
uint16_t addrlen = (uint16_t)args[2];
auxmap__store_sockaddr_param(auxmap, sockaddr_ptr, addrlen);
unsigned long usrsockaddr = args[1];
uint16_t usrsockaddr_len = (uint16_t)args[2];
auxmap__store_sockaddr_param(auxmap, usrsockaddr, usrsockaddr_len);
/*=============================== COLLECT PARAMETERS ===========================*/
@ -57,16 +57,17 @@ int BPF_PROG(connect_x, struct pt_regs *regs, long ret) {
/*=============================== COLLECT PARAMETERS ===========================*/
unsigned long args[2] = {0};
extract__network_args(args, 2, regs);
unsigned long args[3] = {0};
extract__network_args(args, 3, regs);
int64_t socket_fd = (int64_t)(int32_t)args[0];
/* Parameter 1: res (type: PT_ERRNO) */
auxmap__store_s64_param(auxmap, ret);
struct sockaddr *usrsockaddr = (struct sockaddr *)args[1];
/* Parameter 2: tuple (type: PT_SOCKTUPLE) */
if(ret == 0 || ret == -EINPROGRESS) {
struct sockaddr *usrsockaddr = (struct sockaddr *)args[1];
/* Notice: the following will push an empty parameter if
* something goes wrong (e.g.: fd not valid). */
auxmap__store_socktuple_param(auxmap, (int32_t)socket_fd, OUTBOUND, usrsockaddr);
@ -77,6 +78,10 @@ int BPF_PROG(connect_x, struct pt_regs *regs, long ret) {
/* Parameter 3: fd (type: PT_FD) */
auxmap__store_s64_param(auxmap, socket_fd);
/* Parameter 4: addr (type: PT_SOCKADDR) */
uint16_t usrsockaddr_len = (uint16_t)args[2];
auxmap__store_sockaddr_param(auxmap, (unsigned long)usrsockaddr, usrsockaddr_len);
/*=============================== COLLECT PARAMETERS ===========================*/
auxmap__finalize_event_header(auxmap);

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);
@ -1726,10 +1685,13 @@ int f_sys_connect_e(struct event_filler_arguments *args) {
if(usrsockaddr != NULL && usrsockaddr_len != 0) {
/* Copy the address into kernel memory. */
res = addr_to_kernel(usrsockaddr, val, (struct sockaddr *)&address);
res = addr_to_kernel(usrsockaddr, usrsockaddr_len, (struct sockaddr *)&address);
if(likely(res >= 0)) {
/* Convert the fd into socket endpoint information. */
addr_size = pack_addr((struct sockaddr *)&address, val, targetbuf, STR_STORAGE_SIZE);
addr_size = pack_addr((struct sockaddr *)&address,
usrsockaddr_len,
targetbuf,
STR_STORAGE_SIZE);
}
}
@ -1750,63 +1712,63 @@ int f_sys_connect_x(struct event_filler_arguments *args) {
struct sockaddr_storage address;
struct sockaddr *ksockaddr = NULL;
unsigned long sockaddr_len = 0;
bool use_sockaddr = false;
bool can_use_sockaddr_data = false;
char *targetbuf = args->str_storage;
uint16_t tuple_size = 0;
uint16_t tuple_size = 0, addr_size = 0;
/* 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);
/* Get socket file descriptor, sockaddr pointer and length. */
syscall_get_arguments_deprecated(args, 0, 1, &val);
fd = (int64_t)(int32_t)val;
if(retval != 0 && retval != -EINPROGRESS) {
/* Parameter 2: tuple (type: PT_SOCKTUPLE) */
res = push_empty_param(args);
CHECK_RES(res);
/* Parameter 3: fd (type: PT_FD) */
res = val_to_ring(args, fd, 0, false, 0);
CHECK_RES(res);
return add_sentinel(args);
}
/* Get the address */
syscall_get_arguments_deprecated(args, 1, 1, &val);
usrsockaddr = (struct sockaddr __user *)val;
/* Get the address len */
syscall_get_arguments_deprecated(args, 2, 1, &usrsockaddr_len);
/* Copy the user-provided sockaddr into kernel memory, if possible. */
if(usrsockaddr != NULL && usrsockaddr_len != 0) {
/* Copy the address into kernel memory */
res = addr_to_kernel(usrsockaddr, usrsockaddr_len, (struct sockaddr *)&address);
if(likely(res >= 0)) {
ksockaddr = (struct sockaddr *)&address;
sockaddr_len = usrsockaddr_len;
use_sockaddr = true;
can_use_sockaddr_data = true;
}
}
/* Convert the fd into socket endpoint information */
tuple_size = fd_to_socktuple((int)fd,
ksockaddr,
sockaddr_len,
use_sockaddr,
false,
targetbuf,
STR_STORAGE_SIZE);
/* Parameter 2: tuple (type: PT_SOCKTUPLE) */
res = val_to_ring(args, (uint64_t)(unsigned long)targetbuf, tuple_size, false, 0);
if(retval != 0 && retval != -EINPROGRESS) {
res = push_empty_param(args);
} else {
/* Use the file descriptor (and possibly the sockaddr) to obtain the socket tuple.
* The socket tuple is stored into the provided target buffer. */
tuple_size = fd_to_socktuple((int)fd,
ksockaddr,
sockaddr_len,
can_use_sockaddr_data,
false,
targetbuf,
STR_STORAGE_SIZE);
res = val_to_ring(args, (uint64_t)(unsigned long)targetbuf, tuple_size, false, 0);
}
CHECK_RES(res);
/* Parameter 3: fd (type: PT_FD) */
res = val_to_ring(args, fd, 0, false, 0);
CHECK_RES(res);
if(can_use_sockaddr_data) {
/* Encode the address and store it into the target buffer. */
addr_size = pack_addr(ksockaddr, sockaddr_len, targetbuf, STR_STORAGE_SIZE);
}
/* Parameter 2: addr (type: PT_SOCKADDR) */
res = val_to_ring(args, (uint64_t)targetbuf, addr_size, false, 0);
CHECK_RES(res);
return add_sentinel(args);
}
@ -9422,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

@ -74,9 +74,12 @@ TEST(SyscallExit, connectX_INET) {
/* Parameter 3: fd (type: PT_FD) */
evt_test->assert_numeric_param(3, (int64_t)client_socket_fd);
/* Parameter 4: addr (type: PT_SOCKADDR) */
evt_test->assert_addr_info_inet_param(4, PPM_AF_INET, IPV4_SERVER, IPV4_PORT_SERVER_STRING);
/*=============================== ASSERT PARAMETERS ===========================*/
evt_test->assert_num_params_pushed(3);
evt_test->assert_num_params_pushed(4);
}
TEST(SyscallExit, connectX_INET6) {
@ -146,9 +149,12 @@ TEST(SyscallExit, connectX_INET6) {
/* Parameter 3: fd (type: PT_FD) */
evt_test->assert_numeric_param(3, (int64_t)client_socket_fd);
/* Parameter 4: addr (type: PT_SOCKADDR) */
evt_test->assert_addr_info_inet6_param(4, PPM_AF_INET6, IPV6_SERVER, IPV6_PORT_SERVER_STRING);
/*=============================== ASSERT PARAMETERS ===========================*/
evt_test->assert_num_params_pushed(3);
evt_test->assert_num_params_pushed(4);
}
#ifdef __NR_unlinkat
@ -235,9 +241,12 @@ TEST(SyscallExit, connectX_UNIX) {
/* Parameter 3: fd (type: PT_FD) */
evt_test->assert_numeric_param(3, (int64_t)client_socket_fd);
/* Parameter 4: addr (type: PT_SOCKADDR) */
evt_test->assert_addr_info_unix_param(4, PPM_AF_UNIX, server_symlink);
/*=============================== ASSERT PARAMETERS ===========================*/
evt_test->assert_num_params_pushed(3);
evt_test->assert_num_params_pushed(4);
}
#endif /* __NR_unlinkat */
@ -279,9 +288,12 @@ TEST(SyscallExit, connectX_failure) {
/* Parameter 3: fd (type: PT_FD) */
evt_test->assert_numeric_param(3, (int64_t)mock_fd);
/* Parameter 4: addr (type: PT_SOCKADDR) */
evt_test->assert_empty_param(4);
/*=============================== ASSERT PARAMETERS ===========================*/
evt_test->assert_num_params_pushed(3);
evt_test->assert_num_params_pushed(4);
}
TEST(SyscallExit, connectX_failure_ECONNREFUSED) {
@ -340,9 +352,12 @@ TEST(SyscallExit, connectX_failure_ECONNREFUSED) {
/* Parameter 3: fd (type: PT_FD) */
evt_test->assert_numeric_param(3, (int64_t)client_socket_fd);
/* Parameter 4: addr (type: PT_SOCKADDR) */
evt_test->assert_addr_info_inet_param(4, PPM_AF_INET, IPV4_SERVER, IPV4_PORT_SERVER_STRING);
/*=============================== ASSERT PARAMETERS ===========================*/
evt_test->assert_num_params_pushed(3);
evt_test->assert_num_params_pushed(4);
}
TEST(SyscallExit, connectX_failure_EINPROGRESS) {
@ -422,8 +437,11 @@ TEST(SyscallExit, connectX_failure_EINPROGRESS) {
/* Parameter 3: fd (type: PT_FD) */
evt_test->assert_numeric_param(3, (int64_t)client_socket_fd);
/* Parameter 4: addr (type: PT_SOCKADDR) */
evt_test->assert_addr_info_inet_param(4, PPM_AF_INET, IPV4_SERVER, IPV4_PORT_SERVER_STRING);
/*=============================== ASSERT PARAMETERS ===========================*/
evt_test->assert_num_params_pushed(3);
evt_test->assert_num_params_pushed(4);
}
#endif

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

@ -220,9 +220,12 @@ TEST(SyscallExit, socketcall_connectX) {
/* Parameter 3: fd (type: PT_FD) */
evt_test->assert_numeric_param(3, (int64_t)client_socket_fd);
/* Parameter 4: addr (type: PT_SOCKADDR) */
evt_test->assert_addr_info_inet_param(4, PPM_AF_INET, IPV4_SERVER, IPV4_PORT_SERVER_STRING);
/*=============================== ASSERT PARAMETERS ===========================*/
evt_test->assert_num_params_pushed(3);
evt_test->assert_num_params_pushed(4);
}
#endif
@ -486,17 +489,18 @@ TEST(SyscallExit, socketcall_acceptX_INET) {
evt_test->assert_numeric_param(5, (uint32_t)QUEUE_LENGTH);
#ifdef __s390x__
// Under s390x we use accept4 instead of accept, and we collect the flags parameter for it.
/* Parameter 6: flags (type: PT_FLAGS32) */
/* Right now `flags` are not supported so we will catch always `0` */
evt_test->assert_numeric_param(6, (uint32_t)0);
#endif
/* Under s390x we use accept4 instead of accept, and we collect the flags parameter for it.
However, The kmod/bpf can correctly handle accept also on s390x (see also above) */
if(evt_test->is_kmod_engine() || evt_test->is_bpf_engine()) {
evt_test->assert_num_params_pushed(5);
} else {
/* accept4 is used */
/* Parameter 6: flags (type: PT_FLAGS32) */
/* Right now `flags` are not supported so we will catch always `0` */
evt_test->assert_numeric_param(6, (uint32_t)0);
/*=============================== ASSERT PARAMETERS ===========================*/
#ifdef __s390x__
// Under s390x we use accept4 instead of accept, and we collect the flags parameter for it.
evt_test->assert_num_params_pushed(6);
evt_test->assert_num_params_pushed(6);
}
#else
evt_test->assert_num_params_pushed(5);
#endif
@ -585,18 +589,21 @@ TEST(SyscallExit, socketcall_acceptX_INET6) {
/* Parameter 5: queuemax (type: PT_UINT32) */
evt_test->assert_numeric_param(5, (uint32_t)QUEUE_LENGTH);
#ifdef __s390x__
// Under s390x we use accept4 instead of accept, and we collect the flags parameter for it.
/* Parameter 6: flags (type: PT_FLAGS32) */
/* Right now `flags` are not supported so we will catch always `0` */
evt_test->assert_numeric_param(6, (uint32_t)0);
#endif
/*=============================== ASSERT PARAMETERS ===========================*/
#ifdef __s390x__
// Under s390x we use accept4 instead of accept, and we collect the flags parameter for it.
evt_test->assert_num_params_pushed(6);
/* Under s390x we use accept4 instead of accept, and we collect the flags parameter for it.
However, The kmod/bpf can correctly handle accept also on s390x (see also above) */
if(evt_test->is_kmod_engine() || evt_test->is_bpf_engine()) {
evt_test->assert_num_params_pushed(5);
} else {
/* accept4 is used */
/* Parameter 6: flags (type: PT_FLAGS32) */
/* Right now `flags` are not supported so we will catch always `0` */
evt_test->assert_numeric_param(6, (uint32_t)0);
evt_test->assert_num_params_pushed(6);
}
#else
evt_test->assert_num_params_pushed(5);
#endif
@ -684,17 +691,18 @@ TEST(SyscallExit, socketcall_acceptX_UNIX) {
evt_test->assert_numeric_param(5, (uint32_t)QUEUE_LENGTH);
#ifdef __s390x__
// Under s390x we use accept4 instead of accept, and we collect the flags parameter for it.
/* Parameter 6: flags (type: PT_FLAGS32) */
/* Right now `flags` are not supported so we will catch always `0` */
evt_test->assert_numeric_param(6, (uint32_t)0);
#endif
/* Under s390x we use accept4 instead of accept, and we collect the flags parameter for it.
However, The kmod/bpf can correctly handle accept also on s390x (see also above) */
if(evt_test->is_kmod_engine() || evt_test->is_bpf_engine()) {
evt_test->assert_num_params_pushed(5);
} else {
/* accept4 is used */
/* Parameter 6: flags (type: PT_FLAGS32) */
/* Right now `flags` are not supported so we will catch always `0` */
evt_test->assert_numeric_param(6, (uint32_t)0);
/*=============================== ASSERT PARAMETERS ===========================*/
#ifdef __s390x__
// Under s390x we use accept4 instead of accept, and we collect the flags parameter for it.
evt_test->assert_num_params_pushed(6);
evt_test->assert_num_params_pushed(6);
}
#else
evt_test->assert_num_params_pushed(5);
#endif
@ -763,17 +771,18 @@ TEST(SyscallExit, socketcall_acceptX_failure) {
evt_test->assert_numeric_param(5, (uint32_t)0);
#ifdef __s390x__
// Under s390x we use accept4 instead of accept, and we collect the flags parameter for it.
/* Parameter 6: flags (type: PT_FLAGS32) */
/* Right now `flags` are not supported so we will catch always `0` */
evt_test->assert_numeric_param(6, (uint32_t)0);
#endif
/* Under s390x we use accept4 instead of accept, and we collect the flags parameter for it.
However, The kmod/bpf can correctly handle accept also on s390x (see also above) */
if(evt_test->is_kmod_engine() || evt_test->is_bpf_engine()) {
evt_test->assert_num_params_pushed(5);
} else {
/* accept4 is used */
/* Parameter 6: flags (type: PT_FLAGS32) */
/* Right now `flags` are not supported so we will catch always `0` */
evt_test->assert_numeric_param(6, (uint32_t)0);
/*=============================== ASSERT PARAMETERS ===========================*/
#ifdef __s390x__
// Under s390x we use accept4 instead of accept, and we collect the flags parameter for it.
evt_test->assert_num_params_pushed(6);
evt_test->assert_num_params_pushed(6);
}
#else
evt_test->assert_num_params_pushed(5);
#endif

View File

@ -43,7 +43,8 @@ def test_network_activity(sinsp, run_containers: dict):
},
{
"container.id": generator_id,
"evt.args": SinspField.regex_field(fr'^res=0 tuple={ipv4_regex}->10\.2\.3\.4:8192 fd=3\(<4u>{ipv4_regex}->10\.2\.3\.4:8192\)$'),
"evt.args": SinspField.regex_field(
fr'^res=0 tuple={ipv4_regex}->10\.2\.3\.4:8192 fd=3\(<4u>{ipv4_regex}->10\.2\.3\.4:8192\) addr=10.2.3.4:8192$'),
"evt.category": "net",
"evt.num": SinspField.numeric_field(),
"evt.time": SinspField.numeric_field(),

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

@ -40,6 +40,7 @@ limitations under the License.
#include <algorithm>
#include <cassert>
#include <climits>
#include <iostream>
#include <list>
#include <mutex>
@ -1247,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++;
}
@ -1261,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++;
}
@ -1359,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)));
@ -1378,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)));
@ -1442,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

@ -51,6 +51,7 @@ limitations under the License.
#include <algorithm>
#include <cassert>
#include <climits>
#include <list>
#include <numeric>
@ -959,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"));
@ -987,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;
@ -1124,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:
@ -1141,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);
@ -1354,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;
}
@ -1607,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");
@ -1686,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");
@ -1698,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");
@ -1765,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:
@ -1787,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

@ -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
@ -757,15 +769,17 @@ int32_t fill_event_connect_x(scap_sized_buffer scap_buf,
char* scap_err,
int64_t res,
scap_const_sized_buffer tuple,
int64_t fd) {
int64_t fd,
scap_const_sized_buffer addr) {
return scap_event_encode_params(scap_buf,
event_size,
scap_err,
PPME_SOCKET_CONNECT_X,
3,
4,
res,
tuple, // local addr hardcoded 0 -- INVALID
fd);
fd,
addr);
}
// PPME_SYSCALL_SOCKET_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,
@ -251,7 +253,8 @@ int32_t fill_event_connect_x(scap_sized_buffer scap_buf,
char* scap_err,
int64_t res,
scap_const_sized_buffer tuple,
int64_t fd);
int64_t fd,
scap_const_sized_buffer addr);
int32_t fill_event_socket_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:
@ -697,13 +703,14 @@ static parse_result parse_connect(uint32_t id,
return ret;
}
ret.status =
scap_gvisor::fillers::fill_event_connect_x(scap_buf,
&ret.size,
scap_err,
gvisor_evt.exit().result(),
scap_const_sized_buffer{targetbuf, size},
gvisor_evt.fd());
ret.status = scap_gvisor::fillers::fill_event_connect_x(
scap_buf,
&ret.size,
scap_err,
gvisor_evt.exit().result(),
scap_const_sized_buffer{targetbuf, size},
gvisor_evt.fd(),
scap_const_sized_buffer{targetbuf, size});
} else {
char targetbuf[socktuple_buffer_size];

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

@ -23,6 +23,7 @@ limitations under the License.
#include <stdarg.h>
#include <cstdio>
#include <cassert>
#include <limits>
#include <string>
#include <stdexcept>
#include <memory>
@ -120,7 +121,102 @@ static char *get_param_ptr(scap_evt *evt, uint8_t num_param) {
return ptr + ptr_off;
}
static inline uint8_t get_size_bytes_from_type(enum 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:
case PT_FLAGS8:
case PT_ENUMFLAGS8:
case PT_SIGTYPE:
case PT_SOCKADDR: // Sockaddr default parameter is a single-byte PPM_AF_UNSPEC family value.
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:
return 0;
default:
// We forgot to handle something
assert(false);
break;
}
assert(false);
return 0;
}
// `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_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;
default:
return 0;
}
}
// This writes len + the param
static void push_default_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_default_value_size_bytes_from_type(param_type);
const uint16_t lens_offset = sizeof(scap_evt) + param_num * sizeof(uint16_t);
PRINT_MESSAGE(
"push default param (%d, type: %d) with len (%d) at {params_offest (%d), "
"lens_offset (%d)}\n",
param_num,
param_type,
len,
*params_offset,
lens_offset);
uint64_t val = get_default_value_from_type(param_type);
memcpy((char *)evt + *params_offset, (char *)&val, len);
*params_offset += len;
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:
@ -157,7 +253,6 @@ static inline uint8_t get_size_bytes_from_type(enum ppm_param_type t) {
case PT_BYTEBUF:
case PT_CHARBUF:
case PT_SOCKADDR:
case PT_SOCKTUPLE:
case PT_FDLIST:
case PT_FSPATH:
@ -165,6 +260,7 @@ static inline uint8_t get_size_bytes_from_type(enum ppm_param_type t) {
case PT_CHARBUF_PAIR_ARRAY:
case PT_FSRELPATH:
case PT_DYN:
case PT_SOCKADDR:
return 0;
default:
@ -177,29 +273,30 @@ static inline uint8_t get_size_bytes_from_type(enum 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.
// Otherwise we will access the wrong entry in the event table.
const struct ppm_event_info *event_info = &(g_event_info[evt->type]);
uint16_t len = get_size_bytes_from_type(event_info->params[param_num].type);
uint16_t lens_offset = sizeof(scap_evt) + param_num * sizeof(uint16_t);
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 default param (%d, type: %d) with len (%d) at {params_offest (%d), "
"push empty param (%d, type: %d) with len (%d) at {params_offset (%d), "
"lens_offset (%d)}\n",
param_num,
event_info->params[param_num].type,
param_type,
len,
*params_offset,
lens_offset);
// The default param will be always 0 so we just need to copy the right number of 0 bytes.
// 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`
uint64_t val = 0;
memcpy((char *)evt + *params_offset, (char *)&val, len);
// 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, &len, sizeof(uint16_t));
memcpy((char *)evt + lens_offset, &zero, sizeof(uint16_t));
}
// This writes len + the param
@ -214,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,
@ -367,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;
@ -375,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);
@ -409,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(
@ -417,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;
@ -427,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,14 +133,320 @@ 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},
conversion_info()
.action(C_ACTION_ADD_PARAMS)
.instrs({{C_INSTR_FROM_ENTER, 0}, {C_INSTR_FROM_ENTER, 1}})},
/*====================== BRK ======================*/
{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},
conversion_info().action(C_ACTION_ADD_PARAMS).instrs({{C_INSTR_FROM_ENTER, 0}})},
/*====================== CONNECT ======================*/
{conversion_key{PPME_SOCKET_CONNECT_E, 1},
conversion_info().action(C_ACTION_ADD_PARAMS).instrs({{C_INSTR_FROM_DEFAULT, 0}})},
{conversion_key{PPME_SOCKET_CONNECT_E, 2}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SOCKET_CONNECT_X, 2},
conversion_info().action(C_ACTION_ADD_PARAMS).instrs({{C_INSTR_FROM_ENTER, 0}})},
{conversion_key{PPME_SOCKET_CONNECT_X, 3},
conversion_info().action(C_ACTION_ADD_PARAMS).instrs({{C_INSTR_FROM_ENTER, 1}})},
/*====================== SOCKET ======================*/
{conversion_key{PPME_SOCKET_SOCKET_E, 3}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SOCKET_SOCKET_X, 1},
@ -170,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},
@ -244,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},
@ -340,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},
@ -364,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},
@ -378,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},
@ -423,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}})},
@ -447,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)},
@ -456,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},
@ -469,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

@ -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

@ -124,8 +124,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 +134,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, 64, 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) {
@ -552,6 +609,16 @@ int get_exit_event_fd_location(ppm_event_code etype) {
case PPME_SYSCALL_GETDENTS64_X:
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:
@ -567,6 +634,8 @@ int get_exit_event_fd_location(ppm_event_code etype) {
case PPME_SYSCALL_SPLICE_X:
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

@ -156,7 +156,7 @@ static void print_parameter(int16_t num_param, scap_evt *ev, uint16_t offset) {
break;
default:
printf("- error\n");
printf("- error\n");
break;
}
break;

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

@ -23,7 +23,7 @@ endif()
add_executable(sinsp-example ${sources})
target_link_libraries(sinsp-example sinsp)
target_link_libraries(sinsp-example sinsp "${JSONCPP_LIB}")
if(EMSCRIPTEN)
target_compile_options(sinsp-example PRIVATE "-sDISABLE_EXCEPTION_CATCHING=0")

View File

@ -32,6 +32,7 @@ limitations under the License.
#include <unordered_set>
#include <memory>
#include <thread>
#include <json/json.h>
#ifndef _WIN32
extern "C" {
@ -63,7 +64,7 @@ static bool ppm_sc_repair_state = false;
static bool ppm_sc_state_remove_io_sc = false;
static bool enable_glogger = false;
static bool perftest = false;
static bool print_tables = false;
static string table_mode = "";
static string engine_string;
static string filter_string = "";
static string file_path = "";
@ -136,6 +137,152 @@ void print_all_tables(sinsp& inspector) {
}
}
// Table iteration
struct table_iteration_state {
const ss_plugin_table_fieldinfo* fields;
uint32_t nfields;
libsinsp::state::sinsp_table_owner* owner;
libsinsp::state::base_table* table;
std::vector<ss_plugin_table_field_t*>* field_accessors;
Json::Value* table_obj;
uint32_t n_items{0};
};
Json::Value serialize_table(const std::string& table_name, libsinsp::state::base_table* table);
ss_plugin_bool table_iterate_entries(void* s, ss_plugin_table_entry_t* entry) {
auto* state = static_cast<table_iteration_state*>(s);
Json::Value entry_obj;
std::map<ss_plugin_state_type, std::function<void(Json::Value&, ss_plugin_state_data&)>>
type_to_json_converter = {
{SS_PLUGIN_ST_INT8,
[](Json::Value& field, ss_plugin_state_data& field_data) {
field = (int)field_data.s8;
}},
{SS_PLUGIN_ST_INT16,
[](Json::Value& field, ss_plugin_state_data& field_data) {
field = field_data.s16;
}},
{SS_PLUGIN_ST_INT32,
[](Json::Value& field, ss_plugin_state_data& field_data) {
field = field_data.s32;
}},
{SS_PLUGIN_ST_INT64,
[](Json::Value& field, ss_plugin_state_data& field_data) {
field = (Json::Value::Int64)field_data.s64;
}},
{SS_PLUGIN_ST_UINT8,
[](Json::Value& field, ss_plugin_state_data& field_data) {
field = (unsigned)field_data.u8;
}},
{SS_PLUGIN_ST_UINT16,
[](Json::Value& field, ss_plugin_state_data& field_data) {
field = field_data.u16;
}},
{SS_PLUGIN_ST_UINT32,
[](Json::Value& field, ss_plugin_state_data& field_data) {
field = field_data.u32;
}},
{SS_PLUGIN_ST_UINT64,
[](Json::Value& field, ss_plugin_state_data& field_data) {
field = (Json::Value::UInt64)field_data.u64;
}},
{SS_PLUGIN_ST_STRING,
[](Json::Value& field, ss_plugin_state_data& field_data) {
field = field_data.str ? field_data.str : "";
}},
{SS_PLUGIN_ST_BOOL,
[](Json::Value& field, ss_plugin_state_data& field_data) {
field = field_data.b;
}},
{SS_PLUGIN_ST_TABLE, [](Json::Value& field, ss_plugin_state_data& field_data) {
if(field_data.table != nullptr) {
libsinsp::state::table_input_adapter subtable(field_data.table);
field = serialize_table(subtable.name(),
(libsinsp::state::base_table*)&subtable);
} else {
field = "<error: table is null>";
}
}}};
for(uint32_t i = 0; i < state->nfields; i++) {
auto& field = entry_obj[state->fields[i].name];
try {
ss_plugin_state_data field_data;
auto rc = state->table->read_entry_field(state->owner,
entry,
(*state->field_accessors)[i],
&field_data);
if(rc == SS_PLUGIN_SUCCESS) {
auto field_type = state->fields[i].field_type;
if(auto it = type_to_json_converter.find(field_type);
it != type_to_json_converter.end()) {
it->second(field, field_data);
} else {
std::string error{"<unsupported type: "};
error += state_type_to_string(field_type);
error += ">";
field = error;
}
} else {
field = "<error>";
}
} catch(const std::exception& e) {
std::string error{"<error: "};
error += e.what();
error += ">";
field = error;
}
}
(*state->table_obj)["entries"].append(entry_obj);
state->n_items++;
// We're recycling `-n` option here
return (state->n_items < max_events);
}
Json::Value serialize_table(const std::string& table_name, libsinsp::state::base_table* table) {
Json::Value table_obj;
table_obj["name"] = table_name;
table_obj["entries"] = Json::Value(Json::arrayValue);
// Create a temporary owner to call list_fields
libsinsp::state::sinsp_table_owner owner;
uint32_t nfields = 0;
const auto* fields = table->list_fields(&owner, &nfields);
std::vector<ss_plugin_table_field_t*> field_accessors;
for(uint32_t i = 0; i < nfields; i++) {
auto field_accessor = table->get_field(&owner, fields[i].name, fields[i].field_type);
field_accessors.push_back(field_accessor);
}
table_iteration_state state{fields, nfields, &owner, table, &field_accessors, &table_obj};
table->iterate_entries(&owner, &table_iterate_entries, &state);
return table_obj;
}
void print_table_entries(sinsp& inspector) {
auto& reg = inspector.get_table_registry();
const auto& tables = reg->tables();
Json::Value root;
Json::Value tables_array(Json::arrayValue);
for(const auto& [table_name, table] : tables) {
tables_array.append(serialize_table(table_name, table));
}
root["tables"] = tables_array;
Json::StreamWriterBuilder builder;
builder["indentation"] = " ";
std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
writer->write(root, &std::cout);
std::cout << std::endl;
}
#define EVENT_HEADER \
"%evt.num %evt.time cat=%evt.category " \
"proc=%proc.name(%proc.pid.%thread.tid) "
@ -193,7 +340,7 @@ Options:
-g, --enable-glogger Enable libs g_logger, set to SEV_DEBUG. For a different severity adjust the test binary source and re-compile.
-r, --raw raw event ouput
-t, --perftest Run in performance test mode
-T, --tables Print all tables with their fields and types
-T, --tables -T or -Tbrief print tables descriptions. -Tlist print table entries, if -n is specified, print only the first n entries.
)";
cout << usage << endl;
}
@ -233,7 +380,7 @@ void parse_CLI_options(sinsp& inspector, int argc, char** argv) {
{"raw", no_argument, nullptr, 'r'},
{"gvisor", optional_argument, nullptr, 'G'},
{"perftest", no_argument, nullptr, 't'},
{"tables", no_argument, nullptr, 'T'},
{"tables", optional_argument, nullptr, 'T'},
{nullptr, 0, nullptr, 0}};
bool format_set = false;
@ -241,7 +388,7 @@ void parse_CLI_options(sinsp& inspector, int argc, char** argv) {
int long_index = 0;
while((op = getopt_long(argc,
argv,
"hf:jab:mks:p:d:c:Ao:En:zxqgrtTG::",
"hf:jab:mks:p:d:c:Ao:En:zxqgrtT::G::",
long_options,
&long_index)) != -1) {
switch(op) {
@ -362,7 +509,12 @@ void parse_CLI_options(sinsp& inspector, int argc, char** argv) {
perftest = true;
break;
case 'T':
print_tables = true;
table_mode = optarg ? optarg : "brief";
if(table_mode != "brief" && table_mode != "list") {
std::cerr << "Invalid table mode: " << table_mode << ". Use 'brief' or 'list'."
<< std::endl;
exit(EXIT_FAILURE);
}
break;
default:
break;
@ -603,12 +755,16 @@ int main(int argc, char** argv) {
}
}
if(print_tables) {
open_engine(inspector, events_sc_codes);
if(table_mode == "brief") {
print_all_tables(inspector);
return 0;
}
open_engine(inspector, events_sc_codes);
if(table_mode == "list") {
print_table_entries(inspector);
return 0;
}
std::cout << "-- Start capture" << std::endl;
double max_throughput = 0.0;
@ -781,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,8 +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_enter(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);
@ -136,6 +134,16 @@ 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 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,
uint16_t tsport,
@ -143,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,
@ -179,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 {
@ -224,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

@ -12,7 +12,7 @@
class sinsp;
class sinsp_threadinfo;
class sinsp_threadinfo_ctor_params;
struct sinsp_threadinfo_ctor_params;
namespace libsinsp {
enum event_return {

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

@ -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

@ -261,7 +261,7 @@ public:
* @brief Accesses a field with the given accessor and reads its value.
*/
template<typename T, typename Val = T>
inline void get_dynamic_field(const field_accessor<T>& a, Val& out) {
inline void get_dynamic_field(const field_accessor<T>& a, Val& out) const {
_check_defsptr(a.info(), false);
get_dynamic_field(a.info(), reinterpret_cast<void*>(&out));
}
@ -308,7 +308,7 @@ protected:
* according to the type definitions supported in libsinsp::state::typeinfo.
* For strings, "out" is considered of type const char**.
*/
virtual void get_dynamic_field(const field_info& i, void* out) {
virtual void get_dynamic_field(const field_info& i, void* out) const {
const auto* buf = _access_dynamic_field(i.m_index);
if(i.info().type_id() == SS_PLUGIN_ST_STRING) {
*((const char**)out) = ((const std::string*)buf)->c_str();
@ -360,7 +360,7 @@ private:
}
}
inline void* _access_dynamic_field(size_t index) {
inline void* _access_dynamic_field(size_t index) const {
if(!m_dynamic_fields) {
throw sinsp_exception("dynamic struct has no field definitions");
}
@ -397,7 +397,7 @@ private:
}
}
std::vector<void*> m_fields;
mutable std::vector<void*> m_fields;
std::shared_ptr<field_infos> m_dynamic_fields;
};
@ -409,7 +409,7 @@ private:
template<>
inline void libsinsp::state::dynamic_struct::get_dynamic_field<std::string, const char*>(
const field_accessor<std::string>& a,
const char*& out) {
const char*& out) const {
_check_defsptr(a.info(), false);
get_dynamic_field(a.info(), reinterpret_cast<void*>(&out));
}
@ -417,7 +417,7 @@ inline void libsinsp::state::dynamic_struct::get_dynamic_field<std::string, cons
template<>
inline void libsinsp::state::dynamic_struct::get_dynamic_field<std::string, std::string>(
const field_accessor<std::string>& a,
std::string& out) {
std::string& out) const {
const char* s = NULL;
get_dynamic_field(a, s);
if(!s) {

View File

@ -83,7 +83,8 @@ public:
inline void set_value(std::pair<Tfirst, Tsecond>* v) { m_value = v; }
protected:
virtual void get_dynamic_field(const dynamic_struct::field_info& i, void* out) override final {
virtual void get_dynamic_field(const dynamic_struct::field_info& i,
void* out) const override final {
if(i.index() > 1 || i.defs_id() != s_dynamic_fields_id) {
throw sinsp_exception(
"invalid field info passed to pair_table_entry_adapter::get_dynamic_field");
@ -115,7 +116,9 @@ private:
std::pair<Tfirst, Tsecond>* m_value;
template<typename T>
inline void get_dynamic_field(const dynamic_struct::field_info& i, const T* value, void* out) {
inline void get_dynamic_field(const dynamic_struct::field_info& i,
const T* value,
void* out) const {
if(i.info().type_id() == SS_PLUGIN_ST_STRING) {
*((const char**)out) = ((const std::string*)value)->c_str();
} else {
@ -169,7 +172,8 @@ public:
inline void set_value(T* v) { m_value = v; }
protected:
virtual void get_dynamic_field(const dynamic_struct::field_info& i, void* out) override final {
virtual void get_dynamic_field(const dynamic_struct::field_info& i,
void* out) const override final {
if(i.index() != 0 || i.defs_id() != s_dynamic_fields_id) {
throw sinsp_exception(
"invalid field info passed to value_table_entry_adapter::get_dynamic_field");
@ -320,5 +324,100 @@ private:
std::list<TWrap> m_wrappers; // using lists for ptr stability
};
// Simple adapter for ss_plugin_table_input that implements the base_table interface
class table_input_adapter : public libsinsp::state::base_table {
private:
ss_plugin_table_input* m_input;
std::string m_name;
public:
explicit table_input_adapter(ss_plugin_table_input* input):
libsinsp::state::base_table(libsinsp::state::typeinfo::from(input->key_type)),
m_input(input),
m_name(input->name ? input->name : "unknown") {}
// ss_plugin_table_t is an opaque pointer to ss_plugin_table_input
explicit table_input_adapter(ss_plugin_table_t* table):
table_input_adapter(static_cast<ss_plugin_table_input*>(table)) {}
const char* name() const override { return m_name.c_str(); }
const ss_plugin_table_fieldinfo* list_fields(libsinsp::state::sinsp_table_owner* owner,
uint32_t* nfields) override {
return m_input->fields.list_table_fields(m_input->table, nfields);
}
ss_plugin_table_field_t* get_field(libsinsp::state::sinsp_table_owner* owner,
const char* name,
ss_plugin_state_type data_type) override {
return m_input->fields.get_table_field(m_input->table, name, data_type);
}
ss_plugin_table_field_t* add_field(libsinsp::state::sinsp_table_owner* owner,
const char* name,
ss_plugin_state_type data_type) override {
return m_input->fields.add_table_field(m_input->table, name, data_type);
}
uint64_t get_size(libsinsp::state::sinsp_table_owner* owner) override {
return m_input->reader.get_table_size(m_input->table);
}
ss_plugin_table_entry_t* get_entry(libsinsp::state::sinsp_table_owner* owner,
const ss_plugin_state_data* key) override {
return m_input->reader.get_table_entry(m_input->table, key);
}
void release_table_entry(libsinsp::state::sinsp_table_owner* owner,
ss_plugin_table_entry_t* _e) override {
m_input->reader_ext->release_table_entry(m_input->table, _e);
}
ss_plugin_bool iterate_entries(libsinsp::state::sinsp_table_owner* owner,
ss_plugin_table_iterator_func_t it,
ss_plugin_table_iterator_state_t* s) override {
return m_input->reader_ext->iterate_entries(m_input->table, it, s);
}
ss_plugin_rc read_entry_field(libsinsp::state::sinsp_table_owner* owner,
ss_plugin_table_entry_t* _e,
const ss_plugin_table_field_t* f,
ss_plugin_state_data* out) override {
return m_input->reader.read_entry_field(m_input->table, _e, f, out);
}
ss_plugin_rc clear_entries(libsinsp::state::sinsp_table_owner* owner) override {
return m_input->writer.clear_table(m_input->table);
}
ss_plugin_rc erase_entry(libsinsp::state::sinsp_table_owner* owner,
const ss_plugin_state_data* key) override {
return m_input->writer.erase_table_entry(m_input->table, key);
}
ss_plugin_table_entry_t* create_table_entry(
libsinsp::state::sinsp_table_owner* owner) override {
return m_input->writer.create_table_entry(m_input->table);
}
void destroy_table_entry(libsinsp::state::sinsp_table_owner* owner,
ss_plugin_table_entry_t* _e) override {
m_input->writer.destroy_table_entry(m_input->table, _e);
}
ss_plugin_table_entry_t* add_entry(libsinsp::state::sinsp_table_owner* owner,
const ss_plugin_state_data* key,
ss_plugin_table_entry_t* _e) override {
return m_input->writer.add_table_entry(m_input->table, key, _e);
}
ss_plugin_rc write_entry_field(libsinsp::state::sinsp_table_owner* owner,
ss_plugin_table_entry_t* _e,
const ss_plugin_table_field_t* f,
const ss_plugin_state_data* in) override {
return m_input->writer.write_entry_field(m_input->table, _e, f, in);
}
};
}; // namespace state
}; // namespace libsinsp

View File

@ -44,6 +44,8 @@ public:
std::string(typeid(T).name()));
}
static typeinfo from(ss_plugin_state_type state_type);
inline typeinfo() = delete;
inline ~typeinfo() = default;
inline typeinfo(typeinfo&&) = default;
@ -180,5 +182,35 @@ inline typeinfo typeinfo::of<const libsinsp::state::base_table*>() {
return _build<const libsinsp::state::base_table*>("table", SS_PLUGIN_ST_TABLE);
}
inline typeinfo typeinfo::from(ss_plugin_state_type state_type) {
switch(state_type) {
case SS_PLUGIN_ST_INT8:
return typeinfo::of<int8_t>();
case SS_PLUGIN_ST_INT16:
return typeinfo::of<int16_t>();
case SS_PLUGIN_ST_INT32:
return typeinfo::of<int32_t>();
case SS_PLUGIN_ST_INT64:
return typeinfo::of<int64_t>();
case SS_PLUGIN_ST_UINT8:
return typeinfo::of<uint8_t>();
case SS_PLUGIN_ST_UINT16:
return typeinfo::of<uint16_t>();
case SS_PLUGIN_ST_UINT32:
return typeinfo::of<uint32_t>();
case SS_PLUGIN_ST_UINT64:
return typeinfo::of<uint64_t>();
case SS_PLUGIN_ST_STRING:
return typeinfo::of<std::string>();
case SS_PLUGIN_ST_TABLE:
return typeinfo::of<libsinsp::state::base_table*>();
case SS_PLUGIN_ST_BOOL:
return typeinfo::of<bool>();
default:
throw sinsp_exception("state::typeinfo::of invoked for unsupported state_type: " +
std::to_string(state_type));
}
}
}; // namespace state
}; // 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

@ -121,13 +121,15 @@ TEST_F(sinsp_with_test_input, net_ipv4_connect) {
std::vector<uint8_t> socktuple =
test_utils::pack_socktuple(reinterpret_cast<sockaddr*>(&client),
reinterpret_cast<sockaddr*>(&server));
evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SOCKET_CONNECT_X,
3,
(int64_t)0,
scap_const_sized_buffer{socktuple.data(), socktuple.size()},
sinsp_test_input::socket_params::default_fd);
evt = add_event_advance_ts(
increasing_ts(),
1,
PPME_SOCKET_CONNECT_X,
4,
(int64_t)0,
scap_const_sized_buffer{socktuple.data(), socktuple.size()},
sinsp_test_input::socket_params::default_fd,
scap_const_sized_buffer{server_sockaddr.data(), server_sockaddr.size()});
fdinfo = evt->get_fd_info();
ASSERT_NE(fdinfo, nullptr);
@ -195,13 +197,15 @@ TEST_F(sinsp_with_test_input, net_ipv4_connect_with_intermediate_event) {
sinsp_test_input::socket_params::default_fd,
(uint32_t)102,
scap_const_sized_buffer{socktuple.data(), socktuple.size()});
evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SOCKET_CONNECT_X,
3,
return_value,
scap_const_sized_buffer{socktuple.data(), socktuple.size()},
sinsp_test_input::socket_params::default_fd);
evt = add_event_advance_ts(
increasing_ts(),
1,
PPME_SOCKET_CONNECT_X,
4,
return_value,
scap_const_sized_buffer{socktuple.data(), socktuple.size()},
sinsp_test_input::socket_params::default_fd,
scap_const_sized_buffer{server_sockaddr.data(), server_sockaddr.size()});
/* We are able to recover the fdinfo in the connect exit event even when interleaved */
auto fdinfo = evt->get_fd_info();
@ -239,13 +243,15 @@ TEST_F(sinsp_with_test_input, net_ipv6_multiple_connects) {
std::vector<uint8_t> socktuple =
test_utils::pack_socktuple(reinterpret_cast<sockaddr*>(&client),
reinterpret_cast<sockaddr*>(&server1));
evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SOCKET_CONNECT_X,
3,
(int64_t)0,
scap_const_sized_buffer{socktuple.data(), socktuple.size()},
sinsp_test_input::socket_params::default_fd);
evt = add_event_advance_ts(
increasing_ts(),
1,
PPME_SOCKET_CONNECT_X,
4,
(int64_t)0,
scap_const_sized_buffer{socktuple.data(), socktuple.size()},
sinsp_test_input::socket_params::default_fd,
scap_const_sized_buffer{server1_sockaddr.data(), server1_sockaddr.size()});
ASSERT_EQ(get_field_as_string(evt, "fd.name"), DEFAULT_IPV6_FDNAME);
ASSERT_EQ(get_field_as_string(evt, "fd.connected"), "true");
@ -290,13 +296,15 @@ TEST_F(sinsp_with_test_input, net_ipv6_multiple_connects) {
socktuple = test_utils::pack_socktuple(reinterpret_cast<sockaddr*>(&client),
reinterpret_cast<sockaddr*>(&server2));
evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SOCKET_CONNECT_X,
3,
(int64_t)0,
scap_const_sized_buffer{socktuple.data(), socktuple.size()},
sinsp_test_input::socket_params::default_fd);
evt = add_event_advance_ts(
increasing_ts(),
1,
PPME_SOCKET_CONNECT_X,
4,
(int64_t)0,
scap_const_sized_buffer{socktuple.data(), socktuple.size()},
sinsp_test_input::socket_params::default_fd,
scap_const_sized_buffer{server2_sockaddr.data(), server2_sockaddr.size()});
ASSERT_EQ(get_field_as_string(evt, "fd.name_changed"), "true");
std::string new_fd_name = std::string(DEFAULT_IPV6_CLIENT_STRING) + ":" +
std::string(DEFAULT_CLIENT_PORT_STRING) + "->" + ipv6_server2 + ":" +
@ -508,13 +516,15 @@ TEST_F(sinsp_with_test_input, net_connect_exit_event_fails) {
std::vector<uint8_t> socktuple =
test_utils::pack_socktuple(reinterpret_cast<sockaddr*>(&client),
reinterpret_cast<sockaddr*>(&server));
evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SOCKET_CONNECT_X,
3,
(int64_t)0,
scap_const_sized_buffer{socktuple.data(), socktuple.size()},
sinsp_test_input::socket_params::default_fd);
evt = add_event_advance_ts(
increasing_ts(),
1,
PPME_SOCKET_CONNECT_X,
4,
(int64_t)0,
scap_const_sized_buffer{socktuple.data(), socktuple.size()},
sinsp_test_input::socket_params::default_fd,
scap_const_sized_buffer{server_sockaddr.data(), server_sockaddr.size()});
fdinfo = evt->get_fd_info();
ASSERT_NE(fdinfo, nullptr);
@ -537,13 +547,15 @@ TEST_F(sinsp_with_test_input, net_connect_exit_event_fails) {
socktuple = test_utils::pack_socktuple(reinterpret_cast<sockaddr*>(&client),
reinterpret_cast<sockaddr*>(&server2));
evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SOCKET_CONNECT_X,
3,
(int64_t)-2,
scap_const_sized_buffer{socktuple.data(), socktuple.size()},
sinsp_test_input::socket_params::default_fd);
evt = add_event_advance_ts(
increasing_ts(),
1,
PPME_SOCKET_CONNECT_X,
4,
(int64_t)-2,
scap_const_sized_buffer{socktuple.data(), socktuple.size()},
sinsp_test_input::socket_params::default_fd,
scap_const_sized_buffer{server_sockaddr.data(), server_sockaddr.size()});
/* Filterchecks will get an updated fdname since the extraction happens directly on the params,
* while the fdinfo fdname is not updated. Ip and port of the new server are updated by the
@ -615,10 +627,11 @@ TEST_F(sinsp_with_test_input, net_connect_enter_event_is_empty) {
add_event_advance_ts(increasing_ts(),
1,
PPME_SOCKET_CONNECT_X,
3,
4,
(int64_t)0,
scap_const_sized_buffer{socktuple.data(), socktuple.size()},
sinsp_test_input::socket_params::default_fd);
sinsp_test_input::socket_params::default_fd,
scap_const_sized_buffer{server_sockaddr.data(), server_sockaddr.size()});
/* Second connection with an empty sockaddr in the PPME_SOCKET_CONNECT_E event, new client and
* new server */
@ -646,10 +659,11 @@ TEST_F(sinsp_with_test_input, net_connect_enter_event_is_empty) {
evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SOCKET_CONNECT_X,
3,
4,
(int64_t)-2,
scap_const_sized_buffer{socktuple.data(), socktuple.size()},
sinsp_test_input::socket_params::default_fd);
sinsp_test_input::socket_params::default_fd,
null_buf);
/* Only filterchecks will see the new tuple in the fdname all the rest is not updated */
std::string fdname = ipv4_client2 + ":" + port_client2_string + "->" + ipv4_server2 + ":" +
@ -699,19 +713,23 @@ TEST_F(sinsp_with_test_input, net_connect_enter_event_is_missing) {
std::string ipv4_server = "152.40.111.222";
std::string port_server_string = "25632";
sockaddr_in server = test_utils::fill_sockaddr_in(port_server, ipv4_server.c_str());
std::vector<uint8_t> server_sockaddr =
test_utils::pack_sockaddr(reinterpret_cast<sockaddr*>(&server));
/* We dropped connect enter! */
std::vector<uint8_t> socktuple =
test_utils::pack_socktuple(reinterpret_cast<sockaddr*>(&client),
reinterpret_cast<sockaddr*>(&server));
evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SOCKET_CONNECT_X,
3,
(int64_t)0,
scap_const_sized_buffer{socktuple.data(), socktuple.size()},
sinsp_test_input::socket_params::default_fd);
evt = add_event_advance_ts(
increasing_ts(),
1,
PPME_SOCKET_CONNECT_X,
4,
(int64_t)0,
scap_const_sized_buffer{socktuple.data(), socktuple.size()},
sinsp_test_input::socket_params::default_fd,
scap_const_sized_buffer{server_sockaddr.data(), server_sockaddr.size()});
/* Check that everything is updated anyway, even if we lost connect enter */
std::string fdname =
@ -740,56 +758,3 @@ TEST_F(sinsp_with_test_input, net_connect_enter_event_is_missing) {
ASSERT_EQ(fdinfo->m_sockinfo.m_ipv4info.m_fields.m_dport, std::stoi(port_server_string));
ASSERT_EQ(fdinfo->m_sockinfo.m_ipv4info.m_fields.m_sport, std::stoi(port_client_string));
}
/*
* Test that old connect exit event without the third `fd` argument
* were not able to load fd related data if connect enter was dropped.
*/
TEST_F(sinsp_with_test_input, net_connect_enter_event_is_missing_wo_fd_param_exit) {
add_default_init_thread();
open_inspector();
sinsp_evt* evt = NULL;
generate_socket_events(sinsp_test_input::socket_params(PPM_AF_INET, SOCK_DGRAM));
int port_client = 12;
std::string ipv4_client = "80.9.11.45";
std::string port_client_string = "12";
sockaddr_in client = test_utils::fill_sockaddr_in(port_client, ipv4_client.c_str());
int port_server = 25632;
std::string ipv4_server = "152.40.111.222";
std::string port_server_string = "25632";
sockaddr_in server = test_utils::fill_sockaddr_in(port_server, ipv4_server.c_str());
/* We dropped connect enter! */
/* todo!: revisit this when we will manage CONNECT_X in scap files.
* We simulate an event from an old scap file, a connect exit event with just 2 params (no fd!)
*/
std::vector<uint8_t> socktuple =
test_utils::pack_socktuple(reinterpret_cast<sockaddr*>(&client),
reinterpret_cast<sockaddr*>(&server));
evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SOCKET_CONNECT_X,
2,
(int64_t)0,
scap_const_sized_buffer{socktuple.data(), socktuple.size()});
/* We cannot recover the file descriptor from the enter event neither from the exit event */
ASSERT_EQ(evt->get_fd_info(), nullptr);
/* We recover this from the tuple */
ASSERT_EQ(get_field_as_string(evt, "fd.name"), "80.9.11.45:12->152.40.111.222:25632");
/* Check that we are not able to load any info */
ASSERT_FALSE(field_has_value(evt, "fd.sip"));
ASSERT_FALSE(field_has_value(evt, "fd.cip"));
ASSERT_FALSE(field_has_value(evt, "fd.rip"));
ASSERT_FALSE(field_has_value(evt, "fd.lip"));
ASSERT_FALSE(field_has_value(evt, "fd.cport"));
ASSERT_FALSE(field_has_value(evt, "fd.sport"));
ASSERT_FALSE(field_has_value(evt, "fd.lport"));
ASSERT_FALSE(field_has_value(evt, "fd.rport"));
}

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>`
@ -143,7 +143,8 @@ TEST_F(sinsp_with_test_input, sockaddr_empty_param) {
sinsp_evt* evt = NULL;
const sinsp_evt_param* param = NULL;
int64_t fd = 0;
constexpr int64_t res = 0;
constexpr int64_t fd = 3;
/* `PPME_SOCKET_CONNECT_E` is a simple event that uses a `PT_SOCKADDR` */
scap_const_sized_buffer sockaddr_param;
@ -151,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;
@ -160,20 +161,21 @@ TEST_F(sinsp_with_test_input, sockaddr_empty_param) {
evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SOCKET_CONNECT_X,
3,
fd,
4,
res,
socktuple_param,
fd);
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;
fdlist_param.buf = NULL;
fdlist_param.size = 0;
evt = add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_POLL_X, 2, fd, fdlist_param);
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) {
@ -368,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,
@ -395,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

@ -45,13 +45,15 @@ TEST_F(sinsp_with_test_input, net_ipv4_compare) {
std::vector<uint8_t> socktuple =
test_utils::pack_socktuple(reinterpret_cast<sockaddr*>(&client),
reinterpret_cast<sockaddr*>(&server));
evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SOCKET_CONNECT_X,
3,
return_value,
scap_const_sized_buffer{socktuple.data(), socktuple.size()},
sinsp_test_input::socket_params::default_fd);
evt = add_event_advance_ts(
increasing_ts(),
1,
PPME_SOCKET_CONNECT_X,
4,
return_value,
scap_const_sized_buffer{socktuple.data(), socktuple.size()},
sinsp_test_input::socket_params::default_fd,
scap_const_sized_buffer{server_sockaddr.data(), server_sockaddr.size()});
EXPECT_TRUE(eval_filter(evt, "fd.ip == 142.251.111.147"));
EXPECT_TRUE(eval_filter(evt, "fd.sip == 142.251.111.147"));
@ -100,13 +102,15 @@ TEST_F(sinsp_with_test_input, net_ipv6_compare) {
std::vector<uint8_t> socktuple =
test_utils::pack_socktuple(reinterpret_cast<sockaddr*>(&client),
reinterpret_cast<sockaddr*>(&server1));
evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SOCKET_CONNECT_X,
3,
return_value,
scap_const_sized_buffer{socktuple.data(), socktuple.size()},
sinsp_test_input::socket_params::default_fd);
evt = add_event_advance_ts(
increasing_ts(),
1,
PPME_SOCKET_CONNECT_X,
4,
return_value,
scap_const_sized_buffer{socktuple.data(), socktuple.size()},
sinsp_test_input::socket_params::default_fd,
scap_const_sized_buffer{server1_sockaddr.data(), server1_sockaddr.size()});
EXPECT_TRUE(eval_filter(evt, "fd.ip == 2001:4860:4860::8888"));
EXPECT_TRUE(eval_filter(evt, "fd.sip == 2001:4860:4860::8888"));

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

@ -364,13 +364,15 @@ TEST_F(sinsp_with_test_input, check_some_fd_fields) {
std::vector<uint8_t> socktuple =
test_utils::pack_socktuple(reinterpret_cast<sockaddr*>(&client),
reinterpret_cast<sockaddr*>(&server));
auto evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SOCKET_CONNECT_X,
3,
(int64_t)0,
scap_const_sized_buffer{socktuple.data(), socktuple.size()},
sinsp_test_input::socket_params::default_fd);
auto evt = add_event_advance_ts(
increasing_ts(),
1,
PPME_SOCKET_CONNECT_X,
4,
(int64_t)0,
scap_const_sized_buffer{socktuple.data(), socktuple.size()},
sinsp_test_input::socket_params::default_fd,
scap_const_sized_buffer{server_sockaddr.data(), server_sockaddr.size()});
{
// fd.cip will extract an ipv6 we cannot compare it with an ipv4, so we expect false

View File

@ -260,13 +260,15 @@ TEST_F(sinsp_with_test_input, PROC_FILTER_stdin_stdout_stderr) {
std::vector<uint8_t> socktuple =
test_utils::pack_socktuple(reinterpret_cast<sockaddr*>(&client),
reinterpret_cast<sockaddr*>(&server));
evt = add_event_advance_ts(increasing_ts(),
1,
PPME_SOCKET_CONNECT_X,
3,
(int64_t)0,
scap_const_sized_buffer{socktuple.data(), socktuple.size()},
sinsp_test_input::socket_params::default_fd);
evt = add_event_advance_ts(
increasing_ts(),
1,
PPME_SOCKET_CONNECT_X,
4,
(int64_t)0,
scap_const_sized_buffer{socktuple.data(), socktuple.size()},
sinsp_test_input::socket_params::default_fd,
scap_const_sized_buffer{server_sockaddr.data(), server_sockaddr.size()});
// The socket is duped to stdin, stdout, stderr
evt = add_event_advance_ts(increasing_ts(),

View File

@ -51,15 +51,21 @@ TEST_F(sinsp_with_test_input, CONNECT_parse_unix_socket) {
ASSERT_EQ(fdinfo->m_name, "");
// We don't need the enter event!
const std::string sun_path{"/tmp/stream.sock"};
sockaddr_un server = test_utils::fill_sockaddr_un(sun_path.c_str());
std::vector<uint8_t> server_sockaddr =
test_utils::pack_sockaddr(reinterpret_cast<sockaddr*>(&server));
std::vector<uint8_t> socktuple =
test_utils::pack_unix_socktuple(0x9c758d0f, 0x9c758d0a, "/tmp/stream.sock");
evt = add_event_advance_ts(increasing_ts(),
INIT_TID,
PPME_SOCKET_CONNECT_X,
3,
(int64_t)0,
scap_const_sized_buffer{socktuple.data(), socktuple.size()},
sinsp_test_input::socket_params::default_fd);
test_utils::pack_unix_socktuple(0x9c758d0f, 0x9c758d0a, sun_path.c_str());
evt = add_event_advance_ts(
increasing_ts(),
INIT_TID,
PPME_SOCKET_CONNECT_X,
4,
(int64_t)0,
scap_const_sized_buffer{socktuple.data(), socktuple.size()},
sinsp_test_input::socket_params::default_fd,
scap_const_sized_buffer{server_sockaddr.data(), server_sockaddr.size()});
/* FDINFO associated with the event */
fdinfo = evt->get_fd_info();

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

@ -63,6 +63,10 @@ TEST_F(scap_file_test, same_number_of_events) {
{PPME_SYSCALL_SPLICE_E, 253}, {PPME_SYSCALL_SPLICE_X, 253},
{PPME_SYSCALL_LSEEK_E, 329}, {PPME_SYSCALL_LSEEK_X, 329},
{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.
});
@ -82,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.
});
@ -165,16 +170,16 @@ TEST_F(scap_file_test, read_x_check_final_converted_event) {
// - args=fd=33(<4t>127.0.0.1:38308->127.0.0.1:80) size=8192
//
// Let's see the new PPME_SYSCALL_READ_X event!
uint64_t ts = 1380933088076148247;
int64_t tid = 44106;
int64_t res = 270;
constexpr uint64_t ts = 1380933088076148247;
constexpr int64_t tid = 44106;
constexpr int64_t res = 270;
// this is NULL termiinated so we have 81 bytes but in the scap-file we want only 80 bytes
// without the NULL terminator
char read_buf[] = {
constexpr char read_buf[] = {
"HTTP/1.1 302 Found\r\nDate: Sat, 05 Oct 2013 00:31:28 GMT\r\nServer: Apache/2.4.4 "
"(U"};
int64_t fd = 33;
uint32_t size = 8192;
constexpr int64_t fd = 33;
constexpr uint32_t size = 8192;
assert_event_presence(
create_safe_scap_event(ts,
tid,
@ -207,17 +212,17 @@ TEST_F(scap_file_test, pread_x_check_final_converted_event) {
// - args=fd=19(<f>/var/run/utmp) size=400 pos=800
//
// Let's see the new PPME_SYSCALL_PREAD_X event!
uint64_t ts = 1687966733234634809;
int64_t tid = 552;
int64_t res = 400;
uint8_t read_buf[] = {6, 0, 0, 0, '_', 2, 0, 0, 't', 't', 'y', '1', 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 't', 't', 'y', '1', 'L', 'O', 'G', 'I',
'N', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int64_t fd = 19;
uint32_t size = 400;
int64_t pos = 800;
constexpr uint64_t ts = 1687966733234634809;
constexpr int64_t tid = 552;
constexpr int64_t res = 400;
constexpr uint8_t read_buf[] = {
6, 0, 0, 0, '_', 2, 0, 0, 't', 't', 'y', '1', 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
't', 't', 'y', '1', 'L', 'O', 'G', 'I', 'N', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
constexpr int64_t fd = 19;
constexpr uint32_t size = 400;
constexpr int64_t pos = 800;
assert_event_presence(
create_safe_scap_event(ts,
tid,
@ -428,6 +433,81 @@ 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
////////////////////////////
TEST_F(scap_file_test, fcntl_x_check_final_converted_event) {
open_filename("kexec_arm64.scap");
// Inside the scap-file the event `906671` is the following:
// - type=PPME_SYSCALL_FCNTL_X,
// - ts=1687966734198994052
// - tid=114093
// - args=res=0(<f>/dev/null)
//
// And its corresponding enter event `906670` is the following:
// - type=PPME_SYSCALL_FCNTL_E
// - ts=1687966734198993412
// - tid=114093
// - args=fd=19(<f>/sys/fs/cgroup/kubelet.slice/kubelet-kubepods.slice/kubelet-kubepods-
// besteffort.slice/kubelet-kubepods-besteffort-pod03e86e4b_ac6e_4488_883e_e4b50b1be176.
// slice/cgroup.procs)
// cmd=5(F_SETFL)
//
// Let's see the new PPME_SYSCALL_FCNTL_X event!
constexpr uint64_t ts = 1687966734198994052;
constexpr int64_t tid = 114093;
constexpr int64_t res = 0;
constexpr int64_t fd = 19;
constexpr uint8_t cmd = 5;
assert_event_presence(create_safe_scap_event(ts, tid, PPME_SYSCALL_FCNTL_X, 3, res, fd, cmd));
}
////////////////////////////
///// BRK
////////////////////////////
@ -468,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
////////////////////////////
@ -476,28 +676,73 @@ TEST_F(scap_file_test, socket_x_check_final_converted_event) {
open_filename("scap_2013.scap");
// Inside the scap-file the event `515881` is the following:
// - type=PPME_SOCKET_SOCKET_E
// - ts=1380933088295478275
// - tid=44106
// - args=domain=2(AF_INET) type=524289 proto=0
//
// And its corresponding enter event `511520` is the following:
// - type=PPME_SOCKET_SOCKET_X
// - ts=1380933088295552884
// - tid=44106,
// - args=fd=19(<4>)
//
uint64_t ts = 1380933088295552884;
int64_t tid = 44106;
int64_t fd = 19;
uint32_t domain = 2;
uint32_t type = 524289;
uint32_t proto = 0;
// And its corresponding enter event `511520` is the following:
// - type=PPME_SOCKET_SOCKET_E
// - ts=1380933088295478275
// - tid=44106
// - args=domain=2(AF_INET) type=524289 proto=0
//
constexpr uint64_t ts = 1380933088295552884;
constexpr int64_t tid = 44106;
constexpr int64_t fd = 19;
constexpr uint32_t domain = 2;
constexpr uint32_t type = 524289;
constexpr uint32_t proto = 0;
assert_event_presence(
create_safe_scap_event(ts, tid, PPME_SOCKET_SOCKET_X, 4, fd, domain, type, proto));
}
////////////////////////////
// CONNECT
////////////////////////////
// Compile out this test if test_utils helpers are not defined.
#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && !defined(__APPLE__)
TEST_F(scap_file_test, connect_x_check_final_converted_event) {
open_filename("kexec_arm64.scap");
// Inside the scap-file the event `907953` is the following:
// - type=PPME_SOCKET_CONNECT_X
// - ts=1687966734290916318
// - tid=115186
// - args=res=-101(ENETUNREACH) tuple=:::47437->2001:4860:4860::8888:53 fd=13(<6>)
//
// And its corresponding enter event `907952` is the following:
// - type=PPME_SOCKET_CONNECT_E
// - ts=1687966734290903534
// - tid=115186
// - args=fd=13(<6>) addr=2001:4860:4860::8888:53
//
constexpr uint64_t ts = 1687966734290916318;
constexpr int64_t tid = 115186;
constexpr int64_t res = -101;
constexpr int64_t fd = 13;
sockaddr_in6 client_sockaddr = test_utils::fill_sockaddr_in6(47437, "::");
sockaddr_in6 server_sockaddr = test_utils::fill_sockaddr_in6(53, "2001:4860:4860::8888");
const std::vector<uint8_t> tuple =
test_utils::pack_socktuple(reinterpret_cast<struct sockaddr *>(&client_sockaddr),
reinterpret_cast<struct sockaddr *>(&server_sockaddr));
const std::vector<uint8_t> packed_server_sockaddr =
test_utils::pack_sockaddr(reinterpret_cast<sockaddr *>(&server_sockaddr));
assert_event_presence(create_safe_scap_event(
ts,
tid,
PPME_SOCKET_CONNECT_X,
4,
res,
scap_const_sized_buffer{tuple.data(), tuple.size()},
fd,
scap_const_sized_buffer{packed_server_sockaddr.data(), packed_server_sockaddr.size()}));
}
#endif
////////////////////////////
// LISTEN
////////////////////////////
@ -519,11 +764,11 @@ TEST_F(scap_file_test, listen_x_check_final_converted_event) {
//
// Let's see the new PPME_SOCKET_LISTEN_X event!
uint64_t ts = 1687966709944348874;
int64_t tid = 141291;
int64_t res = 0;
int64_t fd = 25;
int32_t backlog = 4096;
constexpr uint64_t ts = 1687966709944348874;
constexpr int64_t tid = 141291;
constexpr int64_t res = 0;
constexpr int64_t fd = 25;
constexpr int32_t backlog = 4096;
assert_event_presence(
create_safe_scap_event(ts, tid, PPME_SOCKET_LISTEN_X, 3, res, fd, backlog));
}
@ -552,17 +797,17 @@ TEST_F(scap_file_test, accept_x_check_final_converted_event) {
//
// Let's see the new PPME_SOCKET_ACCEPT_5_X event!
uint64_t ts = 1380933088302022447;
int64_t tid = 43625;
int64_t fd = 13;
constexpr uint64_t ts = 1380933088302022447;
constexpr int64_t tid = 43625;
constexpr int64_t fd = 13;
sockaddr_in client_sockaddr = test_utils::fill_sockaddr_in(38873, "127.0.0.1");
sockaddr_in server_sockaddr = test_utils::fill_sockaddr_in(80, "127.0.0.1");
const std::vector<uint8_t> tuple =
test_utils::pack_socktuple(reinterpret_cast<struct sockaddr *>(&client_sockaddr),
reinterpret_cast<struct sockaddr *>(&server_sockaddr));
int32_t queuepct = 37;
int32_t queuelen = 0;
int32_t queuemax = 0;
constexpr int32_t queuepct = 37;
constexpr int32_t queuelen = 0;
constexpr int32_t queuemax = 0;
assert_event_presence(
create_safe_scap_event(ts,
tid,
@ -596,16 +841,16 @@ TEST_F(scap_file_test, write_x_check_final_converted_event) {
// - tid=44106,
// - args=fd=13(<4t>127.0.0.1:38904->127.0.0.1:80) size=77
//
uint64_t ts = 1380933088286397273;
int64_t tid = 44106;
int64_t res = 77;
constexpr uint64_t ts = 1380933088286397273;
constexpr int64_t tid = 44106;
constexpr int64_t res = 77;
// this is NULL termiinated so we have 81 bytes but in the scap-file we want only 80 bytes
// without the NULL terminator
char buf[] = {
constexpr char buf[] = {
"GET / HTTP/1.0\r\nHost: 127.0.0.1\r\nUser-Agent: ApacheBench/2.3\r\nAccept: "
"*/*\r\n\r\n"};
int64_t fd = 13;
uint32_t size = 77;
constexpr int64_t fd = 13;
constexpr uint32_t size = 77;
assert_event_presence(create_safe_scap_event(ts,
tid,
PPME_SYSCALL_WRITE_X,
@ -710,8 +955,8 @@ TEST_F(scap_file_test, setresuid_x_check_final_converted_event) {
constexpr int64_t tid = 107389;
constexpr int64_t res = 0;
constexpr uint32_t ruid = 1000;
constexpr uint32_t euid = (uint32_t)-1;
constexpr uint32_t suid = (uint32_t)-1;
constexpr uint32_t euid = static_cast<uint32_t>(-1);
constexpr uint32_t suid = static_cast<uint32_t>(-1);
assert_event_presence(
create_safe_scap_event(ts, tid, PPME_SYSCALL_SETRESUID_X, 4, res, ruid, euid, suid));
@ -738,10 +983,10 @@ TEST_F(scap_file_test, setuid_x_check_final_converted_event) {
//
// Let's see the new PPME_SYSCALL_SETUID_X event!
uint64_t ts = 1687966709959025387;
int64_t tid = 141446;
int64_t res = 0;
int32_t uid = 0;
constexpr uint64_t ts = 1687966709959025387;
constexpr int64_t tid = 141446;
constexpr int64_t res = 0;
constexpr int32_t uid = 0;
assert_event_presence(create_safe_scap_event(ts, tid, PPME_SYSCALL_SETUID_X, 2, res, uid));
}
@ -831,12 +1076,12 @@ TEST_F(scap_file_test, sendto_x_check_final_converted_event) {
//
// Let's see the new PPME_SOCKET_SENDTO_X event!
uint64_t ts = 1687966733172651252;
int64_t tid = 114093;
int64_t res = 17;
constexpr uint64_t ts = 1687966733172651252;
constexpr int64_t tid = 114093;
constexpr int64_t res = 17;
constexpr char data[] = "\x11\x0\x0\x0\x16\x0\x1\x3\x1\x0\x0\x0\x0\x0\x0\x0";
constexpr uint32_t size = sizeof(data);
int64_t fd = 22;
constexpr int64_t fd = 22;
assert_event_presence(create_safe_scap_event(ts,
tid,
PPME_SOCKET_SENDTO_X,
@ -868,11 +1113,11 @@ TEST_F(scap_file_test, shutdown_x_check_final_converted_event) {
//
// Let's see the new PPME_SOCKET_SHUTDOWN_X event!
uint64_t ts = 1687966733231918487;
int64_t tid = 112954;
int64_t res = -107;
int64_t fd = 13;
uint8_t how = 1;
constexpr uint64_t ts = 1687966733231918487;
constexpr int64_t tid = 112954;
constexpr int64_t res = -107;
constexpr int64_t fd = 13;
constexpr uint8_t how = 1;
assert_event_presence(create_safe_scap_event(ts, tid, PPME_SOCKET_SHUTDOWN_X, 3, res, fd, how));
}
@ -1061,11 +1306,11 @@ TEST_F(scap_file_test, mkdir_x_check_final_converted_event) {
//
// Let's see the new PPME_SYSCALL_MKDIR_2_X event!
uint64_t ts = 1749017847850665826;
int64_t tid = 1163259;
int64_t res = -13;
constexpr uint64_t ts = 1749017847850665826;
constexpr int64_t tid = 1163259;
constexpr int64_t res = -13;
constexpr char path[] = "/hello";
uint32_t mode = 0x1ff; // 0777 in octal
constexpr uint32_t mode = 0x1ff; // 0777 in octal
assert_event_presence(
create_safe_scap_event(ts, tid, PPME_SYSCALL_MKDIR_2_X, 3, res, path, mode));
}
@ -1450,13 +1695,13 @@ TEST_F(scap_file_test, ptrace_x_check_final_converted_event) {
//
// Let's see the new PPME_SYSCALL_PTRACE_X event!
uint64_t ts = 1747834548577695347;
int64_t tid = 368860;
int64_t res = 0;
uint8_t addr[] = {0x00, 0x78, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
uint8_t data[] = {0x00, 0x3b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
uint16_t request = 4;
int64_t pid = 368861;
constexpr uint64_t ts = 1747834548577695347;
constexpr int64_t tid = 368860;
constexpr int64_t res = 0;
constexpr uint8_t addr[] = {0x00, 0x78, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
constexpr uint8_t data[] = {0x00, 0x3b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
constexpr uint16_t request = 4;
constexpr int64_t pid = 368861;
assert_event_presence(create_safe_scap_event(ts,
tid,
PPME_SYSCALL_PTRACE_X,
@ -1538,11 +1783,11 @@ TEST_F(scap_file_test, setns_x_check_final_converted_event) {
//
// Let's see the new PPME_SYSCALL_SETNS_X event!
uint64_t ts = 1687889193606963670;
int64_t tid = 107363;
int64_t res = 0;
int64_t fd = 6;
uint32_t nstype = 8; // CLONE_NEWIPC
constexpr uint64_t ts = 1687889193606963670;
constexpr int64_t tid = 107363;
constexpr int64_t res = 0;
constexpr int64_t fd = 6;
constexpr uint32_t nstype = 8; // CLONE_NEWIPC
assert_event_presence(
create_safe_scap_event(ts, tid, PPME_SYSCALL_SETNS_X, 3, res, fd, nstype));
}
@ -1697,10 +1942,10 @@ TEST_F(scap_file_test, fchdir_x_check_final_converted_event) {
//
// Let's see the new PPME_SYSCALL_FCHDIR_X event!
uint64_t ts = 1749117249748433380;
int64_t tid = 1377498;
int64_t res = -9;
int64_t fd = 25;
constexpr uint64_t ts = 1749117249748433380;
constexpr int64_t tid = 1377498;
constexpr int64_t res = -9;
constexpr int64_t fd = 25;
assert_event_presence(create_safe_scap_event(ts, tid, PPME_SYSCALL_FCHDIR_X, 2, res, fd));
}
@ -1725,11 +1970,11 @@ TEST_F(scap_file_test, setpgid_x_check_final_converted_event) {
//
// Let's see the new PPME_SYSCALL_SETPGID_X event!
uint64_t ts = 1687889193490376726;
int64_t tid = 107344;
int64_t res = 0;
int64_t pid = 0;
int64_t pgid = 107344; // zsh process ID
constexpr uint64_t ts = 1687889193490376726;
constexpr int64_t tid = 107344;
constexpr int64_t res = 0;
constexpr int64_t pid = 0;
constexpr int64_t pgid = 107344; // zsh process ID
assert_event_presence(
create_safe_scap_event(ts, tid, PPME_SYSCALL_SETPGID_X, 3, res, pid, pgid));
}
@ -1795,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
////////////////////////////
@ -1857,10 +2108,10 @@ TEST_F(scap_file_test, setgid_x_check_final_converted_event) {
//
// Let's see the new PPME_SYSCALL_SETPGID_X event!
uint64_t ts = 1687889193630645846;
int64_t tid = 107364;
int64_t res = 0;
uint32_t gid = 0;
constexpr uint64_t ts = 1687889193630645846;
constexpr int64_t tid = 107364;
constexpr int64_t res = 0;
constexpr uint32_t gid = 0;
assert_event_presence(create_safe_scap_event(ts, tid, PPME_SYSCALL_SETGID_X, 2, res, gid));
}
@ -1885,12 +2136,12 @@ TEST_F(scap_file_test, setresgid_x_check_final_converted_event) {
//
// Let's see the new PPME_SYSCALL_SETRESGID_X event!
uint64_t ts = 1687889196229751724;
int64_t tid = 107389;
int64_t res = 0;
uint32_t rgid = (uint32_t)-1;
uint32_t egid = 1000;
uint32_t sgid = (uint32_t)-1;
constexpr uint64_t ts = 1687889196229751724;
constexpr int64_t tid = 107389;
constexpr int64_t res = 0;
constexpr uint32_t rgid = static_cast<uint32_t>(-1);
constexpr uint32_t egid = 1000;
constexpr uint32_t sgid = static_cast<uint32_t>(-1);
assert_event_presence(
create_safe_scap_event(ts, tid, PPME_SYSCALL_SETRESGID_X, 4, res, rgid, egid, sgid));
}

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;
}

Some files were not shown because too many files have changed in this diff Show More