linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH AUTOSEL 4.14 1/8] dmaengine: ti: dma-crossbar: Fix a memory leak bug
@ 2019-09-09 15:41 Sasha Levin
  2019-09-09 15:41 ` [PATCH AUTOSEL 4.14 2/8] dmaengine: ti: omap-dma: Add cleanup in omap_dma_probe() Sasha Levin
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Sasha Levin @ 2019-09-09 15:41 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Wenwen Wang, Peter Ujfalusi, Vinod Koul, Sasha Levin, dmaengine

From: Wenwen Wang <wenwen@cs.uga.edu>

[ Upstream commit 2c231c0c1dec42192aca0f87f2dc68b8f0cbc7d2 ]

In ti_dra7_xbar_probe(), 'rsv_events' is allocated through kcalloc(). Then
of_property_read_u32_array() is invoked to search for the property.
However, if this process fails, 'rsv_events' is not deallocated, leading to
a memory leak bug. To fix this issue, free 'rsv_events' before returning
the error.

Signed-off-by: Wenwen Wang <wenwen@cs.uga.edu>
Acked-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Link: https://lore.kernel.org/r/1565938136-7249-1-git-send-email-wenwen@cs.uga.edu
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/dma/ti-dma-crossbar.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/ti-dma-crossbar.c b/drivers/dma/ti-dma-crossbar.c
index 9272b173c7465..6574cb5a12fee 100644
--- a/drivers/dma/ti-dma-crossbar.c
+++ b/drivers/dma/ti-dma-crossbar.c
@@ -395,8 +395,10 @@ static int ti_dra7_xbar_probe(struct platform_device *pdev)
 
 		ret = of_property_read_u32_array(node, pname, (u32 *)rsv_events,
 						 nelm * 2);
-		if (ret)
+		if (ret) {
+			kfree(rsv_events);
 			return ret;
+		}
 
 		for (i = 0; i < nelm; i++) {
 			ti_dra7_xbar_reserve(rsv_events[i][0], rsv_events[i][1],
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH AUTOSEL 4.14 2/8] dmaengine: ti: omap-dma: Add cleanup in omap_dma_probe()
  2019-09-09 15:41 [PATCH AUTOSEL 4.14 1/8] dmaengine: ti: dma-crossbar: Fix a memory leak bug Sasha Levin
@ 2019-09-09 15:41 ` Sasha Levin
  2019-09-09 15:41 ` [PATCH AUTOSEL 4.14 3/8] x86/uaccess: Don't leak the AC flags into __get_user() argument evaluation Sasha Levin
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Sasha Levin @ 2019-09-09 15:41 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Wenwen Wang, Peter Ujfalusi, Vinod Koul, Sasha Levin, dmaengine

From: Wenwen Wang <wenwen@cs.uga.edu>

[ Upstream commit 962411b05a6d3342aa649e39cda1704c1fc042c6 ]

If devm_request_irq() fails to disable all interrupts, no cleanup is
performed before retuning the error. To fix this issue, invoke
omap_dma_free() to do the cleanup.

Signed-off-by: Wenwen Wang <wenwen@cs.uga.edu>
Acked-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Link: https://lore.kernel.org/r/1565938570-7528-1-git-send-email-wenwen@cs.uga.edu
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/dma/omap-dma.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index 8c1665c8fe33a..14b560facf779 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -1534,8 +1534,10 @@ static int omap_dma_probe(struct platform_device *pdev)
 
 		rc = devm_request_irq(&pdev->dev, irq, omap_dma_irq,
 				      IRQF_SHARED, "omap-dma-engine", od);
-		if (rc)
+		if (rc) {
+			omap_dma_free(od);
 			return rc;
+		}
 	}
 
 	if (omap_dma_glbl_read(od, CAPS_0) & CAPS_0_SUPPORT_LL123)
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH AUTOSEL 4.14 3/8] x86/uaccess: Don't leak the AC flags into __get_user() argument evaluation
  2019-09-09 15:41 [PATCH AUTOSEL 4.14 1/8] dmaengine: ti: dma-crossbar: Fix a memory leak bug Sasha Levin
  2019-09-09 15:41 ` [PATCH AUTOSEL 4.14 2/8] dmaengine: ti: omap-dma: Add cleanup in omap_dma_probe() Sasha Levin
