openwrt/target/linux/generic/pending-4.9/304-mips_disable_fpu.patch
Koen Vandeputte 76d1e8a0c2 kernel: bump 4.9 to 4.9.186
Refreshed all patches.

Fixes:
- CVE-2019-3846

Compile-tested on: ar71xx
Runtime-tested on: ar71xx

Signed-off-by: Koen Vandeputte <koen.vandeputte@ncentric.com>
2019-07-31 16:54:50 +02:00

138 lines
4.1 KiB
Diff

From: Manuel Lauss <manuel.lauss@gmail.com>
Subject: [RFC PATCH v4 2/2] MIPS: make FPU emulator optional
This small patch makes the MIPS FPU emulator optional. The kernel
kills float-users on systems without a hardware FPU by sending a SIGILL.
Disabling the emulator shrinks vmlinux by about 54kBytes (32bit,
optimizing for size).
Signed-off-by: Manuel Lauss <manuel.lauss@gmail.com>
---
v4: rediffed because of patch 1/2, should now work with micromips as well
v3: updated patch description with size savings.
v2: incorporated changes suggested by Jonas Gorski
force the fpu emulator on for micromips: relocating the parts
of the mmips code in the emulator to other areas would be a
much larger change; I went the cheap route instead with this.
arch/mips/Kbuild | 2 +-
arch/mips/Kconfig | 14 ++++++++++++++
arch/mips/include/asm/fpu.h | 5 +++--
arch/mips/include/asm/fpu_emulator.h | 15 +++++++++++++++
4 files changed, 33 insertions(+), 3 deletions(-)
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2892,6 +2892,20 @@ config MIPS_O32_FP64_SUPPORT
If unsure, say N.
+config MIPS_FPU_EMULATOR
+ bool "MIPS FPU Emulator"
+ default y
+ help
+ This option lets you disable the built-in MIPS FPU (Coprocessor 1)
+ emulator, which handles floating-point instructions on processors
+ without a hardware FPU. It is generally a good idea to keep the
+ emulator built-in, unless you are perfectly sure you have a
+ complete soft-float environment. With the emulator disabled, all
+ users of float operations will be killed with an illegal instr-
+ uction exception.
+
+ Say Y, please.
+
config USE_OF
bool
select OF
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -287,7 +287,7 @@ OBJCOPYFLAGS += --remove-section=.regin
head-y := arch/mips/kernel/head.o
libs-y += arch/mips/lib/
-libs-y += arch/mips/math-emu/
+libs-$(CONFIG_MIPS_FPU_EMULATOR) += arch/mips/math-emu/
# See arch/mips/Kbuild for content of core part of the kernel
core-y += arch/mips/
--- a/arch/mips/include/asm/fpu.h
+++ b/arch/mips/include/asm/fpu.h
@@ -227,8 +227,10 @@ static inline int init_fpu(void)
/* Restore FRE */
write_c0_config5(config5);
enable_fpu_hazard();
- } else
+ } else if (IS_ENABLED(CONFIG_MIPS_FPU_EMULATOR))
fpu_emulator_init_fpu();
+ else
+ ret = SIGILL;
return ret;
}
--- a/arch/mips/include/asm/fpu_emulator.h
+++ b/arch/mips/include/asm/fpu_emulator.h
@@ -30,6 +30,7 @@
#include <asm/local.h>
#include <asm/processor.h>
+#ifdef CONFIG_MIPS_FPU_EMULATOR
#ifdef CONFIG_DEBUG_FS
struct mips_fpu_emulator_stats {
@@ -63,6 +64,16 @@ do { \
extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
struct mips_fpu_struct *ctx, int has_fpu,
void *__user *fault_addr);
+#else /* no CONFIG_MIPS_FPU_EMULATOR */
+static inline int fpu_emulator_cop1Handler(struct pt_regs *xcp,
+ struct mips_fpu_struct *ctx, int has_fpu,
+ void *__user *fault_addr)
+{
+ *fault_addr = NULL;
+ return SIGILL; /* we don't speak MIPS FPU */
+}
+#endif /* CONFIG_MIPS_FPU_EMULATOR */
+
void force_fcr31_sig(unsigned long fcr31, void __user *fault_addr,
struct task_struct *tsk);
int process_fpemu_return(int sig, void __user *fault_addr,
--- a/arch/mips/include/asm/dsemul.h
+++ b/arch/mips/include/asm/dsemul.h
@@ -41,6 +41,7 @@ struct task_struct;
extern int mips_dsemul(struct pt_regs *regs, mips_instruction ir,
unsigned long branch_pc, unsigned long cont_pc);
+#ifdef CONFIG_MIPS_FPU_EMULATOR
/**
* do_dsemulret() - Return from a delay slot 'emulation' frame
* @xcp: User thread register context.
@@ -88,5 +89,27 @@ extern bool dsemul_thread_rollback(struc
* before @mm is freed in order to avoid memory leaks.
*/
extern void dsemul_mm_cleanup(struct mm_struct *mm);
+#else
+static inline bool do_dsemulret(struct pt_regs *xcp)
+{
+ return false;
+}
+
+static inline bool dsemul_thread_cleanup(struct task_struct *tsk)
+{
+ return false;
+}
+
+static inline bool dsemul_thread_rollback(struct pt_regs *regs)
+{
+ return false;
+}
+
+static inline void dsemul_mm_cleanup(struct mm_struct *mm)
+{
+
+}
+
+#endif
#endif /* __MIPS_ASM_DSEMUL_H__ */