| .. | .. |
|---|
| 20 | 20 | |
|---|
| 21 | 21 | enum reg_type { |
|---|
| 22 | 22 | REG_TYPE_RM = 0, |
|---|
| 23 | + REG_TYPE_REG, |
|---|
| 23 | 24 | REG_TYPE_INDEX, |
|---|
| 24 | 25 | REG_TYPE_BASE, |
|---|
| 25 | 26 | }; |
|---|
| .. | .. |
|---|
| 50 | 51 | default: |
|---|
| 51 | 52 | return false; |
|---|
| 52 | 53 | } |
|---|
| 54 | +} |
|---|
| 55 | + |
|---|
| 56 | +/** |
|---|
| 57 | + * insn_has_rep_prefix() - Determine if instruction has a REP prefix |
|---|
| 58 | + * @insn: Instruction containing the prefix to inspect |
|---|
| 59 | + * |
|---|
| 60 | + * Returns: |
|---|
| 61 | + * |
|---|
| 62 | + * true if the instruction has a REP prefix, false if not. |
|---|
| 63 | + */ |
|---|
| 64 | +bool 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; |
|---|
| 53 | 77 | } |
|---|
| 54 | 78 | |
|---|
| 55 | 79 | /** |
|---|
| .. | .. |
|---|
| 156 | 180 | */ |
|---|
| 157 | 181 | static int resolve_default_seg(struct insn *insn, struct pt_regs *regs, int off) |
|---|
| 158 | 182 | { |
|---|
| 159 | | - if (user_64bit_mode(regs)) |
|---|
| 183 | + if (any_64bit_mode(regs)) |
|---|
| 160 | 184 | return INAT_SEG_REG_IGNORE; |
|---|
| 161 | 185 | /* |
|---|
| 162 | 186 | * Resolve the default segment register as described in Section 3.7.4 |
|---|
| .. | .. |
|---|
| 179 | 203 | /* Need insn to verify address size. */ |
|---|
| 180 | 204 | if (insn->addr_bytes == 2) |
|---|
| 181 | 205 | return -EINVAL; |
|---|
| 206 | + |
|---|
| 207 | + fallthrough; |
|---|
| 182 | 208 | |
|---|
| 183 | 209 | case -EDOM: |
|---|
| 184 | 210 | case offsetof(struct pt_regs, bx): |
|---|
| .. | .. |
|---|
| 265 | 291 | * which may be invalid at this point. |
|---|
| 266 | 292 | */ |
|---|
| 267 | 293 | if (regoff == offsetof(struct pt_regs, ip)) { |
|---|
| 268 | | - if (user_64bit_mode(regs)) |
|---|
| 294 | + if (any_64bit_mode(regs)) |
|---|
| 269 | 295 | return INAT_SEG_REG_IGNORE; |
|---|
| 270 | 296 | else |
|---|
| 271 | 297 | return INAT_SEG_REG_CS; |
|---|
| .. | .. |
|---|
| 288 | 314 | * In long mode, segment override prefixes are ignored, except for |
|---|
| 289 | 315 | * overrides for FS and GS. |
|---|
| 290 | 316 | */ |
|---|
| 291 | | - if (user_64bit_mode(regs)) { |
|---|
| 317 | + if (any_64bit_mode(regs)) { |
|---|
| 292 | 318 | if (idx != INAT_SEG_REG_FS && |
|---|
| 293 | 319 | idx != INAT_SEG_REG_GS) |
|---|
| 294 | 320 | idx = INAT_SEG_REG_IGNORE; |
|---|
| .. | .. |
|---|
| 361 | 387 | case INAT_SEG_REG_GS: |
|---|
| 362 | 388 | return vm86regs->gs; |
|---|
| 363 | 389 | case INAT_SEG_REG_IGNORE: |
|---|
| 364 | | - /* fall through */ |
|---|
| 365 | 390 | default: |
|---|
| 366 | 391 | return -EINVAL; |
|---|
| 367 | 392 | } |
|---|
| .. | .. |
|---|
| 385 | 410 | */ |
|---|
| 386 | 411 | return get_user_gs(regs); |
|---|
| 387 | 412 | case INAT_SEG_REG_IGNORE: |
|---|
| 388 | | - /* fall through */ |
|---|
| 389 | 413 | default: |
|---|
| 390 | 414 | return -EINVAL; |
|---|
| 391 | 415 | } |
|---|
| .. | .. |
|---|
| 437 | 461 | return -EDOM; |
|---|
| 438 | 462 | |
|---|
| 439 | 463 | if (X86_REX_B(insn->rex_prefix.value)) |
|---|
| 464 | + regno += 8; |
|---|
| 465 | + break; |
|---|
| 466 | + |
|---|
| 467 | + case REG_TYPE_REG: |
|---|
| 468 | + regno = X86_MODRM_REG(insn->modrm.value); |
|---|
| 469 | + |
|---|
| 470 | + if (X86_REX_R(insn->rex_prefix.value)) |
|---|
| 440 | 471 | regno += 8; |
|---|
| 441 | 472 | break; |
|---|
| 442 | 473 | |
|---|
| .. | .. |
|---|
| 645 | 676 | */ |
|---|
| 646 | 677 | return (unsigned long)(sel << 4); |
|---|
| 647 | 678 | |
|---|
| 648 | | - if (user_64bit_mode(regs)) { |
|---|
| 679 | + if (any_64bit_mode(regs)) { |
|---|
| 649 | 680 | /* |
|---|
| 650 | 681 | * Only FS or GS will have a base address, the rest of |
|---|
| 651 | 682 | * the segments' bases are forced to 0. |
|---|
| 652 | 683 | */ |
|---|
| 653 | 684 | unsigned long base; |
|---|
| 654 | 685 | |
|---|
| 655 | | - if (seg_reg_idx == INAT_SEG_REG_FS) |
|---|
| 686 | + if (seg_reg_idx == INAT_SEG_REG_FS) { |
|---|
| 656 | 687 | rdmsrl(MSR_FS_BASE, base); |
|---|
| 657 | | - else if (seg_reg_idx == INAT_SEG_REG_GS) |
|---|
| 688 | + } else if (seg_reg_idx == INAT_SEG_REG_GS) { |
|---|
| 658 | 689 | /* |
|---|
| 659 | 690 | * swapgs was called at the kernel entry point. Thus, |
|---|
| 660 | 691 | * MSR_KERNEL_GS_BASE will have the user-space GS base. |
|---|
| 661 | 692 | */ |
|---|
| 662 | | - rdmsrl(MSR_KERNEL_GS_BASE, base); |
|---|
| 663 | | - else |
|---|
| 693 | + if (user_mode(regs)) |
|---|
| 694 | + rdmsrl(MSR_KERNEL_GS_BASE, base); |
|---|
| 695 | + else |
|---|
| 696 | + rdmsrl(MSR_GS_BASE, base); |
|---|
| 697 | + } else { |
|---|
| 664 | 698 | base = 0; |
|---|
| 699 | + } |
|---|
| 665 | 700 | return base; |
|---|
| 666 | 701 | } |
|---|
| 667 | 702 | |
|---|
| .. | .. |
|---|
| 702 | 737 | if (sel < 0) |
|---|
| 703 | 738 | return 0; |
|---|
| 704 | 739 | |
|---|
| 705 | | - if (user_64bit_mode(regs) || v8086_mode(regs)) |
|---|
| 740 | + if (any_64bit_mode(regs) || v8086_mode(regs)) |
|---|
| 706 | 741 | return -1L; |
|---|
| 707 | 742 | |
|---|
| 708 | 743 | if (!sel) |
|---|
| .. | .. |
|---|
| 781 | 816 | */ |
|---|
| 782 | 817 | return INSN_CODE_SEG_PARAMS(4, 8); |
|---|
| 783 | 818 | case 3: /* Invalid setting. CS.L=1, CS.D=1 */ |
|---|
| 784 | | - /* fall through */ |
|---|
| 819 | + fallthrough; |
|---|
| 785 | 820 | default: |
|---|
| 786 | 821 | return -EINVAL; |
|---|
| 787 | 822 | } |
|---|
| .. | .. |
|---|
| 802 | 837 | int insn_get_modrm_rm_off(struct insn *insn, struct pt_regs *regs) |
|---|
| 803 | 838 | { |
|---|
| 804 | 839 | return get_reg_offset(insn, regs, REG_TYPE_RM); |
|---|
| 840 | +} |
|---|
| 841 | + |
|---|
| 842 | +/** |
|---|
| 843 | + * insn_get_modrm_reg_off() - Obtain register in reg part of the ModRM byte |
|---|
| 844 | + * @insn: Instruction containing the ModRM byte |
|---|
| 845 | + * @regs: Register values as seen when entering kernel mode |
|---|
| 846 | + * |
|---|
| 847 | + * Returns: |
|---|
| 848 | + * |
|---|
| 849 | + * The register indicated by the reg part of the ModRM byte. The |
|---|
| 850 | + * register is obtained as an offset from the base of pt_regs. |
|---|
| 851 | + */ |
|---|
| 852 | +int insn_get_modrm_reg_off(struct insn *insn, struct pt_regs *regs) |
|---|
| 853 | +{ |
|---|
| 854 | + return get_reg_offset(insn, regs, REG_TYPE_REG); |
|---|
| 805 | 855 | } |
|---|
| 806 | 856 | |
|---|
| 807 | 857 | /** |
|---|
| .. | .. |
|---|
| 878 | 928 | static int get_eff_addr_reg(struct insn *insn, struct pt_regs *regs, |
|---|
| 879 | 929 | int *regoff, long *eff_addr) |
|---|
| 880 | 930 | { |
|---|
| 881 | | - insn_get_modrm(insn); |
|---|
| 931 | + int ret; |
|---|
| 882 | 932 | |
|---|
| 883 | | - if (!insn->modrm.nbytes) |
|---|
| 884 | | - return -EINVAL; |
|---|
| 933 | + ret = insn_get_modrm(insn); |
|---|
| 934 | + if (ret) |
|---|
| 935 | + return ret; |
|---|
| 885 | 936 | |
|---|
| 886 | 937 | if (X86_MODRM_MOD(insn->modrm.value) != 3) |
|---|
| 887 | 938 | return -EINVAL; |
|---|
| .. | .. |
|---|
| 927 | 978 | int *regoff, long *eff_addr) |
|---|
| 928 | 979 | { |
|---|
| 929 | 980 | long tmp; |
|---|
| 981 | + int ret; |
|---|
| 930 | 982 | |
|---|
| 931 | 983 | if (insn->addr_bytes != 8 && insn->addr_bytes != 4) |
|---|
| 932 | 984 | return -EINVAL; |
|---|
| 933 | 985 | |
|---|
| 934 | | - insn_get_modrm(insn); |
|---|
| 935 | | - |
|---|
| 936 | | - if (!insn->modrm.nbytes) |
|---|
| 937 | | - return -EINVAL; |
|---|
| 986 | + ret = insn_get_modrm(insn); |
|---|
| 987 | + if (ret) |
|---|
| 988 | + return ret; |
|---|
| 938 | 989 | |
|---|
| 939 | 990 | if (X86_MODRM_MOD(insn->modrm.value) > 2) |
|---|
| 940 | 991 | return -EINVAL; |
|---|
| .. | .. |
|---|
| 947 | 998 | * following instruction. |
|---|
| 948 | 999 | */ |
|---|
| 949 | 1000 | if (*regoff == -EDOM) { |
|---|
| 950 | | - if (user_64bit_mode(regs)) |
|---|
| 1001 | + if (any_64bit_mode(regs)) |
|---|
| 951 | 1002 | tmp = regs->ip + insn->length; |
|---|
| 952 | 1003 | else |
|---|
| 953 | 1004 | tmp = 0; |
|---|
| .. | .. |
|---|
| 1056 | 1107 | * @base_offset will have a register, as an offset from the base of pt_regs, |
|---|
| 1057 | 1108 | * that can be used to resolve the associated segment. |
|---|
| 1058 | 1109 | * |
|---|
| 1059 | | - * -EINVAL on error. |
|---|
| 1110 | + * Negative value on error. |
|---|
| 1060 | 1111 | */ |
|---|
| 1061 | 1112 | static int get_eff_addr_sib(struct insn *insn, struct pt_regs *regs, |
|---|
| 1062 | 1113 | int *base_offset, long *eff_addr) |
|---|
| 1063 | 1114 | { |
|---|
| 1064 | 1115 | long base, indx; |
|---|
| 1065 | 1116 | int indx_offset; |
|---|
| 1117 | + int ret; |
|---|
| 1066 | 1118 | |
|---|
| 1067 | 1119 | if (insn->addr_bytes != 8 && insn->addr_bytes != 4) |
|---|
| 1068 | 1120 | return -EINVAL; |
|---|
| 1069 | 1121 | |
|---|
| 1070 | | - insn_get_modrm(insn); |
|---|
| 1122 | + ret = insn_get_modrm(insn); |
|---|
| 1123 | + if (ret) |
|---|
| 1124 | + return ret; |
|---|
| 1071 | 1125 | |
|---|
| 1072 | 1126 | if (!insn->modrm.nbytes) |
|---|
| 1073 | 1127 | return -EINVAL; |
|---|
| .. | .. |
|---|
| 1075 | 1129 | if (X86_MODRM_MOD(insn->modrm.value) > 2) |
|---|
| 1076 | 1130 | return -EINVAL; |
|---|
| 1077 | 1131 | |
|---|
| 1078 | | - insn_get_sib(insn); |
|---|
| 1132 | + ret = insn_get_sib(insn); |
|---|
| 1133 | + if (ret) |
|---|
| 1134 | + return ret; |
|---|
| 1079 | 1135 | |
|---|
| 1080 | 1136 | if (!insn->sib.nbytes) |
|---|
| 1081 | 1137 | return -EINVAL; |
|---|
| .. | .. |
|---|
| 1144 | 1200 | short eff_addr; |
|---|
| 1145 | 1201 | long tmp; |
|---|
| 1146 | 1202 | |
|---|
| 1147 | | - insn_get_modrm(insn); |
|---|
| 1148 | | - insn_get_displacement(insn); |
|---|
| 1203 | + if (insn_get_displacement(insn)) |
|---|
| 1204 | + goto out; |
|---|
| 1149 | 1205 | |
|---|
| 1150 | 1206 | if (insn->addr_bytes != 2) |
|---|
| 1151 | 1207 | goto out; |
|---|
| .. | .. |
|---|
| 1249 | 1305 | * After computed, the effective address is treated as an unsigned |
|---|
| 1250 | 1306 | * quantity. |
|---|
| 1251 | 1307 | */ |
|---|
| 1252 | | - if (!user_64bit_mode(regs) && ((unsigned int)eff_addr > seg_limit)) |
|---|
| 1308 | + if (!any_64bit_mode(regs) && ((unsigned int)eff_addr > seg_limit)) |
|---|
| 1253 | 1309 | goto out; |
|---|
| 1254 | 1310 | |
|---|
| 1255 | 1311 | /* |
|---|
| .. | .. |
|---|
| 1364 | 1420 | return (void __user *)-1L; |
|---|
| 1365 | 1421 | } |
|---|
| 1366 | 1422 | } |
|---|
| 1423 | + |
|---|
| 1424 | +unsigned long insn_get_effective_ip(struct pt_regs *regs) |
|---|
| 1425 | +{ |
|---|
| 1426 | + unsigned long seg_base = 0; |
|---|
| 1427 | + |
|---|
| 1428 | + /* |
|---|
| 1429 | + * If not in user-space long mode, a custom code segment could be in |
|---|
| 1430 | + * use. This is true in protected mode (if the process defined a local |
|---|
| 1431 | + * descriptor table), or virtual-8086 mode. In most of the cases |
|---|
| 1432 | + * seg_base will be zero as in USER_CS. |
|---|
| 1433 | + */ |
|---|
| 1434 | + if (!user_64bit_mode(regs)) { |
|---|
| 1435 | + seg_base = insn_get_seg_base(regs, INAT_SEG_REG_CS); |
|---|
| 1436 | + if (seg_base == -1L) |
|---|
| 1437 | + return 0; |
|---|
| 1438 | + } |
|---|
| 1439 | + |
|---|
| 1440 | + return seg_base + regs->ip; |
|---|
| 1441 | +} |
|---|
| 1442 | + |
|---|
| 1443 | +/** |
|---|
| 1444 | + * insn_fetch_from_user() - Copy instruction bytes from user-space memory |
|---|
| 1445 | + * @regs: Structure with register values as seen when entering kernel mode |
|---|
| 1446 | + * @buf: Array to store the fetched instruction |
|---|
| 1447 | + * |
|---|
| 1448 | + * Gets the linear address of the instruction and copies the instruction bytes |
|---|
| 1449 | + * to the buf. |
|---|
| 1450 | + * |
|---|
| 1451 | + * Returns: |
|---|
| 1452 | + * |
|---|
| 1453 | + * Number of instruction bytes copied. |
|---|
| 1454 | + * |
|---|
| 1455 | + * 0 if nothing was copied. |
|---|
| 1456 | + */ |
|---|
| 1457 | +int insn_fetch_from_user(struct pt_regs *regs, unsigned char buf[MAX_INSN_SIZE]) |
|---|
| 1458 | +{ |
|---|
| 1459 | + unsigned long ip; |
|---|
| 1460 | + int not_copied; |
|---|
| 1461 | + |
|---|
| 1462 | + ip = insn_get_effective_ip(regs); |
|---|
| 1463 | + if (!ip) |
|---|
| 1464 | + return 0; |
|---|
| 1465 | + |
|---|
| 1466 | + not_copied = copy_from_user(buf, (void __user *)ip, MAX_INSN_SIZE); |
|---|
| 1467 | + |
|---|
| 1468 | + return MAX_INSN_SIZE - not_copied; |
|---|
| 1469 | +} |
|---|
| 1470 | + |
|---|
| 1471 | +/** |
|---|
| 1472 | + * insn_fetch_from_user_inatomic() - Copy instruction bytes from user-space memory |
|---|
| 1473 | + * while in atomic code |
|---|
| 1474 | + * @regs: Structure with register values as seen when entering kernel mode |
|---|
| 1475 | + * @buf: Array to store the fetched instruction |
|---|
| 1476 | + * |
|---|
| 1477 | + * Gets the linear address of the instruction and copies the instruction bytes |
|---|
| 1478 | + * to the buf. This function must be used in atomic context. |
|---|
| 1479 | + * |
|---|
| 1480 | + * Returns: |
|---|
| 1481 | + * |
|---|
| 1482 | + * Number of instruction bytes copied. |
|---|
| 1483 | + * |
|---|
| 1484 | + * 0 if nothing was copied. |
|---|
| 1485 | + */ |
|---|
| 1486 | +int insn_fetch_from_user_inatomic(struct pt_regs *regs, unsigned char buf[MAX_INSN_SIZE]) |
|---|
| 1487 | +{ |
|---|
| 1488 | + unsigned long ip; |
|---|
| 1489 | + int not_copied; |
|---|
| 1490 | + |
|---|
| 1491 | + ip = insn_get_effective_ip(regs); |
|---|
| 1492 | + if (!ip) |
|---|
| 1493 | + return 0; |
|---|
| 1494 | + |
|---|
| 1495 | + not_copied = __copy_from_user_inatomic(buf, (void __user *)ip, MAX_INSN_SIZE); |
|---|
| 1496 | + |
|---|
| 1497 | + return MAX_INSN_SIZE - not_copied; |
|---|
| 1498 | +} |
|---|
| 1499 | + |
|---|
| 1500 | +/** |
|---|
| 1501 | + * insn_decode_from_regs() - Decode an instruction |
|---|
| 1502 | + * @insn: Structure to store decoded instruction |
|---|
| 1503 | + * @regs: Structure with register values as seen when entering kernel mode |
|---|
| 1504 | + * @buf: Buffer containing the instruction bytes |
|---|
| 1505 | + * @buf_size: Number of instruction bytes available in buf |
|---|
| 1506 | + * |
|---|
| 1507 | + * Decodes the instruction provided in buf and stores the decoding results in |
|---|
| 1508 | + * insn. Also determines the correct address and operand sizes. |
|---|
| 1509 | + * |
|---|
| 1510 | + * Returns: |
|---|
| 1511 | + * |
|---|
| 1512 | + * True if instruction was decoded, False otherwise. |
|---|
| 1513 | + */ |
|---|
| 1514 | +bool insn_decode_from_regs(struct insn *insn, struct pt_regs *regs, |
|---|
| 1515 | + unsigned char buf[MAX_INSN_SIZE], int buf_size) |
|---|
| 1516 | +{ |
|---|
| 1517 | + int seg_defs; |
|---|
| 1518 | + |
|---|
| 1519 | + insn_init(insn, buf, buf_size, user_64bit_mode(regs)); |
|---|
| 1520 | + |
|---|
| 1521 | + /* |
|---|
| 1522 | + * Override the default operand and address sizes with what is specified |
|---|
| 1523 | + * in the code segment descriptor. The instruction decoder only sets |
|---|
| 1524 | + * the address size it to either 4 or 8 address bytes and does nothing |
|---|
| 1525 | + * for the operand bytes. This OK for most of the cases, but we could |
|---|
| 1526 | + * have special cases where, for instance, a 16-bit code segment |
|---|
| 1527 | + * descriptor is used. |
|---|
| 1528 | + * If there is an address override prefix, the instruction decoder |
|---|
| 1529 | + * correctly updates these values, even for 16-bit defaults. |
|---|
| 1530 | + */ |
|---|
| 1531 | + seg_defs = insn_get_code_seg_params(regs); |
|---|
| 1532 | + if (seg_defs == -EINVAL) |
|---|
| 1533 | + return false; |
|---|
| 1534 | + |
|---|
| 1535 | + insn->addr_bytes = INSN_CODE_SEG_ADDR_SZ(seg_defs); |
|---|
| 1536 | + insn->opnd_bytes = INSN_CODE_SEG_OPND_SZ(seg_defs); |
|---|
| 1537 | + |
|---|
| 1538 | + if (insn_get_length(insn)) |
|---|
| 1539 | + return false; |
|---|
| 1540 | + |
|---|
| 1541 | + if (buf_size < insn->length) |
|---|
| 1542 | + return false; |
|---|
| 1543 | + |
|---|
| 1544 | + return true; |
|---|
| 1545 | +} |
|---|