// Copyright 2021 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "secanomalyd/daemon.h"

#include <sys/types.h>
#include <sysexits.h>

#include <memory>
#include <string>
#include <string_view>

#include <absl/strings/match.h>
#include <base/command_line.h>
#include <base/files/file_util.h>
#include <base/files/file_path.h>
#include <base/logging.h>
#include <base/rand_util.h>
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>
#include <base/time/time.h>

#include <brillo/process/process.h>
#include <brillo/message_loops/message_loop.h>

#include "secanomalyd/audit_log_reader.h"
#include "secanomalyd/metrics.h"
#include "secanomalyd/mount_entry.h"
#include "secanomalyd/mounts.h"
#include "secanomalyd/processes.h"
#include "secanomalyd/reporter.h"
#include "secanomalyd/system_context.h"

namespace secanomalyd {

namespace {

// Sets the sampling frequency for W+X mount count uploads, such that the
// systems with more W+X mounts are more likely to send a crash report, in
// addition to limiting the total number of uploaded reports.
constexpr int CalculateSampleFrequency(size_t wx_mount_count) {
  if (wx_mount_count <= 5)
    return 15;
  else if (wx_mount_count <= 10)
    return 10;
  else if (wx_mount_count <= 15)
    return 5;
  else
    return 2;
}
constexpr int kProcAnomalySampleFrequency = 10000000;  // 10 million

constexpr base::TimeDelta kScanInterval = base::Seconds(30);
// Used to limit the total number of UMA reports.
// Per Platform.DailyUseTime histogram this interval should ensure that enough
// users run the reporting.
constexpr base::TimeDelta kUmaReportInterval = base::Hours(2);

// Generates a unique name for the next element being added to `set`, where the
// element is a unique instance of a certain path type denoted by a `prefix`.
// For example, unknown executable paths are recorded as:
// {"unknown_executable_1", "unknown_executable_2", etc...}
std::string GetNextUniquePath(const FilePaths& set, const std::string& prefix) {
  int num_common_elements = 0;
  for (base::FilePath element : set) {
    if (absl::StartsWith(element.value(), prefix))
      num_common_elements++;
  }
  return prefix + "_" + std::to_string(num_common_elements);
}

bool EmitSeccompCoverageUma(const ProcEntries& proc_entries) {
  size_t total_proc_count = proc_entries.size();
  size_t seccomp_proc_count = 0;
  seccomp_proc_count = std::count_if(
      proc_entries.begin(), proc_entries.end(), [](const ProcEntry& entry) {
        return entry.sandbox_status()[ProcEntry::kSecCompBit] == 1;
      });
  unsigned int seccomp_proc_percentage =
      static_cast<unsigned int>(round((static_cast<float>(seccomp_proc_count) /
                                       static_cast<float>(total_proc_count)) *
                                      100));

  VLOG(1) << "Reporting SecComp coverage UMA metric";
  if (!SendSecCompCoverageToUMA(seccomp_proc_percentage)) {
    LOG(WARNING) << "Could not upload SecComp coverage UMA metric";
    return false;
  }
  return true;
}

bool EmitNnpProcPercentageUma(const ProcEntries& proc_entries) {
  size_t total_proc_count = proc_entries.size();
  size_t nnp_proc_count = 0;
  nnp_proc_count = std::count_if(
      proc_entries.begin(), proc_entries.end(), [](const ProcEntry& entry) {
        return entry.sandbox_status()[ProcEntry::kNoNewPrivsBit] == 1;
      });
  unsigned int nnp_proc_percentage =
      static_cast<unsigned int>(round((static_cast<float>(nnp_proc_count) /
                                       static_cast<float>(total_proc_count)) *
                                      100));

  VLOG(1) << "Reporting no_new_privs process percentage UMA metric";
  if (!SendNnpProcPercentageToUMA(nnp_proc_percentage)) {
    LOG(WARNING)
        << "Could not upload no_new_privs process percentage UMA metric";
    return false;
  }
  return true;
}

bool EmitNonRootProcPercentageUma(const ProcEntries& proc_entries) {
  size_t total_proc_count = proc_entries.size();
  size_t nonroot_proc_count = 0;
  nonroot_proc_count = std::count_if(
      proc_entries.begin(), proc_entries.end(), [](const ProcEntry& entry) {
        return entry.sandbox_status()[ProcEntry::kNonRootBit] == 1;
      });
  unsigned int nonroot_proc_percentage =
      static_cast<unsigned int>(round((static_cast<float>(nonroot_proc_count) /
                                       static_cast<float>(total_proc_count)) *
                                      100));

  VLOG(1) << "Reporting non-root process percentage UMA metric";
  if (!SendNonRootProcPercentageToUMA(nonroot_proc_percentage)) {
    LOG(WARNING) << "Could not upload non-root process percentage UMA metric";
    return false;
  }
  return true;
}

bool EmitUnprivProcPercentageUma(const ProcEntries& proc_entries,
                                 ino_t init_user_ns) {
  size_t total_proc_count = proc_entries.size();
  size_t unpriv_proc_count = 0;
  unpriv_proc_count = std::count_if(
      proc_entries.begin(), proc_entries.end(), [&](const ProcEntry& entry) {
        return entry.sandbox_status()[ProcEntry::kNonRootBit] == 1 &&
               (entry.sandbox_status()[ProcEntry::kNoCapSysAdminBit] == 1 ||
                entry.userns() != init_user_ns);
      });
  unsigned int unpriv_proc_percentage =
      static_cast<unsigned int>(round((static_cast<float>(unpriv_proc_count) /
                                       static_cast<float>(total_proc_count)) *
                                      100));

  VLOG(1) << "Reporting unpriv process percentage UMA metric";
  if (!SendUnprivProcPercentageToUMA(unpriv_proc_percentage)) {
    LOG(WARNING) << "Could not upload unpriv process percentage UMA metric";
    return false;
  }
  return true;
}

bool EmitNonInitNsProcPercentageUma(const ProcEntries& proc_entries,
                                    ino_t init_pid_ns,
                                    ino_t init_mnt_ns) {
  size_t total_proc_count = proc_entries.size();
  size_t non_initns_proc_count = 0;
  non_initns_proc_count = std::count_if(
      proc_entries.begin(), proc_entries.end(), [&](const ProcEntry& entry) {
        return entry.pidns() != init_pid_ns && entry.mntns() != init_mnt_ns;
      });
  unsigned int non_initns_proc_percentage = static_cast<unsigned int>(
      round((static_cast<float>(non_initns_proc_count) /
             static_cast<float>(total_proc_count)) *
            100));

  VLOG(1) << "Reporting non-init namespace process percentage UMA metric";
  if (!SendNonInitNsProcPercentageToUMA(non_initns_proc_percentage)) {
    LOG(WARNING)
        << "Could not upload non-init namespace process percentage UMA metric";
    return false;
  }
  return true;
}

}  // namespace

int Daemon::OnInit() {
  // DBusDaemon::OnInit() initializes the D-Bus connection, making sure |bus_|
  // is populated.
  int ret = brillo::DBusDaemon::OnInit();
  if (ret != EX_OK) {
    return ret;
  }

  // Initializes the audit log reader for accessing the audit log file.
  InitAuditLogReader();

  session_manager_proxy_ = std::make_unique<SessionManagerProxy>(bus_);

  // The raw SessionManagerProxy pointer is un-owned by the SystemContext
  // object.
  system_context_ =
      std::make_unique<SystemContext>(session_manager_proxy_.get());

  return EX_OK;
}

int Daemon::OnEventLoopStarted() {
  ScanForAnomalies();
  ReportUmaMetrics();

  return EX_OK;
}

void Daemon::ScanForAnomalies() {
  VLOG(1) << "Scanning for W+X mounts";
  DoWXMountScan();
  VLOG(1) << "Scanning system processes";
  DoProcScan();
  VLOG(1) << "Scanning for audit log anomalies";
  DoAuditLogScan();

  if (generate_reports_) {
    DoAnomalousSystemReporting();
  }

  brillo::MessageLoop::current()->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(&Daemon::ScanForAnomalies, base::Unretained(this)),
      kScanInterval);
}

