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