3fd5815
From mboxrd@z Thu Jan  1 00:00:00 1970
3fd5815
Return-Path: <SRS0=/BGd=SD=vger.kernel.org=linux-kernel-owner@kernel.org>
3fd5815
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
3fd5815
	aws-us-west-2-korg-lkml-1.web.codeaurora.org
3fd5815
X-Spam-Level: 
3fd5815
X-Spam-Status: No, score=-7.0 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS,
3fd5815
	INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_PASS autolearn=ham
3fd5815
	autolearn_force=no version=3.4.0
3fd5815
Received: from mail.kernel.org (mail.kernel.org [198.145.29.99])
3fd5815
	by smtp.lore.kernel.org (Postfix) with ESMTP id 5BCBAC43381
3fd5815
	for <linux-kernel@archiver.kernel.org>; Mon,  1 Apr 2019 20:16:59 +0000 (UTC)
3fd5815
Received: from vger.kernel.org (vger.kernel.org [209.132.180.67])
3fd5815
	by mail.kernel.org (Postfix) with ESMTP id 31C4F20896
3fd5815
	for <linux-kernel@archiver.kernel.org>; Mon,  1 Apr 2019 20:16:59 +0000 (UTC)
3fd5815
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
3fd5815
        id S1726867AbfDAUQ5 (ORCPT
3fd5815
        <rfc822;linux-kernel@archiver.kernel.org>);
3fd5815
        Mon, 1 Apr 2019 16:16:57 -0400
3fd5815
Received: from mx1.redhat.com ([209.132.183.28]:52924 "EHLO mx1.redhat.com"
3fd5815
        rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP
3fd5815
        id S1726284AbfDAUQ5 (ORCPT <rfc822;linux-kernel@vger.kernel.org>);
3fd5815
        Mon, 1 Apr 2019 16:16:57 -0400
3fd5815
Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22])
3fd5815
        (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))
3fd5815
        (No client certificate requested)
3fd5815
        by mx1.redhat.com (Postfix) with ESMTPS id 6BC20307D933;
3fd5815
        Mon,  1 Apr 2019 20:16:57 +0000 (UTC)
3fd5815
Received: from gimli.home (ovpn-116-99.phx2.redhat.com [10.3.116.99])
3fd5815
        by smtp.corp.redhat.com (Postfix) with ESMTP id AF2DC104C53F;
3fd5815
        Mon,  1 Apr 2019 20:16:52 +0000 (UTC)
3fd5815
Subject: [PATCH] vfio/type1: Limit DMA mappings per container
3fd5815
From:   Alex Williamson <alex.williamson@redhat.com>
3fd5815
To:     alex.williamson@redhat.com
3fd5815
Cc:     kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
3fd5815
        eric.auger@redhat.com, cohuck@redhat.com
3fd5815
Date:   Mon, 01 Apr 2019 14:16:52 -0600
3fd5815
Message-ID: <155414977872.12780.13728555131525362206.stgit@gimli.home>
3fd5815
User-Agent: StGit/0.19-dirty
3fd5815
MIME-Version: 1.0
3fd5815
Content-Type: text/plain; charset="utf-8"
3fd5815
Content-Transfer-Encoding: 7bit
3fd5815
X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22
3fd5815
X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.48]); Mon, 01 Apr 2019 20:16:57 +0000 (UTC)
3fd5815
Sender: linux-kernel-owner@vger.kernel.org
3fd5815
Precedence: bulk
3fd5815
List-ID: <linux-kernel.vger.kernel.org>
3fd5815
X-Mailing-List: linux-kernel@vger.kernel.org
3fd5815
Archived-At: <https://lore.kernel.org/lkml/155414977872.12780.13728555131525362206.stgit@gimli.home/>
3fd5815
List-Archive: <https://lore.kernel.org/lkml/>
3fd5815
List-Post: <mailto:linux-kernel@vger.kernel.org>
3fd5815
3fd5815
Memory backed DMA mappings are accounted against a user's locked
3fd5815
memory limit, including multiple mappings of the same memory.  This
3fd5815
accounting bounds the number of such mappings that a user can create.
3fd5815
However, DMA mappings that are not backed by memory, such as DMA
3fd5815
mappings of device MMIO via mmaps, do not make use of page pinning
3fd5815
and therefore do not count against the user's locked memory limit.
3fd5815
These mappings still consume memory, but the memory is not well
3fd5815
associated to the process for the purpose of oom killing a task.
3fd5815
3fd5815
To add bounding on this use case, we introduce a limit to the total
3fd5815
number of concurrent DMA mappings that a user is allowed to create.
3fd5815
This limit is exposed as a tunable module option where the default
3fd5815
value of 64K is expected to be well in excess of any reasonable use
3fd5815
case (a large virtual machine configuration would typically only make
3fd5815
use of tens of concurrent mappings).
3fd5815
3fd5815
This fixes CVE-2019-3882.
3fd5815
3fd5815
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
3fd5815
---
3fd5815
 drivers/vfio/vfio_iommu_type1.c |   14 ++++++++++++++
