Add arch-specific provider; remove PunchthroughProvider#806
Add arch-specific provider; remove PunchthroughProvider#806jaybosamiya-ms wants to merge 1 commit into
Conversation
e9dffae to
2542f06
Compare
2542f06 to
8f4da91
Compare
|
🤖 SemverChecks 🤖 Click for details |
| Ok(()) | ||
| } | ||
| ArchSpecificRegister::GsBase => { | ||
| unsafe { litebox_common_linux::wrgsbase(val) }; |
There was a problem hiding this comment.
In kernel mode, we call swapgs at the entry and exit of a syscall. At this point, userspace gsbase is stored in MSR (see https://elixir.bootlin.com/linux/v5.19.17/source/arch/x86/kernel/process_64.c#L763).
There was a problem hiding this comment.
Note the issue was found by GPT-5.5
There was a problem hiding this comment.
But it depends on when/where this function is called, right? If the caller is after swapgs and it actually knows that it wants to access which register, this function is correct, right?
There was a problem hiding this comment.
Ah, I see the issue. When this kernel platform code executes, if we do wrfsbase or wrgsbase, it actually directly affects the current gsbase used by the kernel. Is my understanding correct?
There was a problem hiding this comment.
we need wrmsr(IA32_KERNEL_GS_BASE, val) here to change the "user" GSBASE here due to swapgs.
| ) -> Result<usize, ArchSpecificError> { | ||
| match reg { | ||
| ArchSpecificRegister::FsBase => Ok(unsafe { litebox_common_linux::rdfsbase() }), | ||
| ArchSpecificRegister::GsBase => Ok(unsafe { litebox_common_linux::rdgsbase() }), |
| Ok(v) => Ok(v), | ||
| Err(e) => Err(litebox::platform::PunchthroughError::Failure(e)), | ||
| ArchSpecificRegister::GsBase => { | ||
| unsafe { litebox_common_linux::wrgsbase(val) }; |
| ) -> Result<usize, ArchSpecificError> { | ||
| match reg { | ||
| ArchSpecificRegister::FsBase => Ok(unsafe { litebox_common_linux::rdfsbase() }), | ||
| ArchSpecificRegister::GsBase => Ok(unsafe { litebox_common_linux::rdgsbase() }), |
wdcui
left a comment
There was a problem hiding this comment.
I left some comments below. Will have some offline discussion with you.
| // Reaching here means that a shim is attempting to easily run on a platform that | ||
| // fully disallows it. There is no reasonable handling here, so we panic. | ||
| // XXX: should this be ENOSYS? | ||
| panic!() |
There was a problem hiding this comment.
I wouldn't expect an error code conversion function to panic?
| Ok(()) | ||
| } | ||
| ArchSpecificRegister::GsBase => { | ||
| unsafe { litebox_common_linux::wrgsbase(val) }; |
There was a problem hiding this comment.
But it depends on when/where this function is called, right? If the caller is after swapgs and it actually knows that it wants to access which register, this function is correct, right?
| litebox::platform::ArchSpecificRegister::GsBase => { | ||
| // GS base is used internally by this platform to hold the host | ||
| // TLS base across the guest/host fs-gs swap, so it is not | ||
| // directly programmable by the guest. |
There was a problem hiding this comment.
Why would you expect the guest to call this platform trait?
This PR removes the last vestiges of the
PunchthroughProvider, moving out architecture-specific register management into its own trait. For now, I've only added support for x86-64's fsbase/gsbase, with platforms deciding which ones they'd like to support and which ones they do not want to support. This slightly expands beyond the only-fsbase behavior that existed in the old code, but acts as a way to improve clarity on usability (indeed, handling these generically will be needed if/when we want a proper WinNT shim, so might as well generalize right now).