Skip to content

Commit 33762eb

Browse files
committed
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.
1 parent b10cfcd commit 33762eb

File tree

2 files changed

+10
-6
lines changed

2 files changed

+10
-6
lines changed

compiler/rustc_codegen_llvm/src/back/lto.rs

Lines changed: 2 additions & 1 deletion
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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ use rustc_span::symbol::Symbol;
5252
use std::any::Any;
5353
use std::ffi::CStr;
5454
use std::io::Write;
55+
use std::mem::ManuallyDrop;
5556

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

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

414416
unsafe impl Send for ModuleLlvm {}
@@ -419,15 +421,15 @@ impl ModuleLlvm {
419421
unsafe {
420422
let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
421423
let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
422-
ModuleLlvm { llmod_raw, llcx, tm: create_target_machine(tcx, mod_name) }
424+
ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(create_target_machine(tcx, mod_name)) }
423425
}
424426
}
425427

426428
fn new_metadata(tcx: TyCtxt<'_>, mod_name: &str) -> Self {
427429
unsafe {
428430
let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
429431
let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
430-
ModuleLlvm { llmod_raw, llcx, tm: create_informational_target_machine(tcx.sess) }
432+
ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(create_informational_target_machine(tcx.sess)) }
431433
}
432434
}
433435

@@ -448,7 +450,7 @@ impl ModuleLlvm {
448450
}
449451
};
450452

451-
Ok(ModuleLlvm { llmod_raw, llcx, tm })
453+
Ok(ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) })
452454
}
453455
}
454456

@@ -460,6 +462,7 @@ impl ModuleLlvm {
460462
impl Drop for ModuleLlvm {
461463
fn drop(&mut self) {
462464
unsafe {
465+
drop(ManuallyDrop::take(&mut self.tm));
463466
llvm::LLVMContextDispose(&mut *(self.llcx as *mut _));
464467
}
465468
}

0 commit comments

Comments
 (0)