@ 2019-09-09 15:41 ` Sasha Levin
  2019-09-09 15:41 ` [PATCH AUTOSEL 4.14 4/8] x86/hyper-v: Fix overflow bug in fill_gva_list() Sasha Levin
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Sasha Levin @ 2019-09-09 15:41 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Peter Zijlstra, Randy Dunlap, Josh Poimboeuf, Thomas Gleixner,
	broonie, sfr, akpm, mhocko, Sasha Levin

From: Peter Zijlstra <peterz@infradead.org>

[ Upstream commit 9b8bd476e78e89c9ea26c3b435ad0201c3d7dbf5 ]

Identical to __put_user(); the __get_user() argument evalution will too
leak UBSAN crud into the __uaccess_begin() / __uaccess_end() region.
While uncommon this was observed to happen for:

  drivers/xen/gntdev.c: if (__get_user(old_status, batch->status[i]))

where UBSAN added array bound checking.

This complements commit:

  6ae865615fc4 ("x86/uaccess: Dont leak the AC flag into __put_user() argument evaluation")

Tested-by Sedat Dilek <sedat.dilek@gmail.com>
Reported-by: Randy Dunlap <rdunlap@infradead.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Cc: broonie@kernel.org
Cc: sfr@canb.auug.org.au
Cc: akpm@linux-foundation.org
Cc: Randy Dunlap <rdunlap@infradead.org>
Cc: mhocko@suse.cz
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Link: https://lkml.kernel.org/r/20190829082445.GM2369@hirez.programming.kicks-ass.net
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 arch/x86/include/asm/uaccess.h | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 4111edb3188e2..9718303410614 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -451,8 +451,10 @@ do {									\
 ({									\
 	int __gu_err;							\
 	__inttype(*(ptr)) __gu_val;					\
+	__typeof__(ptr) __gu_ptr = (ptr);				\
+	__typeof__(size) __gu_size = (size);				\
 	__uaccess_begin_nospec();					\
-	__get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT);	\
+	__get_user_size(__gu_val, __gu_ptr, __gu_size, __gu_err, -EFAULT);	\
 	__uaccess_end();						\
 	(x) = (__force __typeof__(*(ptr)))__gu_val;			\
 	__builtin_expect(__gu_err, 0);					\
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH AUTOSEL 4.14 4/8] x86/hyper-v: Fix overflow bug in fill_gva_list()
  2019-09-09 15:41 [PATCH AUTOSEL 4.14 1/8] dmaengine: ti: dma-crossbar: Fix a memory leak bug Sasha Levin
  2019-09-09 15:41 ` [PATCH AUTOSEL 4.14 2/8] dmaengine: ti: omap-dma: Add cleanup in omap_dma_probe() Sasha Levin
  2019-09-09 15:41 ` [PATCH AUTOSEL 4.14 3/8] x86/uaccess: Don't leak the AC flags into __get_user() argument evaluation Sasha Levin
@ 2019-09-09 15:41 ` Sasha Levin
  2019-09-09 15:41 ` [PATCH AUTOSEL 4.14 5/8] configfs_register_group() shouldn't be (and isn't) called in rmdirable parts Sasha Levin
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Sasha Levin @ 2019-09-09 15:41 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Tianyu Lan, Jong Hyun Park, Michael Kelley, Borislav Petkov,
	Linus Torvalds, Peter Zijlstra, Thomas Gleixner, Ingo Molnar,
	Sasha Levin, linux-hyperv

From: Tianyu Lan <Tianyu.Lan@microsoft.com>

[ Upstream commit 4030b4c585c41eeefec7bd20ce3d0e100a0f2e4d ]