3fd5815
 1 file changed, 14 insertions(+)
3fd5815
3fd5815
diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
3fd5815
index 73652e21efec..7fc8fd7d4dc7 100644
3fd5815
--- a/drivers/vfio/vfio_iommu_type1.c
3fd5815
+++ b/drivers/vfio/vfio_iommu_type1.c
3fd5815
@@ -58,12 +58,18 @@ module_param_named(disable_hugepages,
3fd5815
 MODULE_PARM_DESC(disable_hugepages,
3fd5815
 		 "Disable VFIO IOMMU support for IOMMU hugepages.");
3fd5815
 
3fd5815
+static int dma_entry_limit __read_mostly = U16_MAX;
3fd5815
+module_param_named(dma_entry_limit, dma_entry_limit, int, 0644);
3fd5815
+MODULE_PARM_DESC(dma_entry_limit,
3fd5815
+		 "Maximum number of user DMA mappings per container (65535).");
3fd5815
+
3fd5815
 struct vfio_iommu {
3fd5815
 	struct list_head	domain_list;
3fd5815
 	struct vfio_domain	*external_domain; /* domain for external user */
3fd5815
 	struct mutex		lock;
3fd5815
 	struct rb_root		dma_list;
3fd5815
 	struct blocking_notifier_head notifier;
3fd5815
+	atomic_t		dma_avail;
3fd5815
 	bool			v2;
3fd5815
 	bool			nesting;
3fd5815
 };
3fd5815
@@ -836,6 +842,7 @@ static void vfio_remove_dma(struct vfio_iommu *iommu, struct vfio_dma *dma)
3fd5815
 	vfio_unlink_dma(iommu, dma);
3fd5815
 	put_task_struct(dma->task);
3fd5815
 	kfree(dma);
3fd5815
+	atomic_inc(&iommu->dma_avail);
3fd5815
 }
3fd5815
 
3fd5815
 static unsigned long vfio_pgsize_bitmap(struct vfio_iommu *iommu)
3fd5815
@@ -1081,8 +1088,14 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
3fd5815
 		goto out_unlock;
3fd5815
 	}
3fd5815
 
3fd5815
+	if (!atomic_add_unless(&iommu->dma_avail, -1, 0)) {
3fd5815
+		ret = -ENOSPC;
3fd5815
+		goto out_unlock;
3fd5815
+	}
3fd5815
+
3fd5815
 	dma = kzalloc(sizeof(*dma), GFP_KERNEL);
3fd5815
 	if (!dma) {
3fd5815
+		atomic_inc(&iommu->dma_avail);
3fd5815
 		ret = -ENOMEM;
3fd5815
 		goto out_unlock;
3fd5815
 	}
3fd5815
@@ -1583,6 +1596,7 @@ static void *vfio_iommu_type1_open(unsigned long arg)
3fd5815
 
3fd5815
 	INIT_LIST_HEAD(&iommu->domain_list);
3fd5815
 	iommu->dma_list = RB_ROOT;
3fd5815
+	atomic_set(&iommu->dma_avail, dma_entry_limit);
3fd5815
 	mutex_init(&iommu->lock);
3fd5815
 	BLOCKING_INIT_NOTIFIER_HEAD(&iommu->notifier);
3fd5815
 
3fd5815
3fd5815