Control Flow Integrity

We are planning to deploy Clang's control flow integrity mechanisms in Chrome.

The current status:
  • CFI for virtual calls is enabled for the official Chrome on Linux x86-64 (M54 and newer).
  • Chrome is bad-cast clean, and we have a bot on chromium.memory that keeps it that way
  • We're working on additional compiler improvements to allow deploying CFI on more platforms.

To build Chrome with control flow integrity for virtual calls and bad casts (Linux x86_64 only):

     gn gen out/cfi '--args=is_debug=false is_cfi=true use_cfi_cast=true use_thin_lto=true' --check
     ninja -C out/cfi chrome  # Chrome will take 6 minutes or so to link.

Building with additional diagnostics:

    gn gen out/cfi-diag '--args=is_debug=false is_cfi=true use_cfi_cast=true use_cfi_diag=true use_thin_lto=true' --check
    ninja -C out/cfi-diag chrome  # Chrome will take 6 minutes or so to link.

The deployment is being tracked here:

  Meta bug: crbug.com/701937
  Linux:  crbug.com/464797
  Android: crbug.com/469376
  ChromeOS: crbug.com/537386 

Diagnosing problems with the CFI instrumentation

By default, a program compiled with CFI will crash with SIGILL if it detects a CFI violation.
For better error messages (but not for production use) add use_cfi_diag=true to your args.gn

Overhead (only tested on x64)

- CPU overhead is < 1%
- Code size overhead is 5%-9%
- RAM overhead is a small constant (read-only tables inside the binary shared between all chrome processes)

Trophies (bugs found or prevented)

- https://crbug.com/658955 - invalid cast in ProcessManagerBrowserTest.NestedURLNavigationsToAppBlocked
https://crbug.com/646615 - invalid cast in blink::BytesConsumerTestUtil::TwoPhaseReader
https://crbug.com/605337 - invalid cast in SkTArray.h
https://crbug.com/600808 - invalid cast in PaymentRequestTest.NullShippingOptionWhenNoOptionsAvailable
https://crbug.com/601193 - HeapVector::operator= is deleting garbage collected elements
- https://crbug.com/577972 - improper deserialization of cc::HeadsUpDisplayLayer
- https://crbug.com/569102 - invalid cast in AutofillDialogControllerTest
- https://crbug.com/568738 - invalid cast in CachingCorrectnessTest.ReuseImageExpiredFromExpires
- https://crbug.com/568736 - invalid cast in AnimationTranslationUtilTest.filtersWork
- https://crbug.com/568407 - invalid cast in TileManagerPerfTest.PrepareTiles
- https://crbug.com/565515 - invalid cast in tile_manager_unittest.cc
- https://crbug.com/557969 - invalid cast in cdm_wrapper
- https://crbug.com/557802 - Bad-cast to blink::HTMLOptionElement from blink::HTMLOptGroupElement
- https://crbug.com/552699 - Bad-cast to webrtc::ProcessThreadImpl from invalid vptr;process_thread_impl.cc
- https://crbug.com/551611 - invalid cast in SafeBrowsingService::GetProtocolManagerDelegate
- https://crbug.com/569108 - invalid cast in browser_plugin_guest
- https://crbug.com/524194 - invalid cast in AutofillDialogControllerTest
https://crbug.com/541708 - invalid cast in net/http/http_proxy_client_socket_pool_unittest.cc
- https://crbug.com/520760 - invalid cast in ppapi/proxy/nacl_message_scanner.cc
- https://crbug.com/538952 - Bad-cast to Profile from invalid vptr;chrome_extensions_network_delegate.cc
- https://crbug.com/538754 - invalid cast in SkTextBlobBuilder::build
- https://crbug.com/517959 - invalid cast in sfntly/port/refcount.h
- https://crbug.com/568891 - invalid cast in HeapTest.VectorDestructorsWithVtable
- https://crbug.com/537398 - invalid cast in blink::LifecycleNotifier
- https://crbug.com/531664 - invalid cast in list_container.h
- https://crbug.com/528799 - Bad-cast to icu_54::UnicodeSet from icu_54::Quantifier
- https://crbug.com/528798 - Bad-cast to blink::ScriptWrappable from blink::WebGLRenderingContextBase::TypedExtensionTracker<blink::ANGLEInstancedArrays>
- https://crbug.com/526339 - invalid cast in RenderFrameHostManagerTest
- https://crbug.com/524194 - invalid cast in AutofillDialogControllerTest
- https://crbug.com/520760 - Invalid cast in ppapi/proxy/nacl_message_scanner.cc
- https://crbug.com/520732 - Invalid cast in message_loop.cc / ToPumpIO
- https://crbug.com/520699 - Invalid static_cast in ThreadLocalPointer::Get
- https://crbug.com/516538 - invalid cast in ChromeLauncherControllerTest
- https://crbug.com/516528 - invalid cast in content::TestWebContents::GetMainFrame
- https://crbug.com/516523 - invalid cast in NavigatorTestWithBrowserSideNavigation
- https://crbug.com/516513 - Invalid cast in AppCacheHost::AddUpdateObserver
- https://crbug.com/515973 - Invalid cast in SkTArray.h
- https://crbug.com/515679 - invalid cast in GrTRecorder.h
- https://crbug.com/515215 - Invalid cast in v8::internal::compiler::Typer::Visitor::Reduce
- https://crbug.com/514817 - Invalid cast in SocketsTcpUnitTest
- https://crbug.com/513953 - Invalid cast in FeedbackUploaderTest
- https://crbug.com/513816 - Bad cast in KeyedServiceBaseFactory
- https://crbug.com/513425 - Invalid cast Event -> CancelModeEvent for NonCancelableEvent
- https://crbug.com/513021 - Invalid cast Task -> RasterTask in gpu_tile_task_worker_pool.cc
- https://crbug.com/531057 - Bad-cast to blink::ScriptWrappable from blink::WorkerWebSocketChannel;DOMWrapperMap.h
- https://crbug.com/530432 - CHECK failed: io_thread_.StartWithOptions(thread_options) in child_process.cc
https://crbug.com/586639 - Invalid cast in TabDesktopMediaListTest


Subpages (1): Overhead