blob: de9a8684f4ac1f481c30a80920a7f785bf5598f3 [file] [log] [blame]
// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <map>
#include <memory>
#include <string>
#include <utility>
#include "absl/status/status.h"
#include "base/strings/stringprintf.h"
#include "base/task/sequenced_task_runner.h"
#include "missive/client/report_queue.h"
#include "missive/client/report_queue_configuration.h"
#include "missive/client/report_queue_factory.h"
#include "missive/proto/record_constants.pb.h"
#include "missive/proto/security_xdr_events.pb.h"
#include "missive/util/status.h"
#include "secagentd/bpf/process.h"
#include "secagentd/message_sender.h"
namespace {
// Fills a FileImage proto with contents from bpf image_info.
void FillImage(const secagentd::bpf::image_info& image,
reporting::FileImage* proto) {
proto->set_pathname(std::string(image.pathname));
proto->set_mnt_ns(image.mnt_ns);
proto->set_inode_device_id(image.inode_device_id);
proto->set_inode(image.inode);
proto->set_canonical_uid(image.uid);
proto->set_canonical_gid(image.gid);
proto->set_mode(image.mode);
}
// Fills a Namespaces proto with contents from bpf namespace_info.
void FillNamespaces(const secagentd::bpf::namespace_info& namespaces,
reporting::Namespaces* proto) {
proto->set_cgroup_ns(namespaces.cgroup_ns);
proto->set_pid_ns(namespaces.pid_ns);
proto->set_user_ns(namespaces.user_ns);
proto->set_uts_ns(namespaces.uts_ns);
proto->set_mnt_ns(namespaces.mnt_ns);
proto->set_net_ns(namespaces.net_ns);
proto->set_ipc_ns(namespaces.ipc_ns);
}
// Creates a ProcessExec proto from the contents of a bpf event.
std::unique_ptr<reporting::ProcessExecEvent> FillProcessExecEvent(
const secagentd::bpf::process_start& event) {
auto process_start = std::make_unique<reporting::ProcessExecEvent>();
// Fill process fields.
auto process = process_start->mutable_process();
process->set_canonical_pid(event.pid);
process->set_canonical_uid(event.uid);
process->set_commandline(event.commandline);
// Fill parent_process fields.
auto parent_process = process_start->mutable_parent_process();
parent_process->set_canonical_pid(event.ppid);
// Fill image fields.
FillImage(event.image_info, process->mutable_image());
// Fill namespace fields.
FillNamespaces(event.spawn_namespace,
process_start->mutable_spawn_namespaces());
return process_start;
}
// Creates a ProcessExit proto from the contents of a bpf event.
std::unique_ptr<reporting::ProcessTerminateEvent> FillProcessExitEvent(
const secagentd::bpf::process_exit& event) {
auto process_exit = std::make_unique<reporting::ProcessTerminateEvent>();
// Fill process fields.
auto process = process_exit->mutable_process();
process->set_canonical_pid(event.ppid);
return process_exit;
}
void EnqueueCallback(secagentd::bpf::process_event_type type,
::reporting::Status status) {
if (!status.ok()) {
LOG(ERROR) << type << ", status=" << status;
}
}
} // namespace
namespace secagentd {
absl::Status MessageSender::InitializeQueues() {
// Array of possible destinations.
const reporting::Destination kDestinations[] = {
reporting::CROS_SECURITY_PROCESS, reporting::CROS_SECURITY_AGENT};
for (auto destination : kDestinations) {
auto report_queue_result =
reporting::ReportQueueFactory::CreateSpeculativeReportQueue(
reporting::EventType::kDevice, destination);
if (report_queue_result == nullptr) {
return absl::InternalError(
"InitializeQueues: Report queue failed to create");
}
queue_map_.insert(
std::make_pair(destination, std::move(report_queue_result)));
}
return absl::OkStatus();
}
absl::Status MessageSender::SendMessage(const bpf::event& event) {
switch (event.type) {
case bpf::process_type: {
auto it = queue_map_.find(reporting::CROS_SECURITY_PROCESS);
CHECK(it != queue_map_.end());
std::unique_ptr<const google::protobuf::MessageLite> proto;
switch (event.data.process_event.type) {
case bpf::process_start_type: {
proto =
FillProcessExecEvent(event.data.process_event.data.process_start);
break;
}
case bpf::process_exit_type: {
proto =
FillProcessExitEvent(event.data.process_event.data.process_exit);
break;
}
default: {
return absl::InvalidArgumentError(base::StringPrintf(
"SendMessage: unknown BPF process event type: %d",
event.data.process_event.type));
}
}
it->second.get()->Enqueue(
std::move(proto), ::reporting::SECURITY,
base::BindOnce(&EnqueueCallback, event.data.process_event.type));
break;
}
default: {
return absl::InvalidArgumentError(base::StringPrintf(
"SendMessage: unknown BPF event type: %d", event.type));
}
}
return absl::OkStatus();
}
} // namespace secagentd