1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#include <linux/kernel.h>
24#include <linux/sched.h>
25#include <linux/ptrace.h>
26#include <linux/uprobes.h>
27#include <linux/uaccess.h>
28
29#include <linux/kdebug.h>
30#include <asm/processor.h>
31#include <asm/insn.h>
32
33
34
35
36#define UPROBE_FIX_NONE 0x0
37
38
39#define UPROBE_FIX_IP 0x1
40
41
42#define UPROBE_FIX_CALL 0x2
43
44
45#define UPROBE_FIX_SETF 0x4
46
47#define UPROBE_FIX_RIP_AX 0x8000
48#define UPROBE_FIX_RIP_CX 0x4000
49
50#define UPROBE_TRAP_NR UINT_MAX
51
52
53#define OPCODE1(insn) ((insn)->opcode.bytes[0])
54#define OPCODE2(insn) ((insn)->opcode.bytes[1])
55#define OPCODE3(insn) ((insn)->opcode.bytes[2])
56#define MODRM_REG(insn) X86_MODRM_REG(insn->modrm.value)
57
58#define W(row, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf)\
59 (((b0##UL << 0x0)|(b1##UL << 0x1)|(b2##UL << 0x2)|(b3##UL << 0x3) | \
60 (b4##UL << 0x4)|(b5##UL << 0x5)|(b6##UL << 0x6)|(b7##UL << 0x7) | \
61 (b8##UL << 0x8)|(b9##UL << 0x9)|(ba##UL << 0xa)|(bb##UL << 0xb) | \
62 (bc##UL << 0xc)|(bd##UL << 0xd)|(be##UL << 0xe)|(bf##UL << 0xf)) \
63 << (row % 32))
64
65
66
67
68
69
70static volatile u32 good_insns_32[256 / 32] = {
71
72
73 W(0x00, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0) |
74 W(0x10, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0) ,
75 W(0x20, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1) |
76 W(0x30, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1) ,
77 W(0x40, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) |
78 W(0x50, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) ,
79 W(0x60, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) |
80 W(0x70, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) ,
81 W(0x80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) |
82 W(0x90, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) ,
83 W(0xa0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) |
84 W(0xb0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) ,
85 W(0xc0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0) |
86 W(0xd0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1) ,
87 W(0xe0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) |
88 W(0xf0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1)
89
90
91};
92
93
94static volatile u32 good_2byte_insns[256 / 32] = {
95
96
97 W(0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1) |
98 W(0x10, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1) ,
99 W(0x20, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1) |
100 W(0x30, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) ,
101 W(0x40, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) |
102 W(0x50, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) ,
103 W(0x60, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) |
104 W(0x70, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1) ,
105 W(0x80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) |
106 W(0x90, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) ,
107 W(0xa0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1) |
108 W(0xb0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1) ,
109 W(0xc0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) |
110 W(0xd0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) ,
111 W(0xe0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) |
112 W(0xf0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)
113
114
115};
116
117#ifdef CONFIG_X86_64
118
119static volatile u32 good_insns_64[256 / 32] = {
120
121
122 W(0x00, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0) |
123 W(0x10, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0) ,
124 W(0x20, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0) |
125 W(0x30, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0) ,
126 W(0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) |
127 W(0x50, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) ,
128 W(0x60, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) |
129 W(0x70, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) ,
130 W(0x80, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) |
131 W(0x90, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) ,
132 W(0xa0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) |
133 W(0xb0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) ,
134 W(0xc0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0) |
135 W(0xd0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1) ,
136 W(0xe0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) |
137 W(0xf0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1)
138
139
140};
141#endif
142#undef W
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195static bool is_prefix_bad(struct insn *insn)
196{
197 int i;
198
199 for (i = 0; i < insn->prefixes.nbytes; i++) {
200 switch (insn->prefixes.bytes[i]) {
201 case 0x26:
202 case 0x2E:
203 case 0x36:
204 case 0x3E:
205 case 0xF0:
206 return true;
207 }
208 }
209 return false;
210}
211
212static int validate_insn_32bits(struct arch_uprobe *auprobe, struct insn *insn)
213{
214 insn_init(insn, auprobe->insn, false);
215
216
217 insn_get_opcode(insn);
218 if (is_prefix_bad(insn))
219 return -ENOTSUPP;
220
221 if (test_bit(OPCODE1(insn), (unsigned long *)good_insns_32))
222 return 0;
223
224 if (insn->opcode.nbytes == 2) {
225 if (test_bit(OPCODE2(insn), (unsigned long *)good_2byte_insns))
226 return 0;
227 }
228
229 return -ENOTSUPP;
230}
231
232
233
234
235
236
237static void prepare_fixups(struct arch_uprobe *auprobe, struct insn *insn)
238{
239 bool fix_ip = true, fix_call = false;
240 int reg;
241
242 insn_get_opcode(insn);
243
244 switch (OPCODE1(insn)) {
245 case 0x9d:
246
247 auprobe->fixups |= UPROBE_FIX_SETF;
248 break;
249 case 0xc3:
250 case 0xcb:
251 case 0xc2:
252 case 0xca:
253
254 fix_ip = false;
255 break;
256 case 0xe8:
257 fix_call = true;
258 break;
259 case 0x9a:
260 fix_call = true;
261 fix_ip = false;
262 break;
263 case 0xff:
264 insn_get_modrm(insn);
265 reg = MODRM_REG(insn);
266 if (reg == 2 || reg == 3) {
267
268
269 fix_call = true;
270 fix_ip = false;
271 } else if (reg == 4 || reg == 5) {
272
273
274 fix_ip = false;
275 }
276 break;
277 case 0xea:
278 fix_ip = false;
279 break;
280 default:
281 break;
282 }
283 if (fix_ip)
284 auprobe->fixups |= UPROBE_FIX_IP;
285 if (fix_call)
286 auprobe->fixups |= UPROBE_FIX_CALL;
287}
288
289#ifdef CONFIG_X86_64
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312static void
313handle_riprel_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, struct insn *insn)
314{
315 u8 *cursor;
316 u8 reg;
317
318 if (mm->context.ia32_compat)
319 return;
320
321 auprobe->rip_rela_target_address = 0x0;
322 if (!insn_rip_relative(insn))
323 return;
324
325
326
327
328
329
330 if (insn->rex_prefix.nbytes) {
331 cursor = auprobe->insn + insn_offset_rex_prefix(insn);
332 *cursor &= 0xfe;
333 }
334
335
336
337
338
339
340 cursor = auprobe->insn + insn_offset_modrm(insn);
341 insn_get_length(insn);
342
343
344
345
346
347
348 reg = MODRM_REG(insn);
349 if (reg == 0) {
350
351
352
353
354
355
356
357 auprobe->fixups = UPROBE_FIX_RIP_CX;
358
359 *cursor = 0x1;
360 } else {
361
362 auprobe->fixups = UPROBE_FIX_RIP_AX;
363
364 *cursor = (reg << 3);
365 }
366
367
368 auprobe->rip_rela_target_address = (long)insn->length + insn->displacement.value;
369
370
371 if (insn->immediate.nbytes) {
372 cursor++;
373 memmove(cursor, cursor + insn->displacement.nbytes, insn->immediate.nbytes);
374 }
375 return;
376}
377
378static int validate_insn_64bits(struct arch_uprobe *auprobe, struct insn *insn)
379{
380 insn_init(insn, auprobe->insn, true);
381
382
383 insn_get_opcode(insn);
384 if (is_prefix_bad(insn))
385 return -ENOTSUPP;
386
387 if (test_bit(OPCODE1(insn), (unsigned long *)good_insns_64))
388 return 0;
389
390 if (insn->opcode.nbytes == 2) {
391 if (test_bit(OPCODE2(insn), (unsigned long *)good_2byte_insns))
392 return 0;
393 }
394 return -ENOTSUPP;
395}
396
397static int validate_insn_bits(struct arch_uprobe *auprobe, struct mm_struct *mm, struct insn *insn)
398{
399 if (mm->context.ia32_compat)
400 return validate_insn_32bits(auprobe, insn);
401 return validate_insn_64bits(auprobe, insn);
402}
403#else
404static void handle_riprel_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, struct insn *insn)
405{
406
407}
408
409static int validate_insn_bits(struct arch_uprobe *auprobe, struct mm_struct *mm, struct insn *insn)
410{
411 return validate_insn_32bits(auprobe, insn);
412}
413#endif
414
415
416
417
418
419
420
421
422int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long addr)
423{
424 int ret;
425 struct insn insn;
426
427 auprobe->fixups = 0;
428 ret = validate_insn_bits(auprobe, mm, &insn);
429 if (ret != 0)
430 return ret;
431
432 handle_riprel_insn(auprobe, mm, &insn);
433 prepare_fixups(auprobe, &insn);
434
435 return 0;
436}
437
438#ifdef CONFIG_X86_64
439
440
441
442
443static void
444pre_xol_rip_insn(struct arch_uprobe *auprobe, struct pt_regs *regs,
445 struct arch_uprobe_task *autask)
446{
447 if (auprobe->fixups & UPROBE_FIX_RIP_AX) {
448 autask->saved_scratch_register = regs->ax;
449 regs->ax = current->utask->vaddr;
450 regs->ax += auprobe->rip_rela_target_address;
451 } else if (auprobe->fixups & UPROBE_FIX_RIP_CX) {
452 autask->saved_scratch_register = regs->cx;
453 regs->cx = current->utask->vaddr;
454 regs->cx += auprobe->rip_rela_target_address;
455 }
456}
457#else
458static void
459pre_xol_rip_insn(struct arch_uprobe *auprobe, struct pt_regs *regs,
460 struct arch_uprobe_task *autask)
461{
462
463}
464#endif
465
466
467
468
469
470
471int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
472{
473 struct arch_uprobe_task *autask;
474
475 autask = ¤t->utask->autask;
476 autask->saved_trap_nr = current->thread.trap_nr;
477 current->thread.trap_nr = UPROBE_TRAP_NR;
478 regs->ip = current->utask->xol_vaddr;
479 pre_xol_rip_insn(auprobe, regs, autask);
480
481 autask->saved_tf = !!(regs->flags & X86_EFLAGS_TF);
482 regs->flags |= X86_EFLAGS_TF;
483 if (test_tsk_thread_flag(current, TIF_BLOCKSTEP))
484 set_task_blockstep(current, false);
485
486 return 0;
487}
488
489
490
491
492
493static int adjust_ret_addr(unsigned long sp, long correction)
494{
495 int rasize, ncopied;
496 long ra = 0;
497
498 if (is_ia32_task())
499 rasize = 4;
500 else
501 rasize = 8;
502
503 ncopied = copy_from_user(&ra, (void __user *)sp, rasize);
504 if (unlikely(ncopied))
505 return -EFAULT;
506
507 ra += correction;
508 ncopied = copy_to_user((void __user *)sp, &ra, rasize);
509 if (unlikely(ncopied))
510 return -EFAULT;
511
512 return 0;
513}
514
515#ifdef CONFIG_X86_64
516static bool is_riprel_insn(struct arch_uprobe *auprobe)
517{
518 return ((auprobe->fixups & (UPROBE_FIX_RIP_AX | UPROBE_FIX_RIP_CX)) != 0);
519}
520
521static void
522handle_riprel_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs, long *correction)
523{
524 if (is_riprel_insn(auprobe)) {
525 struct arch_uprobe_task *autask;
526
527 autask = ¤t->utask->autask;
528 if (auprobe->fixups & UPROBE_FIX_RIP_AX)
529 regs->ax = autask->saved_scratch_register;
530 else
531 regs->cx = autask->saved_scratch_register;
532
533
534
535
536
537
538
539 if (correction)
540 *correction += 4;
541 }
542}
543#else
544static void
545handle_riprel_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs, long *correction)
546{
547
548}
549#endif
550
551
552
553
554
555
556
557
558
559
560
561bool arch_uprobe_xol_was_trapped(struct task_struct *t)
562{
563 if (t->thread.trap_nr != UPROBE_TRAP_NR)
564 return true;
565
566 return false;
567}
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
594{
595 struct uprobe_task *utask;
596 long correction;
597 int result = 0;
598
599 WARN_ON_ONCE(current->thread.trap_nr != UPROBE_TRAP_NR);
600
601 utask = current->utask;
602 current->thread.trap_nr = utask->autask.saved_trap_nr;
603 correction = (long)(utask->vaddr - utask->xol_vaddr);
604 handle_riprel_post_xol(auprobe, regs, &correction);
605 if (auprobe->fixups & UPROBE_FIX_IP)
606 regs->ip += correction;
607
608 if (auprobe->fixups & UPROBE_FIX_CALL)
609 result = adjust_ret_addr(regs->sp, correction);
610
611
612
613
614
615
616 if (utask->autask.saved_tf)
617 send_sig(SIGTRAP, current, 0);
618 else if (!(auprobe->fixups & UPROBE_FIX_SETF))
619 regs->flags &= ~X86_EFLAGS_TF;
620
621 return result;
622}
623
624
625int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data)
626{
627 struct die_args *args = data;
628 struct pt_regs *regs = args->regs;
629 int ret = NOTIFY_DONE;
630
631
632 if (regs && !user_mode_vm(regs))
633 return NOTIFY_DONE;
634
635 switch (val) {
636 case DIE_INT3:
637 if (uprobe_pre_sstep_notifier(regs))
638 ret = NOTIFY_STOP;
639
640 break;
641
642 case DIE_DEBUG:
643 if (uprobe_post_sstep_notifier(regs))
644 ret = NOTIFY_STOP;
645
646 default:
647 break;
648 }
649
650 return ret;
651}
652
653
654
655
656
657
658void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
659{
660 struct uprobe_task *utask = current->utask;
661
662 current->thread.trap_nr = utask->autask.saved_trap_nr;
663 handle_riprel_post_xol(auprobe, regs, NULL);
664 instruction_pointer_set(regs, utask->vaddr);
665
666
667 if (!utask->autask.saved_tf)
668 regs->flags &= ~X86_EFLAGS_TF;
669}
670
671
672
673
674
675static bool __skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
676{
677 int i;
678
679 for (i = 0; i < MAX_UINSN_BYTES; i++) {
680 if (auprobe->insn[i] == 0x66)
681 continue;
682
683 if (auprobe->insn[i] == 0x90) {
684 regs->ip += i + 1;
685 return true;
686 }
687
688 break;
689 }
690 return false;
691}
692
693bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
694{
695 bool ret = __skip_sstep(auprobe, regs);
696 if (ret && (regs->flags & X86_EFLAGS_TF))
697 send_sig(SIGTRAP, current, 0);
698 return ret;
699}
700
701unsigned long
702arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs *regs)
703{
704 int rasize, ncopied;
705 unsigned long orig_ret_vaddr = 0;
706
707 rasize = is_ia32_task() ? 4 : 8;
708 ncopied = copy_from_user(&orig_ret_vaddr, (void __user *)regs->sp, rasize);
709 if (unlikely(ncopied))
710 return -1;
711
712
713 if (orig_ret_vaddr == trampoline_vaddr)
714 return orig_ret_vaddr;
715
716 ncopied = copy_to_user((void __user *)regs->sp, &trampoline_vaddr, rasize);
717 if (likely(!ncopied))
718 return orig_ret_vaddr;
719
720 if (ncopied != rasize) {
721 pr_err("uprobe: return address clobbered: pid=%d, %%sp=%#lx, "
722 "%%ip=%#lx\n", current->pid, regs->sp, regs->ip);
723
724 force_sig_info(SIGSEGV, SEND_SIG_FORCED, current);
725 }
726
727 return -1;
728}
729