When the 'start' parameter is >=  0xFF000000 on 32-bit
systems, or >= 0xFFFFFFFF'FF000000 on 64-bit systems,
fill_gva_list() gets into an infinite loop.

With such inputs, 'cur' overflows after adding HV_TLB_FLUSH_UNIT
and always compares as less than end.  Memory is filled with
guest virtual addresses until the system crashes.

Fix this by never incrementing 'cur' to be larger than 'end'.

Reported-by: Jong Hyun Park <park.jonghyun@yonsei.ac.kr>
Signed-off-by: Tianyu Lan <Tianyu.Lan@microsoft.com>
Reviewed-by: Michael Kelley <mikelley@microsoft.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Fixes: 2ffd9e33ce4a ("x86/hyper-v: Use hypercall for remote TLB flush")
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 arch/x86/hyperv/mmu.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/arch/x86/hyperv/mmu.c b/arch/x86/hyperv/mmu.c
index 56c9ebac946fe..47718fff0b797 100644
--- a/arch/x86/hyperv/mmu.c
+++ b/arch/x86/hyperv/mmu.c
@@ -57,12 +57,14 @@ static inline int fill_gva_list(u64 gva_list[], int offset,
 		 * Lower 12 bits encode the number of additional
 		 * pages to flush (in addition to the 'cur' page).
 		 */
-		if (diff >= HV_TLB_FLUSH_UNIT)
+		if (diff >= HV_TLB_FLUSH_UNIT) {
 			gva_list[gva_n] |= ~PAGE_MASK;
-		else if (diff)
+			cur += HV_TLB_FLUSH_UNIT;
+		}  else if (diff) {
 			gva_list[gva_n] |= (diff - 1) >> PAGE_SHIFT;
+			cur = end;
+		}
 
-		cur += HV_TLB_FLUSH_UNIT;
 		gva_n++;
 
 	} while (cur < end);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH AUTOSEL 4.14 5/8] configfs_register_group() shouldn't be (and isn't) called in rmdirable parts
  2019-09-09 15:41 [PATCH AUTOSEL 4.14 1/8] dmaengine: ti: dma-crossbar: Fix a memory leak bug Sasha Levin
                   ` (2 preceding siblings ...)
  2019-09-09 15:41 ` [PATCH AUTOSEL 4.14 4/8] x86/hyper-v: Fix overflow bug in fill_gva_list() Sasha Levin
@ 2019-09-09 15:41 ` Sasha Levin
  2019-09-09 15:41 ` [PATCH AUTOSEL 4.14 6/8] keys: Fix missing null pointer check in request_key_auth_describe() Sasha Levin
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Sasha Levin @ 2019-09-09 15:41 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: Al Viro, Christoph Hellwig, Sasha Levin

From: Al Viro <viro@zeniv.linux.org.uk>

[ Upstream commit f19e4ed1e1edbfa3c9ccb9fed17759b7d6db24c6 ]

revert cc57c07343bd "configfs: fix registered group removal"
It was an attempt to handle something that fundamentally doesn't
work - configfs_register_group() should never be done in a part
of tree that can be rmdir'ed.  And in mainline it never had been,
so let's not borrow trouble; the fix was racy anyway, it would take
a lot more to make that work and desired semantics is not clear.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 fs/configfs/dir.c | 11 -----------
 1 file changed, 11 deletions(-)

diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index a1985a9ad2d64..64fdb12e6ad61 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -1782,16 +1782,6 @@ void configfs_unregister_group(struct config_group *group)
 	struct dentry *dentry = group->cg_item.ci_dentry;
 	struct dentry *parent = group->cg_item.ci_parent->ci_dentry;
 
-	mutex_lock(&subsys->su_mutex);
-	if (!group->cg_item.ci_parent->ci_group) {
-		/*
-		 * The parent has already been unlinked and detached
-		 * due to a rmdir.
-		 */
-		goto unlink_group;
-	}
-	mutex_unlock(&subsys->su_mutex);
-
 	inode_lock_nested(d_inode(parent), I_MUTEX_PARENT);
 	spin_lock(&configfs_dirent_lock);
 	configfs_detach_prep(dentry, NULL);
