[mips*] Backport math emulation fix from 4.5.
This commit is contained in:
parent
b1fa3fac88
commit
237b83662e
|
@ -59,6 +59,9 @@ linux (4.3.4-1) UNRELEASED; urgency=medium
|
||||||
* tcp: fix zero cwnd in tcp_cwnd_reduction (CVE-2016-2070)
|
* tcp: fix zero cwnd in tcp_cwnd_reduction (CVE-2016-2070)
|
||||||
* netfilter: nf_nat_redirect: add missing NULL pointer check (CVE-2015-8787)
|
* netfilter: nf_nat_redirect: add missing NULL pointer check (CVE-2015-8787)
|
||||||
|
|
||||||
|
[ Aurelien Jarno ]
|
||||||
|
* [mips*] Backport math emulation fix from 4.5.
|
||||||
|
|
||||||
-- Ben Hutchings <ben@decadent.org.uk> Sat, 23 Jan 2016 11:51:46 +0000
|
-- Ben Hutchings <ben@decadent.org.uk> Sat, 23 Jan 2016 11:51:46 +0000
|
||||||
|
|
||||||
linux (4.3.3-7) unstable; urgency=medium
|
linux (4.3.3-7) unstable; urgency=medium
|
||||||
|
|
140
debian/patches/bugfix/mips/mips-math-emu-correctly-handle-nop-emulation.patch
vendored
Normal file
140
debian/patches/bugfix/mips/mips-math-emu-correctly-handle-nop-emulation.patch
vendored
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
From: "Maciej W. Rozycki" <macro@imgtec.com>
|
||||||
|
Date: Fri, 22 Jan 2016 05:20:26 +0000
|
||||||
|
Subject: MIPS: math-emu: Correctly handle NOP emulation
|
||||||
|
Origin: https://git.kernel.org/linus/e4553573b37c3f72533683cb5f3a1ad300b18d37
|
||||||
|
|
||||||
|
Fix an issue introduced with commit 9ab4471c9f1b ("MIPS: math-emu:
|
||||||
|
Correct delay-slot exception propagation") where the emulation of a NOP
|
||||||
|
instruction signals the need to terminate the emulation loop. This in
|
||||||
|
turn, if the PC has not changed from the entry to the loop, will cause
|
||||||
|
the kernel to terminate the program with SIGILL.
|
||||||
|
|
||||||
|
Consider this program:
|
||||||
|
|
||||||
|
static double div(double d)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
d /= 2.0;
|
||||||
|
while (d > .5);
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
return div(argc);
|
||||||
|
}
|
||||||
|
|
||||||
|
which gets compiled to the following binary code:
|
||||||
|
|
||||||
|
00400490 <main>:
|
||||||
|
400490: 44840000 mtc1 a0,$f0
|
||||||
|
400494: 3c020040 lui v0,0x40
|
||||||
|
400498: d44207f8 ldc1 $f2,2040(v0)
|
||||||
|
40049c: 46800021 cvt.d.w $f0,$f0
|
||||||
|
4004a0: 46220002 mul.d $f0,$f0,$f2
|
||||||
|
4004a4: 4620103c c.lt.d $f2,$f0
|
||||||
|
4004a8: 4501fffd bc1t 4004a0 <main+0x10>
|
||||||
|
4004ac: 00000000 nop
|
||||||
|
4004b0: 4620000d trunc.w.d $f0,$f0
|
||||||
|
4004b4: 03e00008 jr ra
|
||||||
|
4004b8: 44020000 mfc1 v0,$f0
|
||||||
|
4004bc: 00000000 nop
|
||||||
|
|
||||||
|
Where the FPU emulator is used, depending on the number of command-line
|
||||||
|
arguments this code will either run to completion or terminate with
|
||||||
|
SIGILL.
|
||||||
|
|
||||||
|
If no arguments are specified, then BC1T will not be taken, NOP will not
|
||||||
|
be emulated and code will complete successfully.
|
||||||
|
|
||||||
|
If one argument is specified, then BC1T will be taken once and NOP will
|
||||||
|
be emulated. At this point the entry PC value will be 0x400498 and the
|
||||||
|
new PC value, set by `mips_dsemul' will be 0x4004a0, the target of BC1T.
|
||||||
|
The emulation loop will terminate, but SIGILL will not be issued,
|
||||||
|
because the PC has changed. The FPU emulator will be entered again and
|
||||||
|
on the second execution BC1T will not be taken, NOP will not be emulated
|
||||||
|
and code will complete successfully.
|
||||||
|
|
||||||
|
If two or more arguments are specified, then the first execution of BC1T
|
||||||
|
will proceed as above. Upon reentering the FPU emulator the emulation
|
||||||
|
loop will continue to BC1T, at which point the branch will be taken and
|
||||||
|
NOP emulated again. At this point however the entry PC value will be
|
||||||
|
0x4004a0, the same as the target of BC1T. This will make the emulator
|
||||||
|
conclude that execution has not advanced and therefore an unsupported
|
||||||
|
FPU instruction has been encountered, and SIGILL will be sent to the
|
||||||
|
process.
|
||||||
|
|
||||||
|
Fix the problem by extending the internal API of `mips_dsemul', making
|
||||||
|
it return -1 if no delay slot emulation frame has been made, the
|
||||||
|
instruction has been handled and execution of the emulation loop needs
|
||||||
|
to continue as if nothing happened. Remove code from `mips_dsemul' to
|
||||||
|
reproduce steps made by the emulation loop at the conclusion of each
|
||||||
|
iteration, as those will be reached normally now. Adjust call sites
|
||||||
|
accordingly. Document the API.
|
||||||
|
|
||||||
|
Signed-off-by: Maciej W. Rozycki <macro@imgtec.com>
|
||||||
|
Cc: Aurelien Jarno <aurelien@aurel32.net>
|
||||||
|
Cc: linux-mips@linux-mips.org
|
||||||
|
Patchwork: https://patchwork.linux-mips.org/patch/12172/
|
||||||
|
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
|
||||||
|
---
|
||||||
|
arch/mips/math-emu/cp1emu.c | 4 ++++
|
||||||
|
arch/mips/math-emu/dsemul.c | 14 ++++++++------
|
||||||
|
2 files changed, 12 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
|
||||||
|
index 32f0e19..cdfd44f 100644
|
||||||
|
--- a/arch/mips/math-emu/cp1emu.c
|
||||||
|
+++ b/arch/mips/math-emu/cp1emu.c
|
||||||
|
@@ -1266,6 +1266,8 @@ branch_common:
|
||||||
|
*/
|
||||||
|
sig = mips_dsemul(xcp, ir,
|
||||||
|
contpc);
|
||||||
|
+ if (sig < 0)
|
||||||
|
+ break;
|
||||||
|
if (sig)
|
||||||
|
xcp->cp0_epc = bcpc;
|
||||||
|
/*
|
||||||
|
@@ -1319,6 +1321,8 @@ branch_common:
|
||||||
|
* instruction in the dslot
|
||||||
|
*/
|
||||||
|
sig = mips_dsemul(xcp, ir, contpc);
|
||||||
|
+ if (sig < 0)
|
||||||
|
+ break;
|
||||||
|
if (sig)
|
||||||
|
xcp->cp0_epc = bcpc;
|
||||||
|
/* SIGILL forces out of the emulation loop. */
|
||||||
|
diff --git a/arch/mips/math-emu/dsemul.c b/arch/mips/math-emu/dsemul.c
|
||||||
|
index cbb36c1..70e4824 100644
|
||||||
|
--- a/arch/mips/math-emu/dsemul.c
|
||||||
|
+++ b/arch/mips/math-emu/dsemul.c
|
||||||
|
@@ -31,18 +31,20 @@ struct emuframe {
|
||||||
|
unsigned long epc;
|
||||||
|
};
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * Set up an emulation frame for instruction IR, from a delay slot of
|
||||||
|
+ * a branch jumping to CPC. Return 0 if successful, -1 if no emulation
|
||||||
|
+ * required, otherwise a signal number causing a frame setup failure.
|
||||||
|
+ */
|
||||||
|
int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
|
||||||
|
{
|
||||||
|
struct emuframe __user *fr;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
+ /* NOP is easy */
|
||||||
|
if ((get_isa16_mode(regs->cp0_epc) && ((ir >> 16) == MM_NOP16)) ||
|
||||||
|
- (ir == 0)) {
|
||||||
|
- /* NOP is easy */
|
||||||
|
- regs->cp0_epc = cpc;
|
||||||
|
- clear_delay_slot(regs);
|
||||||
|
- return 0;
|
||||||
|
- }
|
||||||
|
+ (ir == 0))
|
||||||
|
+ return -1;
|
||||||
|
|
||||||
|
pr_debug("dsemul %lx %lx\n", regs->cp0_epc, cpc);
|
||||||
|
|
||||||
|
--
|
||||||
|
2.7.0.rc3
|
||||||
|
|
|
@ -51,6 +51,7 @@ bugfix/x86/drm-i915-shut-up-gen8-sde-irq-dmesg-noise.patch
|
||||||
bugfix/arm/arm-dts-kirkwood-fix-qnap-ts219-power-off.patch
|
bugfix/arm/arm-dts-kirkwood-fix-qnap-ts219-power-off.patch
|
||||||
bugfix/x86/drm-i915-mark-uneven-memory-banks-on-gen4-desktop-as.patch
|
bugfix/x86/drm-i915-mark-uneven-memory-banks-on-gen4-desktop-as.patch
|
||||||
bugfix/x86/bios-return-actual-size-of-the-buffer-retrieved-via-_rom.patch
|
bugfix/x86/bios-return-actual-size-of-the-buffer-retrieved-via-_rom.patch
|
||||||
|
bugfix/mips/mips-math-emu-correctly-handle-nop-emulation.patch
|
||||||
|
|
||||||
# Arch features
|
# Arch features
|
||||||
features/mips/MIPS-increase-MAX-PHYSMEM-BITS-on-Loongson-3-only.patch
|
features/mips/MIPS-increase-MAX-PHYSMEM-BITS-on-Loongson-3-only.patch
|
||||||
|
|
Loading…
Reference in New Issue