diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs index d37888c27bde3..3ee39eceba174 100644 --- a/library/core/src/fmt/rt.rs +++ b/library/core/src/fmt/rt.rs @@ -133,6 +133,10 @@ impl<'a> Argument<'a> { Self::new(x, USIZE_MARKER) } + // FIXME: Transmuting formatter in new and indirectly branching to/calling + // it here is an explicit CFI violation. + #[allow(inline_no_sanitize)] + #[no_sanitize(cfi)] #[inline(always)] pub(super) fn fmt(&self, f: &mut Formatter<'_>) -> Result { (self.formatter)(self.value, f) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index f39c41764403f..109de87cd0629 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -229,6 +229,7 @@ #![feature(never_type)] #![feature(no_core)] #![feature(no_coverage)] // rust-lang/rust#84605 +#![feature(no_sanitize)] #![feature(platform_intrinsics)] #![feature(prelude_import)] #![feature(repr_simd)] diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs index 67c8245f0bfe0..47fad5f9c841b 100644 --- a/library/core/src/ops/function.rs +++ b/library/core/src/ops/function.rs @@ -280,6 +280,9 @@ mod impls { { type Output = F::Output; + // FIXME: Rust's "try catch" construct (i.e., std::panicking::r#try) use + // of FnOnce explicitly violates CFI. + #[no_sanitize(cfi)] extern "rust-call" fn call_once(self, args: A) -> F::Output { (*self).call(args) } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 1955ef815ff80..15c0fadf94a32 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -245,6 +245,7 @@ #![feature(allow_internal_unstable)] #![feature(c_unwind)] #![feature(cfg_target_thread_local)] +#![feature(cfi_encoding)] #![feature(concat_idents)] #![feature(const_mut_refs)] #![feature(const_trait_impl)] @@ -267,6 +268,7 @@ #![feature(needs_panic_runtime)] #![feature(negative_impls)] #![feature(never_type)] +#![feature(no_sanitize)] #![feature(platform_intrinsics)] #![feature(prelude_import)] #![feature(rustc_attrs)] diff --git a/library/std/src/sys/unix/thread_local_dtor.rs b/library/std/src/sys/unix/thread_local_dtor.rs index 236d2f2ee2928..e6eb8d3db23b9 100644 --- a/library/std/src/sys/unix/thread_local_dtor.rs +++ b/library/std/src/sys/unix/thread_local_dtor.rs @@ -11,28 +11,47 @@ // Note, however, that we run on lots older linuxes, as well as cross // compiling from a newer linux to an older linux, so we also have a // fallback implementation to use as well. +#[allow(unexpected_cfgs)] #[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "redox"))] pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { use crate::mem; use crate::sys_common::thread_local_dtor::register_dtor_fallback; + /// This is necessary because the __cxa_thread_atexit_impl implementation + /// std links to by default may be a C or C++ implementation that was not + /// compiled using the Clang integer normalization option. + #[cfg(not(sanitizer_cfi_normalize_integers))] + #[cfi_encoding = "i"] + #[repr(transparent)] + pub struct c_int(pub libc::c_int); + extern "C" { #[linkage = "extern_weak"] static __dso_handle: *mut u8; #[linkage = "extern_weak"] - static __cxa_thread_atexit_impl: *const libc::c_void; + fn __cxa_thread_atexit_impl( + dtor: unsafe extern "C" fn(*mut libc::c_void), + arg: *mut libc::c_void, + dso_handle: *mut libc::c_void, + ) -> c_int; + } + + // __cxa_thread_atexit_impl may be null because of the extern_weak linkage + fn is_null(f: *mut libc::c_void) -> bool { + f.is_null() } - if !__cxa_thread_atexit_impl.is_null() { - type F = unsafe extern "C" fn( - dtor: unsafe extern "C" fn(*mut u8), - arg: *mut u8, - dso_handle: *mut u8, - ) -> libc::c_int; - mem::transmute::<*const libc::c_void, F>(__cxa_thread_atexit_impl)( - dtor, - t, - &__dso_handle as *const _ as *mut _, - ); + + if !is_null(__cxa_thread_atexit_impl as *mut libc::c_void) { + unsafe { + __cxa_thread_atexit_impl( + mem::transmute::< + unsafe extern "C" fn(*mut u8), + unsafe extern "C" fn(*mut libc::c_void), + >(dtor), + t.cast(), + &__dso_handle as *const _ as *mut _, + ); + } return; } register_dtor_fallback(t, dtor);