chromium/components/gwp_asan/client/gwp_asan.cc

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

#include "components/gwp_asan/client/gwp_asan.h"

#include <algorithm>
#include <cmath>
#include <limits>
#include <optional>
#include <string>
#include <string_view>

#include "base/allocator/partition_alloc_support.h"
#include "base/containers/flat_set.h"
#include "base/debug/crash_logging.h"
#include "base/feature_list.h"
#include "base/functional/callback_helpers.h"
#include "base/functional/function_ref.h"
#include "base/logging.h"
#include "base/metrics/field_trial_params.h"
#include "base/numerics/safe_math.h"
#include "base/rand_util.h"
#include "base/strings/strcat.h"
#include "build/build_config.h"
#include "components/crash/core/common/crash_key.h"
#include "components/gwp_asan/client/extreme_lightweight_detector_malloc_shims.h"
#include "components/gwp_asan/client/guarded_page_allocator.h"
#include "components/gwp_asan/client/gwp_asan_features.h"
#include "components/gwp_asan/client/lightweight_detector/poison_metadata_recorder.h"
#include "components/gwp_asan/client/sampling_helpers.h"
#include "components/gwp_asan/common/crash_key_name.h"
#include "partition_alloc/buildflags.h"

#if PA_BUILDFLAG(USE_ALLOCATOR_SHIM)
#include "components/gwp_asan/client/lightweight_detector/malloc_shims.h"
#include "components/gwp_asan/client/sampling_malloc_shims.h"
#endif  // PA_BUILDFLAG(USE_ALLOCATOR_SHIM)

#if PA_BUILDFLAG(USE_PARTITION_ALLOC)
#include "components/gwp_asan/client/lightweight_detector/partitionalloc_shims.h"
#include "components/gwp_asan/client/sampling_partitionalloc_shims.h"
#endif  // PA_BUILDFLAG(USE_PARTITION_ALLOC)

