| # 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_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") |
| } |
| |
| # Makes the number of empty slot spans that can remain committed larger in |
| # foreground mode compared to background mode |
| # (see `PartitionRoot::AdjustFor(Background|Foreground)`). |
| # |
| # Foreground/background modes are used by default on macOS and Windows so this |
| # must be true on these platforms. It's also true on other platforms to allow |
| # experiments. |
| # |
| # TODO(crbug.com/329199197): Clean this up when experiments are complete. |
| use_large_empty_slot_span_ring = true |
| |
| 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() { |
| # 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 |
| } |
| |
| declare_args() { |
| # Whether PartitionAlloc dispatch can be replaced with another dispatch with |
| # some more safety checks at runtime or not. When true, the allocator shim |
| # provides an extended API to swap PartitionAlloc. |
| enable_allocator_shim_partition_alloc_dispatch_with_advanced_checks_support = |
| use_partition_alloc_as_malloc |
| } |
| |
| declare_args() { |
| # This is a flag for binary experiment on iOS. When BRP for iOS is enabled, |
| # we see some un-actionable `DoubleFreeOrCorruptionDetected` crashes. |
| # This flag enables some extra `CHECK`s to get actionable crash reports. |
| # TODO(crbug.com/371135823): Remove upon completion of investigation. |
| enable_ios_corruption_hardening = use_partition_alloc_as_malloc && is_ios && |
| enable_ios_corruption_hardening_default |
| } |
| |
| assert( |
| !enable_allocator_shim_partition_alloc_dispatch_with_advanced_checks_support || use_partition_alloc_as_malloc, |
| "PartitionAlloc with advanced checks requires PartitionAlloc itself.") |
| |
| assert(!use_allocator_shim || !is_nacl, |
| "The allocator shim supports every platform, except nacl") |
| |
| 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. |
| # Since PartitionAlloc depends on libc++, it is difficult to link libc++.dll |
| # with PartitionAlloc to replace its allocator with PartitionAlloc. |
| # If using libcxx_is_shared=true, |
| # a. since inline methods or inline functions defined in some libc++ headers, |
| # e.g. vector, use new, malloc(), and so on, the memory allocation will |
| # be done inside a client code. |
| # b. on the other hand, libc++.dll deallocates the memory allocated by the |
| # inline methods or inline functions. It will not be run inside the client |
| # code. |
| # So a.'s allocation is done by PartitionAlloc, but b.'s deallocation is |
| # done by system allocator. This will cause heap check failure (WinHeap |
| # doesn't know PartitionAlloc) and crash. |
| # If libcxx_is_shared=false, libc++ is a static library. All libc++ code |
| # will be run inside the client. The above issue will disappear. |
| assert( |
| !is_component_build || (!libcxx_is_shared && !is_debug), |
| "The allocator shim for the Windows component build needs !libcxx_is_shared && !is_debug.") |
| } |
| |
| declare_args() { |
| use_freeslot_bitmap = 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 |
| |
| # Enable reentrancy checks at `partition_alloc::internal::Lock`. |
| # TODO(crbug.com/371135823): Remove upon completion of investigation. |
| enable_partition_lock_reentrancy_check = enable_ios_corruption_hardening |
| |
| # This will write a fixed cookie pattern at the end of each allocation, and |
| # later verify the pattern remain unchanged to ensure there is no OOB write. |
| # It comes with performance and memory cost, hence enabled only in debug. |
| use_partition_cookie = |
| is_debug || dcheck_always_on || enable_ios_corruption_hardening |
| |
| # This will change partition cookie size to 4B or 8B, whichever equivalent to |
| # size of InSlotMetadata. This option is useful for InSlotMetadata corruption |
| # investigation. |
| # TODO(crbug.com/371135823): Remove upon completion of investigation. |
| smaller_partition_cookie = enable_ios_corruption_hardening |
| } |
| |
| declare_args() { |
| # Build support for Use-after-Free protection via BackupRefPtr (BRP), |
| # making the raw_ptr<T> 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() { |
| # We want to use RawPtrBackupRefImpl as the raw_ptr<> implementation |
| # iff BRP support is enabled. However, for purpose of performance |
| # investigations we want to be able to control each separately. |
| # |
| # TEST ONLY! Don't touch unless you think you know what you're doing. Play |
| # with enable_backup_ref_ptr_support instead. |
| use_raw_ptr_backup_ref_impl = enable_backup_ref_ptr_support |
| |
| # 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_raw_ptr_asan_unowned_impl = false |
| } |
| |
| # Use the version of raw_ptr<T> that allows the embedder to implement custom |
| # logic. |
| use_raw_ptr_hookable_impl = 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 modified 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 = |
| enable_backup_ref_ptr_support && use_raw_ptr_backup_ref_impl && |
| # Platforms where BackupRefPtr hasn't shipped yet: |
| !is_castos && !is_ios |
| |
| # While keeping BRP support, override a feature flag to make it disabled |
| # state. This will overwrite `enable_backup_ref_ptr_feature_flag`. |
| # TODO(https://crbug.com/372183586): Fix the bug and remove this arg. |
| force_disable_backup_ref_ptr_feature = |
| enable_backup_ref_ptr_support && enable_ios_corruption_hardening |
| |
| # Build support for Dangling Ptr Detection (DPD) via BackupRefPtr (BRP), |
| # making the raw_ptr<T> implementation to RawPtrBackupRefImpl if active. |
| enable_dangling_raw_ptr_checks = |
| enable_dangling_raw_ptr_checks_default && enable_backup_ref_ptr_support && |
| use_raw_ptr_backup_ref_impl |
| |
| enable_backup_ref_ptr_instance_tracer = false |
| |
| backup_ref_ptr_extra_oob_checks = |
| enable_backup_ref_ptr_support && use_raw_ptr_backup_ref_impl |
| } |
| |
| declare_args() { |
| # Enable the feature flag required to check for dangling pointers. That is to |
| # say `PartitionAllocDanglingPtr`. |
| # |
| # This is meant to be modified 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 |
| } |
| |
| 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 = is_linux && has_64_bit_pointers |
| } |
| |
| 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 |
| } |
| |
| 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`. |
| # |
| # We also disable PA-Everywhere and PA-based features in two types of |
| # toolchains: |
| # - Toolchains that disable PA-Everywhere explicitly. |
| # - The rust host build tools toochain, which builds DLLs to dlopen into the |
| # compiler for proc macros. We would want any allocations to use the same |
| # paths as the compiler. |
| # |
| # Do not clear the following, as they can function outside of PartitionAlloc |
| # - has_64_bit_pointers |
| # - has_memory_tagging |
| if (!use_partition_alloc || |
| (defined(toolchain_allows_use_partition_alloc_as_malloc) && |
| !toolchain_allows_use_partition_alloc_as_malloc) || |
| (defined(toolchain_for_rust_host_build_tools) && |
| toolchain_for_rust_host_build_tools)) { |
| use_partition_alloc_as_malloc = false |
| glue_core_pools = false |
| enable_backup_ref_ptr_support = false |
| use_raw_ptr_backup_ref_impl = false |
| use_asan_backup_ref_ptr = false |
| use_raw_ptr_asan_unowned_impl = false |
| use_raw_ptr_hookable_impl = 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 |
| backup_ref_ptr_extra_oob_checks = false |
| enable_backup_ref_ptr_instance_tracer = 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 |
| } |
| |
| # use_raw_ptr_backup_ref_impl can only be used if |
| # enable_backup_ref_ptr_support is true. |
| assert(enable_backup_ref_ptr_support || !use_raw_ptr_backup_ref_impl, |
| "Can't use RawPtrBackupRefImpl if BRP isn't enabled at all") |
| |
| # 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 BRP checks if it isn't enabled at all") |
| |
| # enable_dangling_raw_ptr_checks can only be used if |
| # enable_backup_ref_ptr_support & use_raw_ptr_backup_ref_impl are true. |
| assert((enable_backup_ref_ptr_support && use_raw_ptr_backup_ref_impl) || |
| !enable_dangling_raw_ptr_checks, |
| "Can't enable dangling raw_ptr checks if BRP isn't enabled and used") |
| |
| # 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 BRP, the underlying feature must be |
| # enabled, too. |
| assert((enable_backup_ref_ptr_support && use_raw_ptr_backup_ref_impl) || |
| !backup_ref_ptr_extra_oob_checks, |
| "Can't enable extra OOB checks if BRP isn't enabled and used") |
| |
| # To poison OOB pointers for BRP, 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_raw_ptr_asan_unowned_impl || !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_raw_ptr_asan_unowned_impl, |
| "Both BackupRefPtr and AsanUnownedPtr can't be enabled at the same time") |
| |
| # RawPtrHookableImpl and BackupRefPtr are mutually exclusive variants of |
| # raw_ptr. |
| assert( |
| !use_raw_ptr_hookable_impl || !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_raw_ptr_hookable_impl || !use_raw_ptr_asan_unowned_impl, |
| "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_raw_ptr_asan_unowned_impl || 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_raw_ptr_hookable_impl, |
| "AsanBackupRefPtr requires RawPtrHookableImpl") |
| |
| # 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. |
| is_pkeys_available = |
| (is_linux || is_chromeos) && current_cpu == "x64" && !is_cronet_build |
| declare_args() { |
| enable_pkeys = is_pkeys_available |
| } |
| assert(!enable_pkeys || is_pkeys_available, |
| "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 |
| } |