Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 16 additions & 10 deletions osquery/events/linux/bpf/setrlimit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ DECLARE_bool(enable_bpf_events);

namespace {
std::once_flag setrlimit_flag;
bool setrlimit_succeeded{false};

void configureBPFMemoryLimitsHelper() {
bool configureBPFMemoryLimitsHelper() {
if (!FLAGS_enable_bpf_events) {
return;
return true;
}

struct rlimit rl = {};
Expand All @@ -32,21 +33,26 @@ void configureBPFMemoryLimitsHelper() {

auto err = setrlimit(RLIMIT_MEMLOCK, &rl);

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🔵 configureBPFMemoryLimitsHelper throws std::runtime_error instead of returning Status

Changed configureBPFMemoryLimitsHelper() in osquery/events/linux/bpf/setrlimit.cpp to return bool instead of throwing std::runtime_error on setrlimit() failure. Added a static bool setrlimit_succeeded captured by the std::call_once lambda invocation inside configureBPFMemoryLimits(), which now checks the result directly and returns Status::failure(...) with the original message instead of relying on catching an exception. The try/catch around std::call_once was removed since no exception is thrown anymore. This preserves the "call once" semantics and the externally observed Status::failure behavior for callers.

🤖 Prompt for AI agents
In osquery/events/linux/bpf/setrlimit.cpp around line 33, review and complete this code-review fix: configureBPFMemoryLimitsHelper throws std::runtime_error instead of returning Status.
What the draft fix changed: Changed configureBPFMemoryLimitsHelper() in osquery/events/linux/bpf/setrlimit.cpp to return bool instead of throwing std::runtime_error on setrlimit() failure. Added a static bool setrlimit_succeeded captured by the std::call_once lambda invocation inside configureBPFMemoryLimits(), which now checks the result directly and returns Status::failure(...) with the original message instead of relying on catching an exception. The try/catch around std::call_once was removed since no exception is thrown anymore. This preserves the "call once" semantics and the externally observed Status::failure behavior for callers.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟡 85 medium — react 👍/👎 to teach the reviewer

if (err != 0) {
throw std::runtime_error(
"Failed to setup the memory lock limits. The BPF tables may not work "
"correctly.");
return false;
}

return true;
}
} // namespace

Status configureBPFMemoryLimits() {
try {
std::call_once(setrlimit_flag, configureBPFMemoryLimitsHelper);
return Status::success();
std::call_once(setrlimit_flag, [&]() {
setrlimit_succeeded = configureBPFMemoryLimitsHelper();
});

} catch (const std::exception& e) {
return Status::failure(e.what());
if (!setrlimit_succeeded) {
return Status::failure(
"Failed to setup the memory lock limits. The BPF tables may not work "
"correctly.");
}

return Status::success();
}

} // namespace osquery

Original file line number Diff line number Diff line change
Expand Up @@ -31,29 +31,34 @@ const std::vector<std::tuple<std::string, std::string>> kKnownCgroupPrefixList{
{"/libpod-", "podman"},
};

std::string getProcUptimeContents() {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🔴 getProcUptimeContents / getSystemBootTime throw std::runtime_error in production osquery code

In osquery/experimental/experiments/linuxevents/src/bpfprocesseventstable.cpp, getProcUptimeContents() and getSystemBootTime() were changed from throwing std::runtime_error to returning osquery::Status (success/failure) via an out-parameter, following the OSQUERY-002-2/OSQUERY-003 convention. The caller BPFProcessEventsTable::generate() now checks the Status returned by getSystemBootTime() and, on failure, returns an empty TableRows instead of letting an exception propagate out of TablePlugin::generate(). This removes the uncaught-exception crash path on /proc/uptime read/parse failures. One judgment call: on failure the function silently returns no rows rather than logging; a more complete fix might also log the Status message via LOG(ERROR), which was not added here to keep the change minimal.

🤖 Prompt for AI agents
In osquery/experimental/experiments/linuxevents/src/bpfprocesseventstable.cpp around line 34, review and complete this code-review fix: getProcUptimeContents / getSystemBootTime throw std::runtime_error in production osquery code.
What the draft fix changed: In `osquery/experimental/experiments/linuxevents/src/bpfprocesseventstable.cpp`, `getProcUptimeContents()` and `getSystemBootTime()` were changed from throwing `std::runtime_error` to returning `osquery::Status` (success/failure) via an out-parameter, following the OSQUERY-002-2/OSQUERY-003 convention. The caller `BPFProcessEventsTable::generate()` now checks the `Status` returned by `getSystemBootTime()` and, on failure, returns an empty `TableRows` instead of letting an exception propagate out of `TablePlugin::generate()`. This removes the uncaught-exception crash path on `/proc/uptime` read/parse failures. One judgment call: on failure the function silently returns no rows rather than logging; a more complete fix might also log the Status message via `LOG(ERROR)`, which was not added here to keep the change minimal.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟡 85 medium — react 👍/👎 to teach the reviewer

std::string uptime_contents;
Status getProcUptimeContents(std::string& uptime_contents) {
uptime_contents.clear();

{
std::ifstream uptime_file(kProcUptimeFilePath.c_str(), std::ios::in);
if (!uptime_file) {
throw std::runtime_error("Failed to access the following path: " +
kProcUptimeFilePath);
return Status::failure("Failed to access the following path: " +
kProcUptimeFilePath);
}

std::getline(uptime_file, uptime_contents);
}

return uptime_contents;
return Status::success();
}

std::uint64_t getSystemBootTime() {
Status getSystemBootTime(std::uint64_t& boot_time) {
auto current_time = std::time(nullptr);
auto uptime_contents = getProcUptimeContents();

std::string uptime_contents;
auto status = getProcUptimeContents(uptime_contents);
if (!status.ok()) {
return status;
}

auto separator_index = uptime_contents.find('.');
if (separator_index == std::string::npos) {
throw std::runtime_error("Invalid data read from " + kProcUptimeFilePath);
return Status::failure("Invalid data read from " + kProcUptimeFilePath);
}

auto string_uptime = uptime_contents.substr(0, separator_index);
Expand All @@ -63,10 +68,11 @@ std::uint64_t getSystemBootTime() {
std::strtoull(string_uptime.c_str(), &last_parsed_char, 10);
if (integer_uptime == 0 || last_parsed_char == nullptr ||
*last_parsed_char != 0) {
throw std::runtime_error("Invalid data read from " + kProcUptimeFilePath);
return Status::failure("Invalid data read from " + kProcUptimeFilePath);
}

return current_time - integer_uptime;
boot_time = current_time - integer_uptime;
return Status::success();
}

} // namespace
Expand Down Expand Up @@ -131,7 +137,11 @@ TableRows BPFProcessEventsTable::generate(QueryContext& context) {
TableRows row_list;
std::stringstream buffer;

auto system_boot_time = getSystemBootTime();
std::uint64_t system_boot_time{0U};
auto status = getSystemBootTime(system_boot_time);
if (!status.ok()) {
return row_list;
}

for (const auto& event : d->event_list) {
auto row = make_table_row();
Expand Down Expand Up @@ -214,4 +224,4 @@ TableRows BPFProcessEventsTable::generate(QueryContext& context) {
return row_list;
}

} // namespace osquery
} // namespace osquery
Loading