libvirt驱动程序启动AMD SEV加密实例

https://blueprints.launchpad.net/nova/+spec/amd-sev-libvirt-support

本文档提出nova的libvirt驱动程序支持启动使用AMD的SEV(安全加密虚拟化)技术加密的KVM实例所需的工作。

问题描述

虽然数据通常在存储到磁盘时进行加密,但它以明文形式存储在DRAM中。这可能使数据容易受到未经授权的管理员或软件窥探,或通过硬件探测。新的非易失性存储器技术(NVDIMM)加剧了这个问题,因为NVDIMM芯片可以从系统中物理移除,数据保持完整,类似于硬盘驱动器。如果没有加密,任何存储的信息,例如敏感数据、密码或密钥都可能轻易被泄露。

AMD的SEV提供了一种VM保护技术,可以透明地使用唯一密钥加密每个VM的内存。它还可以计算内存内容的签名,可以将其发送给VM的所有者作为证明,证明固件已正确加密了内存。SEV特别适用于云计算,因为它能够减少VM需要对主机系统的hypervisor和管理员的信任程度。

用例

  1. 作为云管理员,为了让我的用户对正在运行的实例的安全性更有信心,我希望提供一个包含SEV特定必需特征的额外规格的风味,这将允许用户启动具有该风味的实例,以确保他们的实例在启用SEV加密的SEV功能计算主机上运行。

  2. 作为云用户,为了不必信任我的云运营商来保护我的密钥,我希望能够启动启用SEV功能的VM实例。

提议的变更

对于Stein,目标是实现一个最小但功能性的实现,以满足上述用例。建议初始开发和测试包括以下交付成果

  • 添加对主机SEV功能的支持检测。需要逻辑来检查硬件和软件hypervisor堆栈的各个层是否具有SEV功能。

    • libvirt virConnectGetDomainCapabilities() API调用的响应中存在的以下XML 表明QEMU和AMD安全处理器(AMD-SP)都支持SEV功能

      <domainCapabilities>
        ...
        <features>
          ...
          <sev supported='yes'/>
            ...
          </sev>
        </features>
      </domainCapabilities>
      

      这种面向功能的检查应该可以避免驱动程序中任何版本检查的需求。

    • /sys/module/kvm_amd/parameters/sev 的值应为 1,以指示内核已启用SEV功能。这应该可以被任何用户读取(即,即使是非root用户)。

    请注意,需要进行这两个检查,因为第一个检查的存在并不意味着第二个检查的存在。

  • 支持一个标准特征,该特征将根据上述逻辑自动检测每个计算主机。这很可能被称为 HW_CPU_AMD_SEV 或类似名称,作为 现有CPU特征映射的扩展。

  • 当风味中存在此标准特征时,它将指示libvirt驱动程序在guest的domain定义中包含额外的XML,以确保以下内容

    • 已启用SEV安全。

    • 启动磁盘不能是 virtio-blk(由于与bounce buffer相关的资源限制)。

    • VM使用machine type q35 和通过OVMF的UEFI。(q35 是必需的,以便将所有virtio设备绑定到PCIe桥,以便它们使用virtio 1.0,而不是 virtio 0.9,因为QEMU的 iommu_platform 功能仅在virtio 1.0中添加。)

    • 所有virtio设备的 iommu 属性为 on。尽管名称如此,这并不要求guest或主机具有IOMMU设备,而仅仅启用virtio标志,指示应使用虚拟化DMA。这与SEV代码相关联,以处理内存加密/解密,并防止IO缓冲区在主机和guest之间共享。

      DMA将通过bounce buffer,因此与非SEV guest相比,预计会有一些开销。

      (注意:virtio-net设备队列未加密。)

    • QEMU分配的所有内存区域必须被pinned,这样它们就不能被交换到磁盘。可以通过在domain的XML的 <memtune> 部分设置硬内存限制来实现 <hard_limit>。这反映对额外内存的需求;它仅需要为了实现内存pinned。

      另一种pinned内存的方法是通过引导时设置 hw:mem_page_size=large 属性,启用 hugepages,设置在风味或镜像上,尽管这些具有操作员或用户需要记住一个额外细节的缺点,并且可能需要对风味或镜像进行不必要的复制。

      请注意,这种内存pinned预计是一个临时要求;最新的固件已经支持页面复制(如 AMD SEV-KM API Specification 中记录的 COPY API),因此当OS开始支持页面移动或页面迁移命令时,将不再需要它。

      基于QEMU的工具化,每个VM的限制应按以下方式计算和核算

      内存区域类型

      大小

      核算机制

      VM RAM

      由风味设置

      放置服务

      视频内存

      由风味/镜像设置

      放置服务

      UEFI ROM

      4096KB

      reserved_host_memory_mb

      UEFI var store (pflash)

      4096KB

      reserved_host_memory_mb

      pc.rom

      128KB

      reserved_host_memory_mb

      isa-bios

      128KB

      reserved_host_memory_mb

      ACPI 表

      2384KB

      reserved_host_memory_mb

