Dispose llvm::TargetMachines prior to llvm::Context being disposed
If the TargetMachine is disposed after the Context is disposed, it can lead to use after frees in some cases. I've observed this happening occasionally on code compiled for aarch64-pc-windows-msvc using `-Zstack-protector=strong` but other users have reported AVs from host aarch64-pc-windows-msvc compilers as well.
This commit is contained in:
parent
b10cfcd65f
commit
3323e4dc04
@ -25,6 +25,7 @@
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::iter;
|
||||
use std::mem::ManuallyDrop;
|
||||
use std::path::Path;
|
||||
use std::slice;
|
||||
use std::sync::Arc;
|
||||
@ -734,7 +735,7 @@ pub unsafe fn optimize_thin_module(
|
||||
let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
|
||||
let llmod_raw = parse_module(llcx, module_name, thin_module.data(), &diag_handler)? as *const _;
|
||||
let mut module = ModuleCodegen {
|
||||
module_llvm: ModuleLlvm { llmod_raw, llcx, tm },
|
||||
module_llvm: ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) },
|
||||
name: thin_module.name().to_string(),
|
||||
kind: ModuleKind::Regular,
|
||||
};
|
||||
|
@ -52,6 +52,7 @@
|
||||
use std::any::Any;
|
||||
use std::ffi::CStr;
|
||||
use std::io::Write;
|
||||
use std::mem::ManuallyDrop;
|
||||
|
||||
mod back {
|
||||
pub mod archive;
|
||||
@ -407,8 +408,9 @@ pub struct ModuleLlvm {
|
||||
llcx: &'static mut llvm::Context,
|
||||
llmod_raw: *const llvm::Module,
|
||||
|
||||
// independent from llcx and llmod_raw, resources get disposed by drop impl
|
||||
tm: OwnedTargetMachine,
|
||||
// This field is `ManuallyDrop` because it is important that the `TargetMachine`
|
||||
// is disposed prior to the `Context` being disposed otherwise UAFs can occur.
|
||||
tm: ManuallyDrop<OwnedTargetMachine>,
|
||||
}
|
||||
|
||||
unsafe impl Send for ModuleLlvm {}
|
||||
@ -419,7 +421,11 @@ fn new(tcx: TyCtxt<'_>, mod_name: &str) -> Self {
|
||||
unsafe {
|
||||
let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
|
||||
let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
|
||||
ModuleLlvm { llmod_raw, llcx, tm: create_target_machine(tcx, mod_name) }
|
||||
ModuleLlvm {
|
||||
llmod_raw,
|
||||
llcx,
|
||||
tm: ManuallyDrop::new(create_target_machine(tcx, mod_name)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -427,7 +433,11 @@ fn new_metadata(tcx: TyCtxt<'_>, mod_name: &str) -> Self {
|
||||
unsafe {
|
||||
let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
|
||||
let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
|
||||
ModuleLlvm { llmod_raw, llcx, tm: create_informational_target_machine(tcx.sess) }
|
||||
ModuleLlvm {
|
||||
llmod_raw,
|
||||
llcx,
|
||||
tm: ManuallyDrop::new(create_informational_target_machine(tcx.sess)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -448,7 +458,7 @@ fn parse(
|
||||
}
|
||||
};
|
||||
|
||||
Ok(ModuleLlvm { llmod_raw, llcx, tm })
|
||||
Ok(ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) })
|
||||
}
|
||||
}
|
||||
|
||||
@ -460,6 +470,7 @@ fn llmod(&self) -> &llvm::Module {
|
||||
impl Drop for ModuleLlvm {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
drop(ManuallyDrop::take(&mut self.tm));
|
||||
llvm::LLVMContextDispose(&mut *(self.llcx as *mut _));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user