# Copyright 2022 The Chromium Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import("//build/config/cronet/config.gni") import("//build/config/sanitizers/sanitizers.gni") import("//build_overrides/partition_alloc.gni") # PartitionAlloc have limited support for MSVC's cl.exe compiler. It can only # access the generate "buildflags" and the "raw_ptr" definitions implemented # with RawPtrNoOpImpl. Everything else is considered not supported. # # Since there are no other good ways to detect MSVC's cl.exe, we are reusing the # same definition used by Chrome in //base/BUILD.gn. See # https://crbug.com/988071. is_clang_or_gcc = is_clang || !is_win # Whether 64-bit pointers are used. # A static_assert in partition_alloc_config.h verifies that. if (is_nacl) { # NaCl targets don't use 64-bit pointers. has_64_bit_pointers = false } else if (current_cpu == "x64" || current_cpu == "arm64" || current_cpu == "loong64" || current_cpu == "riscv64") { has_64_bit_pointers = true } else if (current_cpu == "x86" || current_cpu == "arm") { has_64_bit_pointers = false } else { assert(false, "Unknown CPU: $current_cpu") } # Increases the size of the empty slot span ring. use_large_empty_slot_span_ring = is_mac has_memory_tagging = current_cpu == "arm64" && is_clang && !is_asan && (is_linux || is_android) declare_args() { # Causes all the allocations to be routed via allocator_shim.cc. Usually, # the allocator shim will, in turn, route them to PartitionAlloc, but # other allocators are also supported by the allocator shim. use_allocator_shim = use_allocator_shim_default && is_clang_or_gcc # Whether PartitionAlloc should be available for use or not. # true makes PartitionAlloc linked to the executable or shared library and # makes it available for use. It doesn't mean that the default allocator # is PartitionAlloc, which is governed by |use_partition_alloc_as_malloc|. # # N.B. generally, embedders should look at this GN arg and at the # corresponding buildflag to determine whether to interact with PA # source at all (pulling the component in via GN, including headers, # etc.). There is nothing stopping a lazy embedder from ignoring this # and unconditionally using PA, but such a setup is inadvisable. # # In Chromium, this is set true, except: # # 1. On Cronet bots, because Cronet doesn't use PartitionAlloc at all, # and doesn't wish to incur the library size increase (crbug.com/674570). # 2. On NaCl (through this declaration), where PartitionAlloc doesn't # build at all. use_partition_alloc = !is_nacl && is_clang_or_gcc } if (!is_clang_or_gcc) { assert(!use_partition_alloc, "PartitionAlloc's allocator does not support this compiler") assert(!use_allocator_shim, "PartitionAlloc's allocator shim does not support this compiler") } if (is_nacl) { assert(!use_partition_alloc, "PartitionAlloc doesn't build on NaCl") } declare_args() { # Turns on compiler optimizations in PartitionAlloc in Debug build. # If enabling PartitionAlloc-Everywhere in Debug build for tests in Debug # build, since all memory allocations and deallocations are executed by # non-optimized PartitionAlloc, chrome (including tests) will be much # slower. This will cause debug trybots' timeouts. If we want to debug # PartitionAlloc itself, use partition_alloc_optimized_debug=false. # Otherwise, use partition_alloc_optimized_debug=true to enable optimized # PartitionAlloc. partition_alloc_optimized_debug = true # PartitionAlloc-Everywhere (PA-E). Causes allocator_shim.cc to route # calls to PartitionAlloc, rather than some other platform allocator. use_partition_alloc_as_malloc = use_partition_alloc && use_allocator_shim && use_partition_alloc_as_malloc_default } assert(!use_allocator_shim || (is_android || is_apple || is_chromeos || is_fuchsia || is_linux || is_win), "The allocator shim does not (yet) support the platform.") if (use_allocator_shim && is_win) { # It's hard to override CRT's malloc family in every case in the component # build, and it's very easy to override it partially and to be inconsistent # among allocations and deallocations. Then, we'll crash when PA deallocates # a memory region allocated by the CRT's malloc or vice versa. assert(!is_component_build, "The allocator shim doesn't work for the component build on Windows.") } declare_args() { use_freeslot_bitmap = false # Puts the regular and BRP pools right next to each other, so that we can # check "belongs to one of the two pools" with a single bitmask operation. glue_core_pools = false # Introduces pointer compression support in PA. These are 4-byte # pointers that can point within the core pools (regular and BRP). # # This is effective only for memory allocated from PartitionAlloc, so it is # recommended to enable PA-E above, but isn't strictly necessary. Embedders # can create and use PA partitions explicitly. enable_pointer_compression_support = false # Enables a bounds check when two pointers (at least one being raw_ptr) are # subtracted (if supported by the underlying implementation). enable_pointer_subtraction_check = false # Enables a compile-time check that all raw_ptrs to which arithmetic # operations are to be applied are annotated with the AllowPtrArithmetic # trait, enable_pointer_arithmetic_trait_check = true # Forwards all the allocation/freeing calls in shim (e.g. operator new) # through malloc. Useful for using with tools that intercept malloc, e.g. # heaptrack. forward_through_malloc = false } declare_args() { # Build support for Use-after-Free protection via BackupRefPtr (BRP), # making the raw_ptr implementation to RawPtrBackupRefImpl if active. # # These are effective only for memory allocated from PartitionAlloc, so it is # recommended to enable PA-E above, but isn't strictly necessary. Embedders # can create and use PA partitions explicitly. # # Note that |enable_backup_ref_ptr_support = true| doesn't necessarily enable # BRP protection. It'll be enabled only for partition created with # partition_alloc::PartitionOptions::kEnabled. enable_backup_ref_ptr_support = use_partition_alloc && enable_backup_ref_ptr_support_default # RAW_PTR_EXCLUSION macro is disabled on official builds because it increased # binary size. This flag can be used to enable it for official builds too. force_enable_raw_ptr_exclusion = false } assert(!enable_pointer_compression_support || glue_core_pools, "Pointer compression relies on core pools being contiguous.") declare_args() { # Make explicit calls to ASAN at runtime, e.g. to mark quarrantined memory # as poisoned. Allows ASAN to tell if a particular memory error is protected # by BRP in its reports. # # The implementation of ASan BRP is purpose-built to inspect Chromium # internals and is entangled with `//base` s.t. it cannot be used # outside of Chromium. use_asan_backup_ref_ptr = build_with_chromium && is_asan && (is_win || is_android || is_linux || is_mac || is_chromeos) # Use probe-on-destruct unowned ptr detection with ASAN. use_asan_unowned_ptr = false } # Use the version of raw_ptr that allows the embedder to implement custom # logic. use_hookable_raw_ptr = use_asan_backup_ref_ptr declare_args() { # - enable_backup_ref_ptr_slow_checks: enable additional safety checks that # are too expensive to have on by default. # - enable_dangling_raw_ptr_checks: enable checking raw_ptr do not become # dangling during their lifetime. # - backup_ref_ptr_poison_oob_ptr: poison out-of-bounds (OOB) pointers to # generate an exception in the event that an OOB pointer is dereferenced. # - enable_backup_ref_ptr_instance_tracer: use a global table to track all # live raw_ptr/raw_ref instances to help debug dangling pointers at test # end. enable_backup_ref_ptr_slow_checks = enable_backup_ref_ptr_slow_checks_default && enable_backup_ref_ptr_support # Enable the feature flag required to activate backup ref pointers. That is to # say `PartitionAllocBackupRefPtr`. # # This is meant to be used primarily on bots. It is much easier to override # the feature flags using a binary flag instead of updating multiple bots's # scripts to pass command line arguments. # # TODO(328104161): Remove this flag. enable_backup_ref_ptr_feature_flag = false # Build support for Dangling Ptr Detection (DPD) via BackupRefPtr (BRP), # making the raw_ptr implementation to RawPtrBackupRefImpl if active. enable_dangling_raw_ptr_checks = enable_dangling_raw_ptr_checks_default && enable_backup_ref_ptr_support # Enable the feature flag required to check for dangling pointers. That is to # say `PartitionAllocDanglingPtr`. # # This is meant to be used primarily on bots. It is much easier to override # the feature flags using a binary flag instead of updating multiple bots's # scripts to pass command line arguments. # # TODO(328104161): Remove this flag. enable_dangling_raw_ptr_feature_flag = enable_dangling_raw_ptr_checks_default enable_backup_ref_ptr_instance_tracer = false backup_ref_ptr_extra_oob_checks = enable_backup_ref_ptr_support } declare_args() { backup_ref_ptr_poison_oob_ptr = false && backup_ref_ptr_extra_oob_checks && has_64_bit_pointers } declare_args() { # Shadow metadata is still under development and only supports Linux # for now. enable_shadow_metadata = false } declare_args() { # Use full MTE protection available by changing the feature flag default # values. So sync mode on all processes. Also disables permissive MTE. # # This is meant to be used primarily on bots. It is much easier to override # the feature flags using a binary flag instead of updating multiple bots's # scripts to pass command line arguments. use_full_mte = false } # *Scan is currently only used by Chromium, and supports only 64-bit. use_starscan = build_with_chromium && has_64_bit_pointers stack_scan_supported = current_cpu == "x64" || current_cpu == "x86" || current_cpu == "arm" || current_cpu == "arm64" || current_cpu == "riscv64" # We want to provide assertions that guard against inconsistent build # args, but there is no point in having them fire if we're not building # PartitionAlloc at all. If `use_partition_alloc` is false, we jam all # related args to `false`. # # Do not clear the following, as they can function outside of PartitionAlloc # - has_64_bit_pointers # - has_memory_tagging if (!use_partition_alloc) { use_partition_alloc_as_malloc = false enable_backup_ref_ptr_support = false use_asan_backup_ref_ptr = false use_asan_unowned_ptr = false use_hookable_raw_ptr = false enable_backup_ref_ptr_slow_checks = false enable_dangling_raw_ptr_checks = false enable_dangling_raw_ptr_feature_flag = false enable_pointer_subtraction_check = false backup_ref_ptr_poison_oob_ptr = false enable_backup_ref_ptr_instance_tracer = false use_starscan = false use_full_mte = false } # Disable |use_full_mte| if memory tagging is not available. This is for targets that run as part the build process. if (!has_memory_tagging) { use_full_mte = false } # enable_backup_ref_ptr_slow_checks can only be used if # enable_backup_ref_ptr_support is true. assert(enable_backup_ref_ptr_support || !enable_backup_ref_ptr_slow_checks, "Can't enable additional BackupRefPtr checks if it isn't enabled at all") # enable_dangling_raw_ptr_checks can only be used if # enable_backup_ref_ptr_support is true. assert( enable_backup_ref_ptr_support || !enable_dangling_raw_ptr_checks, "Can't enable dangling raw_ptr checks if BackupRefPtr isn't enabled at all") # It's meaningless to force on DPD (e.g. on bots) if the support isn't compiled # in. assert(enable_dangling_raw_ptr_checks || !enable_dangling_raw_ptr_feature_flag, "Meaningless to enable DPD without it compiled.") # To enable extra OOB checks for BackupRefPtr, the underlying feature must be # enabled, too. assert(enable_backup_ref_ptr_support || !backup_ref_ptr_extra_oob_checks, "Can't enable extra OOB checks if BackupRefPtr isn't enabled at all") # To poison OOB pointers for BackupRefPtr, the underlying feature must be # enabled, too. assert(backup_ref_ptr_extra_oob_checks || !backup_ref_ptr_poison_oob_ptr, "Can't enable poisoning for OOB pointers if OOB checks aren't enabled " + "at all") assert(has_64_bit_pointers || !backup_ref_ptr_poison_oob_ptr, "Can't enable poisoning for OOB pointers if pointers are only 32-bit") # AsanBackupRefPtr and AsanUnownedPtr are mutually exclusive variants of # raw_ptr. assert( !use_asan_unowned_ptr || !use_asan_backup_ref_ptr, "Both AsanUnownedPtr and AsanBackupRefPtr can't be enabled at the same " + "time") # BackupRefPtr and AsanBackupRefPtr are mutually exclusive variants of raw_ptr. assert( !enable_backup_ref_ptr_support || !use_asan_backup_ref_ptr, "Both BackupRefPtr and AsanBackupRefPtr can't be enabled at the same time") # BackupRefPtr and AsanUnownedPtr are mutually exclusive variants of raw_ptr. assert(!enable_backup_ref_ptr_support || !use_asan_unowned_ptr, "Both BackupRefPtr and AsanUnownedPtr can't be enabled at the same time") # RawPtrHookableImpl and BackupRefPtr are mutually exclusive variants of # raw_ptr. assert( !use_hookable_raw_ptr || !enable_backup_ref_ptr_support, "Both RawPtrHookableImpl and BackupRefPtr can't be enabled at the same " + "time") # RawPtrHookableImpl and AsanUnownedPtr are mutually exclusive variants of # raw_ptr. assert( !use_hookable_raw_ptr || !use_asan_unowned_ptr, "Both RawPtrHookableImpl and AsanUnownedPtr can't be enabled at the same " + "time") assert(!use_asan_backup_ref_ptr || is_asan, "AsanBackupRefPtr requires AddressSanitizer") assert(!use_asan_unowned_ptr || is_asan, "AsanUnownedPtr requires AddressSanitizer") # AsanBackupRefPtr is not supported outside Chromium. The implementation is # entangled with `//base`. The code is only physically located with the rest of # `raw_ptr` to keep it together. assert(build_with_chromium || !use_asan_backup_ref_ptr, "AsanBackupRefPtr is not supported outside Chromium") assert(!use_asan_backup_ref_ptr || use_hookable_raw_ptr, "AsanBackupRefPtr requires RawPtrHookableImpl") declare_args() { # pkeys support is explicitly disabled in all Cronet builds, as some test # dependencies that use partition_allocator are compiled in AOSP against a # version of glibc that does not include pkeys syscall numbers. enable_pkeys = (is_linux || is_chromeos) && target_cpu == "x64" && !is_cronet_build } assert(!enable_pkeys || ((is_linux || is_chromeos) && target_cpu == "x64"), "Pkeys are only supported on x64 linux and ChromeOS") # Some implementations of raw_ptr<>, like BackupRefPtr, require zeroing when # constructing, destructing or moving out of a pointer. When using these # implementations, raw_ptrs<> will be always be zeroed, no matter what # GN args or flags are present. # # Other implementations of raw_ptr<>, like NoOpImpl, don't require zeroing # and do not do so by default. This can lead to subtle bugs when testing # against one of the zeroing impls and then deploying on a platform that is # using a non-zeroing implementation. Setting the following GN args to # true triggers zeroing even for implementations that don't require it. # This provides consistency with the other impls. This is the recommended # setting. # # Setting these to false will make raw_ptr<> behave more like raw C++ pointer # `T*`, making NoOpImpl act like an actual no-op, so use it if you're worried # about performance of your project. Use at your own risk, as it's unsupported # and untested within Chromium. # # Even when these are set to true, the raw_ptr trait AllowUninitialized # provides a finer-grained mechanism for opting out of initialization on a # pointer by pointer basis when using a non-zeroing implementation. # # Caveat: _zero_on_move and _on_destruct will prevent the type from being # trivially copyable, _zero_on_construct and _on_destruct will prevent the # type from being trivially default constructible. declare_args() { raw_ptr_zero_on_construct = raw_ptr_zero_on_construct_default raw_ptr_zero_on_move = raw_ptr_zero_on_move_default raw_ptr_zero_on_destruct = raw_ptr_zero_on_destruct_default } declare_args() { # Assert that PartitionAlloc and MiraclePtr run on C++20 when set to true. # Embedders may opt-out of using C++ 20 build. assert_cpp20 = assert_cpp20_default }