为了安全起见,建议包含至少256KB的额外填充,因为ROM大小偶尔会发生变化。例如,此处ROMs / ACPI表所需的总共10832KB应向上舍入到16MB。

前两个值预计会因VM而异,并且已经由放置服务动态核算。

其余的传统上(即,对于非SEV实例)通过nova的内存池通过 reserved_host_memory_mb 配置选项核算,这不需要更改。但是,虽然产生的开销与非SEV实例所需相同,但正确设置硬限制在pinned内存时非常重要;如果太低,VM将被杀死,如果太高,则存在主机OOM killer被调用的风险,或者最坏的情况是,主机崩溃,因为它无法回收guest使用的内存。

因此,实施一个额外的检查可能是明智的,该检查将此预留要求乘以实例数,并确保它不会导致主机内存使用量超过可用量。这最初可以作为驱动程序中的检查来实现,但无论如何,必须记录避免这种过度承诺的方法,以便运营商可以正确地规划内存使用情况并相应地配置其云。

例如,假设一个4GB的VM

<domain type='kvm'>
  <os>
    <type arch='x86_64' machine='pc-q35-2.11'>hvm</type>
    <loader readonly='yes' type='pflash'>/usr/share/qemu/ovmf-x86_64-ms-4m-code.bin</loader>
    <nvram>/var/lib/libvirt/qemu/nvram/sles15-sev-guest_VARS.fd</nvram>
    <boot dev='hd'/>
  </os>
  <launchSecurity type='sev'>
    <cbitpos>47</cbitpos>
    <reducedPhysBits>1</reducedPhysBits>
    <policy>0x0037</policy>
  </launchSecurity>
  <memtune>
    <hard_limit unit='KiB'>4718592</hard_limit>
    ...
  </memtune>
  <devices>
    <rng model='virtio'>
      <driver iommu='on'/>
      ...
    </rng>
    <memballoon model='virtio'>
      <driver iommu='on' />
      ...
    </memballoon>
    ...
    <video>
      <model type='qxl' ram='65536' vram='65536' vgamem='16384' heads='1'  primary='yes'/>
    </video>
    ...
  </devices>
  ...
</domain>

如果 hw_machine_type 指定的镜像无法满足SEV的Q35 machine type要求(如果存在),或者 nova.conf 中的 libvirt.hw_machine_type (默认未设置) 的值,则应引发异常,以便构建失败。

cbitposreducedPhysBits 取决于处理器系列,可以通过从 domain capabilities 中的 sev 元素获得。

policy 允许特定的SEV策略,如 AMD SEV-KM API Specification 中所述。最初,该策略将被硬编码,并且不能被云租户或云运营商修改。该策略将是

#define SEV_POLICY_NORM \
    ((SEV_POLICY)(SEV_POLICY_NODBG|SEV_POLICY_NOKS| \
      SEV_POLICY_ES|SEV_POLICY_DOMAIN|SEV_POLICY_SEV))

这相当于 0x0037。将来,当QEMU和libvirt中添加支持时,这将允许实时迁移到同一集群中的其他机器 [1](即,具有相同的OCA证书)并使用SEV-ES,但不会允许其他guest或hypervisor直接检查内存。如果上游对SEV-ES的支持没有及时到来,那么SEV-ES将不会包含在策略中。

可以提交未来的规范,以通过额外的规格或镜像属性使此可配置。

作为参考,AMDSEV GitHub存储库提供了 一个完整的示例,其中启用了 libvirt的SEV选项的domain的XML定义。

上述工作总和也可能意味着具有属性 trait:HW_CPU_AMD_SEV=required 的镜像也会影响实例启动的过程。

限制

