// 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 "secagentd/plugins.h"

#include <cstdint>
#include <memory>
#include <utility>

#include "absl/status/status.h"
#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "missive/proto/record_constants.pb.h"
#include "secagentd/bpf/bpf_types.h"
#include "secagentd/device_user.h"
#include "secagentd/message_sender.h"
#include "secagentd/metrics_sender.h"
#include "secagentd/policies_features_broker.h"
#include "secagentd/proto/security_xdr_events.pb.h"

namespace secagentd {

namespace pb = cros_xdr::reporting;

namespace {

// Fills a Namespaces proto with contents from bpf namespace_info.
void FillNamespaces(const bpf::cros_namespace_info& ns,
                    pb::Namespaces* ns_proto) {
  ns_proto->set_cgroup_ns(ns.cgroup_ns);
  ns_proto->set_pid_ns(ns.pid_ns);
  ns_proto->set_user_ns(ns.user_ns);
  ns_proto->set_uts_ns(ns.uts_ns);
  ns_proto->set_mnt_ns(ns.mnt_ns);
  ns_proto->set_net_ns(ns.net_ns);
  ns_proto->set_ipc_ns(ns.ipc_ns);
}

std::string GetBatchedEventKey(
    const pb::ProcessEventAtomicVariant& process_event) {
  switch (process_event.variant_type_case()) {
    case cros_xdr::reporting::ProcessEventAtomicVariant::kProcessExec:
      return process_event.process_exec().spawn_process().process_uuid();
    case cros_xdr::reporting::ProcessEventAtomicVariant::kProcessTerminate:
      return process_event.process_terminate().process().process_uuid();
    case cros_xdr::reporting::ProcessEventAtomicVariant::VARIANT_TYPE_NOT_SET:
      return "";
  }
}

bool SetTerminateTimestamp(pb::ProcessEventAtomicVariant* exec) {
  if (exec->has_process_exec()) {
    exec->mutable_process_exec()->set_terminate_timestamp_us(
        base::Time::Now().InMillisecondsSinceUnixEpoch() *
        base::Time::kMicrosecondsPerMillisecond);
    return true;
  }

  return false;
}

}  // namespace

ProcessPlugin::ProcessPlugin(
    scoped_refptr<BpfSkeletonFactoryInterface> bpf_skeleton_factory,
    scoped_refptr<MessageSenderInterface> message_sender,
    scoped_refptr<ProcessCacheInterface> process_cache,
    scoped_refptr<PoliciesFeaturesBrokerInterface> policies_features_broker,
    scoped_refptr<DeviceUserInterface> device_user,
    uint32_t batch_interval_s)
    : weak_ptr_factory_(this),
      process_cache_(process_cache),
      policies_features_broker_(policies_features_broker),
      device_user_(device_user),
      batch_sender_(
          std::make_unique<BatchSender<std::string,
                                       pb::XdrProcessEvent,
                                       pb::ProcessEventAtomicVariant>>(
              base::BindRepeating(&GetBatchedEventKey),
              message_sender,
              reporting::Destination::CROS_SECURITY_PROCESS,
              batch_interval_s)),
      bpf_skeleton_helper_(
          std::make_unique<BpfSkeletonHelper<Types::BpfSkeleton::kProcess>>(
              bpf_skeleton_factory, batch_interval_s)) {
  CHECK(message_sender != nullptr);
  CHECK(process_cache != nullptr);
  CHECK(bpf_skeleton_factory);
}

std::string ProcessPlugin::GetName() const {
  return "Process";
}

void ProcessPlugin::HandleRingBufferEvent(const bpf::cros_event& bpf_event) {
  auto atomic_event = std::make_unique<pb::ProcessEventAtomicVariant>();
  if (bpf_event.type != bpf::kProcessEvent) {
    LOG(ERROR) << "ProcessBPF: unknown BPF event type.";
    return;
  }
  const bpf::cros_process_event& pe = bpf_event.data.process_event;
  if (pe.type == bpf::kProcessStartEvent) {
    const bpf::cros_process_start& process_start = pe.data.process_start;
    // Record the newly spawned process into our cache.
    process_cache_->PutFromBpfExec(process_start);
    auto exec_event = MakeExecEvent(process_start);
    const pb::Process* parent_process =
        exec_event->has_process() ? exec_event->mutable_process() : nullptr;
    const pb::Process* process = exec_event->has_spawn_process()
                                     ? exec_event->mutable_spawn_process()
                                     : nullptr;
    if (process_cache_->IsEventFiltered(parent_process, process)) {
      return;
    }
    atomic_event->set_allocated_process_exec(exec_event.release());
  } else if (pe.type == bpf::kProcessExitEvent) {
    const bpf::cros_process_exit& process_exit = pe.data.process_exit;
    auto terminate_event = MakeTerminateEvent(process_exit);
    if (process_exit.is_leaf) {
      process_cache_->EraseProcess(process_exit.task_info.pid,
                                   process_exit.task_info.start_time);
    }
    const pb::Process* parent_process =
        terminate_event->has_parent_process()
            ? terminate_event->mutable_parent_process()
            : nullptr;
    const pb::Process* process = terminate_event->has_process()
                                     ? terminate_event->mutable_process()
                                     : nullptr;
    if (process_cache_->IsEventFiltered(parent_process, process)) {
      return;
    }
    atomic_event->set_allocated_process_terminate(terminate_event.release());
  } else {
    LOG(ERROR) << "ProcessBPF: unknown BPF process event type.";
    return;
  }

  device_user_->GetDeviceUserAsync(
      base::BindOnce(&ProcessPlugin::OnDeviceUserRetrieved,
                     weak_ptr_factory_.GetWeakPtr(), std::move(atomic_event)));
}

void ProcessPlugin::OnDeviceUserRetrieved(
    std::unique_ptr<pb::ProcessEventAtomicVariant> atomic_event,
    const std::string& device_user) {
  atomic_event->mutable_common()->set_device_user(device_user);
  EnqueueBatchedEvent(std::move(atomic_event));
}

absl::Status ProcessPlugin::Activate() {
  struct BpfCallbacks callbacks;
  callbacks.ring_buffer_event_callback = base::BindRepeating(
      &ProcessPlugin::HandleRingBufferEvent, weak_ptr_factory_.GetWeakPtr());

  absl::Status status = bpf_skeleton_helper_->LoadAndAttach(callbacks);
  if (status == absl::OkStatus()) {
    batch_sender_->Start();
  }
  return status;
}

absl::Status ProcessPlugin::Deactivate() {
  return absl::UnimplementedError(
      "Deactivate not implemented for ProcessPlugin.");
}

void ProcessPlugin::EnqueueBatchedEvent(
    std::unique_ptr<pb::ProcessEventAtomicVariant> atomic_event) {
  if (atomic_event->has_process_terminate() &&
      policies_features_broker_->GetFeature(
          PoliciesFeaturesBroker::Feature::
              kCrOSLateBootSecagentdCoalesceTerminates)) {
    if (batch_sender_->Visit(pb::ProcessEventAtomicVariant::kProcessExec,
                             GetBatchedEventKey(*atomic_event),
                             base::BindOnce(&SetTerminateTimestamp))) {
      // Successfully visited and presumably also coalesced.
      return;
    }
  }
  batch_sender_->Enqueue(std::move(atomic_event));
}

bool ProcessPlugin::IsActive() const {
  return bpf_skeleton_helper_->IsAttached();
}

std::unique_ptr<pb::ProcessExecEvent> ProcessPlugin::MakeExecEvent(
    const bpf::cros_process_start& process_start) {
  auto process_exec_event = std::make_unique<pb::ProcessExecEvent>();
  FillNamespaces(process_start.spawn_namespace,
                 process_exec_event->mutable_spawn_namespaces());
  // Fetch information on process that was just spawned, the parent process
  // that spawned that process, and its parent process. I.e a total of
  // three.
  auto hierarchy = process_cache_->GetProcessHierarchy(
      process_start.task_info.pid, process_start.task_info.start_time, 3);
  if (hierarchy.empty()) {
    LOG(ERROR) << "PID:" << process_start.task_info.pid
               << " not found in the process cache.";
  }

  if (hierarchy.size() > 0) {
    process_exec_event->set_allocated_spawn_process(hierarchy[0].release());
  }

  if (hierarchy.size() > 1) {
    process_exec_event->set_allocated_process(hierarchy[1].release());
  }

  if (hierarchy.size() > 2) {
    process_exec_event->set_allocated_parent_process(hierarchy[2].release());
  }

  // Exec event metrics.
  metrics::ProcessEvent exec_event_metric = metrics::ProcessEvent::kFullEvent;
  if (hierarchy.empty()) {
    exec_event_metric = metrics::ProcessEvent::kSpawnPidNotInCache;
  } else if (hierarchy.size() == 1) {
    exec_event_metric = metrics::ProcessEvent::kProcessPidNotInCache;
  } else if (hierarchy.size() == 2 && process_exec_event->has_process() &&
             process_exec_event->process().canonical_pid() > 1) {
    exec_event_metric = metrics::ProcessEvent::kParentPidNotInCache;
  }
  MetricsSender::GetInstance().IncrementCountMetric(
      metrics::kCommandLineSize, process_start.task_info.real_commandline_len);
  MetricsSender::GetInstance().IncrementBatchedMetric(metrics::kExecEvent,
                                                      exec_event_metric);

  return process_exec_event;
}

std::unique_ptr<pb::ProcessTerminateEvent> ProcessPlugin::MakeTerminateEvent(
    const bpf::cros_process_exit& process_exit) {
  auto process_terminate_event = std::make_unique<pb::ProcessTerminateEvent>();
  // Try to fetch from the process cache if possible. The cache has more
  // complete information.
  auto hierarchy = process_cache_->GetProcessHierarchy(
      process_exit.task_info.pid, process_exit.task_info.start_time, 2);

  // If that fails, fill in the task info that we got from BPF.
  if (hierarchy.empty()) {
    process_cache_->FillProcessFromBpf(
        process_exit.task_info, process_exit.image_info,
        process_terminate_event->mutable_process(),
        device_user_->GetUsernamesForRedaction());
    if (!process_exit.has_full_info) {
      LOG(WARNING) << absl::StrFormat(
          "process_exit for pid=%d reltime=%d uuid=%s filled with partial "
          "process info.",
          process_terminate_event->process().canonical_pid(),
          process_terminate_event->process().rel_start_time_s(),
          process_terminate_event->process().process_uuid());
    }

    // Maybe the parent is still alive and in procfs.
    auto parent = process_cache_->GetProcessHierarchy(
        process_exit.task_info.ppid, process_exit.task_info.parent_start_time,
        1);
    if (parent.size() != 0) {
      process_terminate_event->set_allocated_parent_process(
          parent[0].release());
    }
  }

  if (hierarchy.size() > 0) {
    process_terminate_event->set_allocated_process(hierarchy[0].release());
  }

  if (hierarchy.size() > 1) {
    process_terminate_event->set_allocated_parent_process(
        hierarchy[1].release());
  }

  // Terminate event metrics.
  metrics::ProcessEvent terminate_event_metric =
      metrics::ProcessEvent::kFullEvent;
  if (hierarchy.empty()) {
    if (process_terminate_event->has_process()) {
      terminate_event_metric = metrics::ProcessEvent::kParentStillAlive;
    } else {
      terminate_event_metric = metrics::ProcessEvent::kProcessPidNotInCache;
    }
  } else if (hierarchy.size() == 1 && process_terminate_event->has_process() &&
             process_terminate_event->process().canonical_pid() > 1) {
    terminate_event_metric = metrics::ProcessEvent::kParentPidNotInCache;
  }
  MetricsSender::GetInstance().IncrementBatchedMetric(metrics::kTerminateEvent,
                                                      terminate_event_metric);

  return process_terminate_event;
}

}  // namespace secagentd
