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?
| ) -> 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).