stable.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	stable@vger.kernel.org, Helge Deller <deller@gmx.de>,
	John David Anglin <dave.anglin@bell.net>
Subject: [ 22/72] parisc: Fix gcc miscompilation in pa_memcpy()
Date: Thu, 18 Jul 2013 22:25:39 -0700	[thread overview]
Message-ID: <20130719052601.381286751@linuxfoundation.org> (raw)
In-Reply-To: <20130719052559.852627424@linuxfoundation.org>

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

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

From: Helge Deller <deller@gmx.de>

commit 5b879d78bc0818aa710f5d4d9abbfc2aca075cc3 upstream.

When running the LTP testsuite one may hit this kernel BUG() with the
write06 testcase:

kernel BUG at mm/filemap.c:2023!
CPU: 1 PID: 8614 Comm: writev01 Not tainted 3.10.0-rc7-64bit-c3000+ #6
IASQ: 0000000000000000 0000000000000000 IAOQ: 00000000401e6e84 00000000401e6e88
 IIR: 03ffe01f    ISR: 0000000010340000  IOR: 000001fbe0380820
 CPU:        1   CR30: 00000000bef80000 CR31: ffffffffffffffff
 ORIG_R28: 00000000bdc192c0
 IAOQ[0]: iov_iter_advance+0x3c/0xc0
 IAOQ[1]: iov_iter_advance+0x40/0xc0
 RP(r2): generic_file_buffered_write+0x204/0x3f0
Backtrace:
 [<00000000401e764c>] generic_file_buffered_write+0x204/0x3f0
 [<00000000401eab24>] __generic_file_aio_write+0x244/0x448
 [<00000000401eadc0>] generic_file_aio_write+0x98/0x150
 [<000000004024f460>] do_sync_readv_writev+0xc0/0x130
 [<000000004025037c>] compat_do_readv_writev+0x12c/0x340
 [<00000000402505f8>] compat_writev+0x68/0xa0
 [<0000000040251d88>] compat_SyS_writev+0x98/0xf8

Reason for this crash is a gcc miscompilation in the fault handlers of
pa_memcpy() which return the fault address instead of the copied bytes.
Since this seems to be a generic problem with gcc-4.7.x (and below), it's
better to simplify the fault handlers in pa_memcpy to avoid this problem.

Here is a simple reproducer for the problem:

int main(int argc, char **argv)
{
	int fd, nbytes;
	struct iovec wr_iovec[] = {
		{ "TEST STRING                     ",32},
		{ (char*)0x40005000,32} }; // random memory.
	fd = open(DATA_FILE, O_RDWR | O_CREAT, 0666);
	nbytes = writev(fd, wr_iovec, 2);
	printf("return value = %d, errno %d (%s)\n",
		nbytes, errno, strerror(errno));
	return 0;
}

In addition, John David Anglin wrote:
There is no gcc PR as pa_memcpy is not legitimate C code. There is an
implicit assumption that certain variables will contain correct values
when an exception occurs and the code randomly jumps to one of the
exception blocks.  There is no guarantee of this.  If a PR was filed, it
would likely be marked as invalid.

Signed-off-by: Helge Deller <deller@gmx.de>
Signed-off-by: John David Anglin <dave.anglin@bell.net>
Signed-off-by: Helge Deller <deller@gmx.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

---
 arch/parisc/lib/memcpy.c |   79 +++++++++++++++++++++++++++++------------------
 1 file changed, 50 insertions(+), 29 deletions(-)

--- a/arch/parisc/lib/memcpy.c
+++ b/arch/parisc/lib/memcpy.c
@@ -2,6 +2,7 @@
  *    Optimized memory copy routines.
  *
  *    Copyright (C) 2004 Randolph Chung <tausq@debian.org>
+ *    Copyright (C) 2013 Helge Deller <deller@gmx.de>
  *
  *    This program is free software; you can redistribute it and/or modify
  *    it under the terms of the GNU General Public License as published by