void Daemon::ReportUmaMetrics() {
  if (!ShouldReport(dev_)) {
    return;
  }

  EmitWXMountCountUma();
  EmitForbiddenIntersectionProcCountUma();
  EmitMemfdExecProcCountUma();
  EmitSandboxingUma();

  brillo::MessageLoop::current()->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(&Daemon::ReportUmaMetrics, base::Unretained(this)),
      kUmaReportInterval);
}

void Daemon::DoWXMountScan() {
  all_mounts_ = ReadMounts();
  if (!all_mounts_) {
    LOG(ERROR) << "Failed to read mounts";
    return;
  }

  // Refreshed on every check to have the most up-to-date state.
  system_context_->Refresh();

  for (const auto& e : all_mounts_.value()) {
    if (e.IsWX()) {
      // Have we seen the mount yet?
      if (wx_mounts_.count(e.dest()) == 0) {
        if (e.IsUsbDriveOrArchive()) {
          // Figure out what to log in this case.
          // We could log the fact that the mount exists without logging
          // |src| or |dest|.
          continue;
        }

        if (e.IsNamespaceBindMount() || e.IsKnownMount(*system_context_)) {
          // Namespace mounts happen when a namespace file in /proc/<pid>/ns/
          // gets bind-mounted somewhere else. These mounts can be W+X but are
          // not concerning since they consist of a single file and these files
          // cannot be executed.
          // There are other W+X mounts that are low-risk (e.g. non-persistent
          // mounts) and that we're in the process of fixing. These are
          // considered "known" W+X mounts and are also skipped.
          VLOG(1) << "Not recording W+X mount at '" << e.dest() << "', type "
                  << e.type();
          // In case of a known mount, we need to update the context to remember
          // that this mount was observed, as we might use this information to
          // determine whether it should be ignored again in the future scans.
          system_context_->RecordKnownMountObservation(e.dest());
          continue;
        }

        // We haven't seen the mount, and it's not a type we want to skip, so
        // save it.
        wx_mounts_[e.dest()] = e;
        VLOG(1) << "Found W+X mount at '" << e.dest() << "', type " << e.type();
        VLOG(1) << "|wx_mounts_.size()| = " << wx_mounts_.size();

        // Report metrics on the mount, if not running in dev mode.
        if (ShouldReport(dev_)) {
          // Report /usr/local mounts separately because those can indicate
          // systems where |cros_debug == 0| but the system is still a dev
          // system.
          SecurityAnomaly mount_anomaly =
              e.IsDestInUsrLocal()
                  ? SecurityAnomaly::kMount_InitNs_WxInUsrLocal
                  : SecurityAnomaly::kMount_InitNs_WxNotInUsrLocal;
          if (!SendSecurityAnomalyToUMA(mount_anomaly)) {
            LOG(WARNING) << "Could not upload metrics";
          }
        }
      }
    }
  }
}

