Skip to content

Commit

Permalink
Rollup merge of #118464 - wesleywiser:fix_dispose_ordering, r=Nilstrieb
Browse files Browse the repository at this point in the history
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.

I was not able to extract a self-contained test case yet so there is no accompanying test.

Fixes #118462
  • Loading branch information
matthiaskrgr authored Nov 30, 2023
2 parents 49fadee + 1011078 commit 640a431
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 6 deletions.
3 changes: 2 additions & 1 deletion compiler/rustc_codegen_llvm/src/back/lto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use std::ffi::{CStr, CString};
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;
Expand Down Expand Up @@ -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,
};
Expand Down
21 changes: 16 additions & 5 deletions compiler/rustc_codegen_llvm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ use rustc_span::symbol::Symbol;
use std::any::Any;
use std::ffi::CStr;
use std::io::Write;
use std::mem::ManuallyDrop;

mod back {
pub mod archive;
Expand Down Expand Up @@ -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 {}
Expand All @@ -419,15 +421,23 @@ impl ModuleLlvm {
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)),
}
}
}

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)),
}
}
}

Expand All @@ -448,7 +458,7 @@ impl ModuleLlvm {
}
};

Ok(ModuleLlvm { llmod_raw, llcx, tm })
Ok(ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) })
}
}

Expand All @@ -460,6 +470,7 @@ impl ModuleLlvm {
impl Drop for ModuleLlvm {
fn drop(&mut self) {
unsafe {
ManuallyDrop::drop(&mut self.tm);
llvm::LLVMContextDispose(&mut *(self.llcx as *mut _));
}
}
Expand Down

0 comments on commit 640a431

Please sign in to comment.