Message ID | 20230505152046.6575-1-mic@digikod.net (mailing list archive) |
---|---|
Headers | show |
Series | Hypervisor-Enforced Kernel Integrity | expand |
On 5/5/2023 8:20 AM, Mickaël Salaün wrote: > Hi, > > This patch series is a proof-of-concept that implements new KVM features > (extended page tracking, MBEC support, CR pinning) and defines a new API to > protect guest VMs. No VMM (e.g., Qemu) modification is required. > > The main idea being that kernel self-protection mechanisms should be delegated > to a more privileged part of the system, hence the hypervisor. It is still the > role of the guest kernel to request such restrictions according to its Only for the guest kernel images here? Why not for the host OS kernel? Embedded devices w/ Android you have mentioned below supports the host OS as well it seems, right? Do we suggest that all the functionalities should be implemented in the Hypervisor (NS-EL2 for ARM) or even at Secure EL like Secure-EL1 (ARM). I am hoping that whatever we suggest the interface here from the Guest to the Hypervisor becomes the ABI right? > > # Current limitations > > The main limitation of this patch series is the statically enforced > permissions. This is not an issue for kernels without module but this needs to > be addressed. Mechanisms that dynamically impact kernel executable memory are > not handled for now (e.g., kernel modules, tracepoints, eBPF JIT), and such > code will need to be authenticated. Because the hypervisor is highly > privileged and critical to the security of all the VMs, we don't want to > implement a code authentication mechanism in the hypervisor itself but delegate > this verification to something much less privileged. We are thinking of two > ways to solve this: implement this verification in the VMM or spawn a dedicated > special VM (similar to Windows's VBS). There are pros on cons to each approach: > complexity, verification code ownership (guest's or VMM's), access to guest > memory (i.e., confidential computing). Do you foresee the performance regressions due to lot of tracking here? Production kernels do have lot of tracepoints and we use it as feature in the GKI kernel for the vendor hooks implementation and in those cases every vendor driver is a module. Separate VM further fragments this design and delegates more of it to proprietary solutions? Do you have any performance numbers w/ current RFC? ---Trilok Soni
On Fri, 2023-05-05 at 17:20 +0200, Mickaël Salaün wrote: > # How does it work? > > This implementation mainly leverages KVM capabilities to control the > Second > Layer Address Translation (or the Two Dimensional Paging e.g., > Intel's EPT or > AMD's RVI/NPT) and Mode Based Execution Control (Intel's MBEC) > introduced with > the Kaby Lake (7th generation) architecture. This allows to set > permissions on > memory pages in a complementary way to the guest kernel's managed > memory > permissions. Once these permissions are set, they are locked and > there is no > way back. > > A first KVM_HC_LOCK_MEM_PAGE_RANGES hypercall enables the guest > kernel to lock > a set of its memory page ranges with either the HEKI_ATTR_MEM_NOWRITE > or the > HEKI_ATTR_MEM_EXEC attribute. The first one denies write access to a > specific > set of pages (allow-list approach), and the second only allows kernel > execution > for a set of pages (deny-list approach). > > The current implementation sets the whole kernel's .rodata (i.e., any > const or > __ro_after_init variables, which includes critical security data such > as LSM > parameters) and .text sections as non-writable, and the .text section > is the > only one where kernel execution is allowed. This is possible thanks > to the new > MBEC support also brough by this series (otherwise the vDSO would > have to be > executable). Thanks to this hardware support (VT-x, EPT and MBEC), > the > performance impact of such guest protection is negligible. > > The second KVM_HC_LOCK_CR_UPDATE hypercall enables guests to pin some > of its > CPU control register flags (e.g., X86_CR0_WP, X86_CR4_SMEP, > X86_CR4_SMAP), > which is another complementary hardening mechanism. > > Heki can be enabled with the heki=1 boot command argument. > > Can the guest kernel ask the host VMM's emulated devices to DMA into the protected data? It should go through the host userspace mappings I think, which don't care about EPT permissions. Or did I miss where you are protecting that another way? There are a lot of easy ways to ask the host to write to guest memory that don't involve the EPT. You probably need to protect the host userspace mappings, and also the places in KVM that kmap a GPA provided by the guest. [ snip ] > > # Current limitations > > The main limitation of this patch series is the statically enforced > permissions. This is not an issue for kernels without module but this > needs to > be addressed. Mechanisms that dynamically impact kernel executable > memory are > not handled for now (e.g., kernel modules, tracepoints, eBPF JIT), > and such > code will need to be authenticated. Because the hypervisor is highly > privileged and critical to the security of all the VMs, we don't want > to > implement a code authentication mechanism in the hypervisor itself > but delegate > this verification to something much less privileged. We are thinking > of two > ways to solve this: implement this verification in the VMM or spawn a > dedicated > special VM (similar to Windows's VBS). There are pros on cons to each > approach: > complexity, verification code ownership (guest's or VMM's), access to > guest > memory (i.e., confidential computing). The kernel often creates writable aliases in order to write to protected data (kernel text, etc). Some of this is done right as text is being first written out (alternatives for example), and some happens way later (jump labels, etc). So for verification, I wonder what stage you would be verifying? If you want to verify the end state, you would have to maintain knowledge in the verifier of all the touch-ups the kernel does. I think it would get very tricky. It also seems it will be a decent ask for the guest kernel to keep track of GPA permissions as well as normal virtual memory pemirssions, if this thing is not widely used. So I wondering if you could go in two directions with this: 1. Make this a feature only for super locked down kernels (no modules, etc). Forbid any configurations that might modify text. But eBPF is used for seccomp, so you might be turning off some security protections to get this. 2. Loosen the rules to allow the protections to not be so one-way enable. Get less security, but used more widely. There were similar dilemmas with the PV CR pinning stuff.
On 5/24/2023 3:20 PM, Edgecombe, Rick P wrote: > On Fri, 2023-05-05 at 17:20 +0200, Mickaël Salaün wrote: >> # How does it work? >> >> This implementation mainly leverages KVM capabilities to control the >> Second >> Layer Address Translation (or the Two Dimensional Paging e.g., >> Intel's EPT or >> AMD's RVI/NPT) and Mode Based Execution Control (Intel's MBEC) >> introduced with >> the Kaby Lake (7th generation) architecture. This allows to set >> permissions on >> memory pages in a complementary way to the guest kernel's managed >> memory >> permissions. Once these permissions are set, they are locked and >> there is no >> way back. >> >> A first KVM_HC_LOCK_MEM_PAGE_RANGES hypercall enables the guest >> kernel to lock >> a set of its memory page ranges with either the HEKI_ATTR_MEM_NOWRITE >> or the >> HEKI_ATTR_MEM_EXEC attribute. The first one denies write access to a >> specific >> set of pages (allow-list approach), and the second only allows kernel >> execution >> for a set of pages (deny-list approach). >> >> The current implementation sets the whole kernel's .rodata (i.e., any >> const or >> __ro_after_init variables, which includes critical security data such >> as LSM >> parameters) and .text sections as non-writable, and the .text section >> is the >> only one where kernel execution is allowed. This is possible thanks >> to the new >> MBEC support also brough by this series (otherwise the vDSO would >> have to be >> executable). Thanks to this hardware support (VT-x, EPT and MBEC), >> the >> performance impact of such guest protection is negligible. >> >> The second KVM_HC_LOCK_CR_UPDATE hypercall enables guests to pin some >> of its >> CPU control register flags (e.g., X86_CR0_WP, X86_CR4_SMEP, >> X86_CR4_SMAP), >> which is another complementary hardening mechanism. >> >> Heki can be enabled with the heki=1 boot command argument. >> >> > > Can the guest kernel ask the host VMM's emulated devices to DMA into > the protected data? It should go through the host userspace mappings I > think, which don't care about EPT permissions. Or did I miss where you > are protecting that another way? There are a lot of easy ways to ask > the host to write to guest memory that don't involve the EPT. You > probably need to protect the host userspace mappings, and also the > places in KVM that kmap a GPA provided by the guest. > > [ snip ] > >> >> # Current limitations >> >> The main limitation of this patch series is the statically enforced >> permissions. This is not an issue for kernels without module but this >> needs to >> be addressed. Mechanisms that dynamically impact kernel executable >> memory are >> not handled for now (e.g., kernel modules, tracepoints, eBPF JIT), >> and such >> code will need to be authenticated. Because the hypervisor is highly >> privileged and critical to the security of all the VMs, we don't want >> to >> implement a code authentication mechanism in the hypervisor itself >> but delegate >> this verification to something much less privileged. We are thinking >> of two >> ways to solve this: implement this verification in the VMM or spawn a >> dedicated >> special VM (similar to Windows's VBS). There are pros on cons to each >> approach: >> complexity, verification code ownership (guest's or VMM's), access to >> guest >> memory (i.e., confidential computing). > > The kernel often creates writable aliases in order to write to > protected data (kernel text, etc). Some of this is done right as text > is being first written out (alternatives for example), and some happens > way later (jump labels, etc). So for verification, I wonder what stage > you would be verifying? If you want to verify the end state, you would > have to maintain knowledge in the verifier of all the touch-ups the > kernel does. I think it would get very tricky. Right and for the ARM (from what I know) is that Erratas can be applied using the alternatives fwk when you hotplug in the CPU post boot. ---Trilok Soni
On 24/05/2023 23:04, Trilok Soni wrote: > On 5/5/2023 8:20 AM, Mickaël Salaün wrote: >> Hi, >> >> This patch series is a proof-of-concept that implements new KVM features >> (extended page tracking, MBEC support, CR pinning) and defines a new API to >> protect guest VMs. No VMM (e.g., Qemu) modification is required. >> >> The main idea being that kernel self-protection mechanisms should be delegated >> to a more privileged part of the system, hence the hypervisor. It is still the >> role of the guest kernel to request such restrictions according to its > > Only for the guest kernel images here? Why not for the host OS kernel? As explained in the Future work section, protecting the host would be useful, but that doesn't really fit with the KVM model. The Protected KVM project is a first step to help in this direction [11]. In a nutshell, KVM is close to a type-2 hypervisor, and the host kernel is also part of the hypervisor. > Embedded devices w/ Android you have mentioned below supports the host > OS as well it seems, right? What do you mean? > > Do we suggest that all the functionalities should be implemented in the > Hypervisor (NS-EL2 for ARM) or even at Secure EL like Secure-EL1 (ARM). KVM runs in EL2. TrustZone is mainly used to enforce DRM, which means that we may not control the related code. This patch series is dedicated to hypervisor-enforced kernel integrity, then KVM. > > I am hoping that whatever we suggest the interface here from the Guest > to the Hypervisor becomes the ABI right? Yes, hypercalls are part of the KVM ABI. > > >> >> # Current limitations >> >> The main limitation of this patch series is the statically enforced >> permissions. This is not an issue for kernels without module but this needs to >> be addressed. Mechanisms that dynamically impact kernel executable memory are >> not handled for now (e.g., kernel modules, tracepoints, eBPF JIT), and such >> code will need to be authenticated. Because the hypervisor is highly >> privileged and critical to the security of all the VMs, we don't want to >> implement a code authentication mechanism in the hypervisor itself but delegate >> this verification to something much less privileged. We are thinking of two >> ways to solve this: implement this verification in the VMM or spawn a dedicated >> special VM (similar to Windows's VBS). There are pros on cons to each approach: >> complexity, verification code ownership (guest's or VMM's), access to guest >> memory (i.e., confidential computing). > > Do you foresee the performance regressions due to lot of tracking here? The performance impact of execution prevention should be negligible because once configured the hypervisor do nothing except catch illegitimate access attempts. > Production kernels do have lot of tracepoints and we use it as feature > in the GKI kernel for the vendor hooks implementation and in those cases > every vendor driver is a module. As explained in this section, dynamic kernel modifications such as tracepoints or modules are not currently supported by this patch series. Handling tracepoints is possible but requires more work to define and check legitimate changes. This proposal is still useful for static kernels though. > Separate VM further fragments this > design and delegates more of it to proprietary solutions? What do you mean? KVM is not a proprietary solution. For dynamic checks, this would require code not run by KVM itself, but either the VMM or a dedicated VM. In this case, the dynamic authentication code could come from the guest VM or from the VMM itself. In the former case, it is more challenging from a security point of view but doesn't rely on external (proprietary) solution. In the latter case, open-source VMMs should implement the specification to provide the required service (e.g. check kernel module signature). The goal of the common API layer provided by this RFC is to share code as much as possible between different hypervisor backends. > > Do you have any performance numbers w/ current RFC? No, but the only hypervisor performance impact is at boot time and should be negligible. I'll try to get some numbers for the hardware-enforcement impact, but it should be negligible too.
On 25/05/2023 00:20, Edgecombe, Rick P wrote: > On Fri, 2023-05-05 at 17:20 +0200, Mickaël Salaün wrote: >> # How does it work? >> >> This implementation mainly leverages KVM capabilities to control the >> Second >> Layer Address Translation (or the Two Dimensional Paging e.g., >> Intel's EPT or >> AMD's RVI/NPT) and Mode Based Execution Control (Intel's MBEC) >> introduced with >> the Kaby Lake (7th generation) architecture. This allows to set >> permissions on >> memory pages in a complementary way to the guest kernel's managed >> memory >> permissions. Once these permissions are set, they are locked and >> there is no >> way back. >> >> A first KVM_HC_LOCK_MEM_PAGE_RANGES hypercall enables the guest >> kernel to lock >> a set of its memory page ranges with either the HEKI_ATTR_MEM_NOWRITE >> or the >> HEKI_ATTR_MEM_EXEC attribute. The first one denies write access to a >> specific >> set of pages (allow-list approach), and the second only allows kernel >> execution >> for a set of pages (deny-list approach). >> >> The current implementation sets the whole kernel's .rodata (i.e., any >> const or >> __ro_after_init variables, which includes critical security data such >> as LSM >> parameters) and .text sections as non-writable, and the .text section >> is the >> only one where kernel execution is allowed. This is possible thanks >> to the new >> MBEC support also brough by this series (otherwise the vDSO would >> have to be >> executable). Thanks to this hardware support (VT-x, EPT and MBEC), >> the >> performance impact of such guest protection is negligible. >> >> The second KVM_HC_LOCK_CR_UPDATE hypercall enables guests to pin some >> of its >> CPU control register flags (e.g., X86_CR0_WP, X86_CR4_SMEP, >> X86_CR4_SMAP), >> which is another complementary hardening mechanism. >> >> Heki can be enabled with the heki=1 boot command argument. >> >> > > Can the guest kernel ask the host VMM's emulated devices to DMA into > the protected data? It should go through the host userspace mappings I > think, which don't care about EPT permissions. Or did I miss where you > are protecting that another way? There are a lot of easy ways to ask > the host to write to guest memory that don't involve the EPT. You > probably need to protect the host userspace mappings, and also the > places in KVM that kmap a GPA provided by the guest. Good point, I'll check this confused deputy attack. Extended KVM protections should indeed handle all ways to map guests' memory. I'm wondering if current VMMs would gracefully handle such new restrictions though. > > [ snip ] > >> >> # Current limitations >> >> The main limitation of this patch series is the statically enforced >> permissions. This is not an issue for kernels without module but this >> needs to >> be addressed. Mechanisms that dynamically impact kernel executable >> memory are >> not handled for now (e.g., kernel modules, tracepoints, eBPF JIT), >> and such >> code will need to be authenticated. Because the hypervisor is highly >> privileged and critical to the security of all the VMs, we don't want >> to >> implement a code authentication mechanism in the hypervisor itself >> but delegate >> this verification to something much less privileged. We are thinking >> of two >> ways to solve this: implement this verification in the VMM or spawn a >> dedicated >> special VM (similar to Windows's VBS). There are pros on cons to each >> approach: >> complexity, verification code ownership (guest's or VMM's), access to >> guest >> memory (i.e., confidential computing). > > The kernel often creates writable aliases in order to write to > protected data (kernel text, etc). Some of this is done right as text > is being first written out (alternatives for example), and some happens > way later (jump labels, etc). So for verification, I wonder what stage > you would be verifying? If you want to verify the end state, you would > have to maintain knowledge in the verifier of all the touch-ups the > kernel does. I think it would get very tricky. For now, in the static kernel case, all rodata and text GPA is restricted, so aliasing such memory in a writable way before or after the KVM enforcement would still restrict write access to this memory, which could be an issue but not a security one. Do you have such examples in mind? > > It also seems it will be a decent ask for the guest kernel to keep > track of GPA permissions as well as normal virtual memory pemirssions, > if this thing is not widely used. This would indeed be required to properly handle the dynamic cases. > > So I wondering if you could go in two directions with this: > 1. Make this a feature only for super locked down kernels (no modules, > etc). Forbid any configurations that might modify text. But eBPF is > used for seccomp, so you might be turning off some security protections > to get this. Good idea. For "super locked down kernels" :) , we should disable all kernel executable changes with the related kernel build configuration (e.g. eBPF JIT, kernel module, kprobes…) to make sure there is no such legitimate access. This looks like an acceptable initial feature. > 2. Loosen the rules to allow the protections to not be so one-way > enable. Get less security, but used more widely. This is our goal. I think both static and dynamic cases are legitimate and have value according to the level of security sought. This should be a build-time configuration. > > There were similar dilemmas with the PV CR pinning stuff.
On Thu, 2023-05-25 at 15:59 +0200, Mickaël Salaün wrote: [ snip ] > > The kernel often creates writable aliases in order to write to > > protected data (kernel text, etc). Some of this is done right as > > text > > is being first written out (alternatives for example), and some > > happens > > way later (jump labels, etc). So for verification, I wonder what > > stage > > you would be verifying? If you want to verify the end state, you > > would > > have to maintain knowledge in the verifier of all the touch-ups the > > kernel does. I think it would get very tricky. > > For now, in the static kernel case, all rodata and text GPA is > restricted, so aliasing such memory in a writable way before or after > the KVM enforcement would still restrict write access to this memory, > which could be an issue but not a security one. Do you have such > examples in mind? > On x86, look at all the callers of the text_poke() family. In arch/x86/include/asm/text-patching.h. > > > > > It also seems it will be a decent ask for the guest kernel to keep > > track of GPA permissions as well as normal virtual memory > > pemirssions, > > if this thing is not widely used. > > This would indeed be required to properly handle the dynamic cases. > > > > > > So I wondering if you could go in two directions with this: > > 1. Make this a feature only for super locked down kernels (no > > modules, > > etc). Forbid any configurations that might modify text. But eBPF is > > used for seccomp, so you might be turning off some security > > protections > > to get this. > > Good idea. For "super locked down kernels" :) , we should disable all > kernel executable changes with the related kernel build configuration > (e.g. eBPF JIT, kernel module, kprobes…) to make sure there is no > such > legitimate access. This looks like an acceptable initial feature. How many users do you think will want this protection but not protections that would have to be disabled? The main one that came to mind for me is cBPF seccomp stuff. But also, the alternative to JITing cBPF is the eBPF interpreter which AFAIU is considered a juicy enough target for speculative attacks that they created an option to compile it out. And leaving an interpreter in the kernel means any data could be "executed" in the normal non- speculative scenario, kind of working around the hypervisor executable protections. Dropping e/cBPF entirely would be an option, but then I wonder how many users you have left. Hopefully that is all correct, it's hard to keep track with the pace of BPF development. I wonder if it might be a good idea to POC the guest side before settling on the KVM interface. Then you can also look at the whole thing and judge how much usage it would get for the different options of restrictions. > > > > 2. Loosen the rules to allow the protections to not be so one-way > > enable. Get less security, but used more widely. > > This is our goal. I think both static and dynamic cases are > legitimate > and have value according to the level of security sought. This should > be > a build-time configuration. Yea, the proper way to do this is probably to move all text handling stuff into a separate domain of some sort, like you mentioned elsewhere. It would be quite a job.
On Thu, May 25, 2023, Rick P Edgecombe wrote: > I wonder if it might be a good idea to POC the guest side before > settling on the KVM interface. Then you can also look at the whole > thing and judge how much usage it would get for the different options > of restrictions. As I said earlier[*], IMO the control plane logic needs to live in host userspace. I think any attempt to have KVM providen anything but the low level plumbing will suffer the same fate as CR4 pinning and XO memory. Iterating on an imperfect solution to incremently improve security is far, far easier to do in userspace, and far more likely to get merged. [*] https://lore.kernel.org/all/ZFUyhPuhtMbYdJ76@google.com
On 5/25/2023 6:25 AM, Mickaël Salaün wrote: > > On 24/05/2023 23:04, Trilok Soni wrote: >> On 5/5/2023 8:20 AM, Mickaël Salaün wrote: >>> Hi, >>> >>> This patch series is a proof-of-concept that implements new KVM features >>> (extended page tracking, MBEC support, CR pinning) and defines a new >>> API to >>> protect guest VMs. No VMM (e.g., Qemu) modification is required. >>> >>> The main idea being that kernel self-protection mechanisms should be >>> delegated >>> to a more privileged part of the system, hence the hypervisor. It is >>> still the >>> role of the guest kernel to request such restrictions according to its >> >> Only for the guest kernel images here? Why not for the host OS kernel? > > As explained in the Future work section, protecting the host would be > useful, but that doesn't really fit with the KVM model. The Protected > KVM project is a first step to help in this direction [11]. > > In a nutshell, KVM is close to a type-2 hypervisor, and the host kernel > is also part of the hypervisor. > > >> Embedded devices w/ Android you have mentioned below supports the host >> OS as well it seems, right? > > What do you mean? I think you have answered this above w/ pKVM and I was referring the host protection as well w/ Heki. The link/references below refers to the Android OS it seems and not guest VM. > > >> >> Do we suggest that all the functionalities should be implemented in the >> Hypervisor (NS-EL2 for ARM) or even at Secure EL like Secure-EL1 (ARM). > > KVM runs in EL2. TrustZone is mainly used to enforce DRM, which means > that we may not control the related code. > > This patch series is dedicated to hypervisor-enforced kernel integrity, > then KVM. > >> >> I am hoping that whatever we suggest the interface here from the Guest >> to the Hypervisor becomes the ABI right? > > Yes, hypercalls are part of the KVM ABI. Sure. I just hope that they are extensible enough to support for other Hypervisors too. I am not sure if they are on this list like ACRN / Xen and see if it fits their need too. Is there any other Hypervisor you plan to test this feature as well? > >> >> >>> >>> # Current limitations >>> >>> The main limitation of this patch series is the statically enforced >>> permissions. This is not an issue for kernels without module but this >>> needs to >>> be addressed. Mechanisms that dynamically impact kernel executable >>> memory are >>> not handled for now (e.g., kernel modules, tracepoints, eBPF JIT), >>> and such >>> code will need to be authenticated. Because the hypervisor is highly >>> privileged and critical to the security of all the VMs, we don't want to >>> implement a code authentication mechanism in the hypervisor itself >>> but delegate >>> this verification to something much less privileged. We are thinking >>> of two >>> ways to solve this: implement this verification in the VMM or spawn a >>> dedicated >>> special VM (similar to Windows's VBS). There are pros on cons to each >>> approach: >>> complexity, verification code ownership (guest's or VMM's), access to >>> guest >>> memory (i.e., confidential computing). >> >> Do you foresee the performance regressions due to lot of tracking here? > > The performance impact of execution prevention should be negligible > because once configured the hypervisor do nothing except catch > illegitimate access attempts. Yes, if you are using the static kernel only and not considering the other dynamic patching features like explained. They need to be thought upon differently to reduce the likely impact. > > >> Production kernels do have lot of tracepoints and we use it as feature >> in the GKI kernel for the vendor hooks implementation and in those cases >> every vendor driver is a module. > > As explained in this section, dynamic kernel modifications such as > tracepoints or modules are not currently supported by this patch series. > Handling tracepoints is possible but requires more work to define and > check legitimate changes. This proposal is still useful for static > kernels though. > > >> Separate VM further fragments this >> design and delegates more of it to proprietary solutions? > > What do you mean? KVM is not a proprietary solution. Ah, I was referring the VBS Windows VM mentioned in the above text. Is it open-source? The reference of VM (or dedicated VM) didn't mention that VM itself will be open-source running Linux kernel. > > For dynamic checks, this would require code not run by KVM itself, but > either the VMM or a dedicated VM. In this case, the dynamic > authentication code could come from the guest VM or from the VMM itself. > In the former case, it is more challenging from a security point of view > but doesn't rely on external (proprietary) solution. In the latter case, > open-source VMMs should implement the specification to provide the > required service (e.g. check kernel module signature). > > The goal of the common API layer provided by this RFC is to share code > as much as possible between different hypervisor backends. > > >> >> Do you have any performance numbers w/ current RFC? > > No, but the only hypervisor performance impact is at boot time and > should be negligible. I'll try to get some numbers for the > hardware-enforcement impact, but it should be negligible too. Thanks. Please share the data once you have it ready. ---Trilok Soni
On Thu, 2023-05-25 at 09:07 -0700, Sean Christopherson wrote: > On Thu, May 25, 2023, Rick P Edgecombe wrote: > > I wonder if it might be a good idea to POC the guest side before > > settling on the KVM interface. Then you can also look at the whole > > thing and judge how much usage it would get for the different > > options > > of restrictions. > > As I said earlier[*], IMO the control plane logic needs to live in > host userspace. > I think any attempt to have KVM providen anything but the low level > plumbing will > suffer the same fate as CR4 pinning and XO memory. Iterating on an > imperfect > solution to incremently improve security is far, far easier to do in > userspace, > and far more likely to get merged. > > [*] https://lore.kernel.org/all/ZFUyhPuhtMbYdJ76@google.com Sure, I should have put it more generally. I just meant people are not going to want to maintain host-based features that guests can't effectively use. My takeaway from the CR pinning was that the guest kernel integration was surprisingly tricky due to the one-way nature of the interface. XO was more flexible than CR pinning in that respect, because the guest could turn it off (and indeed, in the XO kernel text patches it had to do this a lot).
[Side topic] Would folks be interested in a Linux Plumbers Conference MC on this topic generally, across different hypervisors, VMMs, and architectures? If so, please let me know who the key folk would be and we can try writing up an MC proposal.
On 25/05/2023 15:59, Mickaël Salaün wrote: > > On 25/05/2023 00:20, Edgecombe, Rick P wrote: >> On Fri, 2023-05-05 at 17:20 +0200, Mickaël Salaün wrote: >>> # How does it work? >>> >>> This implementation mainly leverages KVM capabilities to control the >>> Second >>> Layer Address Translation (or the Two Dimensional Paging e.g., >>> Intel's EPT or >>> AMD's RVI/NPT) and Mode Based Execution Control (Intel's MBEC) >>> introduced with >>> the Kaby Lake (7th generation) architecture. This allows to set >>> permissions on >>> memory pages in a complementary way to the guest kernel's managed >>> memory >>> permissions. Once these permissions are set, they are locked and >>> there is no >>> way back. >>> >>> A first KVM_HC_LOCK_MEM_PAGE_RANGES hypercall enables the guest >>> kernel to lock >>> a set of its memory page ranges with either the HEKI_ATTR_MEM_NOWRITE >>> or the >>> HEKI_ATTR_MEM_EXEC attribute. The first one denies write access to a >>> specific >>> set of pages (allow-list approach), and the second only allows kernel >>> execution >>> for a set of pages (deny-list approach). >>> >>> The current implementation sets the whole kernel's .rodata (i.e., any >>> const or >>> __ro_after_init variables, which includes critical security data such >>> as LSM >>> parameters) and .text sections as non-writable, and the .text section >>> is the >>> only one where kernel execution is allowed. This is possible thanks >>> to the new >>> MBEC support also brough by this series (otherwise the vDSO would >>> have to be >>> executable). Thanks to this hardware support (VT-x, EPT and MBEC), >>> the >>> performance impact of such guest protection is negligible. >>> >>> The second KVM_HC_LOCK_CR_UPDATE hypercall enables guests to pin some >>> of its >>> CPU control register flags (e.g., X86_CR0_WP, X86_CR4_SMEP, >>> X86_CR4_SMAP), >>> which is another complementary hardening mechanism. >>> >>> Heki can be enabled with the heki=1 boot command argument. >>> >>> >> >> Can the guest kernel ask the host VMM's emulated devices to DMA into >> the protected data? It should go through the host userspace mappings I >> think, which don't care about EPT permissions. Or did I miss where you >> are protecting that another way? There are a lot of easy ways to ask >> the host to write to guest memory that don't involve the EPT. You >> probably need to protect the host userspace mappings, and also the >> places in KVM that kmap a GPA provided by the guest. > > Good point, I'll check this confused deputy attack. Extended KVM > protections should indeed handle all ways to map guests' memory. I'm > wondering if current VMMs would gracefully handle such new restrictions > though. I guess the host could map arbitrary data to the guest, so that need to be handled, but how could the VMM (not the host kernel) bypass/update EPT initially used for the guest (and potentially later mapped to the host)?
On 25/05/2023 17:52, Edgecombe, Rick P wrote: > On Thu, 2023-05-25 at 15:59 +0200, Mickaël Salaün wrote: > [ snip ] > >>> The kernel often creates writable aliases in order to write to >>> protected data (kernel text, etc). Some of this is done right as >>> text >>> is being first written out (alternatives for example), and some >>> happens >>> way later (jump labels, etc). So for verification, I wonder what >>> stage >>> you would be verifying? If you want to verify the end state, you >>> would >>> have to maintain knowledge in the verifier of all the touch-ups the >>> kernel does. I think it would get very tricky. >> >> For now, in the static kernel case, all rodata and text GPA is >> restricted, so aliasing such memory in a writable way before or after >> the KVM enforcement would still restrict write access to this memory, >> which could be an issue but not a security one. Do you have such >> examples in mind? >> > > On x86, look at all the callers of the text_poke() family. In > arch/x86/include/asm/text-patching.h. OK, thanks! > >> >>> >>> It also seems it will be a decent ask for the guest kernel to keep >>> track of GPA permissions as well as normal virtual memory >>> pemirssions, >>> if this thing is not widely used. >> >> This would indeed be required to properly handle the dynamic cases. >> >> >>> >>> So I wondering if you could go in two directions with this: >>> 1. Make this a feature only for super locked down kernels (no >>> modules, >>> etc). Forbid any configurations that might modify text. But eBPF is >>> used for seccomp, so you might be turning off some security >>> protections >>> to get this. >> >> Good idea. For "super locked down kernels" :) , we should disable all >> kernel executable changes with the related kernel build configuration >> (e.g. eBPF JIT, kernel module, kprobes…) to make sure there is no >> such >> legitimate access. This looks like an acceptable initial feature. > > How many users do you think will want this protection but not > protections that would have to be disabled? The main one that came to > mind for me is cBPF seccomp stuff. > > But also, the alternative to JITing cBPF is the eBPF interpreter which > AFAIU is considered a juicy enough target for speculative attacks that > they created an option to compile it out. And leaving an interpreter in > the kernel means any data could be "executed" in the normal non- > speculative scenario, kind of working around the hypervisor executable > protections. Dropping e/cBPF entirely would be an option, but then I > wonder how many users you have left. Hopefully that is all correct, > it's hard to keep track with the pace of BPF development. seccomp-bpf doesn't rely on JIT, so it is not an issue. For eBPF, JIT is optional, but other text changes may be required according to the eBPF program type (e.g. using kprobes). > > I wonder if it might be a good idea to POC the guest side before > settling on the KVM interface. Then you can also look at the whole > thing and judge how much usage it would get for the different options > of restrictions. The next step is to handle dynamic permissions, but it will be easier to first implement that in KVM itself (which already has the required authentication code). The current interface may be flexible enough though, only new attribute flags should be required (and potentially an async mode). Anyway, this will enable to look at the whole thing. > >> >> >>> 2. Loosen the rules to allow the protections to not be so one-way >>> enable. Get less security, but used more widely. >> >> This is our goal. I think both static and dynamic cases are >> legitimate >> and have value according to the level of security sought. This should >> be >> a build-time configuration. > > Yea, the proper way to do this is probably to move all text handling > stuff into a separate domain of some sort, like you mentioned > elsewhere. It would be quite a job. Not necessarily to move this code, but to make sure that the changes are legitimate (e.g. text signatures, legitimate addresses). This doesn't need to be perfect but it should improve the current state by increasing the cost of attacks.
On 25/05/2023 20:34, Trilok Soni wrote: > On 5/25/2023 6:25 AM, Mickaël Salaün wrote: >> >> On 24/05/2023 23:04, Trilok Soni wrote: >>> On 5/5/2023 8:20 AM, Mickaël Salaün wrote: >>>> Hi, >>>> >>>> This patch series is a proof-of-concept that implements new KVM features >>>> (extended page tracking, MBEC support, CR pinning) and defines a new >>>> API to >>>> protect guest VMs. No VMM (e.g., Qemu) modification is required. >>>> >>>> The main idea being that kernel self-protection mechanisms should be >>>> delegated >>>> to a more privileged part of the system, hence the hypervisor. It is >>>> still the >>>> role of the guest kernel to request such restrictions according to its >>> >>> Only for the guest kernel images here? Why not for the host OS kernel? >> >> As explained in the Future work section, protecting the host would be >> useful, but that doesn't really fit with the KVM model. The Protected >> KVM project is a first step to help in this direction [11]. >> >> In a nutshell, KVM is close to a type-2 hypervisor, and the host kernel >> is also part of the hypervisor. >> >> >>> Embedded devices w/ Android you have mentioned below supports the host >>> OS as well it seems, right? >> >> What do you mean? > > I think you have answered this above w/ pKVM and I was referring the > host protection as well w/ Heki. The link/references below refers to the > Android OS it seems and not guest VM. > >> >> >>> >>> Do we suggest that all the functionalities should be implemented in the >>> Hypervisor (NS-EL2 for ARM) or even at Secure EL like Secure-EL1 (ARM). >> >> KVM runs in EL2. TrustZone is mainly used to enforce DRM, which means >> that we may not control the related code. >> >> This patch series is dedicated to hypervisor-enforced kernel integrity, >> then KVM. >> >>> >>> I am hoping that whatever we suggest the interface here from the Guest >>> to the Hypervisor becomes the ABI right? >> >> Yes, hypercalls are part of the KVM ABI. > > Sure. I just hope that they are extensible enough to support for other > Hypervisors too. I am not sure if they are on this list like ACRN / Xen > and see if it fits their need too. KVM, Hyper-V and Xen mailing lists are CCed. The KVM hypercalls are specific to KVM, but this patch series also include a common guest API intended to be used with all hypervisors. > > Is there any other Hypervisor you plan to test this feature as well? We're also working on Hyper-V. > >> >>> >>> >>>> >>>> # Current limitations >>>> >>>> The main limitation of this patch series is the statically enforced >>>> permissions. This is not an issue for kernels without module but this >>>> needs to >>>> be addressed. Mechanisms that dynamically impact kernel executable >>>> memory are >>>> not handled for now (e.g., kernel modules, tracepoints, eBPF JIT), >>>> and such >>>> code will need to be authenticated. Because the hypervisor is highly >>>> privileged and critical to the security of all the VMs, we don't want to >>>> implement a code authentication mechanism in the hypervisor itself >>>> but delegate >>>> this verification to something much less privileged. We are thinking >>>> of two >>>> ways to solve this: implement this verification in the VMM or spawn a >>>> dedicated >>>> special VM (similar to Windows's VBS). There are pros on cons to each >>>> approach: >>>> complexity, verification code ownership (guest's or VMM's), access to >>>> guest >>>> memory (i.e., confidential computing). >>> >>> Do you foresee the performance regressions due to lot of tracking here? >> >> The performance impact of execution prevention should be negligible >> because once configured the hypervisor do nothing except catch >> illegitimate access attempts. > > Yes, if you are using the static kernel only and not considering the > other dynamic patching features like explained. They need to be thought > upon differently to reduce the likely impact. What do you mean? We plan to support dynamic code, and performance is of course part of the requirement. > >> >> >>> Production kernels do have lot of tracepoints and we use it as feature >>> in the GKI kernel for the vendor hooks implementation and in those cases >>> every vendor driver is a module. >> >> As explained in this section, dynamic kernel modifications such as >> tracepoints or modules are not currently supported by this patch series. >> Handling tracepoints is possible but requires more work to define and >> check legitimate changes. This proposal is still useful for static >> kernels though. >> >> >>> Separate VM further fragments this >>> design and delegates more of it to proprietary solutions? >> >> What do you mean? KVM is not a proprietary solution. > > Ah, I was referring the VBS Windows VM mentioned in the above text. Is > it open-source? The reference of VM (or dedicated VM) didn't mention > that VM itself will be open-source running Linux kernel. This patch series is dedicated to KVM. Windows VBS was only mentioned as a comparable (but much more advanced) set of features. Everything required to use this new KVM features is and will be open-source. There is nothing to worry about licensing, the goal is to make it widely and freely available to protect users. > >> >> For dynamic checks, this would require code not run by KVM itself, but >> either the VMM or a dedicated VM. In this case, the dynamic >> authentication code could come from the guest VM or from the VMM itself. >> In the former case, it is more challenging from a security point of view >> but doesn't rely on external (proprietary) solution. In the latter case, >> open-source VMMs should implement the specification to provide the >> required service (e.g. check kernel module signature). >> >> The goal of the common API layer provided by this RFC is to share code >> as much as possible between different hypervisor backends. >> >> >>> >>> Do you have any performance numbers w/ current RFC? >> >> No, but the only hypervisor performance impact is at boot time and >> should be negligible. I'll try to get some numbers for the >> hardware-enforcement impact, but it should be negligible too. > > Thanks. Please share the data once you have it ready. It's on my todo list, but again, that should not be an issue and I even doubt the difference to be measurable.
On Fri, 2023-05-26 at 17:22 +0200, Mickaël Salaün wrote: > > > Can the guest kernel ask the host VMM's emulated devices to DMA > > > into > > > the protected data? It should go through the host userspace > > > mappings I > > > think, which don't care about EPT permissions. Or did I miss > > > where you > > > are protecting that another way? There are a lot of easy ways to > > > ask > > > the host to write to guest memory that don't involve the EPT. You > > > probably need to protect the host userspace mappings, and also > > > the > > > places in KVM that kmap a GPA provided by the guest. > > > > Good point, I'll check this confused deputy attack. Extended KVM > > protections should indeed handle all ways to map guests' memory. > > I'm > > wondering if current VMMs would gracefully handle such new > > restrictions > > though. > > I guess the host could map arbitrary data to the guest, so that need > to > be handled, but how could the VMM (not the host kernel) bypass/update > EPT initially used for the guest (and potentially later mapped to the > host)? Well traditionally both QEMU and KVM accessed guest memory via host mappings instead of the EPT. So I'm wondering what is stopping the guest from passing a protected gfn when setting up the DMA, and QEMU being enticed to write to it? The emulator as well would use these host userspace mappings and not consult the EPT IIRC. I think Sean was suggesting host userspace should be more involved in this process, so perhaps it could protect its own alias of the protected memory, for example mprotect() it as read-only. There is (was?) some KVM PV features that accessed guest memory via the host direct map as well. I would think mprotect() should protect this at the get_user_pages() stage, but it looks like the details have changed since I last understood it.
On 31/05/2023 22:24, Sean Christopherson wrote: > On Tue, May 30, 2023, Rick P Edgecombe wrote: >> On Fri, 2023-05-26 at 17:22 +0200, Micka�l Sala�n wrote: >>>>> Can the guest kernel ask the host VMM's emulated devices to DMA into >>>>> the protected data? It should go through the host userspace mappings I >>>>> think, which don't care about EPT permissions. Or did I miss where you >>>>> are protecting that another way? There are a lot of easy ways to ask >>>>> the host to write to guest memory that don't involve the EPT. You >>>>> probably need to protect the host userspace mappings, and also the >>>>> places in KVM that kmap a GPA provided by the guest. >>>> >>>> Good point, I'll check this confused deputy attack. Extended KVM >>>> protections should indeed handle all ways to map guests' memory. I'm >>>> wondering if current VMMs would gracefully handle such new restrictions >>>> though. >>> >>> I guess the host could map arbitrary data to the guest, so that need to be >>> handled, but how could the VMM (not the host kernel) bypass/update EPT >>> initially used for the guest (and potentially later mapped to the host)? >> >> Well traditionally both QEMU and KVM accessed guest memory via host >> mappings instead of the EPT.�So I'm wondering what is stopping the >> guest from passing a protected gfn when setting up the DMA, and QEMU >> being enticed to write to it? The emulator as well would use these host >> userspace mappings and not consult the EPT IIRC. >> >> I think Sean was suggesting host userspace should be more involved in >> this process, so perhaps it could protect its own alias of the >> protected memory, for example mprotect() it as read-only. > > Ya, though "suggesting" is really "demanding, unless someone provides super strong > justification for handling this directly in KVM". It's basically the same argument > that led to Linux Security Modules: I'm all for KVM providing the framework and > plumbing, but I don't want KVM to get involved in defining policy, thread models, etc. I agree that KVM should not provide its own policy but only the building blocks to enforce one. There is two complementary points: - policy definition by the guest, provided to KVM and the host; - policy enforcement by KVM and the host. A potential extension of this framework could be to enable the host to define it's own policy for guests, but this would be a different threat model. To avoid too much latency because of the host being involved in policy enforcement, I'd like to explore an asynchronous approach that would especially fit well for dynamic restrictions.