void Daemon::DoProcScan() {
  all_procs_ = ReadProcesses(ProcessFilter::kAll);
  if (!all_procs_) {
    return;
  }
  if (!init_proc_) {
    init_proc_ = GetInitProcEntry(all_procs_.value());
  }
  if (!init_proc_) {
    return;
  }

  ProcEntries procs;
  FilterKernelProcesses(all_procs_.value(), procs);

  ProcEntries flagged_procs;
  std::copy_if(procs.begin(), procs.end(), std::back_inserter(flagged_procs),
               [&](const ProcEntry& e) {
                 return IsProcInForbiddenIntersection(e, init_proc_.value());
               });

  forbidden_intersection_procs_ = MaybeProcEntries(flagged_procs);
  if (forbidden_intersection_procs_) {
    VLOG(1) << "|forbidden_intersection_procs_.size()| = "
            << forbidden_intersection_procs_->size();
  }
}

void Daemon::DoAnomalousSystemReporting() {
  // Skip reporting if for all anomaly types either the daemon has previously
  // attempted to send a report or the anomaly does not exist.
  if ((has_attempted_wx_mount_report_ || wx_mounts_.empty()) &&
      (has_attempted_forbidden_intersection_report_ ||
       forbidden_intersection_procs_.value().empty()) &&
      (has_attempted_memfd_exec_report_ ||
       executables_attempting_memfd_exec_.empty())) {
    return;
  }

  // Makes checking for this anomaly type easier.
  ProcEntries anomalous_procs = forbidden_intersection_procs_
                                    ? forbidden_intersection_procs_.value()
                                    : ProcEntries();

  // Stop subsequent reporting attempts for each discovered anomaly type.
  if (!wx_mounts_.empty()) {
    has_attempted_wx_mount_report_ = true;
  }
  if (!anomalous_procs.empty()) {
    has_attempted_forbidden_intersection_report_ = true;
  }
  if (!executables_attempting_memfd_exec_.empty()) {
    has_attempted_memfd_exec_report_ = true;
  }

  if (!ShouldReport(dev_)) {
    VLOG(1) << "Not reporting anomalous system due to dev mode";
    return;
  }
  VLOG(1) << "Attempting to report anomalous system";

  int range = 0;
  int weight = 1;
  // If |dev_| is set or there are memfd execution attempts, always send the
  // report (memfd execution attempts are exceedingly rare so we can afford to
  // upload them all). Otherwise, if W+X anomalies exist, send one in every
  // |CalculateSampleFrequency(wx_mounts_.size())| reports. Finally, if only
  // forbidden intersection violations exist, send one in every
  // |kProcAnomalySampleFrequency| reports.
  if (dev_ || !executables_attempting_memfd_exec_.empty()) {
    range = 1;
  } else if (!wx_mounts_.empty()) {
    range = CalculateSampleFrequency(wx_mounts_.size());
    weight = range;
  } else if (!anomalous_procs.empty() && forbidden_intersection_only_reports_) {
    range = kProcAnomalySampleFrequency;
  }

  // |base::RandInt(min, max)| returns a random int between [min, max], which in
  // this case gives the report one in |range| chance of being sent.
  if (range < 1 || base::RandInt(1, range) > 1) {
    return;
  }

  bool success = ReportAnomalousSystem(wx_mounts_, anomalous_procs,
                                       executables_attempting_memfd_exec_,
                                       all_mounts_, all_procs_, weight, dev_);
  if (!success) {
    // Reporting is best-effort so on failure we just print a warning.
    LOG(WARNING) << "Failed to report anomalous system";
  }

  // Report whether uploading the anomalous system report succeeded.
  if (!SendAnomalyUploadResultToUMA(success)) {
    LOG(WARNING) << "Could not upload metrics";
  }
}

