gz / rust-x86

Rust library to use x86 (amd64) specific functionality and registers.

Home Page:https://docs.rs/x86

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

sgdt and friends are broken

iankronquist opened this issue · comments

Inline asm is hard, sorry.

The current implementation of sgdt looks something like this:

pub unsafe fn sgdt<T>(idt: &mut DescriptorTablePointer<T>) {
    llvm_asm!("sgdt ($0)" : "=r" (idt as *mut DescriptorTablePointer<T>) :: "memory");
}

The constraint actually needs to be "+r" instead of "=r". "+r" means that it's an inout, while "=r" means a pure output.

Here's an example on the playground:
https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=63c9d1f1ee5eebf4dd4959b4800c6b66
https://gist.github.com/rust-play/b65e90316d752dac7564dc24510c022c

Standard Error:

   Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 1.43s
     Running `target/debug/playground`
timeout: the monitored command dumped core
/playground/tools/entrypoint.sh: line 11:     9 Segmentation fault      timeout --signal=KILL ${timeout} "$@"

Standard Output:

DescriptorTablePointer { limit: 7f, base: fffffe0000001000 }

Thanks for fixing this, and TIL this instructions works in ring 3.

Yeah, it's actually a great way to break kernel address space layout randomization on old kernels. The GDT is in kernel space, and you can just sgdt and get a kernel pointer for free. I'm pretty sure modern kernels just map it at a well known address which doesn't have the ASLR slide to prevent this.
https://lwn.net/Articles/569635/

Oh I see -- that's a neat hack/trick :)!