xref: /openbmc/linux/arch/x86/kernel/uprobes.c (revision 014940bad8e46ca7bd0483f760f9cba60088a3d4)
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 = &current->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, &current->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