Skip to content

Commit 2303087

Browse files
wesleywiserMark-Simulacrum
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.
1 parent 79e9716 commit 2303087

File tree

2 files changed

+18
-6
lines changed

2 files changed

+18
-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
@@ -26,6 +26,7 @@ use std::ffi::{CStr, CString};
2626
use std::fs::File;
2727
use std::io;
2828
use std::iter;
29+
use std::mem::ManuallyDrop;
2930
use std::path::Path;
3031
use std::slice;
3132
use std::sync::Arc;
@@ -736,7 +737,7 @@ pub unsafe fn optimize_thin_module(
736737
let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
737738
let llmod_raw = parse_module(llcx, module_name, thin_module.data(), &diag_handler)? as *const _;
738739
let mut module = ModuleCodegen {
739-
module_llvm: ModuleLlvm { llmod_raw, llcx, tm },
740+
module_llvm: ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) },
740741
name: thin_module.name().to_string(),
741742
kind: ModuleKind::Regular,
742743
};

compiler/rustc_codegen_llvm/src/lib.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ use rustc_span::symbol::Symbol;
4949
use std::any::Any;
5050
use std::ffi::CStr;
5151
use std::io::Write;
52+
use std::mem::ManuallyDrop;
5253

5354
mod back {
5455
pub mod archive;
@@ -404,8 +405,9 @@ pub struct ModuleLlvm {
404405
llcx: &'static mut llvm::Context,
405406
llmod_raw: *const llvm::Module,
406407

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

411413
unsafe impl Send for ModuleLlvm {}
@@ -416,15 +418,23 @@ impl ModuleLlvm {
416418
unsafe {
417419
let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
418420
let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
419-
ModuleLlvm { llmod_raw, llcx, tm: create_target_machine(tcx, mod_name) }
421+
ModuleLlvm {
422+
llmod_raw,
423+
llcx,
424+
tm: ManuallyDrop::new(create_target_machine(tcx, mod_name)),
425+
}
420426
}
421427
}
422428

423429
fn new_metadata(tcx: TyCtxt<'_>, mod_name: &str) -> Self {
424430
unsafe {
425431
let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
426432
let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
427-
ModuleLlvm { llmod_raw, llcx, tm: create_informational_target_machine(tcx.sess) }
433+
ModuleLlvm {
434+
llmod_raw,
435+
llcx,
436+
tm: ManuallyDrop::new(create_informational_target_machine(tcx.sess)),
437+
}
428438
}
429439
}
430440

@@ -445,7 +455,7 @@ impl ModuleLlvm {
445455
}
446456
};
447457

448-
Ok(ModuleLlvm { llmod_raw, llcx, tm })
458+
Ok(ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) })
449459
}
450460
}
451461

@@ -457,6 +467,7 @@ impl ModuleLlvm {
457467
impl Drop for ModuleLlvm {
458468
fn drop(&mut self) {
459469
unsafe {
470+
drop(ManuallyDrop::take(&mut self.tm));
460471
llvm::LLVMContextDispose(&mut *(self.llcx as *mut _));
461472
}
462473
}

0 commit comments

Comments
 (0)