void Daemon::InitAuditLogReader() {
  audit_log_reader_ = std::make_unique<AuditLogReader>(kAuditLogPath);
}

void Daemon::DoAuditLogScan() {
  if (!audit_log_reader_)
    return;

  std::string log_message;
  LogRecord log_record;

  while (audit_log_reader_->GetNextEntry(&log_record)) {
    // This detects a successful memfd_create syscall and reports it to UMA to
    // be used as the baseline metric for memfd execution attempts. The check
    // will not be performed again, once the metric is successfully emitted.
    if (!has_emitted_memfd_baseline_uma_ &&
        log_record.tag == kSyscallRecordTag &&
        secanomalyd::IsMemfdCreate(log_record.message)) {
      // Report baseline condition to UMA if not in dev mode.
      if (ShouldReport(dev_)) {
        if (!SendSecurityAnomalyToUMA(
                SecurityAnomaly::kSuccessfulMemfdCreateSyscall)) {
          LOG(WARNING) << "Could not upload metrics";
        } else {
          has_emitted_memfd_baseline_uma_ = true;
        }
      }
    }
    std::string exe_path;
    if (log_record.tag == kAVCRecordTag &&
        secanomalyd::IsMemfdExecutionAttempt(log_record.message, exe_path)) {
      if (exe_path == secanomalyd::kUnknownExePath) {
        exe_path = GetNextUniquePath(executables_attempting_memfd_exec_,
                                     secanomalyd::kUnknownExePath);
      }
      // Record the anomaly by adding the offending executable path to
      // |executables_attempting_memfd_exec_| set.
      executables_attempting_memfd_exec_.insert(base::FilePath(exe_path));
      VLOG(1) << log_record.message;
      VLOG(1) << "|executables_attempting_memfd_exec_.size()| = "
              << executables_attempting_memfd_exec_.size();
      // Report anomalous condition to UMA if not in dev mode.
      if (ShouldReport(dev_)) {
        if (!SendSecurityAnomalyToUMA(
                SecurityAnomaly::kBlockedMemoryFileExecAttempt))
          LOG(WARNING) << "Could not upload metrics";
      }
    }
  }
}

