From 7d07304234cdd2c2e6d3e31a13b7d38854e9b53b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 10 Dec 2020 15:14:48 +0100 Subject: [PATCH] 4.4-stable patches added patches: x86-uprobes-do-not-use-prefixes.nbytes-when-looping-over-prefixes.bytes.patch --- queue-4.4/series | 1 + ...tes-when-looping-over-prefixes.bytes.patch | 97 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 queue-4.4/x86-uprobes-do-not-use-prefixes.nbytes-when-looping-over-prefixes.bytes.patch diff --git a/queue-4.4/series b/queue-4.4/series index e99a5466c24..f552b8d55a0 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -36,3 +36,4 @@ btrfs-cleanup-cow-block-on-error.patch mm-userfaultfd-do-not-access-vma-vm_mm-after-calling-handle_userfault.patch gfs2-check-for-empty-rgrp-tree-in-gfs2_ri_update.patch input-i8042-fix-error-return-code-in-i8042_setup_aux.patch +x86-uprobes-do-not-use-prefixes.nbytes-when-looping-over-prefixes.bytes.patch diff --git a/queue-4.4/x86-uprobes-do-not-use-prefixes.nbytes-when-looping-over-prefixes.bytes.patch b/queue-4.4/x86-uprobes-do-not-use-prefixes.nbytes-when-looping-over-prefixes.bytes.patch new file mode 100644 index 00000000000..154f8163aba --- /dev/null +++ b/queue-4.4/x86-uprobes-do-not-use-prefixes.nbytes-when-looping-over-prefixes.bytes.patch @@ -0,0 +1,97 @@ +From foo@baz Thu Dec 10 03:08:33 PM CET 2020 +From: Masami Hiramatsu +Date: Thu, 3 Dec 2020 13:50:37 +0900 +Subject: x86/uprobes: Do not use prefixes.nbytes when looping over prefixes.bytes + +From: Masami Hiramatsu + +commit 4e9a5ae8df5b3365183150f6df49e49dece80d8c upstream + +Since insn.prefixes.nbytes can be bigger than the size of +insn.prefixes.bytes[] when a prefix is repeated, the proper check must +be + + insn.prefixes.bytes[i] != 0 and i < 4 + +instead of using insn.prefixes.nbytes. + +Introduce a for_each_insn_prefix() macro for this purpose. Debugged by +Kees Cook . + + [ bp: Massage commit message, sync with the respective header in tools/ + and drop "we". ] + +Fixes: 2b1444983508 ("uprobes, mm, x86: Add the ability to install and remove uprobes breakpoints") +Reported-by: syzbot+9b64b619f10f19d19a7c@syzkaller.appspotmail.com +Signed-off-by: Masami Hiramatsu +Signed-off-by: Borislav Petkov +Reviewed-by: Srikar Dronamraju +Cc: stable@vger.kernel.org +Link: https://lkml.kernel.org/r/160697103739.3146288.7437620795200799020.stgit@devnote2 +[sudip: adjust context, drop change of insn.h in tools] +Signed-off-by: Sudip Mukherjee +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/include/asm/insn.h | 15 +++++++++++++++ + arch/x86/kernel/uprobes.c | 10 ++++++---- + 2 files changed, 21 insertions(+), 4 deletions(-) + +--- a/arch/x86/include/asm/insn.h ++++ b/arch/x86/include/asm/insn.h +@@ -198,6 +198,21 @@ static inline int insn_offset_immediate( + return insn_offset_displacement(insn) + insn->displacement.nbytes; + } + ++/** ++ * for_each_insn_prefix() -- Iterate prefixes in the instruction ++ * @insn: Pointer to struct insn. ++ * @idx: Index storage. ++ * @prefix: Prefix byte. ++ * ++ * Iterate prefix bytes of given @insn. Each prefix byte is stored in @prefix ++ * and the index is stored in @idx (note that this @idx is just for a cursor, ++ * do not change it.) ++ * Since prefixes.nbytes can be bigger than 4 if some prefixes ++ * are repeated, it cannot be used for looping over the prefixes. ++ */ ++#define for_each_insn_prefix(insn, idx, prefix) \ ++ for (idx = 0; idx < ARRAY_SIZE(insn->prefixes.bytes) && (prefix = insn->prefixes.bytes[idx]) != 0; idx++) ++ + #define POP_SS_OPCODE 0x1f + #define MOV_SREG_OPCODE 0x8e + +--- a/arch/x86/kernel/uprobes.c ++++ b/arch/x86/kernel/uprobes.c +@@ -268,10 +268,11 @@ static volatile u32 good_2byte_insns[256 + + static bool is_prefix_bad(struct insn *insn) + { ++ insn_byte_t p; + int i; + +- for (i = 0; i < insn->prefixes.nbytes; i++) { +- switch (insn->prefixes.bytes[i]) { ++ for_each_insn_prefix(insn, i, p) { ++ switch (p) { + case 0x26: /* INAT_PFX_ES */ + case 0x2E: /* INAT_PFX_CS */ + case 0x36: /* INAT_PFX_DS */ +@@ -711,6 +712,7 @@ static struct uprobe_xol_ops branch_xol_ + static int branch_setup_xol_ops(struct arch_uprobe *auprobe, struct insn *insn) + { + u8 opc1 = OPCODE1(insn); ++ insn_byte_t p; + int i; + + switch (opc1) { +@@ -741,8 +743,8 @@ static int branch_setup_xol_ops(struct a + * Intel and AMD behavior differ in 64-bit mode: Intel ignores 66 prefix. + * No one uses these insns, reject any branch insns with such prefix. + */ +- for (i = 0; i < insn->prefixes.nbytes; i++) { +- if (insn->prefixes.bytes[i] == 0x66) ++ for_each_insn_prefix(insn, i, p) { ++ if (p == 0x66) + return -ENOTSUPP; + } + -- 2.47.3