-
Notifications
You must be signed in to change notification settings - Fork 33
fix: include custom container plugin and filtering #3939
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| add_library(collector-container-plugin SHARED ContainerPlugin.cpp) | ||
|
|
||
| set_target_properties(collector-container-plugin PROPERTIES | ||
| PREFIX "" | ||
| OUTPUT_NAME "collector-container-plugin" | ||
| LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/collector" | ||
| ) | ||
|
|
||
| target_include_directories(collector-container-plugin PRIVATE | ||
| ${FALCO_DIR}/userspace | ||
| ${FALCO_DIR}/driver | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| #pragma once | ||
|
|
||
| #include <algorithm> | ||
| #include <cctype> | ||
| #include <optional> | ||
| #include <string_view> | ||
|
|
||
| namespace collector::container_plugin { | ||
|
|
||
| constexpr size_t kContainerIDLength = 64; | ||
| constexpr size_t kShortContainerIDLength = 12; | ||
|
|
||
| inline std::optional<std::string_view> ExtractContainerIDFromCgroup(std::string_view cgroup) { | ||
| const auto scope = cgroup.rfind(".scope"); | ||
| if (scope != std::string_view::npos) { | ||
| cgroup.remove_suffix(cgroup.size() - scope); | ||
| } | ||
| if (cgroup.size() < kContainerIDLength + 1) { | ||
| return {}; | ||
| } | ||
| const auto id_start = cgroup.size() - kContainerIDLength; | ||
| const char separator = cgroup[id_start - 1]; | ||
| if (separator != '/' && separator != '-' && separator != ':') { | ||
| return {}; | ||
| } | ||
| const std::string_view parent = cgroup.substr(0, id_start - 1); | ||
| constexpr std::string_view kConmonSuffix = "-conmon"; | ||
| if (parent.size() >= kConmonSuffix.size() && | ||
| parent.substr(parent.size() - kConmonSuffix.size()) == kConmonSuffix) { | ||
| return {}; | ||
| } | ||
| const std::string_view id = cgroup.substr(id_start); | ||
| if (!std::all_of(id.begin(), id.end(), [](char c) { return std::isxdigit(static_cast<unsigned char>(c)); })) { | ||
| return {}; | ||
| } | ||
| return id.substr(0, kShortContainerIDLength); | ||
| } | ||
|
|
||
| } // namespace collector::container_plugin | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,260 @@ | ||||||||||||||||||||||||
| #include <cctype> | ||||||||||||||||||||||||
| #include <cstdint> | ||||||||||||||||||||||||
| #include <ppm_events_public.h> | ||||||||||||||||||||||||
| #include <string> | ||||||||||||||||||||||||
| #include <string_view> | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| #include <plugin/plugin_api.h> | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| #include "ContainerID.h" | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| namespace { | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| constexpr std::string_view kPluginName = "collector-container"; | ||||||||||||||||||||||||
| constexpr std::string_view kPluginVersion = "0.1.0"; | ||||||||||||||||||||||||
| constexpr std::string_view kHostContainerID = "host"; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| struct plugin_state { | ||||||||||||||||||||||||
| std::string last_error; | ||||||||||||||||||||||||
| ss_plugin_table_t* threads = nullptr; | ||||||||||||||||||||||||
| ss_plugin_table_field_t* cgroups = nullptr; | ||||||||||||||||||||||||
| ss_plugin_table_field_t* cgroup_path = nullptr; | ||||||||||||||||||||||||
| ss_plugin_table_field_t* container_id = nullptr; | ||||||||||||||||||||||||
| std::string extracted_container_id; | ||||||||||||||||||||||||
| const char* extracted_container_id_ptr = nullptr; | ||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| std::string ContainerIDFromCgroup(std::string_view cgroup) { | ||||||||||||||||||||||||
| return std::string(collector::container_plugin::ExtractContainerIDFromCgroup(cgroup).value_or(std::string_view{})); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| struct cgroup_iteration_state { | ||||||||||||||||||||||||
| plugin_state* plugin; | ||||||||||||||||||||||||
| ss_plugin_table_reader_vtable_ext* reader; | ||||||||||||||||||||||||
| ss_plugin_table_t* cgroup_table; | ||||||||||||||||||||||||
| std::string container_id; | ||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ss_plugin_bool FindContainerID(ss_plugin_table_iterator_state_t* data, ss_plugin_table_entry_t* entry) { | ||||||||||||||||||||||||
| auto* state = reinterpret_cast<cgroup_iteration_state*>(data); | ||||||||||||||||||||||||
| ss_plugin_state_data value{}; | ||||||||||||||||||||||||
| if (state->reader->read_entry_field(state->cgroup_table, entry, state->plugin->cgroup_path, &value) != SS_PLUGIN_SUCCESS) { | ||||||||||||||||||||||||
| return 0; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| if (value.str != nullptr) { | ||||||||||||||||||||||||
| state->container_id = ContainerIDFromCgroup(value.str); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
Comment on lines
+44
to
+46
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win Stop the cgroup scan at the first extracted ID.
Keep the first non-empty result and stop the iteration. Early stop makes 🐛 Proposed fix struct cgroup_iteration_state {
plugin_state* plugin;
ss_plugin_table_reader_vtable_ext* reader;
ss_plugin_table_t* cgroup_table;
std::string container_id;
+ bool found = false;
};
ss_plugin_bool FindContainerID(ss_plugin_table_iterator_state_t* data, ss_plugin_table_entry_t* entry) {
auto* state = reinterpret_cast<cgroup_iteration_state*>(data);
ss_plugin_state_data value{};
if (state->reader->read_entry_field(state->cgroup_table, entry, state->plugin->cgroup_path, &value) != SS_PLUGIN_SUCCESS) {
return 0;
}
if (value.str != nullptr) {
- state->container_id = ContainerIDFromCgroup(value.str);
+ std::string id = ContainerIDFromCgroup(value.str);
+ if (!id.empty()) {
+ state->container_id = std::move(id);
+ state->found = true;
+ return 0;
+ }
}
return 1;
} cgroup_iteration_state iteration{state, reader, cgroups.table, {}};
- if (!reader->iterate_entries(cgroups.table, FindContainerID,
- reinterpret_cast<ss_plugin_table_iterator_state_t*>(&iteration))) {
+ const bool completed = reader->iterate_entries(cgroups.table, FindContainerID,
+ reinterpret_cast<ss_plugin_table_iterator_state_t*>(&iteration)) != 0;
+ if (!completed && !iteration.found) {
state->last_error = "failed to inspect thread cgroups";
return SS_PLUGIN_FAILURE;
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||
| return 1; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ss_plugin_rc CacheContainerID(plugin_state* state, | ||||||||||||||||||||||||
| ss_plugin_table_entry_t* thread, | ||||||||||||||||||||||||
| ss_plugin_table_reader_vtable_ext* reader, | ||||||||||||||||||||||||
| ss_plugin_table_writer_vtable_ext* writer) { | ||||||||||||||||||||||||
| ss_plugin_state_data cgroups{}; | ||||||||||||||||||||||||
| if (reader->read_entry_field(state->threads, thread, state->cgroups, &cgroups) != SS_PLUGIN_SUCCESS || | ||||||||||||||||||||||||
| cgroups.table == nullptr) { | ||||||||||||||||||||||||
| state->last_error = "failed to read thread cgroups"; | ||||||||||||||||||||||||
| return SS_PLUGIN_FAILURE; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| cgroup_iteration_state iteration{state, reader, cgroups.table, {}}; | ||||||||||||||||||||||||
| if (!reader->iterate_entries(cgroups.table, FindContainerID, | ||||||||||||||||||||||||
| reinterpret_cast<ss_plugin_table_iterator_state_t*>(&iteration))) { | ||||||||||||||||||||||||
| state->last_error = "failed to inspect thread cgroups"; | ||||||||||||||||||||||||
| return SS_PLUGIN_FAILURE; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ss_plugin_state_data value{}; | ||||||||||||||||||||||||
| const std::string id = iteration.container_id.empty() ? std::string(kHostContainerID) : iteration.container_id; | ||||||||||||||||||||||||
| value.str = id.c_str(); | ||||||||||||||||||||||||
| if (writer->write_entry_field(state->threads, thread, state->container_id, &value) != SS_PLUGIN_SUCCESS) { | ||||||||||||||||||||||||
|
Comment on lines
+68
to
+71
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win 🔎 Supported by static analysis🌐 Web query:
💡 Result: In the Falco plugin API, the write_entry_field function is used to update an entry's field [1][2]. When dealing with dynamic string table fields in libsinsp, the semantics for writing string data involve passing a pointer to the data through the ss_plugin_state_data structure [1][2]. Regarding your specific questions: 1. String Copy Semantics: When you provide a string to write_entry_field, the underlying implementation in libsinsp typically performs a copy of the string data into the storage owned by the table entry [3]. The plugin does not need to maintain the memory after the write_entry_field call returns; the table takes ownership of the copied string data within its internal state representation [3]. 2. Default Value of Unwritten Dynamic String Fields: For dynamic string fields that have not yet been written to, the libsinsp state management implementation defaults these values to an empty string ("") [3]. When reading an unwritten string field (e.g., via read_field or internal state accessors), the implementation returns a pointer to an empty string or an empty string object, ensuring that read operations on unwritten fields do not result in null pointer dereferences or undefined behavior [3]. These behaviors are consistent with the design of the state access layer in libsinsp, which manages field storage and provides safe accessors for both static and dynamic fields [3][4]. Citations:
🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- target and related source files ---'
sed -n '50,82p' collector/container-plugin/ContainerPlugin.cpp
sed -n '229,242p' collector/container-plugin/ContainerPlugin.cpp
sed -n '50,80p' collector/lib/Utility.cpp
printf '%s\n' '--- repository bindings for write_entry_field and field reads ---'
rg -n --hidden --glob '!build/**' --glob '!dist/**' \
'write_entry_field|read_entry_field|container_id|SS_PLUGIN_STATE_TYPE_STRING' \
collector CMakeLists.txt cmake .github 2>/dev/null | head -240
printf '%s\n' '--- dependency declarations ---'
rg -n --hidden --glob '!build/**' --glob '!dist/**' \
'falcosecurity/libs|libsinsp|SCAP|plugin_api' . | head -160Repository: stackrox/collector Length of output: 15667 🤖 get_repo_knowledge executed:
Length of output: 408 🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- Falco/libsinsp version binding ---'
sed -n '1,125p' collector/CMakeLists.txt
sed -n '1,90p' docs/falco-update.md
printf '%s\n' '--- plugin field declaration and extraction path ---'
sed -n '115,145p' collector/container-plugin/ContainerPlugin.cpp
sed -n '194,228p' collector/container-plugin/ContainerPlugin.cpp
printf '%s\n' '--- repository revisions/configuration mentioning Falco versions ---'
rg -n --hidden --glob '!build/**' --glob '!dist/**' \
'FALCO_VERSION|FALCO_DIR|falcosecurity/libs|falco.*(tag|branch|commit)|libs.*(tag|branch|commit)' \
. | head -200Repository: stackrox/collector Length of output: 10542 🌐 Web query:
💡 Result: In the context of the Falco plugin API, the write_entry_field function is a member of the ss_plugin_table_writer_vtable (and its extensions) [1]. It is responsible for updating a specific field within a table entry [1]. When working with dynamic string fields or other data types, the implementation involves using the ss_plugin_state_data union to pass the new value [2]. Specifically: 1. Identification: You must first obtain the ss_plugin_table_field_t accessor for the desired field, typically during the plugin_init phase [1]. 2. Value Preparation: To set a value, you populate an ss_plugin_state_data union [2]. For a string field, you set the str member to point to the null-terminated string [2]. 3. Execution: You invoke the write_entry_field function, passing the target table (ss_plugin_table_t*), the specific entry (ss_plugin_table_entry_t*), the field accessor (ss_plugin_table_field_t*), and the data union (ss_plugin_state_data*) [1]. 4. Return Code: The function returns SS_PLUGIN_SUCCESS if the update is successful, or SS_PLUGIN_FAILURE otherwise [1]. There is no specific "default" implementation for this function provided by the API itself; rather, it is a callback that the plugin developer must utilize as part of the vtable structure provided by the host (libsinsp) to interact with state tables [1][3]. The actual data storage and management for these fields are handled by the libsinsp state engine [4]. Citations:
🏁 Script executed: #!/bin/bash
set -eu
tmp=$(mktemp)
curl -fsSL 'https://api.github.com/repos/falcosecurity/libs/git/trees/0.17.2?recursive=1' >"$tmp"
printf '%s\n' '--- candidate state-table implementation files ---'
jq -r '.tree[] | select(.path | test("plugin|state|table"; "i")) | .path' "$tmp" |
grep -E 'userspace/.*/(plugin|state|table)|userspace/plugin' | head -120
printf '%s\n' '--- plugin API declarations ---'
curl -fsSL 'https://raw.githubusercontent.com/falcosecurity/libs/0.17.2/userspace/plugin/plugin_api.h' |
rg -n -A18 -B8 'write_entry_field|SS_PLUGIN_ST_STRING|ss_plugin_state_data'Repository: stackrox/collector Length of output: 9114 🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- exact source references from the cited state-table change ---'
for url in \
'https://api.github.com/repos/falcosecurity/libs/commits/2bb117cf91d02ea415140239dc33bd21461859dd' \
'https://api.github.com/repos/falcosecurity/libs/commits/adf2436f843cd0820324a83333243a48dc6ba7c6'; do
printf '\n%s\n' "$url"
curl -fsSL "$url" | jq -r '.sha, (.files[]?.filename // empty)'
doneRepository: stackrox/collector Length of output: 640 🏁 Script executed: #!/bin/bash
set -eu
for path in \
userspace/libsinsp/plugin_table_api.cpp \
userspace/libsinsp/state/dynamic_struct.h \
userspace/libsinsp/state/table.h \
userspace/libsinsp/state/type_info.h \
userspace/libsinsp/state/state_struct.h; do
printf '\n--- %s ---\n' "$path"
curl -fsSL "https://raw.githubusercontent.com/falcosecurity/libs/0.17.2/$path" |
rg -n -A24 -B12 \
'write_entry_field|read_entry_field|dynamic.*string|string.*default|m_data|value_init|set_value|new_accessor|dynamic_struct' |
head -240
doneRepository: stackrox/collector Length of output: 25300 🏁 Script executed: #!/bin/bash
set -eu
curl -fsSL 'https://api.github.com/repos/falcosecurity/libs/commits/2bb117cf91d02ea415140239dc33bd21461859dd' |
jq -r '.files[] | "\n--- " + .filename + " ---\n" + (.patch // "[patch unavailable]")' |
head -500Repository: stackrox/collector Length of output: 3271 🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- upstream state string construction and dynamic-field access ---'
curl -fsSL 'https://raw.githubusercontent.com/falcosecurity/libs/0.17.2/userspace/libsinsp/state/dynamic_struct.h' |
sed -n '287,465p'
printf '%s\n' '--- upstream plugin table adapter around dynamic field writes ---'
curl -fsSL 'https://raw.githubusercontent.com/falcosecurity/libs/0.17.2/userspace/libsinsp/plugin_table_api.cpp' |
sed -n '330,465p'Repository: stackrox/collector Length of output: 10707 Initialize
🤖 Prompt for AI Agents |
||||||||||||||||||||||||
| state->last_error = "failed to cache thread container ID"; | ||||||||||||||||||||||||
| return SS_PLUGIN_FAILURE; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| return SS_PLUGIN_SUCCESS; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| struct thread_iteration_state { | ||||||||||||||||||||||||
| plugin_state* plugin; | ||||||||||||||||||||||||
| ss_plugin_table_reader_vtable_ext* reader; | ||||||||||||||||||||||||
| ss_plugin_table_writer_vtable_ext* writer; | ||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ss_plugin_bool CacheInitialThread(ss_plugin_table_iterator_state_t* data, ss_plugin_table_entry_t* entry) { | ||||||||||||||||||||||||
| auto* state = reinterpret_cast<thread_iteration_state*>(data); | ||||||||||||||||||||||||
| return CacheContainerID(state->plugin, entry, state->reader, state->writer) == SS_PLUGIN_SUCCESS; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| } // namespace | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| extern "C" const char* plugin_get_required_api_version() { | ||||||||||||||||||||||||
| return PLUGIN_API_VERSION_STR; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| extern "C" const char* plugin_get_version() { | ||||||||||||||||||||||||
| return kPluginVersion.data(); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| extern "C" const char* plugin_get_name() { | ||||||||||||||||||||||||
| return kPluginName.data(); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| extern "C" const char* plugin_get_description() { | ||||||||||||||||||||||||
| return "Caches Collector container IDs in Falco thread state"; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| extern "C" const char* plugin_get_contact() { | ||||||||||||||||||||||||
| return "https://github.com/stackrox/collector"; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| extern "C" const char* plugin_get_required_event_schema_version(ss_plugin_t*) { | ||||||||||||||||||||||||
| return "4.1.0"; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| extern "C" ss_plugin_t* plugin_init(const ss_plugin_init_input* input, ss_plugin_rc* rc) { | ||||||||||||||||||||||||
| auto* state = new plugin_state; | ||||||||||||||||||||||||
| *rc = SS_PLUGIN_FAILURE; | ||||||||||||||||||||||||
| if (input == nullptr || input->tables == nullptr || input->tables->fields_ext == nullptr || | ||||||||||||||||||||||||
| input->tables->reader_ext == nullptr || input->tables->writer_ext == nullptr) { | ||||||||||||||||||||||||
| state->last_error = "Falco table API is unavailable"; | ||||||||||||||||||||||||
| return reinterpret_cast<ss_plugin_t*>(state); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| state->threads = input->tables->get_table(input->owner, "threads", SS_PLUGIN_ST_INT64); | ||||||||||||||||||||||||
| if (state->threads == nullptr) { | ||||||||||||||||||||||||
| state->last_error = "failed to access Falco threads table"; | ||||||||||||||||||||||||
| return reinterpret_cast<ss_plugin_t*>(state); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| state->cgroups = input->tables->fields_ext->get_table_field(state->threads, "cgroups", SS_PLUGIN_ST_TABLE); | ||||||||||||||||||||||||
| state->container_id = input->tables->fields_ext->add_table_field(state->threads, "container_id", SS_PLUGIN_ST_STRING); | ||||||||||||||||||||||||
| if (state->cgroups == nullptr || state->container_id == nullptr) { | ||||||||||||||||||||||||
| state->last_error = "failed to access Falco thread cgroup or container ID fields"; | ||||||||||||||||||||||||
| return reinterpret_cast<ss_plugin_t*>(state); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ss_plugin_table_entry_t* entry = input->tables->writer_ext->create_table_entry(state->threads); | ||||||||||||||||||||||||
| ss_plugin_state_data cgroups{}; | ||||||||||||||||||||||||
| if (entry == nullptr || input->tables->reader_ext->read_entry_field(state->threads, entry, state->cgroups, &cgroups) != SS_PLUGIN_SUCCESS || | ||||||||||||||||||||||||
| cgroups.table == nullptr) { | ||||||||||||||||||||||||
| if (entry != nullptr) { | ||||||||||||||||||||||||
| input->tables->writer_ext->destroy_table_entry(state->threads, entry); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| state->last_error = "failed to access Falco cgroup table"; | ||||||||||||||||||||||||
| return reinterpret_cast<ss_plugin_t*>(state); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| state->cgroup_path = input->tables->fields_ext->get_table_field(cgroups.table, "second", SS_PLUGIN_ST_STRING); | ||||||||||||||||||||||||
| input->tables->writer_ext->destroy_table_entry(state->threads, entry); | ||||||||||||||||||||||||
| if (state->cgroup_path == nullptr) { | ||||||||||||||||||||||||
| state->last_error = "failed to access Falco cgroup path field"; | ||||||||||||||||||||||||
| return reinterpret_cast<ss_plugin_t*>(state); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| *rc = SS_PLUGIN_SUCCESS; | ||||||||||||||||||||||||
| return reinterpret_cast<ss_plugin_t*>(state); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| extern "C" void plugin_destroy(ss_plugin_t* plugin) { | ||||||||||||||||||||||||
| delete reinterpret_cast<plugin_state*>(plugin); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| extern "C" const char* plugin_get_last_error(ss_plugin_t* plugin) { | ||||||||||||||||||||||||
| return reinterpret_cast<plugin_state*>(plugin)->last_error.c_str(); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| extern "C" const char* plugin_get_parse_event_sources() { | ||||||||||||||||||||||||
| return "[\"syscall\"]"; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| extern "C" uint16_t* plugin_get_parse_event_types(uint32_t* count, ss_plugin_t*) { | ||||||||||||||||||||||||
| static uint16_t event_types[] = { | ||||||||||||||||||||||||
| PPME_SYSCALL_CLONE_20_X, | ||||||||||||||||||||||||
| PPME_SYSCALL_FORK_20_X, | ||||||||||||||||||||||||
| PPME_SYSCALL_VFORK_20_X, | ||||||||||||||||||||||||
| PPME_SYSCALL_CLONE3_X, | ||||||||||||||||||||||||
| PPME_SYSCALL_EXECVE_16_X, | ||||||||||||||||||||||||
| PPME_SYSCALL_EXECVE_17_X, | ||||||||||||||||||||||||
| PPME_SYSCALL_EXECVE_18_X, | ||||||||||||||||||||||||
| PPME_SYSCALL_EXECVE_19_X, | ||||||||||||||||||||||||
| PPME_SYSCALL_EXECVEAT_X, | ||||||||||||||||||||||||
| PPME_SYSCALL_CHROOT_X, | ||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we need chroot? Can it somehow change the cgroups a process belongs to? |
||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||
| *count = sizeof(event_types) / sizeof(event_types[0]); | ||||||||||||||||||||||||
| return event_types; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| extern "C" const char* plugin_get_fields() { | ||||||||||||||||||||||||
| return R"([{"type":"string","name":"container.id","desc":"Cached container ID for the event thread"}])"; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| extern "C" const char* plugin_get_extract_event_sources() { | ||||||||||||||||||||||||
| return "[\"syscall\"]"; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| extern "C" ss_plugin_rc plugin_extract_fields(ss_plugin_t* plugin, | ||||||||||||||||||||||||
| const ss_plugin_event_input* event, | ||||||||||||||||||||||||
| const ss_plugin_field_extract_input* input) { | ||||||||||||||||||||||||
| auto* state = reinterpret_cast<plugin_state*>(plugin); | ||||||||||||||||||||||||
| ss_plugin_state_data key{}; | ||||||||||||||||||||||||
| key.s64 = static_cast<int64_t>(event->evt->tid); | ||||||||||||||||||||||||
| ss_plugin_table_entry_t* thread = input->table_reader_ext->get_table_entry(state->threads, &key); | ||||||||||||||||||||||||
| if (thread == nullptr) { | ||||||||||||||||||||||||
| for (uint32_t i = 0; i < input->num_fields; ++i) { | ||||||||||||||||||||||||
| input->fields[i].res_len = 0; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| return SS_PLUGIN_SUCCESS; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ss_plugin_state_data value{}; | ||||||||||||||||||||||||
| const ss_plugin_rc read_rc = input->table_reader_ext->read_entry_field(state->threads, thread, state->container_id, &value); | ||||||||||||||||||||||||
| input->table_reader_ext->release_table_entry(state->threads, thread); | ||||||||||||||||||||||||
| if (read_rc != SS_PLUGIN_SUCCESS || value.str == nullptr) { | ||||||||||||||||||||||||
| state->last_error = "failed to read cached thread container ID"; | ||||||||||||||||||||||||
| return SS_PLUGIN_FAILURE; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| state->extracted_container_id = value.str; | ||||||||||||||||||||||||
| state->extracted_container_id_ptr = state->extracted_container_id.c_str(); | ||||||||||||||||||||||||
| for (uint32_t i = 0; i < input->num_fields; ++i) { | ||||||||||||||||||||||||
| if (input->fields[i].field_id != 0) { | ||||||||||||||||||||||||
| input->fields[i].res_len = 0; | ||||||||||||||||||||||||
| continue; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| input->fields[i].res.str = &state->extracted_container_id_ptr; | ||||||||||||||||||||||||
| input->fields[i].res_len = 1; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| return SS_PLUGIN_SUCCESS; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| extern "C" ss_plugin_rc plugin_parse_event(ss_plugin_t* plugin, | ||||||||||||||||||||||||
| const ss_plugin_event_input* event, | ||||||||||||||||||||||||
| const ss_plugin_event_parse_input* input) { | ||||||||||||||||||||||||
| auto* state = reinterpret_cast<plugin_state*>(plugin); | ||||||||||||||||||||||||
| ss_plugin_state_data key{}; | ||||||||||||||||||||||||
| key.s64 = static_cast<int64_t>(event->evt->tid); | ||||||||||||||||||||||||
| ss_plugin_table_entry_t* thread = input->table_reader_ext->get_table_entry(state->threads, &key); | ||||||||||||||||||||||||
| if (thread == nullptr) { | ||||||||||||||||||||||||
| return SS_PLUGIN_SUCCESS; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| const ss_plugin_rc rc = CacheContainerID(state, thread, input->table_reader_ext, input->table_writer_ext); | ||||||||||||||||||||||||
| input->table_reader_ext->release_table_entry(state->threads, thread); | ||||||||||||||||||||||||
| return rc; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| extern "C" ss_plugin_rc plugin_capture_open(ss_plugin_t* plugin, const ss_plugin_capture_listen_input* input) { | ||||||||||||||||||||||||
| auto* state = reinterpret_cast<plugin_state*>(plugin); | ||||||||||||||||||||||||
| thread_iteration_state iteration{state, input->table_reader_ext, input->table_writer_ext}; | ||||||||||||||||||||||||
| if (!input->table_reader_ext->iterate_entries( | ||||||||||||||||||||||||
| state->threads, CacheInitialThread, | ||||||||||||||||||||||||
| reinterpret_cast<ss_plugin_table_iterator_state_t*>(&iteration))) { | ||||||||||||||||||||||||
| if (state->last_error.empty()) { | ||||||||||||||||||||||||
| state->last_error = "failed to cache initial thread container IDs"; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| return SS_PLUGIN_FAILURE; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| return SS_PLUGIN_SUCCESS; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| extern "C" ss_plugin_rc plugin_capture_close(ss_plugin_t*, const ss_plugin_capture_listen_input*) { | ||||||||||||||||||||||||
| return SS_PLUGIN_SUCCESS; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.