Skip to content

Commit 76e6681

Browse files
wesleywisercuviper
authored andcommitted
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. (cherry picked from commit 3323e4d)
1 parent 98d3e99 commit 76e6681

File tree

2 files changed

+18
-6
lines changed

2 files changed

+18
-6
lines changed

compiler/rustc_codegen_llvm/src/back/lto.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use std::ffi::{CStr, CString};
2525
use std::fs::File;
2626
use std::io;
2727
use std::iter;
28+
use std::mem::ManuallyDrop;
2829
use std::path::Path;
2930
use std::slice;
3031
use std::sync::Arc;
@@ -734,7 +735,7 @@ pub unsafe fn optimize_thin_module(
734735
let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
735736
let llmod_raw = parse_module(llcx, module_name, thin_module.data(), &diag_handler)? as *const _;
736737
let mut module = ModuleCodegen {
737-
module_llvm: ModuleLlvm { llmod_raw, llcx, tm },
738+
module_llvm: ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) },
738739
name: thin_module.name().to_string(),
739740
kind: ModuleKind::Regular,
740741
};

compiler/rustc_codegen_llvm/src/lib.rs

+16-5
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ use rustc_span::symbol::Symbol;
5353
use std::any::Any;
5454
use std::ffi::CStr;
5555
use std::io::Write;
56+
use std::mem::ManuallyDrop;
5657

5758
mod back {
5859
pub mod archive;
@@ -408,8 +409,9 @@ pub struct ModuleLlvm {
408409
llcx: &'static mut llvm::Context,
409410
llmod_raw: *const llvm::Module,
410411

411-
// independent from llcx and llmod_raw, resources get disposed by drop impl
412-
tm: OwnedTargetMachine,
412+
// This field is `ManuallyDrop` because it is important that the `TargetMachine`
413+
// is disposed prior to the `Context` being disposed otherwise UAFs can occur.
414+
tm: ManuallyDrop<OwnedTargetMachine>,
413415
}
414416

415417
unsafe impl Send for ModuleLlvm {}
@@ -420,15 +422,23 @@ impl ModuleLlvm {
420422
unsafe {
421423
let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
422424
let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
423-
ModuleLlvm { llmod_raw, llcx, tm: create_target_machine(tcx, mod_name) }
425+
ModuleLlvm {
426+
llmod_raw,
427+
llcx,
428+
tm: ManuallyDrop::new(create_target_machine(tcx, mod_name)),
429+
}
424430
}
425431
}
426432

427433
fn new_metadata(tcx: TyCtxt<'_>, mod_name: &str) -> Self {
428434
unsafe {
429435
let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
430436
let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
431-
ModuleLlvm { llmod_raw, llcx, tm: create_informational_target_machine(tcx.sess) }
437+
ModuleLlvm {
438+
llmod_raw,
439+
llcx,
440+
tm: ManuallyDrop::new(create_informational_target_machine(tcx.sess)),
441+
}
432442
}
433443
}
434444

@@ -449,7 +459,7 @@ impl ModuleLlvm {
449459
}
450460
};
451461

452-
Ok(ModuleLlvm { llmod_raw, llcx, tm })
462+
Ok(ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) })
453463
}
454464
}
455465

@@ -461,6 +471,7 @@ impl ModuleLlvm {
461471
impl Drop for ModuleLlvm {
462472
fn drop(&mut self) {
463473
unsafe {
474+
drop(ManuallyDrop::take(&mut self.tm));
464475
llvm::LLVMContextDispose(&mut *(self.llcx as *mut _));
465476
}
466477
}

0 commit comments

Comments
 (0)