以下限制将在硬件、固件和各种软件层获得新功能时在将来删除

  • SEV加密的VM目前无法实时迁移或挂起,因此也无法恢复。如前所述,支持即将到来。但是,这意味着在短期内,SEV的使用将对计算节点维护产生影响,因为SEV加密的实例需要在迁移掉SEV主机之前完全关闭。

  • SEV加密的VM不能包含直接可访问的主机设备(PCI直通)。因此,例如,mdev vGPU支持目前无法工作。但是,基于vhost-user的技术应该可以正常工作。

  • SEV加密的VM的启动磁盘不能是 virtio-blk。使用 virtio-scsi 或SATA作为启动磁盘可以正常工作,就像 virtio-blk 用于非启动磁盘一样。

预计以下限制将是长期的

  • 在加密的虚拟机中运行的操作系统必须包含SEV支持。

  • q35 machine type不提供IDE控制器,因此不支持IDE设备。特别是,这意味着nova的libvirt驱动程序的当前默认行为是在x86_64架构上将config drive作为 iso9660 IDE CD-ROM设备附加,将不起作用。有两种潜在的解决方法

    1. nova.conf 中的 CONF.config_drive_format 从其默认值 iso9660 更改为 vfat。这将导致使用 virtio。但是,此每主机设置可能会破坏期望config drive为IDE CD-ROM的旧版OS的镜像。它也不会处理其他CD-ROM设备。

    2. 将(很大程度上 未记录)镜像属性 hw_cdrom_bus 设置为 virtio,建议将其作为 ide 的替代品,并将 hw_scsi_model 设置为 virtio-scsi

    一些潜在的更清洁的长期解决方案需要代码更改,建议作为下文 工作项 部分中的拉伸目标。

为了消除任何疑问,以下操作预计在使用SEV加密时不会受到限制

  • 冷迁移或搁置,因为它们会在关闭VM之前进行操作,此时没有加密的内存(尽管这可能会改变,因为目前正在进行支持 PMEM 的工作)

  • 快照,因为它只快照磁盘

  • 疏散,因为它只有在假定VM已死或有充分理由杀死它时才会启动

  • 附加任何卷,只要它们不需要通过IDE总线附加

  • 使用spice / VNC / serial / RDP控制台

  • VM guest虚拟NUMA(也称为vNUMA)

备选方案

  1. 而不是立即实现自动检测SEV功能主机并提供通过新标准特征(HW_CPU_AMD_SEV 或类似名称)访问这些主机的功能,

    这将具有稍微减少达到功能原型所需的工作量的优点,并让运营商可以选择在哪些计算主机上允许SEV。但相反,它具有将硬编码引用合并到nova的 master 分支的缺点,需要运营商进行额外工作,并冒着将无法SEV(由于缺少硬件或软件支持)的计算节点标记为SEV功能的风险,这很可能导致VM启动失败。

  2. 而不是使用单个特征来促进需要SEV的实例与SEV功能计算主机的匹配指示nova的libvirt驱动程序在引导时使用SEV,该特征可以仅用于将实例调度到SEV主机,并且可以使用额外的额外规格属性,例如 hw:sev_policy,以确保VM被定义和引导具有必要的额外的SEV特定的domain XML。

    但是,这将为定义SEV启用风味的管理员增加额外的摩擦,并且很难想象为什么有人会想要一个需要实例在SEV功能主机上运行的风味,而不同时利用这些主机的SEV功能。此外,虽然这仍然是一个布尔切换,但使用单个特征与 预先存在的上游协议 一致,该协议指定影响调度和配置的选项。

  3. 而不是使用标准特征,可以使用普通的风味额外规格来要求SEV功能;但是,据了解,这种方法不太可取,因为特征为某些virt驱动程序中的CPU特征提供一致的命名,并且查询特征是高效的

数据模型影响

将使用新的特征来表示SEV功能计算主机。

不需要新的数据对象或数据库模式更改。

REST API 影响

目前没有,但未来的工作可能需要扩展 REST API,以便用户可以验证硬件对内存加密正确性的证明。但是,如果这种扩展对多个 CPU 供应商的其它 virt 驱动程序没有用处,那么通过独立的 AMD 特定服务提供此功能可能更可取。

安全影响

此更改不会添加或处理任何秘密信息,除了当然是来宾 VM 加密内存中的数据。用于实现 SEV 的密钥被锁定在 AMD 硬件内部。硬件随机数生成器使用来自 NIST SP 800-90A 的 CTR_DRBG 结构,该结构未被发现存在任何后门。它使用 AES 计数器模式生成随机数。

