1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
|
// Copyright 2024 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/sampling_helpers.h"
#include <optional>
#include <string_view>
#include "base/containers/fixed_flat_map.h"
#include "base/functional/callback_helpers.h"
#include "base/metrics/histogram.h"
#include "base/metrics/histogram_functions.h"
#include "base/numerics/safe_math.h"
#include "base/strings/strcat.h"
namespace gwp_asan::internal {
namespace {
// The exclusive maximum-valued sample that the histogram supports.
// Arbitrarily chosen.
inline constexpr base::Histogram::Sample32 kMaxSample = 1'000'000'000;
constexpr auto kProcessMap =
base::MakeFixedFlatMap<std::string_view, std::string_view>(
{{"", "Browser"},
{"extension", "Extension"},
{"gpu-process", "Gpu"},
{"ppapi", "Ppapi"},
{"renderer", "Renderer"},
{"utility", "Utility"}});
void ReportOomHistogram(base::HistogramBase* histogram,
size_t sampling_frequency,
size_t allocations) {
base::ClampedNumeric<base::Histogram::Sample32> total_allocations =
allocations;
total_allocations *= sampling_frequency;
// The safety provided by `ClampedNumeric` is well and good, but we
// arbitrarily chose an exclusive maximum for our histogram and have
// to limbo under it.
histogram->Add(total_allocations.Min(kMaxSample - 1));
}
} // namespace
GuardedPageAllocator::OutOfMemoryCallback CreateOomCallback(
std::string_view allocator_name,
std::string_view process_type,
size_t sampling_frequency) {
const auto process_str = ProcessString(process_type);
if (!process_str.has_value()) {
return base::DoNothing();
}
// N.B. we call `FactoryGet()` here to avoid doing it inside the
// callback body, which could result in re-entrancy issues.
// See https://crbug.com/331729344 for details.
const std::string histogram_name =
base::StrCat({"Security.GwpAsan.AllocatorOom.", allocator_name, ".",
process_str.value()});
auto* histogram = base::Histogram::FactoryGet(
histogram_name,
/*minimum=*/1,
/*maximum=*/kMaxSample,
/*bucket_count=*/100,
/*flags=*/base::HistogramBase::Flags::kUmaTargetedHistogramFlag);
CHECK(histogram);
return base::BindOnce(&ReportOomHistogram, histogram, sampling_frequency);
}
// Turns the value passed to --type= into
// * a representation of the process type
// * or `nullopt` if we don't emit for said process.
//
// Used in the patterned histogram `Security.GwpAsan.AllocatorOom...`.
std::optional<std::string_view> ProcessString(std::string_view process_type) {
const auto iter = kProcessMap.find(process_type);
if (iter == kProcessMap.cend()) {
return std::nullopt;
}
return std::make_optional(iter->second);
}
void ReportGwpAsanActivated(std::string_view allocator_name,
std::string_view process_type,
bool activated) {
const auto process_str = ProcessString(process_type);
if (!process_str.has_value()) {
return;
}
const std::string histogram_name =
base::StrCat({"Security.GwpAsan.Activated.", allocator_name, ".",
process_str.value()});
base::UmaHistogramBoolean(histogram_name, activated);
}
} // namespace gwp_asan::internal
|