uprobes/x86: Add uprobe_init_insn(), kill validate_insn_{32,64}bits()
authorOleg Nesterov <oleg@redhat.com>
Sat, 19 Apr 2014 10:34:02 +0000 (12:34 +0200)
committerOleg Nesterov <oleg@redhat.com>
Wed, 30 Apr 2014 17:10:33 +0000 (19:10 +0200)
validate_insn_32bits() and validate_insn_64bits() are very similar,
turn them into the single uprobe_init_insn() which has the additional
"bool x86_64" argument which can be passed to insn_init() and used to
choose between good_insns_64/good_insns_32.

Also kill UPROBE_FIX_NONE, it has no users.

Note: the current code doesn't use ifdef's consistently, good_insns_64
depends on CONFIG_X86_64 but good_insns_32 is unconditional. This patch
removes ifdef around good_insns_64, we will add it back later along with
the similar one for good_insns_32.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Reviewed-by: Jim Keniston <jkenisto@us.ibm.com>
Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
arch/x86/kernel/uprobes.c

index 3cf24a2181966351818b21d129604cc35c6c80ce..b4aff6a70f4d403b5244d2230511120ca4fd275a 100644 (file)
@@ -32,9 +32,6 @@
 
 /* Post-execution fixups. */
 
-/* No fixup needed */
-#define UPROBE_FIX_NONE                0x0
-
 /* Adjust IP back to vicinity of actual insn */
 #define UPROBE_FIX_IP          0x1
 
@@ -114,7 +111,6 @@ static volatile u32 good_2byte_insns[256 / 32] = {
        /*      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f         */
 };
 
-#ifdef CONFIG_X86_64
 /* Good-instruction tables for 64-bit apps */
 static volatile u32 good_insns_64[256 / 32] = {
        /*      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f         */
@@ -138,7 +134,6 @@ static volatile u32 good_insns_64[256 / 32] = {
        /*      ----------------------------------------------         */
        /*      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f         */
 };
-#endif
 #undef W
 
 /*
@@ -209,16 +204,22 @@ static bool is_prefix_bad(struct insn *insn)
        return false;
 }
 
-static int validate_insn_32bits(struct arch_uprobe *auprobe, struct insn *insn)
+static int uprobe_init_insn(struct arch_uprobe *auprobe, struct insn *insn, bool x86_64)
 {
-       insn_init(insn, auprobe->insn, false);
+       u32 volatile *good_insns;
+
+       insn_init(insn, auprobe->insn, x86_64);
 
-       /* Skip good instruction prefixes; reject "bad" ones. */
        insn_get_opcode(insn);
        if (is_prefix_bad(insn))
                return -ENOTSUPP;
 
-       if (test_bit(OPCODE1(insn), (unsigned long *)good_insns_32))
+       if (x86_64)
+               good_insns = good_insns_64;
+       else
+               good_insns = good_insns_32;
+
+       if (test_bit(OPCODE1(insn), (unsigned long *)good_insns))
                return 0;
 
        if (insn->opcode.nbytes == 2) {
@@ -355,30 +356,10 @@ handle_riprel_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs, long *
        }
 }
 
-static int validate_insn_64bits(struct arch_uprobe *auprobe, struct insn *insn)
-{
-       insn_init(insn, auprobe->insn, true);
-
-       /* Skip good instruction prefixes; reject "bad" ones. */
-       insn_get_opcode(insn);
-       if (is_prefix_bad(insn))
-               return -ENOTSUPP;
-
-       if (test_bit(OPCODE1(insn), (unsigned long *)good_insns_64))
-               return 0;
-
-       if (insn->opcode.nbytes == 2) {
-               if (test_bit(OPCODE2(insn), (unsigned long *)good_2byte_insns))
-                       return 0;
-       }
-       return -ENOTSUPP;
-}
-
 static int validate_insn_bits(struct arch_uprobe *auprobe, struct mm_struct *mm, struct insn *insn)
 {
-       if (mm->context.ia32_compat)
-               return validate_insn_32bits(auprobe, insn);
-       return validate_insn_64bits(auprobe, insn);
+       bool x86_64 = !mm->context.ia32_compat;
+       return uprobe_init_insn(auprobe, insn, x86_64);
 }
 #else /* 32-bit: */
 /*
@@ -398,7 +379,7 @@ static void handle_riprel_post_xol(struct arch_uprobe *auprobe, struct pt_regs *
 
 static int validate_insn_bits(struct arch_uprobe *auprobe, struct mm_struct *mm,  struct insn *insn)
 {
-       return validate_insn_32bits(auprobe, insn);
+       return uprobe_init_insn(auprobe, insn, false);
 }
 #endif /* CONFIG_X86_64 */