SEV 保护 VM 的数据免受来自 VM 外部的攻击,包括 hypervisor 和其他 VM。试图欺骗 hypervisor 读取来自另一个 VM 的页面的攻击将不起作用,因为获得的数据将使用攻击者和 hypervisor 无法访问的密钥进行加密。SEV 通过使用所有者标记每个缓存行来保护缓存中的数据,从而防止 hypervisor 和其他 VM 读取缓存的数据。

SEV 不保护 VM 本身免受侧信道攻击或运行在 VM 中的软件上的攻击。保持 VM 及时更新补丁并正确配置 VM 上运行的软件非常重要。

这个最初的提议实现提供了一些保护,但显着缺少了云用户验证 SEV 可以通过 LAUNCH_MEASURE 固件调用提供的证明的能力。将来添加这种证明能力意味着需要对云管理员的信任度降低很多,因为 VM 将使用云用户通过受保护的通道提供给 SEV 固件的密钥进行加密和完整性保护。然后,云用户可以确定他们正在运行正确的镜像,内存确实已加密,并且他们正在运行具有 SEV 硬件的真实 AMD 平台,而不是设置用于窃取其数据的冒名平台。云用户可以在向 VM 提供其他密钥(例如存储解密密钥)之前验证所有这些。此规范是实现 SEV 可以提供的全部价值以防止云管理员访问云用户数据的过程中的第一步。

强烈建议 OpenStack 安全组 随时了解情况,并有机会审查工作的每个阶段,以帮助确保安全措施得到适当实施。

通知影响

可能需要访问实例正在运行加密的信息,例如,计费云提供商可能希望征收安全附加费,从而以加密实例与未加密实例不同的方式计费。但是,这不应立即影响通知,因为版本化通知中的实例有效负载具有 flavor 及其 extra specs,其中将定义 SEV 启用 trait。

如果指定 SEV trait 的是服务器支持的镜像而不是 flavor,则通知中只会包含镜像 UUID。消费者可以通过 UUID 查找镜像来检查是否存在 SEV trait,但这确实会打开一个潜在的竞争窗口,即在创建实例后镜像属性可能会发生变化。可以通过未来的工作来解决这个问题,该工作将包括在实例启动通知中包含镜像属性,或将镜像元数据存储在 instance_extra 中,就像目前 flavor 所做的那样。

其他最终用户影响

最终用户将通过 flavor extra specs 和镜像属性中的 traits 的现有机制来利用 SEV。稍后,添加对调度器提示的支持可能是有意义的(请参阅下面的 未来工作 部分)。

性能影响

预计不会对nova产生性能影响。

初步测试表明,启用 SEV 对 VM 的预期性能影响是适度的;根据特定的工作负载和测试,观察到 1% 到 6% 的降解。更多详细信息可以在 AMD 在 2017 年 Linux Security Summit 上关于 SEV-ES 的演示文稿 的幻灯片 4–6 中看到。

如果交换磁盘正在使用压缩,则可能需要更多的存储空间,因为加密 VM 的内存将无法压缩到更小的尺寸。

内存去重机制,例如 KSM(内核相同页合并),将被渲染无效。

其他部署者影响

为了让用户能够使用 SEV,操作员需要执行以下步骤

  • 将支持 SEV 的硬件作为 nova 计算主机部署。

  • 确保他们拥有适当配置的软件堆栈,以便各个层级都已准备好 SEV

    • kernel >= 4.16

    • QEMU >= 2.12

    • libvirt >= 4.5

    • ovmf >= commit 75b7aa9528bd 2018-07-06

最后,云管理员需要定义 SEV 启用的 flavor,如上所述,除非用户定义 SEV 启用的镜像就足够了。

开发人员影响

升级影响

实现

负责人

主要负责人

adam.spiers

其他贡献者

来自 SUSE 和 AMD 的各种开发人员

工作项

