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 316d20737c0SOleg Nesterov /* 317d20737c0SOleg Nesterov * If we're emulating a rip-relative instruction, save the contents 318d20737c0SOleg Nesterov * of the scratch register and store the target address in that register. 319d20737c0SOleg Nesterov */ 320d20737c0SOleg Nesterov static void 321d20737c0SOleg Nesterov pre_xol_rip_insn(struct arch_uprobe *auprobe, struct pt_regs *regs, 322d20737c0SOleg Nesterov struct arch_uprobe_task *autask) 323d20737c0SOleg Nesterov { 324d20737c0SOleg Nesterov if (auprobe->fixups & UPROBE_FIX_RIP_AX) { 325d20737c0SOleg Nesterov autask->saved_scratch_register = regs->ax; 326d20737c0SOleg Nesterov regs->ax = current->utask->vaddr; 327d20737c0SOleg Nesterov regs->ax += auprobe->rip_rela_target_address; 328d20737c0SOleg Nesterov } else if (auprobe->fixups & UPROBE_FIX_RIP_CX) { 329d20737c0SOleg Nesterov autask->saved_scratch_register = regs->cx; 330d20737c0SOleg Nesterov regs->cx = current->utask->vaddr; 331d20737c0SOleg Nesterov regs->cx += auprobe->rip_rela_target_address; 332d20737c0SOleg Nesterov } 333d20737c0SOleg Nesterov } 334d20737c0SOleg Nesterov 335d20737c0SOleg Nesterov static void 336d20737c0SOleg Nesterov handle_riprel_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs, long *correction) 337d20737c0SOleg Nesterov { 338d20737c0SOleg Nesterov if (auprobe->fixups & (UPROBE_FIX_RIP_AX | UPROBE_FIX_RIP_CX)) { 339d20737c0SOleg Nesterov struct arch_uprobe_task *autask; 340d20737c0SOleg Nesterov 341d20737c0SOleg Nesterov autask = ¤t->utask->autask; 342d20737c0SOleg Nesterov if (auprobe->fixups & UPROBE_FIX_RIP_AX) 343d20737c0SOleg Nesterov regs->ax = autask->saved_scratch_register; 344d20737c0SOleg Nesterov else 345d20737c0SOleg Nesterov regs->cx = autask->saved_scratch_register; 346d20737c0SOleg Nesterov 347d20737c0SOleg Nesterov /* 348d20737c0SOleg Nesterov * The original instruction includes a displacement, and so 349d20737c0SOleg Nesterov * is 4 bytes longer than what we've just single-stepped. 350d20737c0SOleg Nesterov * Caller may need to apply other fixups to handle stuff 351d20737c0SOleg Nesterov * like "jmpq *...(%rip)" and "callq *...(%rip)". 352d20737c0SOleg Nesterov */ 353d20737c0SOleg Nesterov if (correction) 354d20737c0SOleg Nesterov *correction += 4; 355d20737c0SOleg Nesterov } 356d20737c0SOleg Nesterov } 357d20737c0SOleg 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: */ 384d20737c0SOleg Nesterov /* 385d20737c0SOleg Nesterov * No RIP-relative addressing on 32-bit 386d20737c0SOleg Nesterov */ 38759078d4bSOleg Nesterov static void handle_riprel_insn(struct arch_uprobe *auprobe, struct insn *insn) 3882b144498SSrikar Dronamraju { 389d20737c0SOleg Nesterov } 390d20737c0SOleg Nesterov static void pre_xol_rip_insn(struct arch_uprobe *auprobe, struct pt_regs *regs, 391d20737c0SOleg Nesterov struct arch_uprobe_task *autask) 392d20737c0SOleg Nesterov { 393d20737c0SOleg Nesterov } 394d20737c0SOleg Nesterov static void handle_riprel_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs, 395d20737c0SOleg Nesterov long *correction) 396d20737c0SOleg 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 4058ad8e9d3SOleg Nesterov struct uprobe_xol_ops { 4068ad8e9d3SOleg Nesterov bool (*emulate)(struct arch_uprobe *, struct pt_regs *); 4078ad8e9d3SOleg Nesterov int (*pre_xol)(struct arch_uprobe *, struct pt_regs *); 4088ad8e9d3SOleg Nesterov int (*post_xol)(struct arch_uprobe *, struct pt_regs *); 4098ad8e9d3SOleg Nesterov }; 4108ad8e9d3SOleg Nesterov 4118ad8e9d3SOleg Nesterov static int default_pre_xol_op(struct arch_uprobe *auprobe, struct pt_regs *regs) 4128ad8e9d3SOleg Nesterov { 4138ad8e9d3SOleg Nesterov pre_xol_rip_insn(auprobe, regs, ¤t->utask->autask); 4148ad8e9d3SOleg Nesterov return 0; 4158ad8e9d3SOleg Nesterov } 4168ad8e9d3SOleg Nesterov 4178ad8e9d3SOleg Nesterov /* 4188ad8e9d3SOleg Nesterov * Adjust the return address pushed by a call insn executed out of line. 4198ad8e9d3SOleg Nesterov */ 4208ad8e9d3SOleg Nesterov static int adjust_ret_addr(unsigned long sp, long correction) 4218ad8e9d3SOleg Nesterov { 4228ad8e9d3SOleg Nesterov int rasize, ncopied; 4238ad8e9d3SOleg Nesterov long ra = 0; 4248ad8e9d3SOleg Nesterov 4258ad8e9d3SOleg Nesterov if (is_ia32_task()) 4268ad8e9d3SOleg Nesterov rasize = 4; 4278ad8e9d3SOleg Nesterov else 4288ad8e9d3SOleg Nesterov rasize = 8; 4298ad8e9d3SOleg Nesterov 4308ad8e9d3SOleg Nesterov ncopied = copy_from_user(&ra, (void __user *)sp, rasize); 4318ad8e9d3SOleg Nesterov if (unlikely(ncopied)) 4328ad8e9d3SOleg Nesterov return -EFAULT; 4338ad8e9d3SOleg Nesterov 4348ad8e9d3SOleg Nesterov ra += correction; 4358ad8e9d3SOleg Nesterov ncopied = copy_to_user((void __user *)sp, &ra, rasize); 4368ad8e9d3SOleg Nesterov if (unlikely(ncopied)) 4378ad8e9d3SOleg Nesterov return -EFAULT; 4388ad8e9d3SOleg Nesterov 4398ad8e9d3SOleg Nesterov return 0; 4408ad8e9d3SOleg Nesterov } 4418ad8e9d3SOleg Nesterov 4428ad8e9d3SOleg Nesterov static int default_post_xol_op(struct arch_uprobe *auprobe, struct pt_regs *regs) 4438ad8e9d3SOleg Nesterov { 4448ad8e9d3SOleg Nesterov struct uprobe_task *utask = current->utask; 4458ad8e9d3SOleg Nesterov long correction = (long)(utask->vaddr - utask->xol_vaddr); 4468ad8e9d3SOleg Nesterov int ret = 0; 4478ad8e9d3SOleg Nesterov 4488ad8e9d3SOleg Nesterov handle_riprel_post_xol(auprobe, regs, &correction); 4498ad8e9d3SOleg Nesterov if (auprobe->fixups & UPROBE_FIX_IP) 4508ad8e9d3SOleg Nesterov regs->ip += correction; 4518ad8e9d3SOleg Nesterov 4528ad8e9d3SOleg Nesterov if (auprobe->fixups & UPROBE_FIX_CALL) 4538ad8e9d3SOleg Nesterov ret = adjust_ret_addr(regs->sp, correction); 4548ad8e9d3SOleg Nesterov 4558ad8e9d3SOleg Nesterov return ret; 4568ad8e9d3SOleg Nesterov } 4578ad8e9d3SOleg Nesterov 4588ad8e9d3SOleg Nesterov static struct uprobe_xol_ops default_xol_ops = { 4598ad8e9d3SOleg Nesterov .pre_xol = default_pre_xol_op, 4608ad8e9d3SOleg Nesterov .post_xol = default_post_xol_op, 4618ad8e9d3SOleg Nesterov }; 4628ad8e9d3SOleg Nesterov 4632b144498SSrikar Dronamraju /** 4640326f5a9SSrikar Dronamraju * arch_uprobe_analyze_insn - instruction analysis including validity and fixups. 4652b144498SSrikar Dronamraju * @mm: the probed address space. 4663ff54efdSSrikar Dronamraju * @arch_uprobe: the probepoint information. 4677eb9ba5eSAnanth N Mavinakayanahalli * @addr: virtual address at which to install the probepoint 4682b144498SSrikar Dronamraju * Return 0 on success or a -ve number on error. 4692b144498SSrikar Dronamraju */ 4707eb9ba5eSAnanth N Mavinakayanahalli int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long addr) 4712b144498SSrikar Dronamraju { 4722b144498SSrikar Dronamraju struct insn insn; 473ddb69f27SOleg Nesterov bool fix_ip = true, fix_call = false; 474ddb69f27SOleg Nesterov int ret; 4752b144498SSrikar Dronamraju 476e3343e6aSSrikar Dronamraju ret = validate_insn_bits(auprobe, mm, &insn); 477ddb69f27SOleg Nesterov if (ret) 4782b144498SSrikar Dronamraju return ret; 4797b2d81d4SIngo Molnar 480ddb69f27SOleg Nesterov /* 481ddb69f27SOleg Nesterov * Figure out which fixups arch_uprobe_post_xol() will need to perform, 482ddb69f27SOleg Nesterov * and annotate arch_uprobe->fixups accordingly. To start with, ->fixups 483ddb69f27SOleg Nesterov * is either zero or it reflects rip-related fixups. 484ddb69f27SOleg Nesterov */ 485ddb69f27SOleg Nesterov switch (OPCODE1(&insn)) { 486ddb69f27SOleg Nesterov case 0x9d: /* popf */ 487ddb69f27SOleg Nesterov auprobe->fixups |= UPROBE_FIX_SETF; 488ddb69f27SOleg Nesterov break; 489ddb69f27SOleg Nesterov case 0xc3: /* ret or lret -- ip is correct */ 490ddb69f27SOleg Nesterov case 0xcb: 491ddb69f27SOleg Nesterov case 0xc2: 492ddb69f27SOleg Nesterov case 0xca: 493ddb69f27SOleg Nesterov fix_ip = false; 494ddb69f27SOleg Nesterov break; 495ddb69f27SOleg Nesterov case 0xe8: /* call relative - Fix return addr */ 496ddb69f27SOleg Nesterov fix_call = true; 497ddb69f27SOleg Nesterov break; 498ddb69f27SOleg Nesterov case 0x9a: /* call absolute - Fix return addr, not ip */ 499ddb69f27SOleg Nesterov fix_call = true; 500ddb69f27SOleg Nesterov fix_ip = false; 501ddb69f27SOleg Nesterov break; 502ddb69f27SOleg Nesterov case 0xea: /* jmp absolute -- ip is correct */ 503ddb69f27SOleg Nesterov fix_ip = false; 504ddb69f27SOleg Nesterov break; 505ddb69f27SOleg Nesterov case 0xff: 506ddb69f27SOleg Nesterov insn_get_modrm(&insn); 507ddb69f27SOleg Nesterov switch (MODRM_REG(&insn)) { 508ddb69f27SOleg Nesterov case 2: case 3: /* call or lcall, indirect */ 509ddb69f27SOleg Nesterov fix_call = true; 510ddb69f27SOleg Nesterov case 4: case 5: /* jmp or ljmp, indirect */ 511ddb69f27SOleg Nesterov fix_ip = false; 512ddb69f27SOleg Nesterov } 513e55848a4SOleg Nesterov /* fall through */ 514ddb69f27SOleg Nesterov default: 515e55848a4SOleg Nesterov handle_riprel_insn(auprobe, &insn); 516ddb69f27SOleg Nesterov } 517ddb69f27SOleg Nesterov 518ddb69f27SOleg Nesterov if (fix_ip) 519ddb69f27SOleg Nesterov auprobe->fixups |= UPROBE_FIX_IP; 520ddb69f27SOleg Nesterov if (fix_call) 521ddb69f27SOleg Nesterov auprobe->fixups |= UPROBE_FIX_CALL; 5227b2d81d4SIngo Molnar 5238ad8e9d3SOleg Nesterov auprobe->ops = &default_xol_ops; 5242b144498SSrikar Dronamraju return 0; 5252b144498SSrikar Dronamraju } 5260326f5a9SSrikar Dronamraju 5270326f5a9SSrikar Dronamraju /* 5280326f5a9SSrikar Dronamraju * arch_uprobe_pre_xol - prepare to execute out of line. 5290326f5a9SSrikar Dronamraju * @auprobe: the probepoint information. 5300326f5a9SSrikar Dronamraju * @regs: reflects the saved user state of current task. 5310326f5a9SSrikar Dronamraju */ 5320326f5a9SSrikar Dronamraju int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) 5330326f5a9SSrikar Dronamraju { 53434e7317dSOleg Nesterov struct uprobe_task *utask = current->utask; 5350326f5a9SSrikar Dronamraju 53634e7317dSOleg Nesterov regs->ip = utask->xol_vaddr; 53734e7317dSOleg Nesterov utask->autask.saved_trap_nr = current->thread.trap_nr; 5380326f5a9SSrikar Dronamraju current->thread.trap_nr = UPROBE_TRAP_NR; 5390326f5a9SSrikar Dronamraju 54034e7317dSOleg Nesterov utask->autask.saved_tf = !!(regs->flags & X86_EFLAGS_TF); 5414dc316c6SOleg Nesterov regs->flags |= X86_EFLAGS_TF; 5424dc316c6SOleg Nesterov if (test_tsk_thread_flag(current, TIF_BLOCKSTEP)) 5434dc316c6SOleg Nesterov set_task_blockstep(current, false); 5444dc316c6SOleg Nesterov 5458ad8e9d3SOleg Nesterov if (auprobe->ops->pre_xol) 5468ad8e9d3SOleg Nesterov return auprobe->ops->pre_xol(auprobe, regs); 5470326f5a9SSrikar Dronamraju return 0; 5480326f5a9SSrikar Dronamraju } 5490326f5a9SSrikar Dronamraju 5500326f5a9SSrikar Dronamraju /* 5510326f5a9SSrikar Dronamraju * If xol insn itself traps and generates a signal(Say, 5520326f5a9SSrikar Dronamraju * SIGILL/SIGSEGV/etc), then detect the case where a singlestepped 5530326f5a9SSrikar Dronamraju * instruction jumps back to its own address. It is assumed that anything 5540326f5a9SSrikar Dronamraju * like do_page_fault/do_trap/etc sets thread.trap_nr != -1. 5550326f5a9SSrikar Dronamraju * 5560326f5a9SSrikar Dronamraju * arch_uprobe_pre_xol/arch_uprobe_post_xol save/restore thread.trap_nr, 5570326f5a9SSrikar Dronamraju * arch_uprobe_xol_was_trapped() simply checks that ->trap_nr is not equal to 5580326f5a9SSrikar Dronamraju * UPROBE_TRAP_NR == -1 set by arch_uprobe_pre_xol(). 5590326f5a9SSrikar Dronamraju */ 5600326f5a9SSrikar Dronamraju bool arch_uprobe_xol_was_trapped(struct task_struct *t) 5610326f5a9SSrikar Dronamraju { 5620326f5a9SSrikar Dronamraju if (t->thread.trap_nr != UPROBE_TRAP_NR) 5630326f5a9SSrikar Dronamraju return true; 5640326f5a9SSrikar Dronamraju 5650326f5a9SSrikar Dronamraju return false; 5660326f5a9SSrikar Dronamraju } 5670326f5a9SSrikar Dronamraju 5680326f5a9SSrikar Dronamraju /* 5690326f5a9SSrikar Dronamraju * Called after single-stepping. To avoid the SMP problems that can 5700326f5a9SSrikar Dronamraju * occur when we temporarily put back the original opcode to 5710326f5a9SSrikar Dronamraju * single-step, we single-stepped a copy of the instruction. 5720326f5a9SSrikar Dronamraju * 5730326f5a9SSrikar Dronamraju * This function prepares to resume execution after the single-step. 5740326f5a9SSrikar Dronamraju * We have to fix things up as follows: 5750326f5a9SSrikar Dronamraju * 5760326f5a9SSrikar Dronamraju * Typically, the new ip is relative to the copied instruction. We need 5770326f5a9SSrikar Dronamraju * to make it relative to the original instruction (FIX_IP). Exceptions 5780326f5a9SSrikar Dronamraju * are return instructions and absolute or indirect jump or call instructions. 5790326f5a9SSrikar Dronamraju * 5800326f5a9SSrikar Dronamraju * If the single-stepped instruction was a call, the return address that 5810326f5a9SSrikar Dronamraju * is atop the stack is the address following the copied instruction. We 5820326f5a9SSrikar Dronamraju * need to make it the address following the original instruction (FIX_CALL). 5830326f5a9SSrikar Dronamraju * 5840326f5a9SSrikar Dronamraju * If the original instruction was a rip-relative instruction such as 5850326f5a9SSrikar Dronamraju * "movl %edx,0xnnnn(%rip)", we have instead executed an equivalent 5860326f5a9SSrikar Dronamraju * instruction using a scratch register -- e.g., "movl %edx,(%rax)". 5870326f5a9SSrikar Dronamraju * We need to restore the contents of the scratch register and adjust 5880326f5a9SSrikar Dronamraju * the ip, keeping in mind that the instruction we executed is 4 bytes 5890326f5a9SSrikar Dronamraju * shorter than the original instruction (since we squeezed out the offset 5900326f5a9SSrikar Dronamraju * field). (FIX_RIP_AX or FIX_RIP_CX) 5910326f5a9SSrikar Dronamraju */ 5920326f5a9SSrikar Dronamraju int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) 5930326f5a9SSrikar Dronamraju { 59434e7317dSOleg Nesterov struct uprobe_task *utask = current->utask; 5950326f5a9SSrikar Dronamraju 5960326f5a9SSrikar Dronamraju WARN_ON_ONCE(current->thread.trap_nr != UPROBE_TRAP_NR); 597*014940baSOleg Nesterov 598*014940baSOleg Nesterov if (auprobe->ops->post_xol) { 599*014940baSOleg Nesterov int err = auprobe->ops->post_xol(auprobe, regs); 600*014940baSOleg Nesterov if (err) { 601*014940baSOleg Nesterov arch_uprobe_abort_xol(auprobe, regs); 602*014940baSOleg Nesterov return err; 603*014940baSOleg Nesterov } 604*014940baSOleg Nesterov } 605*014940baSOleg Nesterov 6060326f5a9SSrikar Dronamraju current->thread.trap_nr = utask->autask.saved_trap_nr; 6074dc316c6SOleg Nesterov /* 6084dc316c6SOleg Nesterov * arch_uprobe_pre_xol() doesn't save the state of TIF_BLOCKSTEP 6094dc316c6SOleg Nesterov * so we can get an extra SIGTRAP if we do not clear TF. We need 6104dc316c6SOleg Nesterov * to examine the opcode to make it right. 6114dc316c6SOleg Nesterov */ 6124dc316c6SOleg Nesterov if (utask->autask.saved_tf) 6134dc316c6SOleg Nesterov send_sig(SIGTRAP, current, 0); 6144dc316c6SOleg Nesterov else if (!(auprobe->fixups & UPROBE_FIX_SETF)) 6154dc316c6SOleg Nesterov regs->flags &= ~X86_EFLAGS_TF; 6164dc316c6SOleg Nesterov 6178ad8e9d3SOleg Nesterov return 0; 6180326f5a9SSrikar Dronamraju } 6190326f5a9SSrikar Dronamraju 6200326f5a9SSrikar Dronamraju /* callback routine for handling exceptions. */ 6210326f5a9SSrikar Dronamraju int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data) 6220326f5a9SSrikar Dronamraju { 6230326f5a9SSrikar Dronamraju struct die_args *args = data; 6240326f5a9SSrikar Dronamraju struct pt_regs *regs = args->regs; 6250326f5a9SSrikar Dronamraju int ret = NOTIFY_DONE; 6260326f5a9SSrikar Dronamraju 6270326f5a9SSrikar Dronamraju /* We are only interested in userspace traps */ 6280326f5a9SSrikar Dronamraju if (regs && !user_mode_vm(regs)) 6290326f5a9SSrikar Dronamraju return NOTIFY_DONE; 6300326f5a9SSrikar Dronamraju 6310326f5a9SSrikar Dronamraju switch (val) { 6320326f5a9SSrikar Dronamraju case DIE_INT3: 6330326f5a9SSrikar Dronamraju if (uprobe_pre_sstep_notifier(regs)) 6340326f5a9SSrikar Dronamraju ret = NOTIFY_STOP; 6350326f5a9SSrikar Dronamraju 6360326f5a9SSrikar Dronamraju break; 6370326f5a9SSrikar Dronamraju 6380326f5a9SSrikar Dronamraju case DIE_DEBUG: 6390326f5a9SSrikar Dronamraju if (uprobe_post_sstep_notifier(regs)) 6400326f5a9SSrikar Dronamraju ret = NOTIFY_STOP; 6410326f5a9SSrikar Dronamraju 6420326f5a9SSrikar Dronamraju default: 6430326f5a9SSrikar Dronamraju break; 6440326f5a9SSrikar Dronamraju } 6450326f5a9SSrikar Dronamraju 6460326f5a9SSrikar Dronamraju return ret; 6470326f5a9SSrikar Dronamraju } 6480326f5a9SSrikar Dronamraju 6490326f5a9SSrikar Dronamraju /* 6500326f5a9SSrikar Dronamraju * This function gets called when XOL instruction either gets trapped or 651*014940baSOleg Nesterov * the thread has a fatal signal, or if arch_uprobe_post_xol() failed. 652*014940baSOleg Nesterov * Reset the instruction pointer to its probed address for the potential 653*014940baSOleg Nesterov * restart or for post mortem analysis. 6540326f5a9SSrikar Dronamraju */ 6550326f5a9SSrikar Dronamraju void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) 6560326f5a9SSrikar Dronamraju { 6570326f5a9SSrikar Dronamraju struct uprobe_task *utask = current->utask; 6580326f5a9SSrikar Dronamraju 6590326f5a9SSrikar Dronamraju current->thread.trap_nr = utask->autask.saved_trap_nr; 6600326f5a9SSrikar Dronamraju handle_riprel_post_xol(auprobe, regs, NULL); 6610326f5a9SSrikar Dronamraju instruction_pointer_set(regs, utask->vaddr); 6624dc316c6SOleg Nesterov 6634dc316c6SOleg Nesterov /* clear TF if it was set by us in arch_uprobe_pre_xol() */ 6644dc316c6SOleg Nesterov if (!utask->autask.saved_tf) 6654dc316c6SOleg Nesterov regs->flags &= ~X86_EFLAGS_TF; 6660326f5a9SSrikar Dronamraju } 6670326f5a9SSrikar Dronamraju 6680326f5a9SSrikar Dronamraju /* 6690326f5a9SSrikar Dronamraju * Skip these instructions as per the currently known x86 ISA. 670b64b9c93SOleg Nesterov * rep=0x66*; nop=0x90 6710326f5a9SSrikar Dronamraju */ 6723a4664aaSOleg Nesterov static bool __skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) 6730326f5a9SSrikar Dronamraju { 6740326f5a9SSrikar Dronamraju int i; 6750326f5a9SSrikar Dronamraju 6768ad8e9d3SOleg Nesterov if (auprobe->ops->emulate) 6778ad8e9d3SOleg Nesterov return auprobe->ops->emulate(auprobe, regs); 6788ad8e9d3SOleg Nesterov 6798ad8e9d3SOleg Nesterov /* TODO: move this code into ->emulate() hook */ 6800326f5a9SSrikar Dronamraju for (i = 0; i < MAX_UINSN_BYTES; i++) { 681b64b9c93SOleg Nesterov if (auprobe->insn[i] == 0x66) 6820326f5a9SSrikar Dronamraju continue; 6830326f5a9SSrikar Dronamraju 684cf31ec3fSOleg Nesterov if (auprobe->insn[i] == 0x90) { 685cf31ec3fSOleg Nesterov regs->ip += i + 1; 6860326f5a9SSrikar Dronamraju return true; 687cf31ec3fSOleg Nesterov } 6880326f5a9SSrikar Dronamraju 6890326f5a9SSrikar Dronamraju break; 6900326f5a9SSrikar Dronamraju } 6910326f5a9SSrikar Dronamraju return false; 6920326f5a9SSrikar Dronamraju } 693bdc1e472SSebastian Andrzej Siewior 6943a4664aaSOleg Nesterov bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) 6953a4664aaSOleg Nesterov { 6963a4664aaSOleg Nesterov bool ret = __skip_sstep(auprobe, regs); 6973a4664aaSOleg Nesterov if (ret && (regs->flags & X86_EFLAGS_TF)) 6983a4664aaSOleg Nesterov send_sig(SIGTRAP, current, 0); 6993a4664aaSOleg Nesterov return ret; 7003a4664aaSOleg Nesterov } 701791eca10SAnton Arapov 702791eca10SAnton Arapov unsigned long 703791eca10SAnton Arapov arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs *regs) 704791eca10SAnton Arapov { 705791eca10SAnton Arapov int rasize, ncopied; 706791eca10SAnton Arapov unsigned long orig_ret_vaddr = 0; /* clear high bits for 32-bit apps */ 707791eca10SAnton Arapov 708791eca10SAnton Arapov rasize = is_ia32_task() ? 4 : 8; 709791eca10SAnton Arapov ncopied = copy_from_user(&orig_ret_vaddr, (void __user *)regs->sp, rasize); 710791eca10SAnton Arapov if (unlikely(ncopied)) 711791eca10SAnton Arapov return -1; 712791eca10SAnton Arapov 713791eca10SAnton Arapov /* check whether address has been already hijacked */ 714791eca10SAnton Arapov if (orig_ret_vaddr == trampoline_vaddr) 715791eca10SAnton Arapov return orig_ret_vaddr; 716791eca10SAnton Arapov 717791eca10SAnton Arapov ncopied = copy_to_user((void __user *)regs->sp, &trampoline_vaddr, rasize); 718791eca10SAnton Arapov if (likely(!ncopied)) 719791eca10SAnton Arapov return orig_ret_vaddr; 720791eca10SAnton Arapov 721791eca10SAnton Arapov if (ncopied != rasize) { 722791eca10SAnton Arapov pr_err("uprobe: return address clobbered: pid=%d, %%sp=%#lx, " 723791eca10SAnton Arapov "%%ip=%#lx\n", current->pid, regs->sp, regs->ip); 724791eca10SAnton Arapov 725791eca10SAnton Arapov force_sig_info(SIGSEGV, SEND_SIG_FORCED, current); 726791eca10SAnton Arapov } 727791eca10SAnton Arapov 728791eca10SAnton Arapov return -1; 729791eca10SAnton Arapov } 730