From 237b83662e0640933bb89d2272746ac5489d1858 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Wed, 27 Jan 2016 22:33:18 +0100 Subject: [PATCH] [mips*] Backport math emulation fix from 4.5. --- debian/changelog | 3 + ...h-emu-correctly-handle-nop-emulation.patch | 140 ++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 144 insertions(+) create mode 100644 debian/patches/bugfix/mips/mips-math-emu-correctly-handle-nop-emulation.patch diff --git a/debian/changelog b/debian/changelog index b529baaee..2e6203d4d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -59,6 +59,9 @@ linux (4.3.4-1) UNRELEASED; urgency=medium * tcp: fix zero cwnd in tcp_cwnd_reduction (CVE-2016-2070) * netfilter: nf_nat_redirect: add missing NULL pointer check (CVE-2015-8787) + [ Aurelien Jarno ] + * [mips*] Backport math emulation fix from 4.5. + -- Ben Hutchings Sat, 23 Jan 2016 11:51:46 +0000 linux (4.3.3-7) unstable; urgency=medium diff --git a/debian/patches/bugfix/mips/mips-math-emu-correctly-handle-nop-emulation.patch b/debian/patches/bugfix/mips/mips-math-emu-correctly-handle-nop-emulation.patch new file mode 100644 index 000000000..cb2e904bf --- /dev/null +++ b/debian/patches/bugfix/mips/mips-math-emu-correctly-handle-nop-emulation.patch @@ -0,0 +1,140 @@ +From: "Maciej W. Rozycki" +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
: + 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 + 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 +Cc: Aurelien Jarno +Cc: linux-mips@linux-mips.org +Patchwork: https://patchwork.linux-mips.org/patch/12172/ +Signed-off-by: Ralf Baechle +--- + 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 + diff --git a/debian/patches/series b/debian/patches/series index a202989e4..6c7346ba6 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -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/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/mips/mips-math-emu-correctly-handle-nop-emulation.patch # Arch features features/mips/MIPS-increase-MAX-PHYSMEM-BITS-on-Loongson-3-only.patch