@@ -153,17 +154,21 @@ static inline void prefetch_dst(const vo
 #define prefetch_dst(addr) do { } while(0)
 #endif
 
+#define PA_MEMCPY_OK		0
+#define PA_MEMCPY_LOAD_ERROR	1
+#define PA_MEMCPY_STORE_ERROR	2
+
 /* Copy from a not-aligned src to an aligned dst, using shifts. Handles 4 words
  * per loop.  This code is derived from glibc. 
  */
-static inline unsigned long copy_dstaligned(unsigned long dst, unsigned long src, unsigned long len, unsigned long o_dst, unsigned long o_src, unsigned long o_len)
+static inline unsigned long copy_dstaligned(unsigned long dst,
+					unsigned long src, unsigned long len)
 {
 	/* gcc complains that a2 and a3 may be uninitialized, but actually
 	 * they cannot be.  Initialize a2/a3 to shut gcc up.
 	 */
 	register unsigned int a0, a1, a2 = 0, a3 = 0;
 	int sh_1, sh_2;
-	struct exception_data *d;
 
 	/* prefetch_src((const void *)src); */
 
@@ -197,7 +202,7 @@ static inline unsigned long copy_dstalig
 			goto do2;
 		case 0:
 			if (len == 0)
-				return 0;
+				return PA_MEMCPY_OK;
 			/* a3 = ((unsigned int *) src)[0];
 			   a0 = ((unsigned int *) src)[1]; */
 			ldw(s_space, 0, src, a3, cda_ldw_exc);
@@ -256,42 +261,35 @@ do0:
 	preserve_branch(handle_load_error);
 	preserve_branch(handle_store_error);
 
-	return 0;
+	return PA_MEMCPY_OK;
 
 handle_load_error:
 	__asm__ __volatile__ ("cda_ldw_exc:\n");
-	d = &__get_cpu_var(exception_data);
-	DPRINTF("cda_ldw_exc: o_len=%lu fault_addr=%lu o_src=%lu ret=%lu\n",
-		o_len, d->fault_addr, o_src, o_len - d->fault_addr + o_src);
-	return o_len * 4 - d->fault_addr + o_src;
+	return PA_MEMCPY_LOAD_ERROR;
 
 handle_store_error:
 	__asm__ __volatile__ ("cda_stw_exc:\n");
-	d = &__get_cpu_var(exception_data);
-	DPRINTF("cda_stw_exc: o_len=%lu fault_addr=%lu o_dst=%lu ret=%lu\n",
-		o_len, d->fault_addr, o_dst, o_len - d->fault_addr + o_dst);
-	return o_len * 4 - d->fault_addr + o_dst;
+	return PA_MEMCPY_STORE_ERROR;
 }
 
 
-/* Returns 0 for success, otherwise, returns number of bytes not transferred. */
-static unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len)
+/* Returns PA_MEMCPY_OK, PA_MEMCPY_LOAD_ERROR or PA_MEMCPY_STORE_ERROR.
+ * In case of an access fault the faulty address can be read from the per_cpu
+ * exception data struct. */
+static unsigned long pa_memcpy_internal(void *dstp, const void *srcp,
+					unsigned long len)
 {
 	register unsigned long src, dst, t1, t2, t3;
 	register unsigned char *pcs, *pcd;
 	register unsigned int *pws, *pwd;
 	register double *pds, *pdd;
-	unsigned long ret = 0;
-	unsigned long o_dst, o_src, o_len;
-	struct exception_data *d;
+	unsigned long ret;
 
 	src = (unsigned long)srcp;
 	dst = (unsigned long)dstp;
 	pcs = (unsigned char *)srcp;
 	pcd = (unsigned char *)dstp;
 
-	o_dst = dst; o_src = src; o_len = len;
-
 	/* prefetch_src((const void *)srcp); */
 
 	if (len < THRESHOLD)
@@ -401,7 +399,7 @@ byte_copy:
 		len--;
 	}
 
-	return 0;
+	return PA_MEMCPY_OK;
 
 unaligned_copy:
 	/* possibly we are aligned on a word, but not on a double... */
@@ -438,8 +436,7 @@ unaligned_copy:
 		src = (unsigned long)pcs;
 	}
 
-	ret = copy_dstaligned(dst, src, len / sizeof(unsigned int), 
-		o_dst, o_src, o_len);
+	ret = copy_dstaligned(dst, src, len / sizeof(unsigned int));
 	if (ret)
 		return ret;
 
@@ -454,17 +451,41 @@ unaligned_copy:
 
 handle_load_error:
 	__asm__ __volatile__ ("pmc_load_exc:\n");
-	d = &__get_cpu_var(exception_data);
-	DPRINTF("pmc_load_exc: o_len=%lu fault_addr=%lu o_src=%lu ret=%lu\n",
-		o_len, d->fault_addr, o_src, o_len - d->fault_addr + o_src);
-	return o_len - d->fault_addr + o_src;
+	return PA_MEMCPY_LOAD_ERROR;
 
 handle_store_error:
 	__asm__ __volatile__ ("pmc_store_exc:\n");