namespace gwp_asan {

namespace internal {
namespace {

[[maybe_unused]] constexpr bool kCpuIs64Bit =;
#else
    false;
#endif

// GWP-ASAN's default parameters are as follows:
// MaxAllocations determines the maximum number of simultaneous allocations
// allocated from the GWP-ASAN region.
//
// MaxMetadata determines the number of slots in the GWP-ASAN region that have
// associated metadata (e.g. alloc/dealloc stack traces).
//
// TotalPages determines the maximum number of slots used for allocations in the
// GWP-ASAN region. The defaults below use MaxMetadata * 2 on 32-bit builds
// (where OOMing due to lack of address space is a concern.)
//
// The allocation sampling frequency is calculated using the formula:
// SamplingMultiplier * AllocationSamplingRange**rand
// where rand is a random real number in the range [0,1).
//
// ProcessSamplingProbability is the probability of enabling GWP-ASAN in a new
// process.
//
// ProcessSamplingBoost is the multiplier to increase the
// ProcessSamplingProbability in scenarios where we want to perform additional
// testing (e.g., on canary/dev builds).
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_FUCHSIA)
constexpr int kDefaultMaxAllocations =;
constexpr int kDefaultMaxMetadata =;
constexpr int kDefaultTotalPages =;
constexpr int kDefaultAllocationSamplingMultiplier =;
constexpr int kDefaultAllocationSamplingRange =;
constexpr double kDefaultProcessSamplingProbability =;
#elif BUILDFLAG(IS_ANDROID)
constexpr int kDefaultMaxAllocations = 70;
constexpr int kDefaultMaxMetadata = 255;
constexpr int kDefaultTotalPages = 512;
constexpr int kDefaultAllocationSamplingMultiplier = 2000;
constexpr int kDefaultAllocationSamplingRange = 20;
constexpr double kDefaultProcessSamplingProbability = 0.015;
#else
constexpr int kDefaultMaxAllocations = 70;
constexpr int kDefaultMaxMetadata = 255;
constexpr int kDefaultTotalPages = kCpuIs64Bit ? 2048 : kDefaultMaxMetadata * 2;
constexpr int kDefaultAllocationSamplingMultiplier = 1000;
constexpr int kDefaultAllocationSamplingRange = 16;
constexpr double kDefaultProcessSamplingProbability = 0.015;
#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
        // BUILDFLAG(IS_FUCHSIA)
constexpr int kDefaultProcessSamplingBoost2 =;

#if defined(ARCH_CPU_64_BITS)
// The aim is to have the same memory overhead as the default GWP-ASan mode,
// which is:
//   sizeof(SlotMetadata) * kDefaultMaxMetadata +
//     sizeof(SystemPage) * kDefaultMaxAllocations
// The memory overhead of Lightweight UAF detector is:
//   sizeof(LightweightSlotMetadata) * kDefaultMaxLightweightMetadata
constexpr int kDefaultMaxLightweightMetadata =;
#if PA_BUILDFLAG(USE_ALLOCATOR_SHIM)
constexpr int kDefaultMaxTotalSize =;

// A set of parameters temporarily used by the random sampling LUD experiment.
constexpr int kDefaultTotalSizeHighWaterMark =;
constexpr int kDefaultTotalSizeLowWaterMark =;
constexpr int kDefaultEvictionChunkSize =;
constexpr int kDefaultEvictionTaskIntervalMs =;

constexpr int kMaxMaxTotalSize =;
constexpr int kMaxEvictionChunkSize =;
constexpr int kMaxEvictionTaskIntervalMs =;
#endif  // PA_BUILDFLAG(USE_ALLOCATOR_SHIM)
#endif  // defined(ARCH_CPU_64_BITS)

BASE_FEATURE();

constexpr base::FeatureParam<LightweightDetectorMode>::Option
    kLightweightUafDetectorModeOptions[] =;

const base::FeatureParam<LightweightDetectorMode>
    kLightweightUafDetectorModeParam{};

// Gets (integral) named `param` from `feature`,  defaulting to
// `fallback` if unset. Invokes `failure_condition()` on the result to
// validate that the value is acceptable.
std::optional<int> GetIntParam(const base::Feature& feature,
                               const std::string& param,
                               int fallback,
                               std::string_view process_type,
                               base::FunctionRef<bool(int)> failure_condition) {}

// Returns whether this process should be sampled to enable GWP-ASan.
bool SampleProcess(const base::Feature& feature, bool boost_sampling) {}

// Returns the allocation sampling frequency, or 0 on error.
size_t AllocationSamplingFrequency(const base::Feature& feature,
                                   std::string_view process_type) {}

// Don't use both GWP-ASan and LUD at the same time for performance
// reasons. When both features are enabled, we prefer GWP-ASan to
// compensate for its lower sampling rate.
bool IsMutuallyExclusiveFeatureAllowed(const base::Feature& feature) {}

}  // namespace

// Exported for testing.
// Provides ungated access to the allocator settings that _would_
// be assigned to the `feature`.
GWP_ASAN_EXPORT std::optional<AllocatorSettings> GetAllocatorSettingsImpl(
    const base::Feature& feature,
    bool boost_sampling,
    std::string_view process_type) {}

// Exported for testing.
GWP_ASAN_EXPORT std::optional<AllocatorSettings> GetAllocatorSettings(
    const base::Feature& feature,
    bool boost_sampling,
    std::string_view process_type) {}

bool MaybeEnableLightweightDetectorInternal(bool boost_sampling,
                                            const char* process_type) {}

}  // namespace internal

void EnableForMalloc(bool boost_sampling, std::string_view process_type) {}

void EnableForPartitionAlloc(bool boost_sampling,
                             std::string_view process_type) {}

void MaybeEnableLightweightDetector(bool boost_sampling,
                                    const char* process_type) {}

void MaybeEnableExtremeLightweightDetector(bool boost_sampling,
                                           std::string_view process_type) {}

}  // namespace gwp_asan