1
2
3
4
5
6#include <linux/kernel.h>
7#include <linux/string.h>
8#include <linux/ratelimit.h>
9#include <linux/mmu_context.h>
10#include <asm/desc_defs.h>
11#include <asm/desc.h>
12#include <asm/inat.h>
13#include <asm/insn.h>
14#include <asm/insn-eval.h>
15#include <asm/ldt.h>
16#include <asm/vm86.h>
17
18#undef pr_fmt
19#define pr_fmt(fmt) "insn: " fmt
20
21enum reg_type {
22 REG_TYPE_RM = 0,
23 REG_TYPE_REG,
24 REG_TYPE_INDEX,
25 REG_TYPE_BASE,
26};
27
28
29
30
31
32
33
34
35
36
37
38static bool is_string_insn(struct insn *insn)
39{
40 insn_get_opcode(insn);
41
42
43 if (insn->opcode.nbytes != 1)
44 return false;
45
46 switch (insn->opcode.bytes[0]) {
47 case 0x6c ... 0x6f:
48 case 0xa4 ... 0xa7:
49 case 0xaa ... 0xaf:
50 return true;
51 default:
52 return false;
53 }
54}
55
56
57
58
59
60
61
62
63
64bool insn_has_rep_prefix(struct insn *insn)
65{
66 insn_byte_t p;
67 int i;
68
69 insn_get_prefixes(insn);
70
71 for_each_insn_prefix(insn, i, p) {
72 if (p == 0xf2 || p == 0xf3)
73 return true;
74 }
75
76 return false;
77}
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93static int get_seg_reg_override_idx(struct insn *insn)
94{
95 int idx = INAT_SEG_REG_DEFAULT;
96 int num_overrides = 0, i;
97 insn_byte_t p;
98
99 insn_get_prefixes(insn);
100
101
102 for_each_insn_prefix(insn, i, p) {
103 insn_attr_t attr;
104
105 attr = inat_get_opcode_attribute(p);
106 switch (attr) {
107 case INAT_MAKE_PREFIX(INAT_PFX_CS):
108 idx = INAT_SEG_REG_CS;
109 num_overrides++;
110 break;
111 case INAT_MAKE_PREFIX(INAT_PFX_SS):
112 idx = INAT_SEG_REG_SS;
113 num_overrides++;
114 break;
115 case INAT_MAKE_PREFIX(INAT_PFX_DS):
116 idx = INAT_SEG_REG_DS;
117 num_overrides++;
118 break;
119 case INAT_MAKE_PREFIX(INAT_PFX_ES):
120 idx = INAT_SEG_REG_ES;
121 num_overrides++;
122 break;
123 case INAT_MAKE_PREFIX(INAT_PFX_FS):
124 idx = INAT_SEG_REG_FS;
125 num_overrides++;
126 break;
127 case INAT_MAKE_PREFIX(INAT_PFX_GS):
128 idx = INAT_SEG_REG_GS;
129 num_overrides++;
130 break;
131
132 }
133 }
134
135
136 if (num_overrides > 1)
137 return -EINVAL;
138
139 return idx;
140}
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156static bool check_seg_overrides(struct insn *insn, int regoff)
157{
158 if (regoff == offsetof(struct pt_regs, di) && is_string_insn(insn))
159 return false;
160
161 return true;
162}
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181static int resolve_default_seg(struct insn *insn, struct pt_regs *regs, int off)
182{
183 if (any_64bit_mode(regs))
184 return INAT_SEG_REG_IGNORE;
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199 switch (off) {
200 case offsetof(struct pt_regs, ax):
201 case offsetof(struct pt_regs, cx):
202 case offsetof(struct pt_regs, dx):
203
204 if (insn->addr_bytes == 2)
205 return -EINVAL;
206
207 fallthrough;
208
209 case -EDOM:
210 case offsetof(struct pt_regs, bx):
211 case offsetof(struct pt_regs, si):
212 return INAT_SEG_REG_DS;
213
214 case offsetof(struct pt_regs, di):
215 if (is_string_insn(insn))
216 return INAT_SEG_REG_ES;
217 return INAT_SEG_REG_DS;
218
219 case offsetof(struct pt_regs, bp):
220 case offsetof(struct pt_regs, sp):
221 return INAT_SEG_REG_SS;
222
223 case offsetof(struct pt_regs, ip):
224 return INAT_SEG_REG_CS;
225
226 default:
227 return -EINVAL;
228 }
229}
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283static int resolve_seg_reg(struct insn *insn, struct pt_regs *regs, int regoff)
284{
285 int idx;
286
287
288
289
290
291
292
293 if (regoff == offsetof(struct pt_regs, ip)) {
294 if (any_64bit_mode(regs))
295 return INAT_SEG_REG_IGNORE;
296 else
297 return INAT_SEG_REG_CS;
298 }
299
300 if (!insn)
301 return -EINVAL;
302
303 if (!check_seg_overrides(insn, regoff))
304 return resolve_default_seg(insn, regs, regoff);
305
306 idx = get_seg_reg_override_idx(insn);
307 if (idx < 0)
308 return idx;
309
310 if (idx == INAT_SEG_REG_DEFAULT)
311 return resolve_default_seg(insn, regs, regoff);
312
313
314
315
316
317 if (any_64bit_mode(regs)) {
318 if (idx != INAT_SEG_REG_FS &&
319 idx != INAT_SEG_REG_GS)
320 idx = INAT_SEG_REG_IGNORE;
321 }
322
323 return idx;
324}
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345static short get_segment_selector(struct pt_regs *regs, int seg_reg_idx)
346{
347#ifdef CONFIG_X86_64
348 unsigned short sel;
349
350 switch (seg_reg_idx) {
351 case INAT_SEG_REG_IGNORE:
352 return 0;
353 case INAT_SEG_REG_CS:
354 return (unsigned short)(regs->cs & 0xffff);
355 case INAT_SEG_REG_SS:
356 return (unsigned short)(regs->ss & 0xffff);
357 case INAT_SEG_REG_DS:
358 savesegment(ds, sel);
359 return sel;
360 case INAT_SEG_REG_ES:
361 savesegment(es, sel);
362 return sel;
363 case INAT_SEG_REG_FS:
364 savesegment(fs, sel);
365 return sel;
366 case INAT_SEG_REG_GS:
367 savesegment(gs, sel);
368 return sel;
369 default:
370 return -EINVAL;
371 }
372#else
373 struct kernel_vm86_regs *vm86regs = (struct kernel_vm86_regs *)regs;
374
375 if (v8086_mode(regs)) {
376 switch (seg_reg_idx) {
377 case INAT_SEG_REG_CS:
378 return (unsigned short)(regs->cs & 0xffff);
379 case INAT_SEG_REG_SS:
380 return (unsigned short)(regs->ss & 0xffff);
381 case INAT_SEG_REG_DS:
382 return vm86regs->ds;
383 case INAT_SEG_REG_ES:
384 return vm86regs->es;
385 case INAT_SEG_REG_FS:
386 return vm86regs->fs;
387 case INAT_SEG_REG_GS:
388 return vm86regs->gs;
389 case INAT_SEG_REG_IGNORE:
390 default:
391 return -EINVAL;
392 }
393 }
394
395 switch (seg_reg_idx) {
396 case INAT_SEG_REG_CS:
397 return (unsigned short)(regs->cs & 0xffff);
398 case INAT_SEG_REG_SS:
399 return (unsigned short)(regs->ss & 0xffff);
400 case INAT_SEG_REG_DS:
401 return (unsigned short)(regs->ds & 0xffff);
402 case INAT_SEG_REG_ES:
403 return (unsigned short)(regs->es & 0xffff);
404 case INAT_SEG_REG_FS:
405 return (unsigned short)(regs->fs & 0xffff);
406 case INAT_SEG_REG_GS:
407 return get_user_gs(regs);
408 case INAT_SEG_REG_IGNORE:
409 default:
410 return -EINVAL;
411 }
412#endif
413}
414
415static int get_reg_offset(struct insn *insn, struct pt_regs *regs,
416 enum reg_type type)
417{
418 int regno = 0;
419
420 static const int regoff[] = {
421 offsetof(struct pt_regs, ax),
422 offsetof(struct pt_regs, cx),
423 offsetof(struct pt_regs, dx),
424 offsetof(struct pt_regs, bx),
425 offsetof(struct pt_regs, sp),
426 offsetof(struct pt_regs, bp),
427 offsetof(struct pt_regs, si),
428 offsetof(struct pt_regs, di),
429#ifdef CONFIG_X86_64
430 offsetof(struct pt_regs, r8),
431 offsetof(struct pt_regs, r9),
432 offsetof(struct pt_regs, r10),
433 offsetof(struct pt_regs, r11),
434 offsetof(struct pt_regs, r12),
435 offsetof(struct pt_regs, r13),
436 offsetof(struct pt_regs, r14),
437 offsetof(struct pt_regs, r15),
438#endif
439 };
440 int nr_registers = ARRAY_SIZE(regoff);
441
442
443
444
445 if (IS_ENABLED(CONFIG_X86_64) && !insn->x86_64)
446 nr_registers -= 8;
447
448 switch (type) {
449 case REG_TYPE_RM:
450 regno = X86_MODRM_RM(insn->modrm.value);
451
452
453
454
455
456 if (!X86_MODRM_MOD(insn->modrm.value) && regno == 5)
457 return -EDOM;
458
459 if (X86_REX_B(insn->rex_prefix.value))
460 regno += 8;
461 break;
462
463 case REG_TYPE_REG:
464 regno = X86_MODRM_REG(insn->modrm.value);
465
466 if (X86_REX_R(insn->rex_prefix.value))
467 regno += 8;
468 break;
469
470 case REG_TYPE_INDEX:
471 regno = X86_SIB_INDEX(insn->sib.value);
472 if (X86_REX_X(insn->rex_prefix.value))
473 regno += 8;
474
475
476
477
478
479
480
481 if (X86_MODRM_MOD(insn->modrm.value) != 3 && regno == 4)
482 return -EDOM;
483 break;
484
485 case REG_TYPE_BASE:
486 regno = X86_SIB_BASE(insn->sib.value);
487
488
489
490
491
492 if (!X86_MODRM_MOD(insn->modrm.value) && regno == 5)
493 return -EDOM;
494
495 if (X86_REX_B(insn->rex_prefix.value))
496 regno += 8;
497 break;
498
499 default:
500 pr_err_ratelimited("invalid register type: %d\n", type);
501 return -EINVAL;
502 }
503
504 if (regno >= nr_registers) {
505 WARN_ONCE(1, "decoded an instruction with an invalid register");
506 return -EINVAL;
507 }
508 return regoff[regno];
509}
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528static int get_reg_offset_16(struct insn *insn, struct pt_regs *regs,
529 int *offs1, int *offs2)
530{
531
532
533
534
535
536 static const int regoff1[] = {
537 offsetof(struct pt_regs, bx),
538 offsetof(struct pt_regs, bx),
539 offsetof(struct pt_regs, bp),
540 offsetof(struct pt_regs, bp),
541 offsetof(struct pt_regs, si),
542 offsetof(struct pt_regs, di),
543 offsetof(struct pt_regs, bp),
544 offsetof(struct pt_regs, bx),
545 };
546
547 static const int regoff2[] = {
548 offsetof(struct pt_regs, si),
549 offsetof(struct pt_regs, di),
550 offsetof(struct pt_regs, si),
551 offsetof(struct pt_regs, di),
552 -EDOM,
553 -EDOM,
554 -EDOM,
555 -EDOM,
556 };
557
558 if (!offs1 || !offs2)
559 return -EINVAL;
560
561
562 if (X86_MODRM_MOD(insn->modrm.value) == 3) {
563 *offs1 = insn_get_modrm_rm_off(insn, regs);
564 *offs2 = -EDOM;
565 return 0;
566 }
567
568 *offs1 = regoff1[X86_MODRM_RM(insn->modrm.value)];
569 *offs2 = regoff2[X86_MODRM_RM(insn->modrm.value)];
570
571
572
573
574
575
576
577
578 if ((X86_MODRM_MOD(insn->modrm.value) == 0) &&
579 (X86_MODRM_RM(insn->modrm.value) == 6))
580 *offs1 = -EDOM;
581
582 return 0;
583}
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599static bool get_desc(struct desc_struct *out, unsigned short sel)
600{
601 struct desc_ptr gdt_desc = {0, 0};
602 unsigned long desc_base;
603
604#ifdef CONFIG_MODIFY_LDT_SYSCALL
605 if ((sel & SEGMENT_TI_MASK) == SEGMENT_LDT) {
606 bool success = false;
607 struct ldt_struct *ldt;
608
609
610 sel >>= 3;
611
612 mutex_lock(¤t->active_mm->context.lock);
613 ldt = current->active_mm->context.ldt;
614 if (ldt && sel < ldt->nr_entries) {
615 *out = ldt->entries[sel];
616 success = true;
617 }
618
619 mutex_unlock(¤t->active_mm->context.lock);
620
621 return success;
622 }
623#endif
624 native_store_gdt(&gdt_desc);
625
626
627
628
629
630
631
632
633 desc_base = sel & ~(SEGMENT_RPL_MASK | SEGMENT_TI_MASK);
634
635 if (desc_base > gdt_desc.size)
636 return false;
637
638 *out = *(struct desc_struct *)(gdt_desc.address + desc_base);
639 return true;
640}
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659unsigned long insn_get_seg_base(struct pt_regs *regs, int seg_reg_idx)
660{
661 struct desc_struct desc;
662 short sel;
663
664 sel = get_segment_selector(regs, seg_reg_idx);
665 if (sel < 0)
666 return -1L;
667
668 if (v8086_mode(regs))
669
670
671
672
673 return (unsigned long)(sel << 4);
674
675 if (any_64bit_mode(regs)) {
676
677
678
679
680 unsigned long base;
681
682 if (seg_reg_idx == INAT_SEG_REG_FS) {
683 rdmsrl(MSR_FS_BASE, base);
684 } else if (seg_reg_idx == INAT_SEG_REG_GS) {
685
686
687
688
689 if (user_mode(regs))
690 rdmsrl(MSR_KERNEL_GS_BASE, base);
691 else
692 rdmsrl(MSR_GS_BASE, base);
693 } else {
694 base = 0;
695 }
696 return base;
697 }
698
699
700 if (!sel)
701 return -1L;
702
703 if (!get_desc(&desc, sel))
704 return -1L;
705
706 return get_desc_base(&desc);
707}
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726static unsigned long get_seg_limit(struct pt_regs *regs, int seg_reg_idx)
727{
728 struct desc_struct desc;
729 unsigned long limit;
730 short sel;
731
732 sel = get_segment_selector(regs, seg_reg_idx);
733 if (sel < 0)
734 return 0;
735
736 if (any_64bit_mode(regs) || v8086_mode(regs))
737 return -1L;
738
739 if (!sel)
740 return 0;
741
742 if (!get_desc(&desc, sel))
743 return 0;
744
745
746
747
748
749
750
751 limit = get_desc_limit(&desc);
752 if (desc.g)
753 limit = (limit << 12) + 0xfff;
754
755 return limit;
756}
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774int insn_get_code_seg_params(struct pt_regs *regs)
775{
776 struct desc_struct desc;
777 short sel;
778
779 if (v8086_mode(regs))
780
781 return INSN_CODE_SEG_PARAMS(2, 2);
782
783 sel = get_segment_selector(regs, INAT_SEG_REG_CS);
784 if (sel < 0)
785 return sel;
786
787 if (!get_desc(&desc, sel))
788 return -EINVAL;
789
790
791
792
793
794
795 if (!(desc.type & BIT(3)))
796 return -EINVAL;
797
798 switch ((desc.l << 1) | desc.d) {
799 case 0:
800
801
802
803 return INSN_CODE_SEG_PARAMS(2, 2);
804 case 1:
805
806
807
808 return INSN_CODE_SEG_PARAMS(4, 4);
809 case 2:
810
811
812
813 return INSN_CODE_SEG_PARAMS(4, 8);
814 case 3:
815 fallthrough;
816 default:
817 return -EINVAL;
818 }
819}
820
821
822
823
824
825
826
827
828
829
830
831
832
833int insn_get_modrm_rm_off(struct insn *insn, struct pt_regs *regs)
834{
835 return get_reg_offset(insn, regs, REG_TYPE_RM);
836}
837
838
839
840
841
842
843
844
845
846
847
848int insn_get_modrm_reg_off(struct insn *insn, struct pt_regs *regs)
849{
850 return get_reg_offset(insn, regs, REG_TYPE_REG);
851}
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874static int get_seg_base_limit(struct insn *insn, struct pt_regs *regs,
875 int regoff, unsigned long *base,
876 unsigned long *limit)
877{
878 int seg_reg_idx;
879
880 if (!base)
881 return -EINVAL;
882
883 seg_reg_idx = resolve_seg_reg(insn, regs, regoff);
884 if (seg_reg_idx < 0)
885 return seg_reg_idx;
886
887 *base = insn_get_seg_base(regs, seg_reg_idx);
888 if (*base == -1L)
889 return -EINVAL;
890
891 if (!limit)
892 return 0;
893
894 *limit = get_seg_limit(regs, seg_reg_idx);
895 if (!(*limit))
896 return -EINVAL;
897
898 return 0;
899}
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924static int get_eff_addr_reg(struct insn *insn, struct pt_regs *regs,
925 int *regoff, long *eff_addr)
926{
927 int ret;
928
929 ret = insn_get_modrm(insn);
930 if (ret)
931 return ret;
932
933 if (X86_MODRM_MOD(insn->modrm.value) != 3)
934 return -EINVAL;
935
936 *regoff = get_reg_offset(insn, regs, REG_TYPE_RM);
937 if (*regoff < 0)
938 return -EINVAL;
939
940
941 if (insn->addr_bytes == 2)
942 *eff_addr = regs_get_register(regs, *regoff) & 0xffff;
943 else if (insn->addr_bytes == 4)
944 *eff_addr = regs_get_register(regs, *regoff) & 0xffffffff;
945 else
946 *eff_addr = regs_get_register(regs, *regoff);
947
948 return 0;
949}
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973static int get_eff_addr_modrm(struct insn *insn, struct pt_regs *regs,
974 int *regoff, long *eff_addr)
975{
976 long tmp;
977 int ret;
978
979 if (insn->addr_bytes != 8 && insn->addr_bytes != 4)
980 return -EINVAL;
981
982 ret = insn_get_modrm(insn);
983 if (ret)
984 return ret;
985
986 if (X86_MODRM_MOD(insn->modrm.value) > 2)
987 return -EINVAL;
988
989 *regoff = get_reg_offset(insn, regs, REG_TYPE_RM);
990
991
992
993
994
995
996 if (*regoff == -EDOM) {
997 if (any_64bit_mode(regs))
998 tmp = regs->ip + insn->length;
999 else
1000 tmp = 0;
1001 } else if (*regoff < 0) {
1002 return -EINVAL;
1003 } else {
1004 tmp = regs_get_register(regs, *regoff);
1005 }
1006
1007 if (insn->addr_bytes == 4) {
1008 int addr32 = (int)(tmp & 0xffffffff) + insn->displacement.value;
1009
1010 *eff_addr = addr32 & 0xffffffff;
1011 } else {
1012 *eff_addr = tmp + insn->displacement.value;
1013 }
1014
1015 return 0;
1016}
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040static int get_eff_addr_modrm_16(struct insn *insn, struct pt_regs *regs,
1041 int *regoff, short *eff_addr)
1042{
1043 int addr_offset1, addr_offset2, ret;
1044 short addr1 = 0, addr2 = 0, displacement;
1045
1046 if (insn->addr_bytes != 2)
1047 return -EINVAL;
1048
1049 insn_get_modrm(insn);
1050
1051 if (!insn->modrm.nbytes)
1052 return -EINVAL;
1053
1054 if (X86_MODRM_MOD(insn->modrm.value) > 2)
1055 return -EINVAL;
1056
1057 ret = get_reg_offset_16(insn, regs, &addr_offset1, &addr_offset2);
1058 if (ret < 0)
1059 return -EINVAL;
1060
1061
1062
1063
1064
1065
1066 if (addr_offset1 != -EDOM)
1067 addr1 = regs_get_register(regs, addr_offset1) & 0xffff;
1068
1069 if (addr_offset2 != -EDOM)
1070 addr2 = regs_get_register(regs, addr_offset2) & 0xffff;
1071
1072 displacement = insn->displacement.value & 0xffff;
1073 *eff_addr = addr1 + addr2 + displacement;
1074
1075
1076
1077
1078
1079
1080
1081 *regoff = addr_offset1;
1082
1083 return 0;
1084}
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108static int get_eff_addr_sib(struct insn *insn, struct pt_regs *regs,
1109 int *base_offset, long *eff_addr)
1110{
1111 long base, indx;
1112 int indx_offset;
1113 int ret;
1114
1115 if (insn->addr_bytes != 8 && insn->addr_bytes != 4)
1116 return -EINVAL;
1117
1118 ret = insn_get_modrm(insn);
1119 if (ret)
1120 return ret;
1121
1122 if (!insn->modrm.nbytes)
1123 return -EINVAL;
1124
1125 if (X86_MODRM_MOD(insn->modrm.value) > 2)
1126 return -EINVAL;
1127
1128 ret = insn_get_sib(insn);
1129 if (ret)
1130 return ret;
1131
1132 if (!insn->sib.nbytes)
1133 return -EINVAL;
1134
1135 *base_offset = get_reg_offset(insn, regs, REG_TYPE_BASE);
1136 indx_offset = get_reg_offset(insn, regs, REG_TYPE_INDEX);
1137
1138
1139
1140
1141
1142
1143 if (*base_offset == -EDOM)
1144 base = 0;
1145 else if (*base_offset < 0)
1146 return -EINVAL;
1147 else
1148 base = regs_get_register(regs, *base_offset);
1149
1150 if (indx_offset == -EDOM)
1151 indx = 0;
1152 else if (indx_offset < 0)
1153 return -EINVAL;
1154 else
1155 indx = regs_get_register(regs, indx_offset);
1156
1157 if (insn->addr_bytes == 4) {
1158 int addr32, base32, idx32;
1159
1160 base32 = base & 0xffffffff;
1161 idx32 = indx & 0xffffffff;
1162
1163 addr32 = base32 + idx32 * (1 << X86_SIB_SCALE(insn->sib.value));
1164 addr32 += insn->displacement.value;
1165
1166 *eff_addr = addr32 & 0xffffffff;
1167 } else {
1168 *eff_addr = base + indx * (1 << X86_SIB_SCALE(insn->sib.value));
1169 *eff_addr += insn->displacement.value;
1170 }
1171
1172 return 0;
1173}
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192static void __user *get_addr_ref_16(struct insn *insn, struct pt_regs *regs)
1193{
1194 unsigned long linear_addr = -1L, seg_base, seg_limit;
1195 int ret, regoff;
1196 short eff_addr;
1197 long tmp;
1198
1199 if (insn_get_displacement(insn))
1200 goto out;
1201
1202 if (insn->addr_bytes != 2)
1203 goto out;
1204
1205 if (X86_MODRM_MOD(insn->modrm.value) == 3) {
1206 ret = get_eff_addr_reg(insn, regs, ®off, &tmp);
1207 if (ret)
1208 goto out;
1209
1210 eff_addr = tmp;
1211 } else {
1212 ret = get_eff_addr_modrm_16(insn, regs, ®off, &eff_addr);
1213 if (ret)
1214 goto out;
1215 }
1216
1217 ret = get_seg_base_limit(insn, regs, regoff, &seg_base, &seg_limit);
1218 if (ret)
1219 goto out;
1220
1221
1222
1223
1224
1225
1226
1227 if ((unsigned long)(eff_addr & 0xffff) > seg_limit)
1228 goto out;
1229
1230 linear_addr = (unsigned long)(eff_addr & 0xffff) + seg_base;
1231
1232
1233 if (v8086_mode(regs))
1234 linear_addr &= 0xfffff;
1235
1236out:
1237 return (void __user *)linear_addr;
1238}
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256static void __user *get_addr_ref_32(struct insn *insn, struct pt_regs *regs)
1257{
1258 unsigned long linear_addr = -1L, seg_base, seg_limit;
1259 int eff_addr, regoff;
1260 long tmp;
1261 int ret;
1262
1263 if (insn->addr_bytes != 4)
1264 goto out;
1265
1266 if (X86_MODRM_MOD(insn->modrm.value) == 3) {
1267 ret = get_eff_addr_reg(insn, regs, ®off, &tmp);
1268 if (ret)
1269 goto out;
1270
1271 eff_addr = tmp;
1272
1273 } else {
1274 if (insn->sib.nbytes) {
1275 ret = get_eff_addr_sib(insn, regs, ®off, &tmp);
1276 if (ret)
1277 goto out;
1278
1279 eff_addr = tmp;
1280 } else {
1281 ret = get_eff_addr_modrm(insn, regs, ®off, &tmp);
1282 if (ret)
1283 goto out;
1284
1285 eff_addr = tmp;
1286 }
1287 }
1288
1289 ret = get_seg_base_limit(insn, regs, regoff, &seg_base, &seg_limit);
1290 if (ret)
1291 goto out;
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304 if (!any_64bit_mode(regs) && ((unsigned int)eff_addr > seg_limit))
1305 goto out;
1306
1307
1308
1309
1310
1311 if (v8086_mode(regs) && (eff_addr & ~0xffff))
1312 goto out;
1313
1314
1315
1316
1317
1318
1319 linear_addr = (unsigned long)(eff_addr & 0xffffffff) + seg_base;
1320
1321
1322 if (v8086_mode(regs))
1323 linear_addr &= 0xfffff;
1324
1325out:
1326 return (void __user *)linear_addr;
1327}
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344#ifndef CONFIG_X86_64
1345static void __user *get_addr_ref_64(struct insn *insn, struct pt_regs *regs)
1346{
1347 return (void __user *)-1L;
1348}
1349#else
1350static void __user *get_addr_ref_64(struct insn *insn, struct pt_regs *regs)
1351{
1352 unsigned long linear_addr = -1L, seg_base;
1353 int regoff, ret;
1354 long eff_addr;
1355
1356 if (insn->addr_bytes != 8)
1357 goto out;
1358
1359 if (X86_MODRM_MOD(insn->modrm.value) == 3) {
1360 ret = get_eff_addr_reg(insn, regs, ®off, &eff_addr);
1361 if (ret)
1362 goto out;
1363
1364 } else {
1365 if (insn->sib.nbytes) {
1366 ret = get_eff_addr_sib(insn, regs, ®off, &eff_addr);
1367 if (ret)
1368 goto out;
1369 } else {
1370 ret = get_eff_addr_modrm(insn, regs, ®off, &eff_addr);
1371 if (ret)
1372 goto out;
1373 }
1374
1375 }
1376
1377 ret = get_seg_base_limit(insn, regs, regoff, &seg_base, NULL);
1378 if (ret)
1379 goto out;
1380
1381 linear_addr = (unsigned long)eff_addr + seg_base;
1382
1383out:
1384 return (void __user *)linear_addr;
1385}
1386#endif
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs)
1404{
1405 if (!insn || !regs)
1406 return (void __user *)-1L;
1407
1408 switch (insn->addr_bytes) {
1409 case 2:
1410 return get_addr_ref_16(insn, regs);
1411 case 4:
1412 return get_addr_ref_32(insn, regs);
1413 case 8:
1414 return get_addr_ref_64(insn, regs);
1415 default:
1416 return (void __user *)-1L;
1417 }
1418}
1419
1420static int insn_get_effective_ip(struct pt_regs *regs, unsigned long *ip)
1421{
1422 unsigned long seg_base = 0;
1423
1424
1425
1426
1427
1428
1429
1430 if (!user_64bit_mode(regs)) {
1431 seg_base = insn_get_seg_base(regs, INAT_SEG_REG_CS);
1432 if (seg_base == -1L)
1433 return -EINVAL;
1434 }
1435
1436 *ip = seg_base + regs->ip;
1437
1438 return 0;
1439}
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455int insn_fetch_from_user(struct pt_regs *regs, unsigned char buf[MAX_INSN_SIZE])
1456{
1457 unsigned long ip;
1458 int not_copied;
1459
1460 if (insn_get_effective_ip(regs, &ip))
1461 return -EINVAL;
1462
1463 not_copied = copy_from_user(buf, (void __user *)ip, MAX_INSN_SIZE);
1464
1465 return MAX_INSN_SIZE - not_copied;
1466}
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483int insn_fetch_from_user_inatomic(struct pt_regs *regs, unsigned char buf[MAX_INSN_SIZE])
1484{
1485 unsigned long ip;
1486 int not_copied;
1487
1488 if (insn_get_effective_ip(regs, &ip))
1489 return -EINVAL;
1490
1491 not_copied = __copy_from_user_inatomic(buf, (void __user *)ip, MAX_INSN_SIZE);
1492
1493 return MAX_INSN_SIZE - not_copied;
1494}
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510bool insn_decode_from_regs(struct insn *insn, struct pt_regs *regs,
1511 unsigned char buf[MAX_INSN_SIZE], int buf_size)
1512{
1513 int seg_defs;
1514
1515 insn_init(insn, buf, buf_size, user_64bit_mode(regs));
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527 seg_defs = insn_get_code_seg_params(regs);
1528 if (seg_defs == -EINVAL)
1529 return false;
1530
1531 insn->addr_bytes = INSN_CODE_SEG_ADDR_SZ(seg_defs);
1532 insn->opnd_bytes = INSN_CODE_SEG_OPND_SZ(seg_defs);
1533
1534 if (insn_get_length(insn))
1535 return false;
1536
1537 if (buf_size < insn->length)
1538 return false;
1539
1540 return true;
1541}
1542