summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuke Nelson <lukenels@cs.washington.edu>2019-06-29 01:57:50 -0400
committerDaniel Borkmann <daniel@iogearbox.net>2019-07-03 05:14:28 -0400
commit6fa632e719eec4d1b1ebf3ddc0b2d667997b057b (patch)
treed2d6f3e67778c27a1e27c37059ac1b0a31122fd2
parent68a8357ec15bdce55266e9fba8b8b3b8143fa7d2 (diff)
bpf, x32: Fix bug with ALU64 {LSH, RSH, ARSH} BPF_K shift by 0
The current x32 BPF JIT does not correctly compile shift operations when the immediate shift amount is 0. The expected behavior is for this to be a no-op. The following program demonstrates the bug. The expexceted result is 1, but the current JITed code returns 2. r0 = 1 r1 = 1 r1 <<= 0 if r1 == 1 goto end r0 = 2 end: exit This patch simplifies the code and fixes the bug. Fixes: 03f5781be2c7 ("bpf, x86_32: add eBPF JIT compiler for ia32") Co-developed-by: Xi Wang <xi.wang@gmail.com> Signed-off-by: Xi Wang <xi.wang@gmail.com> Signed-off-by: Luke Nelson <luke.r.nels@gmail.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
-rw-r--r--arch/x86/net/bpf_jit_comp32.c63
1 files changed, 6 insertions, 57 deletions
diff --git a/arch/x86/net/bpf_jit_comp32.c b/arch/x86/net/bpf_jit_comp32.c
index f34ef513f4f9..1d12d2174085 100644
--- a/arch/x86/net/bpf_jit_comp32.c
+++ b/arch/x86/net/bpf_jit_comp32.c
@@ -894,27 +894,10 @@ static inline void emit_ia32_lsh_i64(const u8 dst[], const u32 val,
894 } 894 }
895 /* Do LSH operation */ 895 /* Do LSH operation */
896 if (val < 32) { 896 if (val < 32) {
897 /* shl dreg_hi,imm8 */ 897 /* shld dreg_hi,dreg_lo,imm8 */
898 EMIT3(0xC1, add_1reg(0xE0, dreg_hi), val); 898 EMIT4(0x0F, 0xA4, add_2reg(0xC0, dreg_hi, dreg_lo), val);
899 /* mov ebx,dreg_lo */
900 EMIT2(0x8B, add_2reg(0xC0, dreg_lo, IA32_EBX));
901 /* shl dreg_lo,imm8 */ 899 /* shl dreg_lo,imm8 */
902 EMIT3(0xC1, add_1reg(0xE0, dreg_lo), val); 900 EMIT3(0xC1, add_1reg(0xE0, dreg_lo), val);
903
904 /* IA32_ECX = 32 - val */
905 /* mov ecx,val */
906 EMIT2(0xB1, val);
907 /* movzx ecx,ecx */
908 EMIT3(0x0F, 0xB6, add_2reg(0xC0, IA32_ECX, IA32_ECX));
909 /* neg ecx */
910 EMIT2(0xF7, add_1reg(0xD8, IA32_ECX));
911 /* add ecx,32 */
912 EMIT3(0x83, add_1reg(0xC0, IA32_ECX), 32);
913
914 /* shr ebx,cl */
915 EMIT2(0xD3, add_1reg(0xE8, IA32_EBX));
916 /* or dreg_hi,ebx */
917 EMIT2(0x09, add_2reg(0xC0, dreg_hi, IA32_EBX));
918 } else if (val >= 32 && val < 64) { 901 } else if (val >= 32 && val < 64) {
919 u32 value = val - 32; 902 u32 value = val - 32;
920 903
@@ -960,27 +943,10 @@ static inline void emit_ia32_rsh_i64(const u8 dst[], const u32 val,
960 943
961 /* Do RSH operation */ 944 /* Do RSH operation */
962 if (val < 32) { 945 if (val < 32) {
963 /* shr dreg_lo,imm8 */ 946 /* shrd dreg_lo,dreg_hi,imm8 */
964 EMIT3(0xC1, add_1reg(0xE8, dreg_lo), val); 947 EMIT4(0x0F, 0xAC, add_2reg(0xC0, dreg_lo, dreg_hi), val);
965 /* mov ebx,dreg_hi */
966 EMIT2(0x8B, add_2reg(0xC0, dreg_hi, IA32_EBX));
967 /* shr dreg_hi,imm8 */ 948 /* shr dreg_hi,imm8 */
968 EMIT3(0xC1, add_1reg(0xE8, dreg_hi), val); 949 EMIT3(0xC1, add_1reg(0xE8, dreg_hi), val);
969
970 /* IA32_ECX = 32 - val */
971 /* mov ecx,val */
972 EMIT2(0xB1, val);
973 /* movzx ecx,ecx */
974 EMIT3(0x0F, 0xB6, add_2reg(0xC0, IA32_ECX, IA32_ECX));
975 /* neg ecx */
976 EMIT2(0xF7, add_1reg(0xD8, IA32_ECX));
977 /* add ecx,32 */
978 EMIT3(0x83, add_1reg(0xC0, IA32_ECX), 32);
979
980 /* shl ebx,cl */
981 EMIT2(0xD3, add_1reg(0xE0, IA32_EBX));
982 /* or dreg_lo,ebx */
983 EMIT2(0x09, add_2reg(0xC0, dreg_lo, IA32_EBX));
984 } else if (val >= 32 && val < 64) { 950 } else if (val >= 32 && val < 64) {
985 u32 value = val - 32; 951 u32 value = val - 32;
986 952
@@ -1025,27 +991,10 @@ static inline void emit_ia32_arsh_i64(const u8 dst[], const u32 val,
1025 } 991 }
1026 /* Do RSH operation */ 992 /* Do RSH operation */
1027 if (val < 32) { 993 if (val < 32) {
1028 /* shr dreg_lo,imm8 */ 994 /* shrd dreg_lo,dreg_hi,imm8 */
1029 EMIT3(0xC1, add_1reg(0xE8, dreg_lo), val); 995 EMIT4(0x0F, 0xAC, add_2reg(0xC0, dreg_lo, dreg_hi), val);
1030 /* mov ebx,dreg_hi */
1031 EMIT2(0x8B, add_2reg(0xC0, dreg_hi, IA32_EBX));
1032 /* ashr dreg_hi,imm8 */ 996 /* ashr dreg_hi,imm8 */
1033 EMIT3(0xC1, add_1reg(0xF8, dreg_hi), val); 997 EMIT3(0xC1, add_1reg(0xF8, dreg_hi), val);
1034
1035 /* IA32_ECX = 32 - val */
1036 /* mov ecx,val */
1037 EMIT2(0xB1, val);
1038 /* movzx ecx,ecx */
1039 EMIT3(0x0F, 0xB6, add_2reg(0xC0, IA32_ECX, IA32_ECX));
1040 /* neg ecx */
1041 EMIT2(0xF7, add_1reg(0xD8, IA32_ECX));
1042 /* add ecx,32 */
1043 EMIT3(0x83, add_1reg(0xC0, IA32_ECX), 32);
1044
1045 /* shl ebx,cl */
1046 EMIT2(0xD3, add_1reg(0xE0, IA32_EBX));
1047 /* or dreg_lo,ebx */
1048 EMIT2(0x09, add_2reg(0xC0, dreg_lo, IA32_EBX));
1049 } else if (val >= 32 && val < 64) { 998 } else if (val >= 32 && val < 64) {
1050 u32 value = val - 32; 999 u32 value = val - 32;
1051 1000