+	return PA_MEMCPY_STORE_ERROR;
+}
+
+
+/* Returns 0 for success, otherwise, returns number of bytes not transferred. */
+static unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len)
+{
+	unsigned long ret, fault_addr, reference;
+	struct exception_data *d;
+
+	ret = pa_memcpy_internal(dstp, srcp, len);
+	if (likely(ret == PA_MEMCPY_OK))
+		return 0;
+
+	/* if a load or store fault occured we can get the faulty addr */
 	d = &__get_cpu_var(exception_data);
-	DPRINTF("pmc_store_exc: o_len=%lu fault_addr=%lu o_dst=%lu ret=%lu\n",
-		o_len, d->fault_addr, o_dst, o_len - d->fault_addr + o_dst);
-	return o_len - d->fault_addr + o_dst;
+	fault_addr = d->fault_addr;
+
+	/* error in load or store? */
+	if (ret == PA_MEMCPY_LOAD_ERROR)
+		reference = (unsigned long) srcp;
+	else
+		reference = (unsigned long) dstp;
+
+	DPRINTF("pa_memcpy: fault type = %lu, len=%lu fault_addr=%lu ref=%lu\n",
+		ret, len, fault_addr, reference);
+
+	if (fault_addr >= reference)
+		return len - (fault_addr - reference);
+	else
+		return len;
 }
 
 #ifdef __KERNEL__



  parent reply	other threads:[~2013-07-19  5:25 UTC|newest]

