12b144498SSrikar Dronamraju /* 27b2d81d4SIngo Molnar * User-space Probes (UProbes) for x86 32b144498SSrikar Dronamraju * 42b144498SSrikar Dronamraju * This program is free software; you can redistribute it and/or modify 52b144498SSrikar Dronamraju * it under the terms of the GNU General Public License as published by 62b144498SSrikar Dronamraju * the Free Software Foundation; either version 2 of the License, or 72b144498SSrikar Dronamraju * (at your option) any later version. 82b144498SSrikar Dronamraju * 92b144498SSrikar Dronamraju * This program is distributed in the hope that it will be useful, 102b144498SSrikar Dronamraju * but WITHOUT ANY WARRANTY; without even the implied warranty of 112b144498SSrikar Dronamraju * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 122b144498SSrikar Dronamraju * GNU General Public License for more details. 132b144498SSrikar Dronamraju * 142b144498SSrikar Dronamraju * You should have received a copy of the GNU General Public License 152b144498SSrikar Dronamraju * along with this program; if not, write to the Free Software 162b144498SSrikar Dronamraju * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 172b144498SSrikar Dronamraju * 182b144498SSrikar Dronamraju * Copyright (C) IBM Corporation, 2008-2011 192b144498SSrikar Dronamraju * Authors: 202b144498SSrikar Dronamraju * Srikar Dronamraju 212b144498SSrikar Dronamraju * Jim Keniston 222b144498SSrikar Dronamraju */ 232b144498SSrikar Dronamraju #include <linux/kernel.h> 242b144498SSrikar Dronamraju #include <linux/sched.h> 252b144498SSrikar Dronamraju #include <linux/ptrace.h> 262b144498SSrikar Dronamraju #include <linux/uprobes.h> 270326f5a9SSrikar Dronamraju #include <linux/uaccess.h> 282b144498SSrikar Dronamraju 292b144498SSrikar Dronamraju #include <linux/kdebug.h> 300326f5a9SSrikar Dronamraju #include <asm/processor.h> 312b144498SSrikar Dronamraju #include <asm/insn.h> 322b144498SSrikar Dronamraju 332b144498SSrikar Dronamraju /* Post-execution fixups. */ 342b144498SSrikar Dronamraju 352b144498SSrikar Dronamraju /* No fixup needed */ 36900771a4SSrikar Dronamraju #define UPROBE_FIX_NONE 0x0 370326f5a9SSrikar Dronamraju 382b144498SSrikar Dronamraju /* Adjust IP back to vicinity of actual insn */ 39900771a4SSrikar Dronamraju #define UPROBE_FIX_IP 0x1 400326f5a9SSrikar Dronamraju 412b144498SSrikar Dronamraju /* Adjust the return address of a call insn */ 42900771a4SSrikar Dronamraju #define UPROBE_FIX_CALL 0x2 432b144498SSrikar Dronamraju 44bdc1e472SSebastian Andrzej Siewior /* Instruction will modify TF, don't change it */ 45bdc1e472SSebastian Andrzej Siewior #define UPROBE_FIX_SETF 0x4 46bdc1e472SSebastian Andrzej Siewior 47900771a4SSrikar Dronamraju #define UPROBE_FIX_RIP_AX 0x8000 48900771a4SSrikar Dronamraju #define UPROBE_FIX_RIP_CX 0x4000 492b144498SSrikar Dronamraju 500326f5a9SSrikar Dronamraju #define UPROBE_TRAP_NR UINT_MAX 510326f5a9SSrikar Dronamraju 522b144498SSrikar Dronamraju /* Adaptations for mhiramat x86 decoder v14. */ 532b144498SSrikar Dronamraju #define OPCODE1(insn) ((insn)->opcode.bytes[0]) 542b144498SSrikar Dronamraju #define OPCODE2(insn) ((insn)->opcode.bytes[1]) 552b144498SSrikar Dronamraju #define OPCODE3(insn) ((insn)->opcode.bytes[2]) 56ddb69f27SOleg Nesterov #define MODRM_REG(insn) X86_MODRM_REG((insn)->modrm.value) 572b144498SSrikar Dronamraju 582b144498SSrikar Dronamraju #define W(row, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf)\ 592b144498SSrikar Dronamraju (((b0##UL << 0x0)|(b1##UL << 0x1)|(b2##UL << 0x2)|(b3##UL << 0x3) | \ 602b144498SSrikar Dronamraju (b4##UL << 0x4)|(b5##UL << 0x5)|(b6##UL << 0x6)|(b7##UL << 0x7) | \ 612b144498SSrikar Dronamraju (b8##UL << 0x8)|(b9##UL << 0x9)|(ba##UL << 0xa)|(bb##UL << 0xb) | \ 622b144498SSrikar Dronamraju (bc##UL << 0xc)|(bd##UL << 0xd)|(be##UL << 0xe)|(bf##UL << 0xf)) \ 632b144498SSrikar Dronamraju << (row % 32)) 642b144498SSrikar Dronamraju 6504a3d984SSrikar Dronamraju /* 6604a3d984SSrikar Dronamraju * Good-instruction tables for 32-bit apps. This is non-const and volatile 6704a3d984SSrikar Dronamraju * to keep gcc from statically optimizing it out, as variable_test_bit makes 6804a3d984SSrikar Dronamraju * some versions of gcc to think only *(unsigned long*) is used. 6904a3d984SSrikar Dronamraju */ 7004a3d984SSrikar Dronamraju static volatile u32 good_insns_32[256 / 32] = { 712b144498SSrikar Dronamraju /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 722b144498SSrikar Dronamraju /* ---------------------------------------------- */ 732b144498SSrikar Dronamraju W(0x00, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0) | /* 00 */ 742b144498SSrikar Dronamraju W(0x10, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0) , /* 10 */ 752b144498SSrikar Dronamraju W(0x20, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1) | /* 20 */ 762b144498SSrikar Dronamraju W(0x30, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1) , /* 30 */ 772b144498SSrikar Dronamraju W(0x40, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 40 */ 782b144498SSrikar Dronamraju W(0x50, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 50 */ 792b144498SSrikar Dronamraju W(0x60, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) | /* 60 */ 802b144498SSrikar Dronamraju W(0x70, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 70 */ 812b144498SSrikar Dronamraju W(0x80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 80 */ 822b144498SSrikar Dronamraju W(0x90, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 90 */ 832b144498SSrikar Dronamraju W(0xa0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* a0 */ 842b144498SSrikar Dronamraju W(0xb0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* b0 */ 852b144498SSrikar Dronamraju W(0xc0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0) | /* c0 */ 862b144498SSrikar Dronamraju W(0xd0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* d0 */ 872b144498SSrikar Dronamraju W(0xe0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) | /* e0 */ 882b144498SSrikar Dronamraju W(0xf0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1) /* f0 */ 892b144498SSrikar Dronamraju /* ---------------------------------------------- */ 902b144498SSrikar Dronamraju /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 912b144498SSrikar Dronamraju }; 922b144498SSrikar Dronamraju 932b144498SSrikar Dronamraju /* Using this for both 64-bit and 32-bit apps */ 9404a3d984SSrikar Dronamraju static volatile u32 good_2byte_insns[256 / 32] = { 952b144498SSrikar Dronamraju /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 962b144498SSrikar Dronamraju /* ---------------------------------------------- */ 972b144498SSrikar Dronamraju W(0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1) | /* 00 */ 982b144498SSrikar Dronamraju W(0x10, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1) , /* 10 */ 992b144498SSrikar Dronamraju W(0x20, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1) | /* 20 */ 1002b144498SSrikar Dronamraju W(0x30, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) , /* 30 */ 1012b144498SSrikar Dronamraju W(0x40, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 40 */ 1022b144498SSrikar Dronamraju W(0x50, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 50 */ 1032b144498SSrikar Dronamraju W(0x60, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 60 */ 1042b144498SSrikar Dronamraju W(0x70, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1) , /* 70 */ 1052b144498SSrikar Dronamraju W(0x80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 80 */ 1062b144498SSrikar Dronamraju W(0x90, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 90 */ 1072b144498SSrikar Dronamraju W(0xa0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1) | /* a0 */ 1082b144498SSrikar Dronamraju W(0xb0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1) , /* b0 */ 1092b144498SSrikar Dronamraju W(0xc0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* c0 */ 1102b144498SSrikar Dronamraju W(0xd0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* d0 */ 1112b144498SSrikar Dronamraju W(0xe0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* e0 */ 1122b144498SSrikar Dronamraju W(0xf0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0) /* f0 */ 1132b144498SSrikar Dronamraju /* ---------------------------------------------- */ 1142b144498SSrikar Dronamraju /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 1152b144498SSrikar Dronamraju }; 1162b144498SSrikar Dronamraju 11704a3d984SSrikar Dronamraju #ifdef CONFIG_X86_64 11804a3d984SSrikar Dronamraju /* Good-instruction tables for 64-bit apps */ 11904a3d984SSrikar Dronamraju static volatile u32 good_insns_64[256 / 32] = { 12004a3d984SSrikar Dronamraju /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 12104a3d984SSrikar Dronamraju /* ---------------------------------------------- */ 12204a3d984SSrikar Dronamraju W(0x00, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0) | /* 00 */ 12304a3d984SSrikar Dronamraju W(0x10, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0) , /* 10 */ 12404a3d984SSrikar Dronamraju W(0x20, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0) | /* 20 */ 12504a3d984SSrikar Dronamraju W(0x30, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0) , /* 30 */ 12604a3d984SSrikar Dronamraju W(0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) | /* 40 */ 12704a3d984SSrikar Dronamraju W(0x50, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 50 */ 12804a3d984SSrikar Dronamraju W(0x60, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) | /* 60 */ 12904a3d984SSrikar Dronamraju W(0x70, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 70 */ 13004a3d984SSrikar Dronamraju W(0x80, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 80 */ 13104a3d984SSrikar Dronamraju W(0x90, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 90 */ 13204a3d984SSrikar Dronamraju W(0xa0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* a0 */ 13304a3d984SSrikar Dronamraju W(0xb0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* b0 */ 13404a3d984SSrikar Dronamraju W(0xc0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0) | /* c0 */ 13504a3d984SSrikar Dronamraju W(0xd0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* d0 */ 13604a3d984SSrikar Dronamraju W(0xe0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) | /* e0 */ 13704a3d984SSrikar Dronamraju W(0xf0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1) /* f0 */ 13804a3d984SSrikar Dronamraju /* ---------------------------------------------- */ 13904a3d984SSrikar Dronamraju /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 14004a3d984SSrikar Dronamraju }; 14104a3d984SSrikar Dronamraju #endif 1422b144498SSrikar Dronamraju #undef W 1432b144498SSrikar Dronamraju 1442b144498SSrikar Dronamraju /* 1452b144498SSrikar Dronamraju * opcodes we'll probably never support: 1467b2d81d4SIngo Molnar * 1472b144498SSrikar Dronamraju * 6c-6d, e4-e5, ec-ed - in 1482b144498SSrikar Dronamraju * 6e-6f, e6-e7, ee-ef - out 1492b144498SSrikar Dronamraju * cc, cd - int3, int 1502b144498SSrikar Dronamraju * cf - iret 1512b144498SSrikar Dronamraju * d6 - illegal instruction 1522b144498SSrikar Dronamraju * f1 - int1/icebp 1532b144498SSrikar Dronamraju * f4 - hlt 1542b144498SSrikar Dronamraju * fa, fb - cli, sti 1552b144498SSrikar Dronamraju * 0f - lar, lsl, syscall, clts, sysret, sysenter, sysexit, invd, wbinvd, ud2 1562b144498SSrikar Dronamraju * 1572b144498SSrikar Dronamraju * invalid opcodes in 64-bit mode: 1582b144498SSrikar Dronamraju * 1597b2d81d4SIngo Molnar * 06, 0e, 16, 1e, 27, 2f, 37, 3f, 60-62, 82, c4-c5, d4-d5 1602b144498SSrikar Dronamraju * 63 - we support this opcode in x86_64 but not in i386. 1612b144498SSrikar Dronamraju * 1622b144498SSrikar Dronamraju * opcodes we may need to refine support for: 1637b2d81d4SIngo Molnar * 1642b144498SSrikar Dronamraju * 0f - 2-byte instructions: For many of these instructions, the validity 1652b144498SSrikar Dronamraju * depends on the prefix and/or the reg field. On such instructions, we 1662b144498SSrikar Dronamraju * just consider the opcode combination valid if it corresponds to any 1672b144498SSrikar Dronamraju * valid instruction. 1687b2d81d4SIngo Molnar * 1692b144498SSrikar Dronamraju * 8f - Group 1 - only reg = 0 is OK 1702b144498SSrikar Dronamraju * c6-c7 - Group 11 - only reg = 0 is OK 1712b144498SSrikar Dronamraju * d9-df - fpu insns with some illegal encodings 1722b144498SSrikar Dronamraju * f2, f3 - repnz, repz prefixes. These are also the first byte for 1732b144498SSrikar Dronamraju * certain floating-point instructions, such as addsd. 1747b2d81d4SIngo Molnar * 1752b144498SSrikar Dronamraju * fe - Group 4 - only reg = 0 or 1 is OK 1762b144498SSrikar Dronamraju * ff - Group 5 - only reg = 0-6 is OK 1772b144498SSrikar Dronamraju * 1782b144498SSrikar Dronamraju * others -- Do we need to support these? 1797b2d81d4SIngo Molnar * 1802b144498SSrikar Dronamraju * 0f - (floating-point?) prefetch instructions 1812b144498SSrikar Dronamraju * 07, 17, 1f - pop es, pop ss, pop ds 1822b144498SSrikar Dronamraju * 26, 2e, 36, 3e - es:, cs:, ss:, ds: segment prefixes -- 1832b144498SSrikar Dronamraju * but 64 and 65 (fs: and gs:) seem to be used, so we support them 1842b144498SSrikar Dronamraju * 67 - addr16 prefix 1852b144498SSrikar Dronamraju * ce - into 1862b144498SSrikar Dronamraju * f0 - lock prefix 1872b144498SSrikar Dronamraju */ 1882b144498SSrikar Dronamraju 1892b144498SSrikar Dronamraju /* 1902b144498SSrikar Dronamraju * TODO: 1912b144498SSrikar Dronamraju * - Where necessary, examine the modrm byte and allow only valid instructions 1922b144498SSrikar Dronamraju * in the different Groups and fpu instructions. 1932b144498SSrikar Dronamraju */ 1942b144498SSrikar Dronamraju 1952b144498SSrikar Dronamraju static bool is_prefix_bad(struct insn *insn) 1962b144498SSrikar Dronamraju { 1972b144498SSrikar Dronamraju int i; 1982b144498SSrikar Dronamraju 1992b144498SSrikar Dronamraju for (i = 0; i < insn->prefixes.nbytes; i++) { 2002b144498SSrikar Dronamraju switch (insn->prefixes.bytes[i]) { 2012b144498SSrikar Dronamraju case 0x26: /* INAT_PFX_ES */ 2022b144498SSrikar Dronamraju case 0x2E: /* INAT_PFX_CS */ 2032b144498SSrikar Dronamraju case 0x36: /* INAT_PFX_DS */ 2042b144498SSrikar Dronamraju case 0x3E: /* INAT_PFX_SS */ 2052b144498SSrikar Dronamraju case 0xF0: /* INAT_PFX_LOCK */ 2062b144498SSrikar Dronamraju return true; 2072b144498SSrikar Dronamraju } 2082b144498SSrikar Dronamraju } 2092b144498SSrikar Dronamraju return false; 2102b144498SSrikar Dronamraju } 2112b144498SSrikar Dronamraju 2123ff54efdSSrikar Dronamraju static int validate_insn_32bits(struct arch_uprobe *auprobe, struct insn *insn) 2132b144498SSrikar Dronamraju { 2143ff54efdSSrikar Dronamraju insn_init(insn, auprobe->insn, false); 2152b144498SSrikar Dronamraju 2162b144498SSrikar Dronamraju /* Skip good instruction prefixes; reject "bad" ones. */ 2172b144498SSrikar Dronamraju insn_get_opcode(insn); 2182b144498SSrikar Dronamraju if (is_prefix_bad(insn)) 2192b144498SSrikar Dronamraju return -ENOTSUPP; 2207b2d81d4SIngo Molnar 2212b144498SSrikar Dronamraju if (test_bit(OPCODE1(insn), (unsigned long *)good_insns_32)) 2222b144498SSrikar Dronamraju return 0; 2237b2d81d4SIngo Molnar 2242b144498SSrikar Dronamraju if (insn->opcode.nbytes == 2) { 2252b144498SSrikar Dronamraju if (test_bit(OPCODE2(insn), (unsigned long *)good_2byte_insns)) 2262b144498SSrikar Dronamraju return 0; 2272b144498SSrikar Dronamraju } 2287b2d81d4SIngo Molnar 2292b144498SSrikar Dronamraju return -ENOTSUPP; 2302b144498SSrikar Dronamraju } 2312b144498SSrikar Dronamraju 2322b144498SSrikar Dronamraju #ifdef CONFIG_X86_64 2332b144498SSrikar Dronamraju /* 2343ff54efdSSrikar Dronamraju * If arch_uprobe->insn doesn't use rip-relative addressing, return 2352b144498SSrikar Dronamraju * immediately. Otherwise, rewrite the instruction so that it accesses 2362b144498SSrikar Dronamraju * its memory operand indirectly through a scratch register. Set 2373ff54efdSSrikar Dronamraju * arch_uprobe->fixups and arch_uprobe->rip_rela_target_address 2382b144498SSrikar Dronamraju * accordingly. (The contents of the scratch register will be saved 2392b144498SSrikar Dronamraju * before we single-step the modified instruction, and restored 2402b144498SSrikar Dronamraju * afterward.) 2412b144498SSrikar Dronamraju * 2422b144498SSrikar Dronamraju * We do this because a rip-relative instruction can access only a 2432b144498SSrikar Dronamraju * relatively small area (+/- 2 GB from the instruction), and the XOL 2442b144498SSrikar Dronamraju * area typically lies beyond that area. At least for instructions 2452b144498SSrikar Dronamraju * that store to memory, we can't execute the original instruction 2462b144498SSrikar Dronamraju * and "fix things up" later, because the misdirected store could be 2472b144498SSrikar Dronamraju * disastrous. 2482b144498SSrikar Dronamraju * 2492b144498SSrikar Dronamraju * Some useful facts about rip-relative instructions: 2507b2d81d4SIngo Molnar * 2512b144498SSrikar Dronamraju * - There's always a modrm byte. 2522b144498SSrikar Dronamraju * - There's never a SIB byte. 2532b144498SSrikar Dronamraju * - The displacement is always 4 bytes. 2542b144498SSrikar Dronamraju */ 255e3343e6aSSrikar Dronamraju static void 25659078d4bSOleg Nesterov handle_riprel_insn(struct arch_uprobe *auprobe, struct insn *insn) 2572b144498SSrikar Dronamraju { 2582b144498SSrikar Dronamraju u8 *cursor; 2592b144498SSrikar Dronamraju u8 reg; 2602b144498SSrikar Dronamraju 2612b144498SSrikar Dronamraju if (!insn_rip_relative(insn)) 2622b144498SSrikar Dronamraju return; 2632b144498SSrikar Dronamraju 2642b144498SSrikar Dronamraju /* 2652b144498SSrikar Dronamraju * insn_rip_relative() would have decoded rex_prefix, modrm. 2662b144498SSrikar Dronamraju * Clear REX.b bit (extension of MODRM.rm field): 2672b144498SSrikar Dronamraju * we want to encode rax/rcx, not r8/r9. 2682b144498SSrikar Dronamraju */ 2692b144498SSrikar Dronamraju if (insn->rex_prefix.nbytes) { 2703ff54efdSSrikar Dronamraju cursor = auprobe->insn + insn_offset_rex_prefix(insn); 2712b144498SSrikar Dronamraju *cursor &= 0xfe; /* Clearing REX.B bit */ 2722b144498SSrikar Dronamraju } 2732b144498SSrikar Dronamraju 2742b144498SSrikar Dronamraju /* 2752b144498SSrikar Dronamraju * Point cursor at the modrm byte. The next 4 bytes are the 2762b144498SSrikar Dronamraju * displacement. Beyond the displacement, for some instructions, 2772b144498SSrikar Dronamraju * is the immediate operand. 2782b144498SSrikar Dronamraju */ 2793ff54efdSSrikar Dronamraju cursor = auprobe->insn + insn_offset_modrm(insn); 2802b144498SSrikar Dronamraju insn_get_length(insn); 2812b144498SSrikar Dronamraju 2822b144498SSrikar Dronamraju /* 2832b144498SSrikar Dronamraju * Convert from rip-relative addressing to indirect addressing 2842b144498SSrikar Dronamraju * via a scratch register. Change the r/m field from 0x5 (%rip) 2852b144498SSrikar Dronamraju * to 0x0 (%rax) or 0x1 (%rcx), and squeeze out the offset field. 2862b144498SSrikar Dronamraju */ 2872b144498SSrikar Dronamraju reg = MODRM_REG(insn); 2882b144498SSrikar Dronamraju if (reg == 0) { 2892b144498SSrikar Dronamraju /* 2902b144498SSrikar Dronamraju * The register operand (if any) is either the A register 2912b144498SSrikar Dronamraju * (%rax, %eax, etc.) or (if the 0x4 bit is set in the 2922b144498SSrikar Dronamraju * REX prefix) %r8. In any case, we know the C register 2932b144498SSrikar Dronamraju * is NOT the register operand, so we use %rcx (register 2942b144498SSrikar Dronamraju * #1) for the scratch register. 2952b144498SSrikar Dronamraju */ 296900771a4SSrikar Dronamraju auprobe->fixups = UPROBE_FIX_RIP_CX; 2972b144498SSrikar Dronamraju /* Change modrm from 00 000 101 to 00 000 001. */ 2982b144498SSrikar Dronamraju *cursor = 0x1; 2992b144498SSrikar Dronamraju } else { 3002b144498SSrikar Dronamraju /* Use %rax (register #0) for the scratch register. */ 301900771a4SSrikar Dronamraju auprobe->fixups = UPROBE_FIX_RIP_AX; 3022b144498SSrikar Dronamraju /* Change modrm from 00 xxx 101 to 00 xxx 000 */ 3032b144498SSrikar Dronamraju *cursor = (reg << 3); 3042b144498SSrikar Dronamraju } 3052b144498SSrikar Dronamraju 3062b144498SSrikar Dronamraju /* Target address = address of next instruction + (signed) offset */ 3073ff54efdSSrikar Dronamraju auprobe->rip_rela_target_address = (long)insn->length + insn->displacement.value; 3087b2d81d4SIngo Molnar 3092b144498SSrikar Dronamraju /* Displacement field is gone; slide immediate field (if any) over. */ 3102b144498SSrikar Dronamraju if (insn->immediate.nbytes) { 3112b144498SSrikar Dronamraju cursor++; 3127b2d81d4SIngo Molnar memmove(cursor, cursor + insn->displacement.nbytes, insn->immediate.nbytes); 3132b144498SSrikar Dronamraju } 3142b144498SSrikar Dronamraju } 3152b144498SSrikar Dronamraju 316*d20737c0SOleg Nesterov /* 317*d20737c0SOleg Nesterov * If we're emulating a rip-relative instruction, save the contents 318*d20737c0SOleg Nesterov * of the scratch register and store the target address in that register. 319*d20737c0SOleg Nesterov */ 320*d20737c0SOleg Nesterov static void 321*d20737c0SOleg Nesterov pre_xol_rip_insn(struct arch_uprobe *auprobe, struct pt_regs *regs, 322*d20737c0SOleg Nesterov struct arch_uprobe_task *autask) 323*d20737c0SOleg Nesterov { 324*d20737c0SOleg Nesterov if (auprobe->fixups & UPROBE_FIX_RIP_AX) { 325*d20737c0SOleg Nesterov autask->saved_scratch_register = regs->ax; 326*d20737c0SOleg Nesterov regs->ax = current->utask->vaddr; 327*d20737c0SOleg Nesterov regs->ax += auprobe->rip_rela_target_address; 328*d20737c0SOleg Nesterov } else if (auprobe->fixups & UPROBE_FIX_RIP_CX) { 329*d20737c0SOleg Nesterov autask->saved_scratch_register = regs->cx; 330*d20737c0SOleg Nesterov regs->cx = current->utask->vaddr; 331*d20737c0SOleg Nesterov regs->cx += auprobe->rip_rela_target_address; 332*d20737c0SOleg Nesterov } 333*d20737c0SOleg Nesterov } 334*d20737c0SOleg Nesterov 335*d20737c0SOleg Nesterov static void 336*d20737c0SOleg Nesterov handle_riprel_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs, long *correction) 337*d20737c0SOleg Nesterov { 338*d20737c0SOleg Nesterov if (auprobe->fixups & (UPROBE_FIX_RIP_AX | UPROBE_FIX_RIP_CX)) { 339*d20737c0SOleg Nesterov struct arch_uprobe_task *autask; 340*d20737c0SOleg Nesterov 341*d20737c0SOleg Nesterov autask = ¤t->utask->autask; 342*d20737c0SOleg Nesterov if (auprobe->fixups & UPROBE_FIX_RIP_AX) 343*d20737c0SOleg Nesterov regs->ax = autask->saved_scratch_register; 344*d20737c0SOleg Nesterov else 345*d20737c0SOleg Nesterov regs->cx = autask->saved_scratch_register; 346*d20737c0SOleg Nesterov 347*d20737c0SOleg Nesterov /* 348*d20737c0SOleg Nesterov * The original instruction includes a displacement, and so 349*d20737c0SOleg Nesterov * is 4 bytes longer than what we've just single-stepped. 350*d20737c0SOleg Nesterov * Caller may need to apply other fixups to handle stuff 351*d20737c0SOleg Nesterov * like "jmpq *...(%rip)" and "callq *...(%rip)". 352*d20737c0SOleg Nesterov */ 353*d20737c0SOleg Nesterov if (correction) 354*d20737c0SOleg Nesterov *correction += 4; 355*d20737c0SOleg Nesterov } 356*d20737c0SOleg Nesterov } 357*d20737c0SOleg Nesterov 3583ff54efdSSrikar Dronamraju static int validate_insn_64bits(struct arch_uprobe *auprobe, struct insn *insn) 3592b144498SSrikar Dronamraju { 3603ff54efdSSrikar Dronamraju insn_init(insn, auprobe->insn, true); 3612b144498SSrikar Dronamraju 3622b144498SSrikar Dronamraju /* Skip good instruction prefixes; reject "bad" ones. */ 3632b144498SSrikar Dronamraju insn_get_opcode(insn); 3642b144498SSrikar Dronamraju if (is_prefix_bad(insn)) 3652b144498SSrikar Dronamraju return -ENOTSUPP; 3667b2d81d4SIngo Molnar 3672b144498SSrikar Dronamraju if (test_bit(OPCODE1(insn), (unsigned long *)good_insns_64)) 3682b144498SSrikar Dronamraju return 0; 3697b2d81d4SIngo Molnar 3702b144498SSrikar Dronamraju if (insn->opcode.nbytes == 2) { 3712b144498SSrikar Dronamraju if (test_bit(OPCODE2(insn), (unsigned long *)good_2byte_insns)) 3722b144498SSrikar Dronamraju return 0; 3732b144498SSrikar Dronamraju } 3742b144498SSrikar Dronamraju return -ENOTSUPP; 3752b144498SSrikar Dronamraju } 3762b144498SSrikar Dronamraju 377e3343e6aSSrikar Dronamraju static int validate_insn_bits(struct arch_uprobe *auprobe, struct mm_struct *mm, struct insn *insn) 3782b144498SSrikar Dronamraju { 3792b144498SSrikar Dronamraju if (mm->context.ia32_compat) 3803ff54efdSSrikar Dronamraju return validate_insn_32bits(auprobe, insn); 3813ff54efdSSrikar Dronamraju return validate_insn_64bits(auprobe, insn); 3822b144498SSrikar Dronamraju } 3837b2d81d4SIngo Molnar #else /* 32-bit: */ 384*d20737c0SOleg Nesterov /* 385*d20737c0SOleg Nesterov * No RIP-relative addressing on 32-bit 386*d20737c0SOleg Nesterov */ 38759078d4bSOleg Nesterov static void handle_riprel_insn(struct arch_uprobe *auprobe, struct insn *insn) 3882b144498SSrikar Dronamraju { 389*d20737c0SOleg Nesterov } 390*d20737c0SOleg Nesterov static void pre_xol_rip_insn(struct arch_uprobe *auprobe, struct pt_regs *regs, 391*d20737c0SOleg Nesterov struct arch_uprobe_task *autask) 392*d20737c0SOleg Nesterov { 393*d20737c0SOleg Nesterov } 394*d20737c0SOleg Nesterov static void handle_riprel_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs, 395*d20737c0SOleg Nesterov long *correction) 396*d20737c0SOleg Nesterov { 3972b144498SSrikar Dronamraju } 3982b144498SSrikar Dronamraju 399e3343e6aSSrikar Dronamraju static int validate_insn_bits(struct arch_uprobe *auprobe, struct mm_struct *mm, struct insn *insn) 4002b144498SSrikar Dronamraju { 4013ff54efdSSrikar Dronamraju return validate_insn_32bits(auprobe, insn); 4022b144498SSrikar Dronamraju } 4032b144498SSrikar Dronamraju #endif /* CONFIG_X86_64 */ 4042b144498SSrikar Dronamraju 4052b144498SSrikar Dronamraju /** 4060326f5a9SSrikar Dronamraju * arch_uprobe_analyze_insn - instruction analysis including validity and fixups. 4072b144498SSrikar Dronamraju * @mm: the probed address space. 4083ff54efdSSrikar Dronamraju * @arch_uprobe: the probepoint information. 4097eb9ba5eSAnanth N Mavinakayanahalli * @addr: virtual address at which to install the probepoint 4102b144498SSrikar Dronamraju * Return 0 on success or a -ve number on error. 4112b144498SSrikar Dronamraju */ 4127eb9ba5eSAnanth N Mavinakayanahalli int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long addr) 4132b144498SSrikar Dronamraju { 4142b144498SSrikar Dronamraju struct insn insn; 415ddb69f27SOleg Nesterov bool fix_ip = true, fix_call = false; 416ddb69f27SOleg Nesterov int ret; 4172b144498SSrikar Dronamraju 418e3343e6aSSrikar Dronamraju ret = validate_insn_bits(auprobe, mm, &insn); 419ddb69f27SOleg Nesterov if (ret) 4202b144498SSrikar Dronamraju return ret; 4217b2d81d4SIngo Molnar 422ddb69f27SOleg Nesterov /* 423ddb69f27SOleg Nesterov * Figure out which fixups arch_uprobe_post_xol() will need to perform, 424ddb69f27SOleg Nesterov * and annotate arch_uprobe->fixups accordingly. To start with, ->fixups 425ddb69f27SOleg Nesterov * is either zero or it reflects rip-related fixups. 426ddb69f27SOleg Nesterov */ 42759078d4bSOleg Nesterov handle_riprel_insn(auprobe, &insn); 428ddb69f27SOleg Nesterov 429ddb69f27SOleg Nesterov switch (OPCODE1(&insn)) { 430ddb69f27SOleg Nesterov case 0x9d: /* popf */ 431ddb69f27SOleg Nesterov auprobe->fixups |= UPROBE_FIX_SETF; 432ddb69f27SOleg Nesterov break; 433ddb69f27SOleg Nesterov case 0xc3: /* ret or lret -- ip is correct */ 434ddb69f27SOleg Nesterov case 0xcb: 435ddb69f27SOleg Nesterov case 0xc2: 436ddb69f27SOleg Nesterov case 0xca: 437ddb69f27SOleg Nesterov fix_ip = false; 438ddb69f27SOleg Nesterov break; 439ddb69f27SOleg Nesterov case 0xe8: /* call relative - Fix return addr */ 440ddb69f27SOleg Nesterov fix_call = true; 441ddb69f27SOleg Nesterov break; 442ddb69f27SOleg Nesterov case 0x9a: /* call absolute - Fix return addr, not ip */ 443ddb69f27SOleg Nesterov fix_call = true; 444ddb69f27SOleg Nesterov fix_ip = false; 445ddb69f27SOleg Nesterov break; 446ddb69f27SOleg Nesterov case 0xea: /* jmp absolute -- ip is correct */ 447ddb69f27SOleg Nesterov fix_ip = false; 448ddb69f27SOleg Nesterov break; 449ddb69f27SOleg Nesterov case 0xff: 450ddb69f27SOleg Nesterov insn_get_modrm(&insn); 451ddb69f27SOleg Nesterov switch (MODRM_REG(&insn)) { 452ddb69f27SOleg Nesterov case 2: case 3: /* call or lcall, indirect */ 453ddb69f27SOleg Nesterov fix_call = true; 454ddb69f27SOleg Nesterov case 4: case 5: /* jmp or ljmp, indirect */ 455ddb69f27SOleg Nesterov fix_ip = false; 456ddb69f27SOleg Nesterov } 457ddb69f27SOleg Nesterov break; 458ddb69f27SOleg Nesterov default: 459ddb69f27SOleg Nesterov break; 460ddb69f27SOleg Nesterov } 461ddb69f27SOleg Nesterov 462ddb69f27SOleg Nesterov if (fix_ip) 463ddb69f27SOleg Nesterov auprobe->fixups |= UPROBE_FIX_IP; 464ddb69f27SOleg Nesterov if (fix_call) 465ddb69f27SOleg Nesterov auprobe->fixups |= UPROBE_FIX_CALL; 4667b2d81d4SIngo Molnar 4672b144498SSrikar Dronamraju return 0; 4682b144498SSrikar Dronamraju } 4690326f5a9SSrikar Dronamraju 4700326f5a9SSrikar Dronamraju /* 4710326f5a9SSrikar Dronamraju * arch_uprobe_pre_xol - prepare to execute out of line. 4720326f5a9SSrikar Dronamraju * @auprobe: the probepoint information. 4730326f5a9SSrikar Dronamraju * @regs: reflects the saved user state of current task. 4740326f5a9SSrikar Dronamraju */ 4750326f5a9SSrikar Dronamraju int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) 4760326f5a9SSrikar Dronamraju { 4770326f5a9SSrikar Dronamraju struct arch_uprobe_task *autask; 4780326f5a9SSrikar Dronamraju 4790326f5a9SSrikar Dronamraju autask = ¤t->utask->autask; 4800326f5a9SSrikar Dronamraju autask->saved_trap_nr = current->thread.trap_nr; 4810326f5a9SSrikar Dronamraju current->thread.trap_nr = UPROBE_TRAP_NR; 4820326f5a9SSrikar Dronamraju regs->ip = current->utask->xol_vaddr; 4830326f5a9SSrikar Dronamraju pre_xol_rip_insn(auprobe, regs, autask); 4840326f5a9SSrikar Dronamraju 4854dc316c6SOleg Nesterov autask->saved_tf = !!(regs->flags & X86_EFLAGS_TF); 4864dc316c6SOleg Nesterov regs->flags |= X86_EFLAGS_TF; 4874dc316c6SOleg Nesterov if (test_tsk_thread_flag(current, TIF_BLOCKSTEP)) 4884dc316c6SOleg Nesterov set_task_blockstep(current, false); 4894dc316c6SOleg Nesterov 4900326f5a9SSrikar Dronamraju return 0; 4910326f5a9SSrikar Dronamraju } 4920326f5a9SSrikar Dronamraju 4930326f5a9SSrikar Dronamraju /* 4940326f5a9SSrikar Dronamraju * This function is called by arch_uprobe_post_xol() to adjust the return 4950326f5a9SSrikar Dronamraju * address pushed by a call instruction executed out of line. 4960326f5a9SSrikar Dronamraju */ 4970326f5a9SSrikar Dronamraju static int adjust_ret_addr(unsigned long sp, long correction) 4980326f5a9SSrikar Dronamraju { 4990326f5a9SSrikar Dronamraju int rasize, ncopied; 5000326f5a9SSrikar Dronamraju long ra = 0; 5010326f5a9SSrikar Dronamraju 5020326f5a9SSrikar Dronamraju if (is_ia32_task()) 5030326f5a9SSrikar Dronamraju rasize = 4; 5040326f5a9SSrikar Dronamraju else 5050326f5a9SSrikar Dronamraju rasize = 8; 5060326f5a9SSrikar Dronamraju 5070326f5a9SSrikar Dronamraju ncopied = copy_from_user(&ra, (void __user *)sp, rasize); 5080326f5a9SSrikar Dronamraju if (unlikely(ncopied)) 5090326f5a9SSrikar Dronamraju return -EFAULT; 5100326f5a9SSrikar Dronamraju 5110326f5a9SSrikar Dronamraju ra += correction; 5120326f5a9SSrikar Dronamraju ncopied = copy_to_user((void __user *)sp, &ra, rasize); 5130326f5a9SSrikar Dronamraju if (unlikely(ncopied)) 5140326f5a9SSrikar Dronamraju return -EFAULT; 5150326f5a9SSrikar Dronamraju 5160326f5a9SSrikar Dronamraju return 0; 5170326f5a9SSrikar Dronamraju } 5180326f5a9SSrikar Dronamraju 5190326f5a9SSrikar Dronamraju /* 5200326f5a9SSrikar Dronamraju * If xol insn itself traps and generates a signal(Say, 5210326f5a9SSrikar Dronamraju * SIGILL/SIGSEGV/etc), then detect the case where a singlestepped 5220326f5a9SSrikar Dronamraju * instruction jumps back to its own address. It is assumed that anything 5230326f5a9SSrikar Dronamraju * like do_page_fault/do_trap/etc sets thread.trap_nr != -1. 5240326f5a9SSrikar Dronamraju * 5250326f5a9SSrikar Dronamraju * arch_uprobe_pre_xol/arch_uprobe_post_xol save/restore thread.trap_nr, 5260326f5a9SSrikar Dronamraju * arch_uprobe_xol_was_trapped() simply checks that ->trap_nr is not equal to 5270326f5a9SSrikar Dronamraju * UPROBE_TRAP_NR == -1 set by arch_uprobe_pre_xol(). 5280326f5a9SSrikar Dronamraju */ 5290326f5a9SSrikar Dronamraju bool arch_uprobe_xol_was_trapped(struct task_struct *t) 5300326f5a9SSrikar Dronamraju { 5310326f5a9SSrikar Dronamraju if (t->thread.trap_nr != UPROBE_TRAP_NR) 5320326f5a9SSrikar Dronamraju return true; 5330326f5a9SSrikar Dronamraju 5340326f5a9SSrikar Dronamraju return false; 5350326f5a9SSrikar Dronamraju } 5360326f5a9SSrikar Dronamraju 5370326f5a9SSrikar Dronamraju /* 5380326f5a9SSrikar Dronamraju * Called after single-stepping. To avoid the SMP problems that can 5390326f5a9SSrikar Dronamraju * occur when we temporarily put back the original opcode to 5400326f5a9SSrikar Dronamraju * single-step, we single-stepped a copy of the instruction. 5410326f5a9SSrikar Dronamraju * 5420326f5a9SSrikar Dronamraju * This function prepares to resume execution after the single-step. 5430326f5a9SSrikar Dronamraju * We have to fix things up as follows: 5440326f5a9SSrikar Dronamraju * 5450326f5a9SSrikar Dronamraju * Typically, the new ip is relative to the copied instruction. We need 5460326f5a9SSrikar Dronamraju * to make it relative to the original instruction (FIX_IP). Exceptions 5470326f5a9SSrikar Dronamraju * are return instructions and absolute or indirect jump or call instructions. 5480326f5a9SSrikar Dronamraju * 5490326f5a9SSrikar Dronamraju * If the single-stepped instruction was a call, the return address that 5500326f5a9SSrikar Dronamraju * is atop the stack is the address following the copied instruction. We 5510326f5a9SSrikar Dronamraju * need to make it the address following the original instruction (FIX_CALL). 5520326f5a9SSrikar Dronamraju * 5530326f5a9SSrikar Dronamraju * If the original instruction was a rip-relative instruction such as 5540326f5a9SSrikar Dronamraju * "movl %edx,0xnnnn(%rip)", we have instead executed an equivalent 5550326f5a9SSrikar Dronamraju * instruction using a scratch register -- e.g., "movl %edx,(%rax)". 5560326f5a9SSrikar Dronamraju * We need to restore the contents of the scratch register and adjust 5570326f5a9SSrikar Dronamraju * the ip, keeping in mind that the instruction we executed is 4 bytes 5580326f5a9SSrikar Dronamraju * shorter than the original instruction (since we squeezed out the offset 5590326f5a9SSrikar Dronamraju * field). (FIX_RIP_AX or FIX_RIP_CX) 5600326f5a9SSrikar Dronamraju */ 5610326f5a9SSrikar Dronamraju int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) 5620326f5a9SSrikar Dronamraju { 5630326f5a9SSrikar Dronamraju struct uprobe_task *utask; 5640326f5a9SSrikar Dronamraju long correction; 5650326f5a9SSrikar Dronamraju int result = 0; 5660326f5a9SSrikar Dronamraju 5670326f5a9SSrikar Dronamraju WARN_ON_ONCE(current->thread.trap_nr != UPROBE_TRAP_NR); 5680326f5a9SSrikar Dronamraju 5690326f5a9SSrikar Dronamraju utask = current->utask; 5700326f5a9SSrikar Dronamraju current->thread.trap_nr = utask->autask.saved_trap_nr; 5710326f5a9SSrikar Dronamraju correction = (long)(utask->vaddr - utask->xol_vaddr); 5720326f5a9SSrikar Dronamraju handle_riprel_post_xol(auprobe, regs, &correction); 5730326f5a9SSrikar Dronamraju if (auprobe->fixups & UPROBE_FIX_IP) 5740326f5a9SSrikar Dronamraju regs->ip += correction; 5750326f5a9SSrikar Dronamraju 5760326f5a9SSrikar Dronamraju if (auprobe->fixups & UPROBE_FIX_CALL) 5770326f5a9SSrikar Dronamraju result = adjust_ret_addr(regs->sp, correction); 5780326f5a9SSrikar Dronamraju 5794dc316c6SOleg Nesterov /* 5804dc316c6SOleg Nesterov * arch_uprobe_pre_xol() doesn't save the state of TIF_BLOCKSTEP 5814dc316c6SOleg Nesterov * so we can get an extra SIGTRAP if we do not clear TF. We need 5824dc316c6SOleg Nesterov * to examine the opcode to make it right. 5834dc316c6SOleg Nesterov */ 5844dc316c6SOleg Nesterov if (utask->autask.saved_tf) 5854dc316c6SOleg Nesterov send_sig(SIGTRAP, current, 0); 5864dc316c6SOleg Nesterov else if (!(auprobe->fixups & UPROBE_FIX_SETF)) 5874dc316c6SOleg Nesterov regs->flags &= ~X86_EFLAGS_TF; 5884dc316c6SOleg Nesterov 5890326f5a9SSrikar Dronamraju return result; 5900326f5a9SSrikar Dronamraju } 5910326f5a9SSrikar Dronamraju 5920326f5a9SSrikar Dronamraju /* callback routine for handling exceptions. */ 5930326f5a9SSrikar Dronamraju int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data) 5940326f5a9SSrikar Dronamraju { 5950326f5a9SSrikar Dronamraju struct die_args *args = data; 5960326f5a9SSrikar Dronamraju struct pt_regs *regs = args->regs; 5970326f5a9SSrikar Dronamraju int ret = NOTIFY_DONE; 5980326f5a9SSrikar Dronamraju 5990326f5a9SSrikar Dronamraju /* We are only interested in userspace traps */ 6000326f5a9SSrikar Dronamraju if (regs && !user_mode_vm(regs)) 6010326f5a9SSrikar Dronamraju return NOTIFY_DONE; 6020326f5a9SSrikar Dronamraju 6030326f5a9SSrikar Dronamraju switch (val) { 6040326f5a9SSrikar Dronamraju case DIE_INT3: 6050326f5a9SSrikar Dronamraju if (uprobe_pre_sstep_notifier(regs)) 6060326f5a9SSrikar Dronamraju ret = NOTIFY_STOP; 6070326f5a9SSrikar Dronamraju 6080326f5a9SSrikar Dronamraju break; 6090326f5a9SSrikar Dronamraju 6100326f5a9SSrikar Dronamraju case DIE_DEBUG: 6110326f5a9SSrikar Dronamraju if (uprobe_post_sstep_notifier(regs)) 6120326f5a9SSrikar Dronamraju ret = NOTIFY_STOP; 6130326f5a9SSrikar Dronamraju 6140326f5a9SSrikar Dronamraju default: 6150326f5a9SSrikar Dronamraju break; 6160326f5a9SSrikar Dronamraju } 6170326f5a9SSrikar Dronamraju 6180326f5a9SSrikar Dronamraju return ret; 6190326f5a9SSrikar Dronamraju } 6200326f5a9SSrikar Dronamraju 6210326f5a9SSrikar Dronamraju /* 6220326f5a9SSrikar Dronamraju * This function gets called when XOL instruction either gets trapped or 6230326f5a9SSrikar Dronamraju * the thread has a fatal signal, so reset the instruction pointer to its 6240326f5a9SSrikar Dronamraju * probed address. 6250326f5a9SSrikar Dronamraju */ 6260326f5a9SSrikar Dronamraju void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) 6270326f5a9SSrikar Dronamraju { 6280326f5a9SSrikar Dronamraju struct uprobe_task *utask = current->utask; 6290326f5a9SSrikar Dronamraju 6300326f5a9SSrikar Dronamraju current->thread.trap_nr = utask->autask.saved_trap_nr; 6310326f5a9SSrikar Dronamraju handle_riprel_post_xol(auprobe, regs, NULL); 6320326f5a9SSrikar Dronamraju instruction_pointer_set(regs, utask->vaddr); 6334dc316c6SOleg Nesterov 6344dc316c6SOleg Nesterov /* clear TF if it was set by us in arch_uprobe_pre_xol() */ 6354dc316c6SOleg Nesterov if (!utask->autask.saved_tf) 6364dc316c6SOleg Nesterov regs->flags &= ~X86_EFLAGS_TF; 6370326f5a9SSrikar Dronamraju } 6380326f5a9SSrikar Dronamraju 6390326f5a9SSrikar Dronamraju /* 6400326f5a9SSrikar Dronamraju * Skip these instructions as per the currently known x86 ISA. 641b64b9c93SOleg Nesterov * rep=0x66*; nop=0x90 6420326f5a9SSrikar Dronamraju */ 6433a4664aaSOleg Nesterov static bool __skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) 6440326f5a9SSrikar Dronamraju { 6450326f5a9SSrikar Dronamraju int i; 6460326f5a9SSrikar Dronamraju 6470326f5a9SSrikar Dronamraju for (i = 0; i < MAX_UINSN_BYTES; i++) { 648b64b9c93SOleg Nesterov if (auprobe->insn[i] == 0x66) 6490326f5a9SSrikar Dronamraju continue; 6500326f5a9SSrikar Dronamraju 651cf31ec3fSOleg Nesterov if (auprobe->insn[i] == 0x90) { 652cf31ec3fSOleg Nesterov regs->ip += i + 1; 6530326f5a9SSrikar Dronamraju return true; 654cf31ec3fSOleg Nesterov } 6550326f5a9SSrikar Dronamraju 6560326f5a9SSrikar Dronamraju break; 6570326f5a9SSrikar Dronamraju } 6580326f5a9SSrikar Dronamraju return false; 6590326f5a9SSrikar Dronamraju } 660bdc1e472SSebastian Andrzej Siewior 6613a4664aaSOleg Nesterov bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) 6623a4664aaSOleg Nesterov { 6633a4664aaSOleg Nesterov bool ret = __skip_sstep(auprobe, regs); 6643a4664aaSOleg Nesterov if (ret && (regs->flags & X86_EFLAGS_TF)) 6653a4664aaSOleg Nesterov send_sig(SIGTRAP, current, 0); 6663a4664aaSOleg Nesterov return ret; 6673a4664aaSOleg Nesterov } 668791eca10SAnton Arapov 669791eca10SAnton Arapov unsigned long 670791eca10SAnton Arapov arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs *regs) 671791eca10SAnton Arapov { 672791eca10SAnton Arapov int rasize, ncopied; 673791eca10SAnton Arapov unsigned long orig_ret_vaddr = 0; /* clear high bits for 32-bit apps */ 674791eca10SAnton Arapov 675791eca10SAnton Arapov rasize = is_ia32_task() ? 4 : 8; 676791eca10SAnton Arapov ncopied = copy_from_user(&orig_ret_vaddr, (void __user *)regs->sp, rasize); 677791eca10SAnton Arapov if (unlikely(ncopied)) 678791eca10SAnton Arapov return -1; 679791eca10SAnton Arapov 680791eca10SAnton Arapov /* check whether address has been already hijacked */ 681791eca10SAnton Arapov if (orig_ret_vaddr == trampoline_vaddr) 682791eca10SAnton Arapov return orig_ret_vaddr; 683791eca10SAnton Arapov 684791eca10SAnton Arapov ncopied = copy_to_user((void __user *)regs->sp, &trampoline_vaddr, rasize); 685791eca10SAnton Arapov if (likely(!ncopied)) 686791eca10SAnton Arapov return orig_ret_vaddr; 687791eca10SAnton Arapov 688791eca10SAnton Arapov if (ncopied != rasize) { 689791eca10SAnton Arapov pr_err("uprobe: return address clobbered: pid=%d, %%sp=%#lx, " 690791eca10SAnton Arapov "%%ip=%#lx\n", current->pid, regs->sp, regs->ip); 691791eca10SAnton Arapov 692791eca10SAnton Arapov force_sig_info(SIGSEGV, SEND_SIG_FORCED, current); 693791eca10SAnton Arapov } 694791eca10SAnton Arapov 695791eca10SAnton Arapov return -1; 696791eca10SAnton Arapov } 697