mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git/
synced 2026-04-18 06:33:43 -04:00
Merge tag 'tsm-for-6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/devsec/tsm
Pull PCIe Link Encryption and Device Authentication from Dan Williams:
"New PCI infrastructure and one architecture implementation for PCIe
link encryption establishment via platform firmware services.
This work is the result of multiple vendors coming to consensus on
some core infrastructure (thanks Alexey, Yilun, and Aneesh!), and
three vendor implementations, although only one is included in this
pull. The PCI core changes have an ack from Bjorn, the crypto/ccp/
changes have an ack from Tom, and the iommu/amd/ changes have an ack
from Joerg.
PCIe link encryption is made possible by the soup of acronyms
mentioned in the shortlog below. Link Integrity and Data Encryption
(IDE) is a protocol for installing keys in the transmitter and
receiver at each end of a link. That protocol is transported over Data
Object Exchange (DOE) mailboxes using PCI configuration requests.
The aspect that makes this a "platform firmware service" is that the
key provisioning and protocol is coordinated through a Trusted
Execution Envrionment (TEE) Security Manager (TSM). That is either
firmware running in a coprocessor (AMD SEV-TIO), or quasi-hypervisor
software (Intel TDX Connect / ARM CCA) running in a protected CPU
mode.
Now, the only reason to ask a TSM to run this protocol and install the
keys rather than have a Linux driver do the same is so that later, a
confidential VM can ask the TSM directly "can you certify this
device?".
That precludes host Linux from provisioning its own keys, because host
Linux is outside the trust domain for the VM. It also turns out that
all architectures, save for one, do not publish a mechanism for an OS
to establish keys in the root port. So "TSM-established link
encryption" is the only cross-architecture path for this capability
for the foreseeable future.
This unblocks the other arch implementations to follow in v6.20/v7.0,
once they clear some other dependencies, and it unblocks the next
phase of work to implement the end-to-end flow of confidential device
assignment. The PCIe specification calls this end-to-end flow Trusted
Execution Environment (TEE) Device Interface Security Protocol
(TDISP).
In the meantime, Linux gets a link encryption facility which has
practical benefits along the same lines as memory encryption. It
authenticates devices via certificates and may protect against
interposer attacks trying to capture clear-text PCIe traffic.
Summary:
- Introduce the PCI/TSM core for the coordination of device
authentication, link encryption and establishment (IDE), and later
management of the device security operational states (TDISP).
Notify the new TSM core layer of PCI device arrival and departure
- Add a low level TSM driver for the link encryption establishment
capabilities of the AMD SEV-TIO architecture
- Add a library of helpers TSM drivers to use for IDE establishment
and the DOE transport
- Add skeleton support for 'bind' and 'guest_request' operations in
support of TDISP"
* tag 'tsm-for-6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/devsec/tsm: (23 commits)
crypto/ccp: Fix CONFIG_PCI=n build
virt: Fix Kconfig warning when selecting TSM without VIRT_DRIVERS
crypto/ccp: Implement SEV-TIO PCIe IDE (phase1)
iommu/amd: Report SEV-TIO support
psp-sev: Assign numbers to all status codes and add new
ccp: Make snp_reclaim_pages and __sev_do_cmd_locked public
PCI/TSM: Add 'dsm' and 'bound' attributes for dependent functions
PCI/TSM: Add pci_tsm_guest_req() for managing TDIs
PCI/TSM: Add pci_tsm_bind() helper for instantiating TDIs
PCI/IDE: Initialize an ID for all IDE streams
PCI/IDE: Add Address Association Register setup for downstream MMIO
resource: Introduce resource_assigned() for discerning active resources
PCI/TSM: Drop stub for pci_tsm_doe_transfer()
drivers/virt: Drop VIRT_DRIVERS build dependency
PCI/TSM: Report active IDE streams
PCI/IDE: Report available IDE streams
PCI/IDE: Add IDE establishment helpers
PCI: Establish document for PCI host bridge sysfs attributes
PCI: Add PCIe Device 3 Extended Capability enumeration
PCI/TSM: Establish Secure Sessions and Link Encryption
...
This commit is contained in:
@@ -75,6 +75,14 @@ static bool psp_init_on_probe = true;
|
||||
module_param(psp_init_on_probe, bool, 0444);
|
||||
MODULE_PARM_DESC(psp_init_on_probe, " if true, the PSP will be initialized on module init. Else the PSP will be initialized on the first command requiring it");
|
||||
|
||||
#if IS_ENABLED(CONFIG_PCI_TSM)
|
||||
static bool sev_tio_enabled = true;
|
||||
module_param_named(tio, sev_tio_enabled, bool, 0444);
|
||||
MODULE_PARM_DESC(tio, "Enables TIO in SNP_INIT_EX");
|
||||
#else
|
||||
static const bool sev_tio_enabled = false;
|
||||
#endif
|
||||
|
||||
MODULE_FIRMWARE("amd/amd_sev_fam17h_model0xh.sbin"); /* 1st gen EPYC */
|
||||
MODULE_FIRMWARE("amd/amd_sev_fam17h_model3xh.sbin"); /* 2nd gen EPYC */
|
||||
MODULE_FIRMWARE("amd/amd_sev_fam19h_model0xh.sbin"); /* 3rd gen EPYC */
|
||||
@@ -251,7 +259,7 @@ static int sev_cmd_buffer_len(int cmd)
|
||||
case SEV_CMD_SNP_COMMIT: return sizeof(struct sev_data_snp_commit);
|
||||
case SEV_CMD_SNP_FEATURE_INFO: return sizeof(struct sev_data_snp_feature_info);
|
||||
case SEV_CMD_SNP_VLEK_LOAD: return sizeof(struct sev_user_data_snp_vlek_load);
|
||||
default: return 0;
|
||||
default: return sev_tio_cmd_buffer_len(cmd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -380,13 +388,7 @@ static int sev_write_init_ex_file_if_required(int cmd_id)
|
||||
return sev_write_init_ex_file();
|
||||
}
|
||||
|
||||
/*
|
||||
* snp_reclaim_pages() needs __sev_do_cmd_locked(), and __sev_do_cmd_locked()
|
||||
* needs snp_reclaim_pages(), so a forward declaration is needed.
|
||||
*/
|
||||
static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret);
|
||||
|
||||
static int snp_reclaim_pages(unsigned long paddr, unsigned int npages, bool locked)
|
||||
int snp_reclaim_pages(unsigned long paddr, unsigned int npages, bool locked)
|
||||
{
|
||||
int ret, err, i;
|
||||
|
||||
@@ -420,6 +422,7 @@ cleanup:
|
||||
snp_leak_pages(__phys_to_pfn(paddr), npages - i);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snp_reclaim_pages);
|
||||
|
||||
static int rmp_mark_pages_firmware(unsigned long paddr, unsigned int npages, bool locked)
|
||||
{
|
||||
@@ -850,7 +853,7 @@ static int snp_reclaim_cmd_buf(int cmd, void *cmd_buf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret)
|
||||
int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret)
|
||||
{
|
||||
struct cmd_buf_desc desc_list[CMD_BUF_DESC_MAX] = {0};
|
||||
struct psp_device *psp = psp_master;
|
||||
@@ -1392,6 +1395,8 @@ static int __sev_snp_init_locked(int *error, unsigned int max_snp_asid)
|
||||
*
|
||||
*/
|
||||
if (sev_version_greater_or_equal(SNP_MIN_API_MAJOR, 52)) {
|
||||
bool tio_supp = !!(sev->snp_feat_info_0.ebx & SNP_SEV_TIO_SUPPORTED);
|
||||
|
||||
/*
|
||||
* Firmware checks that the pages containing the ranges enumerated
|
||||
* in the RANGES structure are either in the default page state or in the
|
||||
@@ -1432,6 +1437,17 @@ static int __sev_snp_init_locked(int *error, unsigned int max_snp_asid)
|
||||
data.init_rmp = 1;
|
||||
data.list_paddr_en = 1;
|
||||
data.list_paddr = __psp_pa(snp_range_list);
|
||||
|
||||
data.tio_en = tio_supp && sev_tio_enabled && amd_iommu_sev_tio_supported();
|
||||
|
||||
/*
|
||||
* When psp_init_on_probe is disabled, the userspace calling
|
||||
* SEV ioctl can inadvertently shut down SNP and SEV-TIO causing
|
||||
* unexpected state loss.
|
||||
*/
|
||||
if (data.tio_en && !psp_init_on_probe)
|
||||
dev_warn(sev->dev, "SEV-TIO as incompatible with psp_init_on_probe=0\n");
|
||||
|
||||
cmd = SEV_CMD_SNP_INIT_EX;
|
||||
} else {
|
||||
cmd = SEV_CMD_SNP_INIT;
|
||||
@@ -1469,7 +1485,8 @@ static int __sev_snp_init_locked(int *error, unsigned int max_snp_asid)
|
||||
|
||||
snp_hv_fixed_pages_state_update(sev, HV_FIXED);
|
||||
sev->snp_initialized = true;
|
||||
dev_dbg(sev->dev, "SEV-SNP firmware initialized\n");
|
||||
dev_dbg(sev->dev, "SEV-SNP firmware initialized, SEV-TIO is %s\n",
|
||||
data.tio_en ? "enabled" : "disabled");
|
||||
|
||||
dev_info(sev->dev, "SEV-SNP API:%d.%d build:%d\n", sev->api_major,
|
||||
sev->api_minor, sev->build);
|
||||
@@ -1477,6 +1494,23 @@ static int __sev_snp_init_locked(int *error, unsigned int max_snp_asid)
|
||||
atomic_notifier_chain_register(&panic_notifier_list,
|
||||
&snp_panic_notifier);
|
||||
|
||||
if (data.tio_en) {
|
||||
/*
|
||||
* This executes with the sev_cmd_mutex held so down the stack
|
||||
* snp_reclaim_pages(locked=false) might be needed (which is extremely
|
||||
* unlikely) but will cause a deadlock.
|
||||
* Instead of exporting __snp_alloc_firmware_pages(), allocate a page
|
||||
* for this one call here.
|
||||
*/
|
||||
void *tio_status = page_address(__snp_alloc_firmware_pages(
|
||||
GFP_KERNEL_ACCOUNT | __GFP_ZERO, 0, true));
|
||||
|
||||
if (tio_status) {
|
||||
sev_tsm_init_locked(sev, tio_status);
|
||||
__snp_free_firmware_pages(virt_to_page(tio_status), 0, true);
|
||||
}
|
||||
}
|
||||
|
||||
sev_es_tmr_size = SNP_TMR_SIZE;
|
||||
|
||||
return 0;
|
||||
@@ -2756,8 +2790,20 @@ static void __sev_firmware_shutdown(struct sev_device *sev, bool panic)
|
||||
|
||||
static void sev_firmware_shutdown(struct sev_device *sev)
|
||||
{
|
||||
/*
|
||||
* Calling without sev_cmd_mutex held as TSM will likely try disconnecting
|
||||
* IDE and this ends up calling sev_do_cmd() which locks sev_cmd_mutex.
|
||||
*/
|
||||
if (sev->tio_status)
|
||||
sev_tsm_uninit(sev);
|
||||
|
||||
mutex_lock(&sev_cmd_mutex);
|
||||
|
||||
__sev_firmware_shutdown(sev, false);
|
||||
|
||||
kfree(sev->tio_status);
|
||||
sev->tio_status = NULL;
|
||||
|
||||
mutex_unlock(&sev_cmd_mutex);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user