Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1319683

[PATCH 4.3 147/157] parisc iommu: fix panic due to trying to allocate too large region

From Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Newsgroups linux.kernel
Subject [PATCH 4.3 147/157] parisc iommu: fix panic due to trying to allocate too large region
Date 2016-01-27 21:30 +0100
Message-ID <qVET1-FR-45@gated-at.bofh.it> (permalink)
References <qVCRc-7CM-17@gated-at.bofh.it>
Organization linux.* mail to news gateway

Show all headers | View raw


4.3-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Mikulas Patocka <mpatocka@redhat.com>

commit e46e31a3696ae2d66f32c207df3969613726e636 upstream.

When using the Promise TX2+ SATA controller on PA-RISC, the system often
crashes with kernel panic, for example just writing data with the dd
utility will make it crash.

Kernel panic - not syncing: drivers/parisc/sba_iommu.c: I/O MMU @ 000000000000a000 is out of mapping resources

CPU: 0 PID: 18442 Comm: mkspadfs Not tainted 4.4.0-rc2 #2
Backtrace:
 [<000000004021497c>] show_stack+0x14/0x20
 [<0000000040410bf0>] dump_stack+0x88/0x100
 [<000000004023978c>] panic+0x124/0x360
 [<0000000040452c18>] sba_alloc_range+0x698/0x6a0
 [<0000000040453150>] sba_map_sg+0x260/0x5b8
 [<000000000c18dbb4>] ata_qc_issue+0x264/0x4a8 [libata]
 [<000000000c19535c>] ata_scsi_translate+0xe4/0x220 [libata]
 [<000000000c19a93c>] ata_scsi_queuecmd+0xbc/0x320 [libata]
 [<0000000040499bbc>] scsi_dispatch_cmd+0xfc/0x130
 [<000000004049da34>] scsi_request_fn+0x6e4/0x970
 [<00000000403e95a8>] __blk_run_queue+0x40/0x60
 [<00000000403e9d8c>] blk_run_queue+0x3c/0x68
 [<000000004049a534>] scsi_run_queue+0x2a4/0x360
 [<000000004049be68>] scsi_end_request+0x1a8/0x238
 [<000000004049de84>] scsi_io_completion+0xfc/0x688
 [<0000000040493c74>] scsi_finish_command+0x17c/0x1d0

The cause of the crash is not exhaustion of the IOMMU space, there is
plenty of free pages. The function sba_alloc_range is called with size
0x11000, thus the pages_needed variable is 0x11. The function
sba_search_bitmap is called with bits_wanted 0x11 and boundary size is
0x10 (because dma_get_seg_boundary(dev) returns 0xffff).

The function sba_search_bitmap attempts to allocate 17 pages that must not
cross 16-page boundary - it can't satisfy this requirement
(iommu_is_span_boundary always returns true) and fails even if there are
many free entries in the IOMMU space.

How did it happen that we try to allocate 17 pages that don't cross
16-page boundary? The cause is in the function iommu_coalesce_chunks. This
function tries to coalesce adjacent entries in the scatterlist. The
function does several checks if it may coalesce one entry with the next,
one of those checks is this:

	if (startsg->length + dma_len > max_seg_size)
		break;

When it finishes coalescing adjacent entries, it allocates the mapping:

sg_dma_len(contig_sg) = dma_len;
dma_len = ALIGN(dma_len + dma_offset, IOVP_SIZE);
sg_dma_address(contig_sg) =
	PIDE_FLAG
	| (iommu_alloc_range(ioc, dev, dma_len) << IOVP_SHIFT)
	| dma_offset;

It is possible that (startsg->length + dma_len > max_seg_size) is false
(we are just near the 0x10000 max_seg_size boundary), so the funcion
decides to coalesce this entry with the next entry. When the coalescing
succeeds, the function performs
	dma_len = ALIGN(dma_len + dma_offset, IOVP_SIZE);
And now, because of non-zero dma_offset, dma_len is greater than 0x10000.
iommu_alloc_range (a pointer to sba_alloc_range) is called and it attempts
to allocate 17 pages for a device that must not cross 16-page boundary.

To fix the bug, we must make sure that dma_len after addition of
dma_offset and alignment doesn't cross the segment boundary. I.e. change
	if (startsg->length + dma_len > max_seg_size)
		break;
to
	if (ALIGN(dma_len + dma_offset + startsg->length, IOVP_SIZE) > max_seg_size)
		break;

This patch makes this change (it precalculates max_seg_boundary at the
beginning of the function iommu_coalesce_chunks). I also added a check
that the mapping length doesn't exceed dma_get_seg_boundary(dev) (it is
not needed for Promise TX2+ SATA, but it may be needed for other devices
that have dma_get_seg_boundary lower than dma_get_max_seg_size).

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Helge Deller <deller@gmx.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

---
 drivers/parisc/iommu-helpers.h |   15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

