Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/bpf: Add support for bpf constant blinding

In line with similar support for other architectures by Daniel Borkmann.

'MOD Default X' from test_bpf without constant blinding:
84 bytes emitted from JIT compiler (pass:3, flen:7)
d0000000058a4688 + <x>:
0: nop
4: nop
8: std r27,-40(r1)
c: std r28,-32(r1)
10: xor r8,r8,r8
14: xor r28,r28,r28
18: mr r27,r3
1c: li r8,66
20: cmpwi r28,0
24: bne 0x0000000000000030
28: li r8,0
2c: b 0x0000000000000044
30: divwu r9,r8,r28
34: mullw r9,r28,r9
38: subf r8,r9,r8
3c: rotlwi r8,r8,0
40: li r8,66
44: ld r27,-40(r1)
48: ld r28,-32(r1)
4c: mr r3,r8
50: blr

... and with constant blinding:
140 bytes emitted from JIT compiler (pass:3, flen:11)
d00000000bd6ab24 + <x>:
0: nop
4: nop
8: std r27,-40(r1)
c: std r28,-32(r1)
10: xor r8,r8,r8
14: xor r28,r28,r28
18: mr r27,r3
1c: lis r2,-22834
20: ori r2,r2,36083
24: rotlwi r2,r2,0
28: xori r2,r2,36017
2c: xoris r2,r2,42702
30: rotlwi r2,r2,0
34: mr r8,r2
38: rotlwi r8,r8,0
3c: cmpwi r28,0
40: bne 0x000000000000004c
44: li r8,0
48: b 0x000000000000007c
4c: divwu r9,r8,r28
50: mullw r9,r28,r9
54: subf r8,r9,r8
58: rotlwi r8,r8,0
5c: lis r2,-17137
60: ori r2,r2,39065
64: rotlwi r2,r2,0
68: xori r2,r2,39131
6c: xoris r2,r2,48399
70: rotlwi r2,r2,0
74: mr r8,r2
78: rotlwi r8,r8,0
7c: ld r27,-40(r1)
80: ld r28,-32(r1)
84: mr r3,r8
88: blr

Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

authored by

Naveen N. Rao and committed by
Michael Ellerman
b7b7013c ce076141

+37 -14
+5 -4
arch/powerpc/net/bpf_jit64.h
··· 39 39 #ifndef __ASSEMBLY__ 40 40 41 41 /* BPF register usage */ 42 - #define SKB_HLEN_REG (MAX_BPF_REG + 0) 43 - #define SKB_DATA_REG (MAX_BPF_REG + 1) 44 - #define TMP_REG_1 (MAX_BPF_REG + 2) 45 - #define TMP_REG_2 (MAX_BPF_REG + 3) 42 + #define SKB_HLEN_REG (MAX_BPF_JIT_REG + 0) 43 + #define SKB_DATA_REG (MAX_BPF_JIT_REG + 1) 44 + #define TMP_REG_1 (MAX_BPF_JIT_REG + 2) 45 + #define TMP_REG_2 (MAX_BPF_JIT_REG + 3) 46 46 47 47 /* BPF to ppc register mappings */ 48 48 static const int b2p[] = { ··· 62 62 /* frame pointer aka BPF_REG_10 */ 63 63 [BPF_REG_FP] = 31, 64 64 /* eBPF jit internal registers */ 65 + [BPF_REG_AX] = 2, 65 66 [SKB_HLEN_REG] = 25, 66 67 [SKB_DATA_REG] = 26, 67 68 [TMP_REG_1] = 9,
+32 -10
arch/powerpc/net/bpf_jit_comp64.c
··· 974 974 int pass; 975 975 int flen; 976 976 struct bpf_binary_header *bpf_hdr; 977 + struct bpf_prog *org_fp = fp; 978 + struct bpf_prog *tmp_fp; 979 + bool bpf_blinded = false; 977 980 978 981 if (!bpf_jit_enable) 979 - return fp; 982 + return org_fp; 983 + 984 + tmp_fp = bpf_jit_blind_constants(org_fp); 985 + if (IS_ERR(tmp_fp)) 986 + return org_fp; 987 + 988 + if (tmp_fp != org_fp) { 989 + bpf_blinded = true; 990 + fp = tmp_fp; 991 + } 980 992 981 993 flen = fp->len; 982 994 addrs = kzalloc((flen+1) * sizeof(*addrs), GFP_KERNEL); 983 - if (addrs == NULL) 984 - return fp; 985 - 986 - cgctx.idx = 0; 987 - cgctx.seen = 0; 988 - /* Scouting faux-generate pass 0 */ 989 - if (bpf_jit_build_body(fp, 0, &cgctx, addrs)) 990 - /* We hit something illegal or unsupported. */ 995 + if (addrs == NULL) { 996 + fp = org_fp; 991 997 goto out; 998 + } 999 + 1000 + memset(&cgctx, 0, sizeof(struct codegen_context)); 1001 + 1002 + /* Scouting faux-generate pass 0 */ 1003 + if (bpf_jit_build_body(fp, 0, &cgctx, addrs)) { 1004 + /* We hit something illegal or unsupported. */ 1005 + fp = org_fp; 1006 + goto out; 1007 + } 992 1008 993 1009 /* 994 1010 * Pretend to build prologue, given the features we've seen. This will ··· 1019 1003 1020 1004 bpf_hdr = bpf_jit_binary_alloc(alloclen, &image, 4, 1021 1005 bpf_jit_fill_ill_insns); 1022 - if (!bpf_hdr) 1006 + if (!bpf_hdr) { 1007 + fp = org_fp; 1023 1008 goto out; 1009 + } 1024 1010 1025 1011 code_base = (u32 *)(image + FUNCTION_DESCR_SIZE); 1026 1012 ··· 1059 1041 1060 1042 out: 1061 1043 kfree(addrs); 1044 + 1045 + if (bpf_blinded) 1046 + bpf_jit_prog_release_other(fp, fp == org_fp ? tmp_fp : org_fp); 1047 + 1062 1048 return fp; 1063 1049 } 1064 1050