From 55a23e404af058e04acc3a50c18f34ace76cfd54 Mon Sep 17 00:00:00 2001 From: Salvatore Bonaccorso Date: Sun, 5 May 2019 15:54:13 +0200 Subject: [PATCH] [amd64,arm64] vfio/type1: Limit DMA mappings per container (CVE-2019-3882) --- debian/changelog | 1 + ...pe1-Limit-DMA-mappings-per-container.patch | 94 +++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 96 insertions(+) create mode 100644 debian/patches/bugfix/all/vfio-type1-Limit-DMA-mappings-per-container.patch diff --git a/debian/changelog b/debian/changelog index 3b19e7a3d..2f44f8bce 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1117,6 +1117,7 @@ linux (4.19.37-1) UNRELEASED; urgency=medium * xen/pciback: Don't disable PCI_COMMAND on PCI device reset. (CVE-2015-8553) * [x86] Disable R3964 due to lack of security support + * [amd64,arm64] vfio/type1: Limit DMA mappings per container (CVE-2019-3882) [ Aurelien Jarno ] * [mips] Fix indirect syscall tracing & seccomp filtering for big endian diff --git a/debian/patches/bugfix/all/vfio-type1-Limit-DMA-mappings-per-container.patch b/debian/patches/bugfix/all/vfio-type1-Limit-DMA-mappings-per-container.patch new file mode 100644 index 000000000..6046e5e64 --- /dev/null +++ b/debian/patches/bugfix/all/vfio-type1-Limit-DMA-mappings-per-container.patch @@ -0,0 +1,94 @@ +From: Alex Williamson +Date: Wed, 3 Apr 2019 12:36:21 -0600 +Subject: vfio/type1: Limit DMA mappings per container +Origin: https://git.kernel.org/linus/492855939bdb59c6f947b0b5b44af9ad82b7e38c +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2019-3882 + +Memory backed DMA mappings are accounted against a user's locked +memory limit, including multiple mappings of the same memory. This +accounting bounds the number of such mappings that a user can create. +However, DMA mappings that are not backed by memory, such as DMA +mappings of device MMIO via mmaps, do not make use of page pinning +and therefore do not count against the user's locked memory limit. +These mappings still consume memory, but the memory is not well +associated to the process for the purpose of oom killing a task. + +To add bounding on this use case, we introduce a limit to the total +number of concurrent DMA mappings that a user is allowed to create. +This limit is exposed as a tunable module option where the default +value of 64K is expected to be well in excess of any reasonable use +case (a large virtual machine configuration would typically only make +use of tens of concurrent mappings). + +This fixes CVE-2019-3882. + +Reviewed-by: Eric Auger +Tested-by: Eric Auger +Reviewed-by: Peter Xu +Reviewed-by: Cornelia Huck +Signed-off-by: Alex Williamson +--- + drivers/vfio/vfio_iommu_type1.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c +index 73652e21efec..d0f731c9920a 100644 +--- a/drivers/vfio/vfio_iommu_type1.c ++++ b/drivers/vfio/vfio_iommu_type1.c +@@ -58,12 +58,18 @@ module_param_named(disable_hugepages, + MODULE_PARM_DESC(disable_hugepages, + "Disable VFIO IOMMU support for IOMMU hugepages."); + ++static unsigned int dma_entry_limit __read_mostly = U16_MAX; ++module_param_named(dma_entry_limit, dma_entry_limit, uint, 0644); ++MODULE_PARM_DESC(dma_entry_limit, ++ "Maximum number of user DMA mappings per container (65535)."); ++ + struct vfio_iommu { + struct list_head domain_list; + struct vfio_domain *external_domain; /* domain for external user */ + struct mutex lock; + struct rb_root dma_list; + struct blocking_notifier_head notifier; ++ unsigned int dma_avail; + bool v2; + bool nesting; + }; +@@ -836,6 +842,7 @@ static void vfio_remove_dma(struct vfio_iommu *iommu, struct vfio_dma *dma) + vfio_unlink_dma(iommu, dma); + put_task_struct(dma->task); + kfree(dma); ++ iommu->dma_avail++; + } + + static unsigned long vfio_pgsize_bitmap(struct vfio_iommu *iommu) +@@ -1081,12 +1088,18 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu, + goto out_unlock; + } + ++ if (!iommu->dma_avail) { ++ ret = -ENOSPC; ++ goto out_unlock; ++ } ++ + dma = kzalloc(sizeof(*dma), GFP_KERNEL); + if (!dma) { + ret = -ENOMEM; + goto out_unlock; + } + ++ iommu->dma_avail--; + dma->iova = iova; + dma->vaddr = vaddr; + dma->prot = prot; +@@ -1583,6 +1596,7 @@ static void *vfio_iommu_type1_open(unsigned long arg) + + INIT_LIST_HEAD(&iommu->domain_list); + iommu->dma_list = RB_ROOT; ++ iommu->dma_avail = dma_entry_limit; + mutex_init(&iommu->lock); + BLOCKING_INIT_NOTIFIER_HEAD(&iommu->notifier); + +-- +2.11.0 + diff --git a/debian/patches/series b/debian/patches/series index dcb83f1d9..cb13f13ba 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -161,6 +161,7 @@ features/all/db-mok-keyring/modsign-make-shash-allocation-failure-fatal.patch debian/i386-686-pae-pci-set-pci-nobios-by-default.patch bugfix/all/xen-pciback-Don-t-disable-PCI_COMMAND-on-PCI-device-.patch debian/ntfs-mark-it-as-broken.patch +bugfix/all/vfio-type1-Limit-DMA-mappings-per-container.patch # Fix exported symbol versions bugfix/all/module-disable-matching-missing-version-crc.patch