bevy
bevy copied to clipboard
User-mode data execution prevention (DEP) violation when loading Dynamic Plugins
Bevy version
0.13.2
[Optional] Relevant system information
OS: Windows 11 Pro for Workstations - 23H2 - 22631.3447 CPU: AMD Ryzen 7 4800H with Radeon Graphics 2.90 GHz GPU: NVIDIA GeForce GTX 1650Ti for Laptop RAM: 64GB Rust Version: rustc 1.77.2 (25ef9e3d8 2024-04-09) Cargo Version: cargo 1.77.2 (e52e36006 2024-03-26)
What you did
I am tring to test whether Bevy can share component type throuth different dynamic plugins(i.e. System in one dylib can detect component spawned by System in another dylib). So I create three crates inside the main project. One defines Components, Others depend this static lib and run Systems. In main.rs of this project, I enable bevy's "bevy_dynamic_plugin" feature then invoke load_plugin()
What went wrong
Whether test success or fail, dynamic_plugin should built successfully, but I encountered Exception: Exception 0xc0000005 encountered at address 0x000000: User-mode data execution prevention (DEP) violation at location 0x00000000
and then bevy crashed.
Additional information
I debug the application several times. I'm sure that dlls are successfully loaded.
The last step before exception is as follows:
then, it crashes:
The top of trace stack is:
It appears that the address of self
is 0x0 or 0x4 or many other address nearby 0x0, but actually self
has its own address. What happend when app calls plugin.build(self)
?
I switched lib type to cdylib, but it makes nonsense.
The content of dll is quite simple(This problem exists whether these lines are commented or not ):
use bevy::app::DynamicPlugin;
use bevy::prelude::{App, Commands, Component, Plugin, Query, Startup, Update};
use xk_python::Test1;
#[derive(DynamicPlugin)]
pub struct XkUiplugin;
impl Plugin for XkUiplugin {
fn build(&self, app: &mut App) {
// println!("build ui");
// app.add_systems(Update, test_ui);
}
}
same to main.rs
pub mod prelude;
use bevy::prelude::*;
use std::env;
pub fn main() {
unsafe {
println!("{}", String::from(env::current_dir().unwrap().to_str().unwrap()) + "\\xk_ui.dll");
App::new()
.load_plugin( "D:\\WorkSpace\\Project\\FormalProject\\XKGIS\\XKGIS-Core\\target\\debug\\xk_ui.dll")
.load_plugin("D:\\WorkSpace\\Project\\FormalProject\\XKGIS\\XKGIS-Core\\target\\debug\\xk_show_screen.dll")
.add_plugins(MinimalPlugins)
.run();
}
}
My friend helped me checked dll content with IDA, he says the dll files I used are completely normal. Debugger of RustRover gives me assembly code, I don't know whether it can help.
bevy_dynamic_plugin::loader::impl$0::load_plugin<ref$<str$> >(*mut bevy_app::app::App,ref$<str$>):
pushq %rbp
subq $0xe0, %rsp
leaq 0x80(%rsp), %rbp
movq $-0x2, 0x58(%rbp)
movq %rcx, -0x50(%rbp)
movq %rcx, 0x18(%rbp)
movq %rdx, 0x20(%rbp)
movq %r8, 0x28(%rbp)
movb $0x0, 0x17(%rbp)
leaq -0x18(%rbp), %rcx
callq 0x140002cb0 ; bevy_dynamic_plugin::loader::dynamically_load_plugin<ref$<str$> >(ref$<str$>) at loader.rs:29
cmpq $0x2, -0x18(%rbp)
je 0x140001852 ; <+130> [inlined] enum2$<core::result::Result<tuple$<libloading::safe::Library,alloc::boxed::Box<dyn$<bevy_app::plugin::Plugin>,alloc::alloc::Global> >,enum2$<bevy_dynamic_plugin::loader::DynamicPluginLoadError> > >::unwrap(enum2$<core::result::Result<tuple$<libloading::safe::Library,alloc::boxed::Box<dyn$<bevy_app::plugin::Plugin>,alloc::alloc::Global> >,enum2$<bevy_dynamic_plugin::loader::DynamicPluginLoadError> > >,*mut core::panic::location::Location) + 77 at loader.rs:59
movq 0x8(%rbp), %rax
movq %rax, 0x50(%rbp)
movups -0x18(%rbp), %xmm0
movups -0x8(%rbp), %xmm1
movaps %xmm1, 0x40(%rbp)
movaps %xmm0, 0x30(%rbp)
leaq 0x3d8c95(%rip), %rcx
movq %rsp, %rax
movq %rcx, 0x20(%rax)
leaq 0x3d8bc7(%rip), %rcx
leaq 0x3d8bf0(%rip), %r9 ; impl$<enum2$<bevy_dynamic_plugin::loader::DynamicPluginLoadError>, core::fmt::Debug>::vtable$
movl $0x2b, %edx
leaq 0x30(%rbp), %r8
callq 0x1403d9830 ; core::result::unwrap_failed() at result.rs:1648
jmp 0x140001850 ; <+128> [inlined] enum2$<core::result::Result<tuple$<libloading::safe::Library,alloc::boxed::Box<dyn$<bevy_app::plugin::Plugin>,alloc::alloc::Global> >,enum2$<bevy_dynamic_plugin::loader::DynamicPluginLoadError> > >::unwrap(enum2$<core::result::Result<tuple$<libloading::safe::Library,alloc::boxed::Box<dyn$<bevy_app::plugin::Plugin>,alloc::alloc::Global> >,enum2$<bevy_dynamic_plugin::loader::DynamicPluginLoadError> > >,*mut core::panic::location::Location) + 75 at loader.rs:59
ud2
movq (%rbp), %rax
movq %rax, -0x20(%rbp)
movups -0x10(%rbp), %xmm0
movaps %xmm0, -0x30(%rbp)
movb $0x1, 0x17(%rbp)
movq -0x30(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x28(%rbp), %rcx
movq -0x20(%rbp), %rax
movq %rcx, -0x40(%rbp)
movq %rax, -0x38(%rbp)
movb $0x0, 0x17(%rbp)
movq -0x48(%rbp), %rcx
callq 0x140002810 ; core::mem::forget<libloading::safe::Library>(libloading::safe::Library) at mod.rs:148
jmp 0x14000188d ; <+189> at loader.rs:61
movq -0x50(%rbp), %rdx
movq -0x40(%rbp), %rcx
movq -0x38(%rbp), %rax
movq 0x50(%rax), %rax
callq *%rax
jmp 0x1400018a1 ; <+209> at loader.rs:63
leaq -0x40(%rbp), %rcx
callq 0x1400c4bf0 ; core::ptr::drop_in_place<alloc::boxed::Box<dyn$<bevy_app::plugin::Plugin>,alloc::alloc::Global> >(*mut alloc::boxed::Box<dyn$<bevy_app::plugin::Plugin>,alloc::alloc::Global>) at mod.rs:507
jmp 0x1400018ac ; <+220> at loader.rs:63
movq -0x50(%rbp), %rax
movb $0x0, 0x17(%rbp)
addq $0xe0, %rsp
popq %rbp
retq
nopl (%rax)
movq %rdx, 0x10(%rsp)
pushq %rbp
subq $0x30, %rsp
leaq 0x80(%rdx), %rbp
leaq 0x30(%rbp), %rcx
callq 0x140001dc0 ; core::ptr::drop_in_place<enum2$<bevy_dynamic_plugin::loader::DynamicPluginLoadError> >(*mut enum2$<bevy_dynamic_plugin::loader::DynamicPluginLoadError>) at mod.rs:507
nop
addq $0x30, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
movq %rdx, 0x10(%rsp)
pushq %rbp
subq $0x30, %rsp
leaq 0x80(%rdx), %rbp
leaq -0x40(%rbp), %rcx
callq 0x1400c4bf0 ; core::ptr::drop_in_place<alloc::boxed::Box<dyn$<bevy_app::plugin::Plugin>,alloc::alloc::Global> >(*mut alloc::boxed::Box<dyn$<bevy_app::plugin::Plugin>,alloc::alloc::Global>) at mod.rs:507
nop
addq $0x30, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
movq %rdx, 0x10(%rsp)
pushq %rbp
subq $0x30, %rsp
leaq 0x80(%rdx), %rbp
testb $0x1, 0x17(%rbp)
jne 0x14000193f ; <+367> at loader.rs:63
jmp 0x140001939 ; <+361> at loader.rs:57
addq $0x30, %rsp
popq %rbp
retq
leaq -0x48(%rbp), %rcx
callq 0x1400100b0 ; core::ptr::drop_in_place<libloading::safe::Library>(*mut libloading::safe::Library) at mod.rs:507
jmp 0x140001939 ; <+361> at loader.rs:57
As I reruned the app, I found that addresses in vtable of dyn Plugin changed unnormally.
Bevy's dynamic plugin interface is almost certainly unsound, and I think this may be one such case. You may find #11969 interesting in this regard. Other bits of code that are related include dynamically_load_plugin
, the CreatePlugin
type, and the DynamicPlugin
derive.