预计以下扩展序列,或类似序列,需要对 nova 的 libvirt 驱动程序进行修改

  1. 如上所述详细检测主机 SEV 功能。

  2. 为了提供 HW_CPU_AMD_SEV trait,使用新的 SEV 检测代码。

  3. 添加一个新的 nova.virt.libvirt.LibvirtConfigGuestFeatureSEV 类。

  4. 扩展 nova.virt.libvirt.LibvirtDriver._set_features(),以便在正在启动的 VM 的 flavor 中存在新的 trait 时,将所需的 XML 添加到 VM 的域定义中。

  5. 由于在主机之间进行实时迁移尚未(目前)支持

    防止 nova 实时迁移任何 SEV 加密的实例,或调整到不同的计算主机。或者,nova 可以捕获 QEMU 抛出的错误,该错误将通过 libvirt 传播,并适当处理它。如果它对操作员来说成为一个主要问题,我们可以稍后构建更高层次的检查。

  6. 同样,尝试暂停/恢复 SEV 加密的域目前也不受支持,因此应该防止这样做,或者捕获错误并处理它。

  7. (Stretch goal)采用以下建议的代码更改,以减少或消除 CD-ROM 设备(例如 config drive)在 x86 架构上使用 IDE 总线的情况

    1. 简单地将 x86 上 CD-ROM 的硬编码 IDE 总线使用情况更改为 scsi,以与所有其他 CPU 架构保持一致,因为似乎 ide 的使用仅由于遗留 x86 代码以及后来添加了对其他 CPU 架构的支持。 hw_cdrom_bus=ide 镜像属性可以在缺少 SCSI 支持的遗留镜像上覆盖此设置。

    2. 自动检测 VM 没有 IDE 控制器的情况,并自动切换到 scsivirtio-scsi

    3. 引入一个新的 nova.conf 选项,用于指定 CD-ROM 使用的默认总线。然后,默认值可以是 scsi(与其他 CPU 架构一致)或 virtiohw_cdrom_bus 覆盖所需时该值。这可能更具未来证明性,因为非常旧的机器类型的用途正在逐渐淘汰,尽管缺点是存在破坏遗留镜像的风险。

      如果存在使用此类遗留 x86 镜像很常见的云,则可以将选项设置为 ide,并且 hw_cdrom_bus=virtio 在需要 SEV(或任何其他原因)的新机器类型时覆盖它。虽然这可能不太可能需要一个新的配置选项。

此外,应编写文档,如 文档影响 部分所述。

未来工作

展望 Stein 之外,nova 的 SEV 支持还有许多额外的改进空间

  • 扩展 ComputeCapabilitiesFilter 调度器过滤器以支持调度器提示,以便可以为每个实例选择启用 SEV,从而无需操作员配置 SEV 特定 flavor 或镜像。

  • 如果用户有足够的需求,则可以通过 extra spec 或镜像属性使 SEV 策略可配置。

  • 提供一种机制,允许用户访问 SEV 的 LAUNCH_MEASURE 命令提供的证明测量结果,以便验证固件是否正确加密了来宾内存。例如,可以扩展 nova 的 API;但是,如果无法以适用于 virt 驱动程序/CPU 供应商的方式完成此操作,则可能超出 nova 的范围,需要替代方法,例如单独的 AMD 特定端点。

依赖项

测试

需要调整 fakelibvirt 测试驱动程序以模拟支持 SEV 的硬件。

需要扩展或添加相应的单元/功能测试,以涵盖

  • 检测支持 SEV 的硬件和软件,例如,作为 nova.tests.functional.libvirt.test_report_cpu_traits.LibvirtReportTraitsTests 的扩展。

  • nova.tests.unit.virt.libvirt.test_config中包含额外的SEV特定libvirt domain XML配置的trait的使用

Nova 代码或其测试中可能存在由于面向 Intel CPU 的硬编码假设而导致的问题。

如果可用 SEV 硬件,则可以在 gate 或通过第三方 CI 中包含 Tempest 测试。

文档影响

  • 应在 Feature Support Matrix 中添加一个新条目,该条目引用新的 trait 并显示当前的 限制

  • 应更新 Configuration Guide 的 KVM 部分,其中包含有关如何设置支持 SEV 的 hypervisor 的详细信息。同样,提及当前的 限制 也是明智的,包括对 config drive 配置的影响、计算主机维护、根据主机上同时运行的 SEV 来宾的预期最大数量正确计算 reserved_host_memory_mb 的需要,以及上述关于如何正确计算它的详细信息。

还应更新其他非nova文档

  • os-traits文档应在适当的地方进行扩展。

  • “Hardening the virtualization layers” 部分 Security Guide 将是描述提供和使用 SEV 功能的整个过程的理想位置。

参考资料

历史

修订

发布名称

描述

Stein

引入