Thread overview: 87+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-07-19  5:25 [ 00/72] 3.10.2-stable review Greg Kroah-Hartman
2013-07-19  5:25 ` [ 01/72] CIFS use sensible file nlink values if unprovided Greg Kroah-Hartman
2013-07-19  5:25 ` [ 02/72] CIFS: Fix a deadlock when a file is reopened Greg Kroah-Hartman
2013-07-19  5:25 ` [ 03/72] rtlwifi: rtl8192cu: Add new USB ID for TP-Link TL-WN8200ND Greg Kroah-Hartman
2013-07-19  5:25 ` [ 04/72] rtlwifi: rtl8723ae: Fix typo in firmware names Greg Kroah-Hartman
2013-07-19  5:25 ` [ 05/72] rtlwifi: rtl8192cu: Fix duplicate if test Greg Kroah-Hartman
2013-07-19  5:25 ` [ 06/72] jbd2: move superblock checksum calculation to jbd2_write_superblock() Greg Kroah-Hartman
2013-07-19  5:25 ` [ 07/72] jbd2: fix theoretical race in jbd2__journal_restart Greg Kroah-Hartman
2013-07-19  5:25 ` [ 08/72] ext4: fix corruption when online resizing a fs with 1K block size Greg Kroah-Hartman
2013-07-19  5:25 ` [ 09/72] ext3,ext4: dont mess with dir_file->f_pos in htree_dirblock_to_tree() Greg Kroah-Hartman
2013-07-19  5:25 ` [ 10/72] ext4: check error return from ext4_write_inline_data_end() Greg Kroah-Hartman
2013-07-19  5:25 ` [ 11/72] pch_uart: Add uart_clk selection for the MinnowBoard Greg Kroah-Hartman
2013-07-19  5:25 ` [ 12/72] USB: option,qcserial: move Novatel Gobi1K IDs to qcserial Greg Kroah-Hartman
2013-07-19  5:25 ` [ 13/72] usb: gadget: f_mass_storage: add missing memory barrier for thread_wakeup_needed Greg Kroah-Hartman
2013-07-19  5:25 ` [ 14/72] USB: ehci-omap: Tweak PHY initialization sequence Greg Kroah-Hartman
2013-07-19  5:25 ` [ 15/72] xhci: check for failed dma pool allocation Greg Kroah-Hartman
2013-07-19  5:25 ` [ 16/72] usb: host: xhci-plat: release mem region while removing module Greg Kroah-Hartman
2013-07-19  5:25 ` [ 17/72] drivers: hv: switch to use mb() instead of smp_mb() Greg Kroah-Hartman
2013-07-19  5:25 ` [ 18/72] pcmcia: at91_cf: fix gpio_get_value in at91_cf_get_status Greg Kroah-Hartman
2013-07-19  5:25 ` [ 19/72] cgroup: fix umount vs cgroup_event_remove() race Greg Kroah-Hartman
2013-07-19  5:25 ` [ 20/72] cgroup: fix RCU accesses to task->cgroups Greg Kroah-Hartman
2013-07-19  5:25 ` [ 21/72] parisc: document the shadow registers Greg Kroah-Hartman
2013-07-19  5:25 ` Greg Kroah-Hartman [this message]
2013-07-19  5:25 ` [ 23/72] slab: fix init_lock_keys Greg Kroah-Hartman
2013-07-19  5:25 ` [ 24/72] parisc: Ensure volatile space register %sr1 is not clobbered Greg Kroah-Hartman
2013-07-19  5:25 ` [ 25/72] parisc: fix LMMIO mismatch between PAT length and MASK register Greg Kroah-Hartman
2013-07-19  5:25 ` [ 26/72] parisc: optimize mtsp(0,sr) inline assembly Greg Kroah-Hartman
2013-07-19  5:25 ` [ 27/72] x86, efi: retry ExitBootServices() on failure Greg Kroah-Hartman
2013-07-19  5:25 ` [ 28/72] xen/time: remove blocked time accounting from xen "clockchip" Greg Kroah-Hartman
2013-07-19  5:25 ` [ 29/72] xen/pcifront: Deal with toolstack missing XenbusStateClosing state Greg Kroah-Hartman
2013-07-19  5:25 ` [ 30/72] genirq: Fix can_request_irq() for IRQs without an action Greg Kroah-Hartman
2013-07-19  5:25 ` [ 31/72] drivers/rtc/rtc-rv3029c2.c: fix disabling AIE irq Greg Kroah-Hartman
2013-07-19  5:25 ` [ 32/72] ACPI: Add CMOS RTC Operation Region handler support Greg Kroah-Hartman
2013-07-19  5:25 ` [ 33/72] ACPI / EC: Add HP Folio 13 to ec_dmi_table in order to skip DSDT scan Greg Kroah-Hartman
2013-07-19  5:25 ` [ 34/72] ACPICA: Do not use extended sleep registers unless HW-reduced bit is set Greg Kroah-Hartman
2013-07-19  5:25 ` [ 35/72] ACPI / PM: Fix corner case in acpi_bus_update_power() Greg Kroah-Hartman
2013-07-19  5:25 ` [ 36/72] HID: apple: Add support for the 2013 Macbook Air Greg Kroah-Hartman
2013-07-19  5:25 ` [ 37/72] Input: bcm5974 - add support for the 2013 MacBook Air Greg Kroah-Hartman
2013-07-19  5:40   ` Dmitry Torokhov
2013-07-19  5:44     ` Greg Kroah-Hartman
2013-07-22  1:42       ` Greg Kroah-Hartman
2013-07-22  2:21         ` Dmitry Torokhov
2013-07-22 10:07           ` rydberg
2013-07-19  5:25 ` [ 38/72] arch: c6x: mm: include "asm/uaccess.h" to pass compiling Greg Kroah-Hartman
2013-07-19  5:25 ` [ 39/72] ocfs2: xattr: fix inlined xattr reflink Greg Kroah-Hartman
2013-07-19  5:25 ` [ 40/72] nbd: correct disconnect behavior Greg Kroah-Hartman
2013-07-19  5:25 ` [ 41/72] PCI: Finish SR-IOV VF setup before adding the device Greg Kroah-Hartman
2013-07-19  5:25 ` [ 42/72] PCI: Fix refcount issue in pci_create_root_bus() error recovery path Greg Kroah-Hartman
2013-07-19  5:26 ` [ 43/72] iwlwifi: pcie: fix race in queue unmapping Greg Kroah-Hartman
2013-07-19  5:26 ` [ 44/72] iwlwifi: pcie: wake the queue if stopped when being unmapped Greg Kroah-Hartman
2013-07-19  5:26 ` [ 45/72] ahci: Add AMD CZ SATA device ID Greg Kroah-Hartman
2013-07-19  5:26 ` [ 46/72] ahci: AHCI-mode SATA patch for Intel Coleto Creek DeviceIDs Greg Kroah-Hartman
2013-07-19  5:26 ` [ 47/72] ahci: remove pmp link online check in FBS EH Greg Kroah-Hartman
2013-07-19  5:26 ` [ 48/72] timer: Fix jiffies wrap behavior of round_jiffies_common() Greg Kroah-Hartman
2013-07-19  5:26 ` [ 49/72] Btrfs: fix estale with btrfs send Greg Kroah-Hartman
2013-07-19  5:26 ` [ 50/72] Btrfs: hold the tree mod lock in __tree_mod_log_rewind Greg Kroah-Hartman
2013-07-19  5:26 ` [ 51/72] Btrfs: only do the tree_mod_log_free_eb if this is our last ref Greg Kroah-Hartman
2013-07-19  5:26 ` [ 52/72] ext4: fix data offset overflow on 32-bit archs in ext4_inline_data_fiemap() Greg Kroah-Hartman
2013-07-19  5:26 ` [ 53/72] ext4: fix overflows in SEEK_HOLE, SEEK_DATA implementations Greg Kroah-Hartman
2013-07-19  5:26 ` [ 54/72] ext4: fix data offset overflow in ext4_xattr_fiemap() on 32-bit archs Greg Kroah-Hartman
2013-07-19  5:26 ` [ 55/72] ext4: fix overflow when counting used blocks on 32-bit architectures Greg Kroah-Hartman
2013-07-19  5:26 ` [ 56/72] ext4: fix ext4_get_group_number() Greg Kroah-Hartman
2013-07-19  5:26 ` [ 57/72] ext4: dont show usrquota/grpquota twice in /proc/mounts Greg Kroah-Hartman
2013-07-19  5:26 ` [ 58/72] ext4: dont allow ext4_free_blocks() to fail due to ENOMEM Greg Kroah-Hartman
2013-07-19  5:26 ` [ 59/72] ARM: 7765/1: perf: Record the user-mode PC in the call chain Greg Kroah-Hartman
2013-07-19  5:26 ` [ 60/72] ARM: 7767/1: let the ASID allocator handle suspended animation Greg Kroah-Hartman
2013-07-19  5:26 ` [ 61/72] ARM: 7768/1: prevent risks of out-of-bound access in ASID allocator Greg Kroah-Hartman
2013-07-19  5:26 ` [ 62/72] ARM: 7769/1: Cortex-A15: fix erratum 798181 implementation Greg Kroah-Hartman
2013-07-19  5:26 ` [ 63/72] ARM: 7778/1: smp_twd: twd_update_frequency need be run on all online CPUs Greg Kroah-Hartman
2013-07-19  5:26 ` [ 64/72] ARM: dts: imx: cpus/cpu nodes dts updates Greg Kroah-Hartman
2013-07-19  5:26 ` [ 65/72] ARM: shmobile: r8a73a4: Fix resources for SCIFB0 Greg Kroah-Hartman
2013-07-19  5:26 ` [ 66/72] ARM: shmobile: emev2 GIO3 resource fix Greg Kroah-Hartman
2013-07-19  5:26 ` [ 67/72] ARM: mm: fix boot on SA1110 Assabet Greg Kroah-Hartman
2013-07-19  5:26 ` [ 68/72] drivers/dma/pl330.c: fix locking in pl330_free_chan_resources() Greg Kroah-Hartman
2013-07-19  5:26 ` [ 69/72] memcg, kmem: fix reference count handling on the error path Greg Kroah-Hartman
2013-07-19  5:26 ` [ 70/72] mm/memory-hotplug: fix lowmem count overflow when offline pages Greg Kroah-Hartman
2013-07-19  5:26 ` [ 71/72] Handle big endianness in NTLM (ntlmv2) authentication Greg Kroah-Hartman
2013-07-19  5:26 ` [ 72/72] UBIFS: correct mount message Greg Kroah-Hartman
2013-07-19  7:27 ` [ 00/72] 3.10.2-stable review Sven Joachim
2013-07-19 15:40   ` Greg Kroah-Hartman
2013-07-21  2:23     ` Satoru Takeuchi
2013-07-19 23:16 ` Shuah Khan
2013-07-19 23:44   ` Greg Kroah-Hartman
2013-07-20  0:17 ` Stefan Lippers-Hollmann
2013-07-20  0:25   ` [please disregard] " Stefan Lippers-Hollmann
2013-07-21  7:56 ` Willy Tarreau
2013-07-21 15:50   ` Greg Kroah-Hartman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20130719052601.381286751@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=dave.anglin@bell.net \
    --cc=deller@gmx.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).