aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-04-05 23:17:38 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-04-05 23:17:38 -0400
commitea6b1720ce25f92f7a17b2e0c2b653d20773d10a (patch)
tree2f27d5e61bf96897fa4b2fdc83f86467da7f0a4c /tools
parentaeb4a5768179f525dd7ec9393f34012c147e78cf (diff)
parentc383bdd14f91562babd269aa7c36b46fee7b6c75 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking fixes from David Miller: 1) Reject invalid updates to netfilter expectation policies, from Pablo Neira Ayuso. 2) Fix memory leak in nfnl_cthelper, from Jeffy Chen. 3) Don't do stupid things if we get a neigh_probe() on a neigh entry whose ops lack a solicit method. From Eric Dumazet. 4) Don't transmit packets in r8152 driver when the carrier is off, from Hayes Wang. 5) Fix ipv6 packet type detection in aquantia driver, from Pavel Belous. 6) Don't write uninitialized data into hw registers in bna driver, from Arnd Bergmann. 7) Fix locking in ping_unhash(), from Eric Dumazet. 8) Make BPF verifier range checks able to understand certain sequences emitted by LLVM, from Alexei Starovoitov. 9) Fix use after free in ipconfig, from Mark Rutland. 10) Fix refcount leak on force commit in openvswitch, from Jarno Rajahalme. 11) Fix various overflow checks in AF_PACKET, from Andrey Konovalov. 12) Fix endianness bug in be2net driver, from Suresh Reddy. 13) Don't forget to wake TX queues when processing a timeout, from Grygorii Strashko. 14) ARP header on-stack storage is wrong in flow dissector, from Simon Horman. 15) Lost retransmit and reordering SNMP stats in TCP can be underreported. From Yuchung Cheng. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (82 commits) nfp: fix potential use after free on xdp prog tcp: fix reordering SNMP under-counting tcp: fix lost retransmit SNMP under-counting sctp: get sock from transport in sctp_transport_update_pmtu net: ethernet: ti: cpsw: fix race condition during open() l2tp: fix PPP pseudo-wire auto-loading bnx2x: fix spelling mistake in macros HW_INTERRUT_ASSERT_SET_* l2tp: take reference on sessions being dumped tcp: minimize false-positives on TCP/GRO check sctp: check for dst and pathmtu update in sctp_packet_config flow dissector: correct size of storage for ARP net: ethernet: ti: cpsw: wake tx queues on ndo_tx_timeout l2tp: take a reference on sessions used in genetlink handlers l2tp: hold session while sending creation notifications l2tp: fix duplicate session creation l2tp: ensure session can't get removed during pppol2tp_session_ioctl() l2tp: fix race in l2tp_recv_common() sctp: use right in and out stream cnt bpf: add various verifier test cases for self-tests bpf, verifier: fix rejection of unaligned access checks for map_value_adj ...
Diffstat (limited to 'tools')
-rw-r--r--tools/include/linux/filter.h10
-rw-r--r--tools/testing/selftests/bpf/Makefile9
-rw-r--r--tools/testing/selftests/bpf/test_verifier.c290
3 files changed, 303 insertions, 6 deletions
diff --git a/tools/include/linux/filter.h b/tools/include/linux/filter.h
index 122153b16ea4..390d7c9685fd 100644
--- a/tools/include/linux/filter.h
+++ b/tools/include/linux/filter.h
@@ -168,6 +168,16 @@
168 .off = OFF, \ 168 .off = OFF, \
169 .imm = 0 }) 169 .imm = 0 })
170 170
171/* Atomic memory add, *(uint *)(dst_reg + off16) += src_reg */
172
173#define BPF_STX_XADD(SIZE, DST, SRC, OFF) \
174 ((struct bpf_insn) { \
175 .code = BPF_STX | BPF_SIZE(SIZE) | BPF_XADD, \
176 .dst_reg = DST, \
177 .src_reg = SRC, \
178 .off = OFF, \
179 .imm = 0 })
180
171/* Memory store, *(uint *) (dst_reg + off16) = imm32 */ 181/* Memory store, *(uint *) (dst_reg + off16) = imm32 */
172 182
173#define BPF_ST_MEM(SIZE, DST, OFF, IMM) \ 183#define BPF_ST_MEM(SIZE, DST, OFF, IMM) \
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 6a1ad58cb66f..9af09e8099c0 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -1,7 +1,14 @@
1LIBDIR := ../../../lib 1LIBDIR := ../../../lib
2BPFDIR := $(LIBDIR)/bpf 2BPFDIR := $(LIBDIR)/bpf
3APIDIR := ../../../include/uapi
4GENDIR := ../../../../include/generated
5GENHDR := $(GENDIR)/autoconf.h
3 6
4CFLAGS += -Wall -O2 -I../../../include/uapi -I$(LIBDIR) 7ifneq ($(wildcard $(GENHDR)),)
8 GENFLAGS := -DHAVE_GENHDR
9endif
10
11CFLAGS += -Wall -O2 -I$(APIDIR) -I$(LIBDIR) -I$(GENDIR) $(GENFLAGS)
5LDLIBS += -lcap 12LDLIBS += -lcap
6 13
7TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map 14TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
index d1555e4240c0..c848e90b6421 100644
--- a/tools/testing/selftests/bpf/test_verifier.c
+++ b/tools/testing/selftests/bpf/test_verifier.c
@@ -30,6 +30,14 @@
30 30
31#include <bpf/bpf.h> 31#include <bpf/bpf.h>
32 32
33#ifdef HAVE_GENHDR
34# include "autoconf.h"
35#else
36# if defined(__i386) || defined(__x86_64) || defined(__s390x__) || defined(__aarch64__)
37# define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 1
38# endif
39#endif
40
33#include "../../../include/linux/filter.h" 41#include "../../../include/linux/filter.h"
34 42
35#ifndef ARRAY_SIZE 43#ifndef ARRAY_SIZE
@@ -39,6 +47,8 @@
39#define MAX_INSNS 512 47#define MAX_INSNS 512
40#define MAX_FIXUPS 8 48#define MAX_FIXUPS 8
41 49
50#define F_NEEDS_EFFICIENT_UNALIGNED_ACCESS (1 << 0)
51
42struct bpf_test { 52struct bpf_test {
43 const char *descr; 53 const char *descr;
44 struct bpf_insn insns[MAX_INSNS]; 54 struct bpf_insn insns[MAX_INSNS];
@@ -53,6 +63,7 @@ struct bpf_test {
53 REJECT 63 REJECT
54 } result, result_unpriv; 64 } result, result_unpriv;
55 enum bpf_prog_type prog_type; 65 enum bpf_prog_type prog_type;
66 uint8_t flags;
56}; 67};
57 68
58/* Note we want this to be 64 bit aligned so that the end of our array is 69/* Note we want this to be 64 bit aligned so that the end of our array is
@@ -2432,6 +2443,30 @@ static struct bpf_test tests[] = {
2432 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 2443 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2433 }, 2444 },
2434 { 2445 {
2446 "direct packet access: test15 (spill with xadd)",
2447 .insns = {
2448 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
2449 offsetof(struct __sk_buff, data)),
2450 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
2451 offsetof(struct __sk_buff, data_end)),
2452 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
2453 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
2454 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 8),
2455 BPF_MOV64_IMM(BPF_REG_5, 4096),
2456 BPF_MOV64_REG(BPF_REG_4, BPF_REG_10),
2457 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, -8),
2458 BPF_STX_MEM(BPF_DW, BPF_REG_4, BPF_REG_2, 0),
2459 BPF_STX_XADD(BPF_DW, BPF_REG_4, BPF_REG_5, 0),
2460 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_4, 0),
2461 BPF_STX_MEM(BPF_W, BPF_REG_2, BPF_REG_5, 0),
2462 BPF_MOV64_IMM(BPF_REG_0, 0),
2463 BPF_EXIT_INSN(),
2464 },
2465 .errstr = "R2 invalid mem access 'inv'",
2466 .result = REJECT,
2467 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2468 },
2469 {
2435 "helper access to packet: test1, valid packet_ptr range", 2470 "helper access to packet: test1, valid packet_ptr range",
2436 .insns = { 2471 .insns = {
2437 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 2472 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
@@ -2934,6 +2969,7 @@ static struct bpf_test tests[] = {
2934 .errstr_unpriv = "R0 pointer arithmetic prohibited", 2969 .errstr_unpriv = "R0 pointer arithmetic prohibited",
2935 .result_unpriv = REJECT, 2970 .result_unpriv = REJECT,
2936 .result = ACCEPT, 2971 .result = ACCEPT,
2972 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
2937 }, 2973 },
2938 { 2974 {
2939 "valid map access into an array with a variable", 2975 "valid map access into an array with a variable",
@@ -2957,6 +2993,7 @@ static struct bpf_test tests[] = {
2957 .errstr_unpriv = "R0 pointer arithmetic prohibited", 2993 .errstr_unpriv = "R0 pointer arithmetic prohibited",
2958 .result_unpriv = REJECT, 2994 .result_unpriv = REJECT,
2959 .result = ACCEPT, 2995 .result = ACCEPT,
2996 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
2960 }, 2997 },
2961 { 2998 {
2962 "valid map access into an array with a signed variable", 2999 "valid map access into an array with a signed variable",
@@ -2984,6 +3021,7 @@ static struct bpf_test tests[] = {
2984 .errstr_unpriv = "R0 pointer arithmetic prohibited", 3021 .errstr_unpriv = "R0 pointer arithmetic prohibited",
2985 .result_unpriv = REJECT, 3022 .result_unpriv = REJECT,
2986 .result = ACCEPT, 3023 .result = ACCEPT,
3024 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
2987 }, 3025 },
2988 { 3026 {
2989 "invalid map access into an array with a constant", 3027 "invalid map access into an array with a constant",
@@ -3025,6 +3063,7 @@ static struct bpf_test tests[] = {
3025 .errstr = "R0 min value is outside of the array range", 3063 .errstr = "R0 min value is outside of the array range",
3026 .result_unpriv = REJECT, 3064 .result_unpriv = REJECT,
3027 .result = REJECT, 3065 .result = REJECT,
3066 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
3028 }, 3067 },
3029 { 3068 {
3030 "invalid map access into an array with a variable", 3069 "invalid map access into an array with a variable",
@@ -3048,6 +3087,7 @@ static struct bpf_test tests[] = {
3048 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.", 3087 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
3049 .result_unpriv = REJECT, 3088 .result_unpriv = REJECT,
3050 .result = REJECT, 3089 .result = REJECT,
3090 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
3051 }, 3091 },
3052 { 3092 {
3053 "invalid map access into an array with no floor check", 3093 "invalid map access into an array with no floor check",
@@ -3074,6 +3114,7 @@ static struct bpf_test tests[] = {
3074 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.", 3114 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
3075 .result_unpriv = REJECT, 3115 .result_unpriv = REJECT,
3076 .result = REJECT, 3116 .result = REJECT,
3117 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
3077 }, 3118 },
3078 { 3119 {
3079 "invalid map access into an array with a invalid max check", 3120 "invalid map access into an array with a invalid max check",
@@ -3100,6 +3141,7 @@ static struct bpf_test tests[] = {
3100 .errstr = "invalid access to map value, value_size=48 off=44 size=8", 3141 .errstr = "invalid access to map value, value_size=48 off=44 size=8",
3101 .result_unpriv = REJECT, 3142 .result_unpriv = REJECT,
3102 .result = REJECT, 3143 .result = REJECT,
3144 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
3103 }, 3145 },
3104 { 3146 {
3105 "invalid map access into an array with a invalid max check", 3147 "invalid map access into an array with a invalid max check",
@@ -3129,6 +3171,7 @@ static struct bpf_test tests[] = {
3129 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.", 3171 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
3130 .result_unpriv = REJECT, 3172 .result_unpriv = REJECT,
3131 .result = REJECT, 3173 .result = REJECT,
3174 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
3132 }, 3175 },
3133 { 3176 {
3134 "multiple registers share map_lookup_elem result", 3177 "multiple registers share map_lookup_elem result",
@@ -3252,6 +3295,7 @@ static struct bpf_test tests[] = {
3252 .result = REJECT, 3295 .result = REJECT,
3253 .errstr_unpriv = "R0 pointer arithmetic prohibited", 3296 .errstr_unpriv = "R0 pointer arithmetic prohibited",
3254 .result_unpriv = REJECT, 3297 .result_unpriv = REJECT,
3298 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
3255 }, 3299 },
3256 { 3300 {
3257 "constant register |= constant should keep constant type", 3301 "constant register |= constant should keep constant type",
@@ -3418,6 +3462,26 @@ static struct bpf_test tests[] = {
3418 .prog_type = BPF_PROG_TYPE_LWT_XMIT, 3462 .prog_type = BPF_PROG_TYPE_LWT_XMIT,
3419 }, 3463 },
3420 { 3464 {
3465 "overlapping checks for direct packet access",
3466 .insns = {
3467 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
3468 offsetof(struct __sk_buff, data)),
3469 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
3470 offsetof(struct __sk_buff, data_end)),
3471 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
3472 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
3473 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 4),
3474 BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
3475 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6),
3476 BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1),
3477 BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_2, 6),
3478 BPF_MOV64_IMM(BPF_REG_0, 0),
3479 BPF_EXIT_INSN(),
3480 },
3481 .result = ACCEPT,
3482 .prog_type = BPF_PROG_TYPE_LWT_XMIT,
3483 },
3484 {
3421 "invalid access of tc_classid for LWT_IN", 3485 "invalid access of tc_classid for LWT_IN",
3422 .insns = { 3486 .insns = {
3423 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 3487 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
@@ -3961,7 +4025,208 @@ static struct bpf_test tests[] = {
3961 .result_unpriv = REJECT, 4025 .result_unpriv = REJECT,
3962 }, 4026 },
3963 { 4027 {
3964 "map element value (adjusted) is preserved across register spilling", 4028 "map element value or null is marked on register spilling",
4029 .insns = {
4030 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4031 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4032 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4033 BPF_LD_MAP_FD(BPF_REG_1, 0),
4034 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4035 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
4036 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -152),
4037 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
4038 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
4039 BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_1, 0),
4040 BPF_ST_MEM(BPF_DW, BPF_REG_3, 0, 42),
4041 BPF_EXIT_INSN(),
4042 },
4043 .fixup_map2 = { 3 },
4044 .errstr_unpriv = "R0 leaks addr",
4045 .result = ACCEPT,
4046 .result_unpriv = REJECT,
4047 },
4048 {
4049 "map element value store of cleared call register",
4050 .insns = {
4051 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4052 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4053 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4054 BPF_LD_MAP_FD(BPF_REG_1, 0),
4055 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4056 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
4057 BPF_STX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 0),
4058 BPF_EXIT_INSN(),
4059 },
4060 .fixup_map2 = { 3 },
4061 .errstr_unpriv = "R1 !read_ok",
4062 .errstr = "R1 !read_ok",
4063 .result = REJECT,
4064 .result_unpriv = REJECT,
4065 },
4066 {
4067 "map element value with unaligned store",
4068 .insns = {
4069 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4070 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4071 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4072 BPF_LD_MAP_FD(BPF_REG_1, 0),
4073 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4074 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 17),
4075 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 3),
4076 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 42),
4077 BPF_ST_MEM(BPF_DW, BPF_REG_0, 2, 43),
4078 BPF_ST_MEM(BPF_DW, BPF_REG_0, -2, 44),
4079 BPF_MOV64_REG(BPF_REG_8, BPF_REG_0),
4080 BPF_ST_MEM(BPF_DW, BPF_REG_8, 0, 32),
4081 BPF_ST_MEM(BPF_DW, BPF_REG_8, 2, 33),
4082 BPF_ST_MEM(BPF_DW, BPF_REG_8, -2, 34),
4083 BPF_ALU64_IMM(BPF_ADD, BPF_REG_8, 5),
4084 BPF_ST_MEM(BPF_DW, BPF_REG_8, 0, 22),
4085 BPF_ST_MEM(BPF_DW, BPF_REG_8, 4, 23),
4086 BPF_ST_MEM(BPF_DW, BPF_REG_8, -7, 24),
4087 BPF_MOV64_REG(BPF_REG_7, BPF_REG_8),
4088 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, 3),
4089 BPF_ST_MEM(BPF_DW, BPF_REG_7, 0, 22),
4090 BPF_ST_MEM(BPF_DW, BPF_REG_7, 4, 23),
4091 BPF_ST_MEM(BPF_DW, BPF_REG_7, -4, 24),
4092 BPF_EXIT_INSN(),
4093 },
4094 .fixup_map2 = { 3 },
4095 .errstr_unpriv = "R0 pointer arithmetic prohibited",
4096 .result = ACCEPT,
4097 .result_unpriv = REJECT,
4098 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
4099 },
4100 {
4101 "map element value with unaligned load",
4102 .insns = {
4103 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4104 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4105 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4106 BPF_LD_MAP_FD(BPF_REG_1, 0),
4107 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4108 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 11),
4109 BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
4110 BPF_JMP_IMM(BPF_JGE, BPF_REG_1, MAX_ENTRIES, 9),
4111 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 3),
4112 BPF_LDX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
4113 BPF_LDX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 2),
4114 BPF_MOV64_REG(BPF_REG_8, BPF_REG_0),
4115 BPF_LDX_MEM(BPF_DW, BPF_REG_7, BPF_REG_8, 0),
4116 BPF_LDX_MEM(BPF_DW, BPF_REG_7, BPF_REG_8, 2),
4117 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 5),
4118 BPF_LDX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
4119 BPF_LDX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 4),
4120 BPF_EXIT_INSN(),
4121 },
4122 .fixup_map2 = { 3 },
4123 .errstr_unpriv = "R0 pointer arithmetic prohibited",
4124 .result = ACCEPT,
4125 .result_unpriv = REJECT,
4126 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
4127 },
4128 {
4129 "map element value illegal alu op, 1",
4130 .insns = {
4131 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4132 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4133 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4134 BPF_LD_MAP_FD(BPF_REG_1, 0),
4135 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4136 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
4137 BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 8),
4138 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 22),
4139 BPF_EXIT_INSN(),
4140 },
4141 .fixup_map2 = { 3 },
4142 .errstr_unpriv = "R0 pointer arithmetic prohibited",
4143 .errstr = "invalid mem access 'inv'",
4144 .result = REJECT,
4145 .result_unpriv = REJECT,
4146 },
4147 {
4148 "map element value illegal alu op, 2",
4149 .insns = {
4150 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4151 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4152 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4153 BPF_LD_MAP_FD(BPF_REG_1, 0),
4154 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4155 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
4156 BPF_ALU32_IMM(BPF_ADD, BPF_REG_0, 0),
4157 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 22),
4158 BPF_EXIT_INSN(),
4159 },
4160 .fixup_map2 = { 3 },
4161 .errstr_unpriv = "R0 pointer arithmetic prohibited",
4162 .errstr = "invalid mem access 'inv'",
4163 .result = REJECT,
4164 .result_unpriv = REJECT,
4165 },
4166 {
4167 "map element value illegal alu op, 3",
4168 .insns = {
4169 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4170 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4171 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4172 BPF_LD_MAP_FD(BPF_REG_1, 0),
4173 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4174 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
4175 BPF_ALU64_IMM(BPF_DIV, BPF_REG_0, 42),
4176 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 22),
4177 BPF_EXIT_INSN(),
4178 },
4179 .fixup_map2 = { 3 },
4180 .errstr_unpriv = "R0 pointer arithmetic prohibited",
4181 .errstr = "invalid mem access 'inv'",
4182 .result = REJECT,
4183 .result_unpriv = REJECT,
4184 },
4185 {
4186 "map element value illegal alu op, 4",
4187 .insns = {
4188 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4189 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4190 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4191 BPF_LD_MAP_FD(BPF_REG_1, 0),
4192 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4193 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
4194 BPF_ENDIAN(BPF_FROM_BE, BPF_REG_0, 64),
4195 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 22),
4196 BPF_EXIT_INSN(),
4197 },
4198 .fixup_map2 = { 3 },
4199 .errstr_unpriv = "R0 pointer arithmetic prohibited",
4200 .errstr = "invalid mem access 'inv'",
4201 .result = REJECT,
4202 .result_unpriv = REJECT,
4203 },
4204 {
4205 "map element value illegal alu op, 5",
4206 .insns = {
4207 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4208 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4209 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
4210 BPF_LD_MAP_FD(BPF_REG_1, 0),
4211 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
4212 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
4213 BPF_MOV64_IMM(BPF_REG_3, 4096),
4214 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
4215 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
4216 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_0, 0),
4217 BPF_STX_XADD(BPF_DW, BPF_REG_2, BPF_REG_3, 0),
4218 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, 0),
4219 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 22),
4220 BPF_EXIT_INSN(),
4221 },
4222 .fixup_map2 = { 3 },
4223 .errstr_unpriv = "R0 invalid mem access 'inv'",
4224 .errstr = "R0 invalid mem access 'inv'",
4225 .result = REJECT,
4226 .result_unpriv = REJECT,
4227 },
4228 {
4229 "map element value is preserved across register spilling",
3965 .insns = { 4230 .insns = {
3966 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 4231 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
3967 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 4232 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
@@ -3983,6 +4248,7 @@ static struct bpf_test tests[] = {
3983 .errstr_unpriv = "R0 pointer arithmetic prohibited", 4248 .errstr_unpriv = "R0 pointer arithmetic prohibited",
3984 .result = ACCEPT, 4249 .result = ACCEPT,
3985 .result_unpriv = REJECT, 4250 .result_unpriv = REJECT,
4251 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
3986 }, 4252 },
3987 { 4253 {
3988 "helper access to variable memory: stack, bitwise AND + JMP, correct bounds", 4254 "helper access to variable memory: stack, bitwise AND + JMP, correct bounds",
@@ -4421,6 +4687,7 @@ static struct bpf_test tests[] = {
4421 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.", 4687 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
4422 .result = REJECT, 4688 .result = REJECT,
4423 .result_unpriv = REJECT, 4689 .result_unpriv = REJECT,
4690 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
4424 }, 4691 },
4425 { 4692 {
4426 "invalid range check", 4693 "invalid range check",
@@ -4452,6 +4719,7 @@ static struct bpf_test tests[] = {
4452 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.", 4719 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
4453 .result = REJECT, 4720 .result = REJECT,
4454 .result_unpriv = REJECT, 4721 .result_unpriv = REJECT,
4722 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
4455 } 4723 }
4456}; 4724};
4457 4725
@@ -4530,11 +4798,11 @@ static void do_test_fixup(struct bpf_test *test, struct bpf_insn *prog,
4530static void do_test_single(struct bpf_test *test, bool unpriv, 4798static void do_test_single(struct bpf_test *test, bool unpriv,
4531 int *passes, int *errors) 4799 int *passes, int *errors)
4532{ 4800{
4801 int fd_prog, expected_ret, reject_from_alignment;
4533 struct bpf_insn *prog = test->insns; 4802 struct bpf_insn *prog = test->insns;
4534 int prog_len = probe_filter_length(prog); 4803 int prog_len = probe_filter_length(prog);
4535 int prog_type = test->prog_type; 4804 int prog_type = test->prog_type;
4536 int fd_f1 = -1, fd_f2 = -1, fd_f3 = -1; 4805 int fd_f1 = -1, fd_f2 = -1, fd_f3 = -1;
4537 int fd_prog, expected_ret;
4538 const char *expected_err; 4806 const char *expected_err;
4539 4807
4540 do_test_fixup(test, prog, &fd_f1, &fd_f2, &fd_f3); 4808 do_test_fixup(test, prog, &fd_f1, &fd_f2, &fd_f3);
@@ -4547,8 +4815,19 @@ static void do_test_single(struct bpf_test *test, bool unpriv,
4547 test->result_unpriv : test->result; 4815 test->result_unpriv : test->result;
4548 expected_err = unpriv && test->errstr_unpriv ? 4816 expected_err = unpriv && test->errstr_unpriv ?
4549 test->errstr_unpriv : test->errstr; 4817 test->errstr_unpriv : test->errstr;
4818
4819 reject_from_alignment = fd_prog < 0 &&
4820 (test->flags & F_NEEDS_EFFICIENT_UNALIGNED_ACCESS) &&
4821 strstr(bpf_vlog, "Unknown alignment.");
4822#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
4823 if (reject_from_alignment) {
4824 printf("FAIL\nFailed due to alignment despite having efficient unaligned access: '%s'!\n",
4825 strerror(errno));
4826 goto fail_log;
4827 }
4828#endif
4550 if (expected_ret == ACCEPT) { 4829 if (expected_ret == ACCEPT) {
4551 if (fd_prog < 0) { 4830 if (fd_prog < 0 && !reject_from_alignment) {
4552 printf("FAIL\nFailed to load prog '%s'!\n", 4831 printf("FAIL\nFailed to load prog '%s'!\n",
4553 strerror(errno)); 4832 strerror(errno));
4554 goto fail_log; 4833 goto fail_log;
@@ -4558,14 +4837,15 @@ static void do_test_single(struct bpf_test *test, bool unpriv,
4558 printf("FAIL\nUnexpected success to load!\n"); 4837 printf("FAIL\nUnexpected success to load!\n");
4559 goto fail_log; 4838 goto fail_log;
4560 } 4839 }
4561 if (!strstr(bpf_vlog, expected_err)) { 4840 if (!strstr(bpf_vlog, expected_err) && !reject_from_alignment) {
4562 printf("FAIL\nUnexpected error message!\n"); 4841 printf("FAIL\nUnexpected error message!\n");
4563 goto fail_log; 4842 goto fail_log;
4564 } 4843 }
4565 } 4844 }
4566 4845
4567 (*passes)++; 4846 (*passes)++;
4568 printf("OK\n"); 4847 printf("OK%s\n", reject_from_alignment ?
4848 " (NOTE: reject due to unknown alignment)" : "");
4569close_fds: 4849close_fds:
4570 close(fd_prog); 4850 close(fd_prog);
4571 close(fd_f1); 4851 close(fd_f1);