blob: 8c32d70265314f4376db29a3c6d83f0f9116bb0a [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/chrome_cleaner/scanner/scanner_controller.h"
#include <stdlib.h>
#include <time.h>
#include <memory>
#include "base/bind.h"
#include "base/logging.h"
#include "base/run_loop.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/chrome_cleaner/ipc/sandbox.h"
#include "chrome/chrome_cleaner/logging/logging_service_api.h"
#include "chrome/chrome_cleaner/os/process.h"
#include "chrome/chrome_cleaner/os/shutdown_watchdog.h"
#include "chrome/chrome_cleaner/settings/settings.h"
namespace chrome_cleaner {
namespace {
// The maximal allowed time to run the scanner (5 minutes).
const uint32_t kWatchdogTimeoutInSeconds = 5 * 60;
ResultCode GetResultCodeFromFoundUws(const std::vector<UwSId>& found_uws) {
for (UwSId uws_id : found_uws) {
if (!PUPData::IsKnownPUP(uws_id))
return RESULT_CODE_ENGINE_REPORTED_UNSUPPORTED_UWS;
}
// Removal has precedence over other states.
if (PUPData::HasFlaggedPUP(found_uws, &PUPData::HasRemovalFlag)) {
return RESULT_CODE_SUCCESS;
}
if (PUPData::HasFlaggedPUP(found_uws, &PUPData::HasConfirmedUwSFlag)) {
return RESULT_CODE_EXAMINED_FOR_REMOVAL_ONLY;
}
if (PUPData::HasFlaggedPUP(found_uws, &PUPData::HasReportOnlyFlag)) {
return RESULT_CODE_REPORT_ONLY_PUPS_FOUND;
}
DCHECK(found_uws.empty());
return RESULT_CODE_NO_PUPS_FOUND;
}
} // namespace
ScannerController::~ScannerController() = default;
int ScannerController::ScanOnly() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// Make sure the scanning process gets completed in a reasonable amount of
// time, otherwise log it and terminate the process.
base::TimeDelta watchdog_timeout =
base::TimeDelta::FromSeconds(watchdog_timeout_in_seconds_);
Settings* settings = Settings::GetInstance();
if (settings->scanning_timeout_overridden())
watchdog_timeout = settings->scanning_timeout();
std::unique_ptr<ShutdownWatchdog> watchdog;
if (!watchdog_timeout.is_zero()) {
watchdog = std::make_unique<ShutdownWatchdog>(
watchdog_timeout,
base::BindOnce(&ScannerController::WatchdogTimeoutCallback,
base::Unretained(this)));
watchdog->Arm();
}
base::RunLoop run_loop;
quit_closure_ = run_loop.QuitWhenIdleClosure();
StartScan();
run_loop.Run();
if (watchdog)
watchdog->Disarm();
DCHECK_NE(RESULT_CODE_INVALID, result_code_);
return static_cast<int>(result_code_);
}
ScannerController::ScannerController(RegistryLogger* registry_logger)
: registry_logger_(registry_logger),
watchdog_timeout_in_seconds_(kWatchdogTimeoutInSeconds) {
DCHECK(registry_logger);
}
void ScannerController::DoneScanning(ResultCode status,
const std::vector<UwSId>& found_pups) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
UpdateScanResults(found_pups);
if (status == RESULT_CODE_SUCCESS)
status = GetResultCodeFromFoundUws(found_pups);
{
base::AutoLock lock(lock_);
result_code_ = status;
}
LoggingServiceAPI* logging_service_api = LoggingServiceAPI::GetInstance();
SystemResourceUsage stats;
if (GetSystemResourceUsage(::GetCurrentProcess(), &stats))
logging_service_api->LogProcessInformation(SandboxType::kNonSandboxed,
stats);
std::map<SandboxType, SystemResourceUsage> sbox_process_usage =
GetSandboxSystemResourceUsage();
for (const auto& type_usage : sbox_process_usage) {
LoggingServiceAPI::GetInstance()->LogProcessInformation(type_usage.first,
type_usage.second);
}
logging_service_api->SetExitCode(status);
logging_service_api->MaybeSaveLogsToFile(L"");
logging_service_api->SendLogsToSafeBrowsing(
base::BindRepeating(&ScannerController::LogsUploadComplete,
base::Unretained(this)),
registry_logger_);
}
void ScannerController::UpdateScanResults(
const std::vector<UwSId>& found_pups) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// Log which PUPs were found.
registry_logger_->RecordFoundPUPs(found_pups);
ResultCode result = GetResultCodeFromFoundUws(found_pups);
{
base::AutoLock lock(lock_);
result_code_ = result;
}
}
int ScannerController::WatchdogTimeoutCallback() {
ResultCode result_code;
{
base::AutoLock lock(lock_);
result_code = result_code_;
}
int watchdog_result_code =
result_code == RESULT_CODE_SUCCESS
? RESULT_CODE_WATCHDOG_TIMEOUT_WITH_REMOVABLE_UWS
: RESULT_CODE_WATCHDOG_TIMEOUT_WITHOUT_REMOVABLE_UWS;
registry_logger_->WriteExitCode(watchdog_result_code);
registry_logger_->WriteEndTime();
return watchdog_result_code;
}
void ScannerController::LogsUploadComplete(bool success) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
std::move(quit_closure_));
}
} // namespace chrome_cleaner