--- a/drivers/parisc/iommu-helpers.h
+++ b/drivers/parisc/iommu-helpers.h
@@ -104,7 +104,11 @@ iommu_coalesce_chunks(struct ioc *ioc, s
 	struct scatterlist *contig_sg;	   /* contig chunk head */
 	unsigned long dma_offset, dma_len; /* start/len of DMA stream */
 	unsigned int n_mappings = 0;
-	unsigned int max_seg_size = dma_get_max_seg_size(dev);
+	unsigned int max_seg_size = min(dma_get_max_seg_size(dev),
+					(unsigned)DMA_CHUNK_SIZE);
+	unsigned int max_seg_boundary = dma_get_seg_boundary(dev) + 1;
+	if (max_seg_boundary)	/* check if the addition above didn't overflow */
+		max_seg_size = min(max_seg_size, max_seg_boundary);
 
 	while (nents > 0) {
 
@@ -138,14 +142,11 @@ iommu_coalesce_chunks(struct ioc *ioc, s
 
 			/*
 			** First make sure current dma stream won't
-			** exceed DMA_CHUNK_SIZE if we coalesce the
+			** exceed max_seg_size if we coalesce the
 			** next entry.
 			*/   
-			if(unlikely(ALIGN(dma_len + dma_offset + startsg->length,
-					    IOVP_SIZE) > DMA_CHUNK_SIZE))
-				break;
-
-			if (startsg->length + dma_len > max_seg_size)
+			if (unlikely(ALIGN(dma_len + dma_offset + startsg->length, IOVP_SIZE) >
+				     max_seg_size))
 				break;
 
 			/*

Back to linux.kernel | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

[PATCH 4.3 000/157] 4.3.5-stable review Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2016-01-27 20:10 +0100
  [PATCH 4.3 001/157] x86 smpboot: Re-enable init_udelay=0 by default on modern CPUs Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2016-01-27 20:10 +0100
    Re: [PATCH 4.3 001/157] x86 smpboot: Re-enable init_udelay=0 by  default on modern CPUs Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2016-01-27 23:30 +0100
    Re: [PATCH 4.3 001/157] x86 smpboot: Re-enable init_udelay=0 by  default on modern CPUs Donald Parsons <dparsons@brightdsl.net> - 2016-01-27 23:30 +0100
  [PATCH 4.3 052/157] ALSA: seq: Fix race at timer setup and close Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2016-01-27 20:10 +0100
  [PATCH 4.3 046/157] ALSA: hda - Add mic mute hotkey quirk for Lenovo ThinkCentre AIO Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2016-01-27 20:10 +0100
  [PATCH 4.3 010/157] KVM: svm: unconditionally intercept #DB Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2016-01-27 20:10 +0100
  [PATCH 4.3 155/157] mn10300: Select CONFIG_HAVE_UID16 to fix build failure Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2016-01-27 20:10 +0100
  [PATCH 4.3 154/157] fix the regression from "direct-io: Fix negative return from dio read beyond eof" Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2016-01-27 21:20 +0100
  [PATCH 4.3 126/157] powerpc/opal-irqchip: Fix deadlock introduced by "Fix double endian conversion" Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2016-01-27 21:20 +0100
  [PATCH 4.3 135/157] arm64: cmpxchg_dbl: fix return value type Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2016-01-27 21:20 +0100
  [PATCH 4.3 134/157] arm64: bpf: fix mod-by-zero case Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2016-01-27 21:20 +0100
  [PATCH 4.3 044/157] ALSA: hda - Set SKL+ hda controller power at freeze() and thaw() Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2016-01-27 21:30 +0100
  [PATCH 4.3 128/157] powerpc: Make value-returning atomics fully ordered Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2016-01-27 21:30 +0100
  [PATCH 4.3 157/157] arm64: KVM: Add workaround for Cortex-A57 erratum 834220 Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2016-01-27 21:30 +0100
  [PATCH 4.3 131/157] powerpc/module: Handle R_PPC64_ENTRY relocations Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2016-01-27 21:30 +0100
  [PATCH 4.3 129/157] powerpc: Make {cmp}xchg* and their atomic_ versions fully ordered Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2016-01-27 21:30 +0100
  [PATCH 4.3 133/157] arm64: bpf: fix div-by-zero case Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2016-01-27 21:30 +0100
  [PATCH 4.3 156/157] arm64: restore bogomips information in /proc/cpuinfo Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2016-01-27 21:30 +0100
  [PATCH 4.3 147/157] parisc iommu: fix panic due to trying to allocate too large region Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2016-01-27 21:30 +0100
  [PATCH 4.3 132/157] recordmcount: arm64: Replace the ignored mcount call into nop Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2016-01-27 21:30 +0100
  [PATCH 4.3 148/157] HID: wacom: Tie cached HID_DG_CONTACTCOUNT indices to report ID Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2016-01-27 21:30 +0100
  [PATCH 4.3 150/157] HID: core: Avoid uninitialized buffer access Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2016-01-27 21:30 +0100
  [PATCH 4.3 149/157] HID: wacom: Expect touch_max touches if HID_DG_CONTACTCOUNT not present Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2016-01-27 21:30 +0100
  [PATCH 4.3 130/157] scripts/recordmcount.pl: support data in text section on powerpc Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2016-01-27 21:30 +0100
  [PATCH 4.3 153/157] direct-io: Fix negative return from dio read beyond eof Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2016-01-27 21:30 +0100
  Re: [PATCH 4.3 000/157] 4.3.5-stable review Shuah Khan <shuahkh@osg.samsung.com> - 2016-01-28 00:30 +0100
  Re: [PATCH 4.3 000/157] 4.3.5-stable review Guenter Roeck <linux@roeck-us.net> - 2016-01-28 03:20 +0100

csiph-web