void Daemon::EmitWXMountCountUma() {
  VLOG(1) << "Reporting W+X mount count UMA metric";
  if (SendWXMountCountToUMA(wx_mounts_.size())) {
    // After successfully reporting W+X mount count, clear the map.
    // If mounts still exist they'll be re-added on the next scan.
    wx_mounts_.clear();
  } else {
    LOG(WARNING) << "Could not upload W+X mount count UMA metric";
  }
}

void Daemon::EmitForbiddenIntersectionProcCountUma() {
  // Skip if already emitted or |forbidden_intersection_procs_| has not yet been
  // populated.
  if (has_emitted_forbidden_intersection_uma_ ||
      !forbidden_intersection_procs_) {
    return;
  }
  // Only report forbidden intersection process count in the logged-in state.
  system_context_->Refresh(/*skip_known_mount_refresh=*/true);
  if (!system_context_->IsUserLoggedIn()) {
    return;
  }
  VLOG(1) << "Reporting forbidden intersection process count UMA metric";
  if (!SendForbiddenIntersectionProcCountToUMA(
          forbidden_intersection_procs_->size())) {
    LOG(WARNING)
        << "Could not upload forbidden intersection process count UMA metric";
  }
}

void Daemon::EmitMemfdExecProcCountUma() {
  VLOG(1) << "Reporting memfd exec process count UMA metric";
  if (SendAttemptedMemfdExecProcCountToUMA(
          executables_attempting_memfd_exec_.size())) {
    // After successfully reporting process count, clear the set. If the same
    // processes attempt memfd executions again, they will be re-added to the
    // set.
    executables_attempting_memfd_exec_.clear();
  } else {
    LOG(WARNING) << "Could not upload memfd exec process count UMA metric";
  }
}

void Daemon::EmitSandboxingUma() {
  if (!has_emitted_landlock_status_uma_) {
    VLOG(1) << "Reporting Landlock status UMA metric";
    // If landlock is in any other state than enabled, such as not supported or
    // an unknown state, we consider it disabled.
    if (!SendLandlockStatusToUMA(system_context_->GetLandlockState() ==
                                 LandlockState::kEnabled)) {
      LOG(WARNING) << "Could not upload Landlock status UMA metric";
    } else {
      has_emitted_landlock_status_uma_ = true;
    }
  }

  // Refresh the login state.
  system_context_->Refresh(/*skip_known_mount_refresh=*/true);

  if ((!has_emitted_seccomp_coverage_uma_ ||
       !has_emitted_nonroot_proc_percentage_uma_ ||
       !has_emitted_unpriv_proc_percentage_uma_) &&
      system_context_->IsUserLoggedIn()) {
    MaybeProcEntries maybe_proc_entries =
        ReadProcesses(ProcessFilter::kNoKernelTasks);
    if (!maybe_proc_entries.has_value() ||
        maybe_proc_entries.value().size() == 0) {
      return;
    }

    if (!has_emitted_seccomp_coverage_uma_) {
      has_emitted_seccomp_coverage_uma_ =
          EmitSeccompCoverageUma(maybe_proc_entries.value());
    }

    if (!has_emitted_nnp_proc_percentage_uma_) {
      has_emitted_nnp_proc_percentage_uma_ =
          EmitNnpProcPercentageUma(maybe_proc_entries.value());
    }

    if (!has_emitted_nonroot_proc_percentage_uma_) {
      has_emitted_nonroot_proc_percentage_uma_ =
          EmitNonRootProcPercentageUma(maybe_proc_entries.value());
    }

    // For the rest of the metrics, we need to have the init process entry.
    if (!init_proc_) {
      return;
    }

    if (!has_emitted_unpriv_proc_percentage_uma_) {
      has_emitted_unpriv_proc_percentage_uma_ = EmitUnprivProcPercentageUma(
          maybe_proc_entries.value(), init_proc_.value().userns());
    }

    if (!has_emitted_non_initns_proc_percentage_uma_) {
      has_emitted_non_initns_proc_percentage_uma_ =
          EmitNonInitNsProcPercentageUma(maybe_proc_entries.value(),
                                         init_proc_.value().pidns(),
                                         init_proc_.value().mntns());
    }
  }
}

}  // namespace secanomalyd