@@ -1806,7 +1796,6 @@ void configfs_unregister_group(struct config_group *group)
 	dput(dentry);
 
 	mutex_lock(&subsys->su_mutex);
-unlink_group:
 	unlink_group(group);
 	mutex_unlock(&subsys->su_mutex);
 }
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH AUTOSEL 4.14 6/8] keys: Fix missing null pointer check in request_key_auth_describe()
  2019-09-09 15:41 [PATCH AUTOSEL 4.14 1/8] dmaengine: ti: dma-crossbar: Fix a memory leak bug Sasha Levin
                   ` (3 preceding siblings ...)
  2019-09-09 15:41 ` [PATCH AUTOSEL 4.14 5/8] configfs_register_group() shouldn't be (and isn't) called in rmdirable parts Sasha Levin
@ 2019-09-09 15:41 ` Sasha Levin
  2019-09-09 15:41 ` [PATCH AUTOSEL 4.14 7/8] iommu/amd: Flush old domains in kdump kernel Sasha Levin
  2019-09-09 15:41 ` [PATCH AUTOSEL 4.14 8/8] iommu/amd: Fix race in increase_address_space() Sasha Levin
  6 siblings, 0 replies; 8+ messages in thread
From: Sasha Levin @ 2019-09-09 15:41 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Hillf Danton, Sachin Sant, David Howells, Linus Torvalds,
	Sasha Levin, keyrings, linux-security-module

From: Hillf Danton <hdanton@sina.com>

[ Upstream commit d41a3effbb53b1bcea41e328d16a4d046a508381 ]

If a request_key authentication token key gets revoked, there's a window in
which request_key_auth_describe() can see it with a NULL payload - but it
makes no check for this and something like the following oops may occur:

	BUG: Kernel NULL pointer dereference at 0x00000038
	Faulting instruction address: 0xc0000000004ddf30
	Oops: Kernel access of bad area, sig: 11 [#1]
	...
	NIP [...] request_key_auth_describe+0x90/0xd0
	LR [...] request_key_auth_describe+0x54/0xd0
	Call Trace:
	[...] request_key_auth_describe+0x54/0xd0 (unreliable)
	[...] proc_keys_show+0x308/0x4c0
	[...] seq_read+0x3d0/0x540
	[...] proc_reg_read+0x90/0x110
	[...] __vfs_read+0x3c/0x70
	[...] vfs_read+0xb4/0x1b0
	[...] ksys_read+0x7c/0x130
	[...] system_call+0x5c/0x70

Fix this by checking for a NULL pointer when describing such a key.

Also make the read routine check for a NULL pointer to be on the safe side.

[DH: Modified to not take already-held rcu lock and modified to also check
 in the read routine]

Fixes: 04c567d9313e ("[PATCH] Keys: Fix race between two instantiators of a key")
Reported-by: Sachin Sant <sachinp@linux.vnet.ibm.com>
Signed-off-by: Hillf Danton <hdanton@sina.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Tested-by: Sachin Sant <sachinp@linux.vnet.ibm.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 security/keys/request_key_auth.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
index 5e515791ccd11..1d34b2a5f485e 100644
--- a/security/keys/request_key_auth.c
+++ b/security/keys/request_key_auth.c
@@ -71,6 +71,9 @@ static void request_key_auth_describe(const struct key *key,
 {
 	struct request_key_auth *rka = get_request_key_auth(key);
 
+	if (!rka)
+		return;
+
 	seq_puts(m, "key:");
 	seq_puts(m, key->description);
 	if (key_is_positive(key))
@@ -88,6 +91,9 @@ static long request_key_auth_read(const struct key *key,
 	size_t datalen;
 	long ret;
 
+	if (!rka)
+		return -EKEYREVOKED;
+
 	datalen = rka->callout_len;
 	ret = datalen;
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH AUTOSEL 4.14 7/8] iommu/amd: Flush old domains in kdump kernel
  2019-09-09 15:41 [PATCH AUTOSEL 4.14 1/8] dmaengine: ti: dma-crossbar: Fix a memory leak bug Sasha Levin
                   ` (4 preceding siblings ...)
  2019-09-09 15:41 ` [PATCH AUTOSEL 4.14 6/8] keys: Fix missing null pointer check in request_key_auth_describe() Sasha Levin
@ 2019-09-09 15:41 ` Sasha Levin
  2019-09-09 15:41 ` [PATCH AUTOSEL 4.14 8/8] iommu/amd: Fix race in increase_address_space() Sasha Levin
  6 siblings, 0 replies; 8+ messages in thread
From: Sasha Levin @ 2019-09-09 15:41 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: Stuart Hayes, Joerg Roedel, Sasha Levin, iommu

From: Stuart Hayes <stuart.w.hayes@gmail.com>

[ Upstream commit 36b7200f67dfe75b416b5281ed4ace9927b513bc ]

When devices are attached to the amd_iommu in a kdump kernel, the old device
table entries (DTEs), which were copied from the crashed kernel, will be
overwritten with a new domain number.  When the new DTE is written, the IOMMU
is told to flush the DTE from its internal cache--but it is not told to flush
the translation cache entries for the old domain number.

Without this patch, AMD systems using the tg3 network driver fail when kdump
tries to save the vmcore to a network system, showing network timeouts and
(sometimes) IOMMU errors in the kernel log.

This patch will flush IOMMU translation cache entries for the old domain when
a DTE gets overwritten with a new domain number.

Signed-off-by: Stuart Hayes <stuart.w.hayes@gmail.com>
Fixes: 3ac3e5ee5ed5 ('iommu/amd: Copy old trans table from old kernel')
Signed-off-by: Joerg Roedel <jroedel@suse.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/iommu/amd_iommu.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 684f7cdd814b6..822c85226a29f 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -1150,6 +1150,17 @@ static void amd_iommu_flush_tlb_all(struct amd_iommu *iommu)
 	iommu_completion_wait(iommu);
 }
 
+static void amd_iommu_flush_tlb_domid(struct amd_iommu *iommu, u32 dom_id)
+{
+	struct iommu_cmd cmd;
+
+	build_inv_iommu_pages(&cmd, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS,
+			      dom_id, 1);
+	iommu_queue_command(iommu, &cmd);
+
+	iommu_completion_wait(iommu);
+}
+
 static void amd_iommu_flush_all(struct amd_iommu *iommu)
 {
 	struct iommu_cmd cmd;
@@ -1835,6 +1846,7 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats)
 {
 	u64 pte_root = 0;
 	u64 flags = 0;
+	u32 old_domid;
 
 	if (domain->mode != PAGE_MODE_NONE)
 		pte_root = iommu_virt_to_phys(domain->pt_root);
@@ -1877,8 +1889,20 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats)
 	flags &= ~DEV_DOMID_MASK;
 	flags |= domain->id;
 
+	old_domid = amd_iommu_dev_table[devid].data[1] & DEV_DOMID_MASK;
 	amd_iommu_dev_table[devid].data[1]  = flags;
 	amd_iommu_dev_table[devid].data[0]  = pte_root;
+
+	/*
+	 * A kdump kernel might be replacing a domain ID that was copied from
+	 * the previous kernel--if so, it needs to flush the translation cache
+	 * entries for the old domain ID that is being overwritten
+	 */
+	if (old_domid) {
+		struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
+
+		amd_iommu_flush_tlb_domid(iommu, old_domid);
+	}
 }
 
 static void clear_dte_entry(u16 devid)
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH AUTOSEL 4.14 8/8] iommu/amd: Fix race in increase_address_space()
  2019-09-09 15:41 [PATCH AUTOSEL 4.14 1/8] dmaengine: ti: dma-crossbar: Fix a memory leak bug Sasha Levin
                   ` (5 preceding siblings ...)
  2019-09-09 15:41 ` [PATCH AUTOSEL 4.14 7/8] iommu/amd: Flush old domains in kdump kernel Sasha Levin
@ 2019-09-09 15:41 ` Sasha Levin
  6 siblings, 0 replies; 8+ messages in thread
From: Sasha Levin @ 2019-09-09 15:41 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: Joerg Roedel, Qian Cai, Sasha Levin, iommu

From: Joerg Roedel <jroedel@suse.de>

[ Upstream commit 754265bcab78a9014f0f99cd35e0d610fcd7dfa7 ]

After the conversion to lock-less dma-api call the
increase_address_space() function can be called without any
locking. Multiple CPUs could potentially race for increasing
the address space, leading to invalid domain->mode settings
and invalid page-tables. This has been happening in the wild
under high IO load and memory pressure.

Fix the race by locking this operation. The function is
called infrequently so that this does not introduce
a performance regression in the dma-api path again.

Reported-by: Qian Cai <cai@lca.pw>
Fixes: 256e4621c21a ('iommu/amd: Make use of the generic IOVA allocator')
Signed-off-by: Joerg Roedel <jroedel@suse.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/iommu/amd_iommu.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 822c85226a29f..a1174e61daf4e 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -1337,18 +1337,21 @@ static void domain_flush_devices(struct protection_domain *domain)
  * another level increases the size of the address space by 9 bits to a size up
  * to 64 bits.
  */
-static bool increase_address_space(struct protection_domain *domain,
+static void increase_address_space(struct protection_domain *domain,
 				   gfp_t gfp)
 {
+	unsigned long flags;
 	u64 *pte;
 
-	if (domain->mode == PAGE_MODE_6_LEVEL)
+	spin_lock_irqsave(&domain->lock, flags);
+
+	if (WARN_ON_ONCE(domain->mode == PAGE_MODE_6_LEVEL))
 		/* address space already 64 bit large */
-		return false;
+		goto out;
 
 	pte = (void *)get_zeroed_page(gfp);
 	if (!pte)
-		return false;
+		goto out;
 
 	*pte             = PM_LEVEL_PDE(domain->mode,
 					iommu_virt_to_phys(domain->pt_root));
@@ -1356,7 +1359,10 @@ static bool increase_address_space(struct protection_domain *domain,
 	domain->mode    += 1;
 	domain->updated  = true;
 
-	return true;
+out:
+	spin_unlock_irqrestore(&domain->lock, flags);
+
+	return;
 }
 
 static u64 *alloc_pte(struct protection_domain *domain,
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2019-09-09 22:18 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-09-09 15:41 [PATCH AUTOSEL 4.14 1/8] dmaengine: ti: dma-crossbar: Fix a memory leak bug Sasha Levin
2019-09-09 15:41 ` [PATCH AUTOSEL 4.14 2/8] dmaengine: ti: omap-dma: Add cleanup in omap_dma_probe() Sasha Levin
2019-09-09 15:41 ` [PATCH AUTOSEL 4.14 3/8] x86/uaccess: Don't leak the AC flags into __get_user() argument evaluation Sasha Levin
2019-09-09 15:41 ` [PATCH AUTOSEL 4.14 4/8] x86/hyper-v: Fix overflow bug in fill_gva_list() Sasha Levin
2019-09-09 15:41 ` [PATCH AUTOSEL 4.14 5/8] configfs_register_group() shouldn't be (and isn't) called in rmdirable parts Sasha Levin
2019-09-09 15:41 ` [PATCH AUTOSEL 4.14 6/8] keys: Fix missing null pointer check in request_key_auth_describe() Sasha Levin
2019-09-09 15:41 ` [PATCH AUTOSEL 4.14 7/8] iommu/amd: Flush old domains in kdump kernel Sasha Levin
2019-09-09 15:41 ` [PATCH AUTOSEL 4.14 8/8] iommu/amd: Fix race in increase_address_space() Sasha Levin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).