aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-10-31 20:34:08 -0400
committerDavid S. Miller <davem@davemloft.net>2018-10-31 20:34:08 -0400
commitdf975da4e578eb06453f41a3ecd73c2a4c28044d (patch)
tree74dd370bd058feb814e2303bcc4999b8210d42de
parente2acdddde01511c74e4f6f1d5951a0f5d9bea14a (diff)
parentdfeb8f4c9692fd5e6c3eef19c2e4ae5338dbdb01 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf
Daniel Borkmann says: ==================== pull-request: bpf 2018-11-01 The following pull-request contains BPF updates for your *net* tree. The main changes are: 1) Fix tcp_bpf_recvmsg() to return -EAGAIN instead of 0 in non-blocking case when no data is available yet, from John. 2) Fix a compilation error in libbpf_attach_type_by_name() when compiled with clang 3.8, from Andrey. 3) Fix a partial copy of map pointer on scalar alu and remove id generation for RET_PTR_TO_MAP_VALUE return types, from Daniel. 4) Add unlimited memlock limit for kernel selftest's flow_dissector_load program, from Yonghong. 5) Fix ping for some BPF shell based kselftests where distro does not ship "ping -6" anymore, from Li. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/bpf_verifier.h3
-rw-r--r--kernel/bpf/verifier.c21
-rw-r--r--net/ipv4/tcp_bpf.c1
-rw-r--r--tools/lib/bpf/libbpf.c13
-rw-r--r--tools/testing/selftests/bpf/flow_dissector_load.c2
-rwxr-xr-xtools/testing/selftests/bpf/test_skb_cgroup_id.sh3
-rwxr-xr-xtools/testing/selftests/bpf/test_sock_addr.sh3
-rw-r--r--tools/testing/selftests/bpf/test_verifier.c321
8 files changed, 319 insertions, 48 deletions
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index 9e8056ec20fa..d93e89761a8b 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -51,6 +51,9 @@ struct bpf_reg_state {
51 * PTR_TO_MAP_VALUE_OR_NULL 51 * PTR_TO_MAP_VALUE_OR_NULL
52 */ 52 */
53 struct bpf_map *map_ptr; 53 struct bpf_map *map_ptr;
54
55 /* Max size from any of the above. */
56 unsigned long raw;
54 }; 57 };
55 /* Fixed part of pointer offset, pointer types only */ 58 /* Fixed part of pointer offset, pointer types only */
56 s32 off; 59 s32 off;
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 171a2c88e77d..1971ca325fb4 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -2852,10 +2852,6 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn
2852 regs[BPF_REG_0].type = NOT_INIT; 2852 regs[BPF_REG_0].type = NOT_INIT;
2853 } else if (fn->ret_type == RET_PTR_TO_MAP_VALUE_OR_NULL || 2853 } else if (fn->ret_type == RET_PTR_TO_MAP_VALUE_OR_NULL ||
2854 fn->ret_type == RET_PTR_TO_MAP_VALUE) { 2854 fn->ret_type == RET_PTR_TO_MAP_VALUE) {
2855 if (fn->ret_type == RET_PTR_TO_MAP_VALUE)
2856 regs[BPF_REG_0].type = PTR_TO_MAP_VALUE;
2857 else
2858 regs[BPF_REG_0].type = PTR_TO_MAP_VALUE_OR_NULL;
2859 /* There is no offset yet applied, variable or fixed */ 2855 /* There is no offset yet applied, variable or fixed */
2860 mark_reg_known_zero(env, regs, BPF_REG_0); 2856 mark_reg_known_zero(env, regs, BPF_REG_0);
2861 /* remember map_ptr, so that check_map_access() 2857 /* remember map_ptr, so that check_map_access()
@@ -2868,7 +2864,12 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn
2868 return -EINVAL; 2864 return -EINVAL;
2869 } 2865 }
2870 regs[BPF_REG_0].map_ptr = meta.map_ptr; 2866 regs[BPF_REG_0].map_ptr = meta.map_ptr;
2871 regs[BPF_REG_0].id = ++env->id_gen; 2867 if (fn->ret_type == RET_PTR_TO_MAP_VALUE) {
2868 regs[BPF_REG_0].type = PTR_TO_MAP_VALUE;
2869 } else {
2870 regs[BPF_REG_0].type = PTR_TO_MAP_VALUE_OR_NULL;
2871 regs[BPF_REG_0].id = ++env->id_gen;
2872 }
2872 } else if (fn->ret_type == RET_PTR_TO_SOCKET_OR_NULL) { 2873 } else if (fn->ret_type == RET_PTR_TO_SOCKET_OR_NULL) {
2873 int id = acquire_reference_state(env, insn_idx); 2874 int id = acquire_reference_state(env, insn_idx);
2874 if (id < 0) 2875 if (id < 0)
@@ -3046,7 +3047,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
3046 dst_reg->umax_value = umax_ptr; 3047 dst_reg->umax_value = umax_ptr;
3047 dst_reg->var_off = ptr_reg->var_off; 3048 dst_reg->var_off = ptr_reg->var_off;
3048 dst_reg->off = ptr_reg->off + smin_val; 3049 dst_reg->off = ptr_reg->off + smin_val;
3049 dst_reg->range = ptr_reg->range; 3050 dst_reg->raw = ptr_reg->raw;
3050 break; 3051 break;
3051 } 3052 }
3052 /* A new variable offset is created. Note that off_reg->off 3053 /* A new variable offset is created. Note that off_reg->off
@@ -3076,10 +3077,11 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
3076 } 3077 }
3077 dst_reg->var_off = tnum_add(ptr_reg->var_off, off_reg->var_off); 3078 dst_reg->var_off = tnum_add(ptr_reg->var_off, off_reg->var_off);
3078 dst_reg->off = ptr_reg->off; 3079 dst_reg->off = ptr_reg->off;
3080 dst_reg->raw = ptr_reg->raw;
3079 if (reg_is_pkt_pointer(ptr_reg)) { 3081 if (reg_is_pkt_pointer(ptr_reg)) {
3080 dst_reg->id = ++env->id_gen; 3082 dst_reg->id = ++env->id_gen;
3081 /* something was added to pkt_ptr, set range to zero */ 3083 /* something was added to pkt_ptr, set range to zero */
3082 dst_reg->range = 0; 3084 dst_reg->raw = 0;
3083 } 3085 }
3084 break; 3086 break;
3085 case BPF_SUB: 3087 case BPF_SUB:
@@ -3108,7 +3110,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
3108 dst_reg->var_off = ptr_reg->var_off; 3110 dst_reg->var_off = ptr_reg->var_off;
3109 dst_reg->id = ptr_reg->id; 3111 dst_reg->id = ptr_reg->id;
3110 dst_reg->off = ptr_reg->off - smin_val; 3112 dst_reg->off = ptr_reg->off - smin_val;
3111 dst_reg->range = ptr_reg->range; 3113 dst_reg->raw = ptr_reg->raw;
3112 break; 3114 break;
3113 } 3115 }
3114 /* A new variable offset is created. If the subtrahend is known 3116 /* A new variable offset is created. If the subtrahend is known
@@ -3134,11 +3136,12 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
3134 } 3136 }
3135 dst_reg->var_off = tnum_sub(ptr_reg->var_off, off_reg->var_off); 3137 dst_reg->var_off = tnum_sub(ptr_reg->var_off, off_reg->var_off);
3136 dst_reg->off = ptr_reg->off; 3138 dst_reg->off = ptr_reg->off;
3139 dst_reg->raw = ptr_reg->raw;
3137 if (reg_is_pkt_pointer(ptr_reg)) { 3140 if (reg_is_pkt_pointer(ptr_reg)) {
3138 dst_reg->id = ++env->id_gen; 3141 dst_reg->id = ++env->id_gen;
3139 /* something was added to pkt_ptr, set range to zero */ 3142 /* something was added to pkt_ptr, set range to zero */
3140 if (smin_val < 0) 3143 if (smin_val < 0)
3141 dst_reg->range = 0; 3144 dst_reg->raw = 0;
3142 } 3145 }
3143 break; 3146 break;
3144 case BPF_AND: 3147 case BPF_AND:
diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c
index b7918d4caa30..3b45fe530f91 100644
--- a/net/ipv4/tcp_bpf.c
+++ b/net/ipv4/tcp_bpf.c
@@ -145,6 +145,7 @@ msg_bytes_ready:
145 ret = err; 145 ret = err;
146 goto out; 146 goto out;
147 } 147 }
148 copied = -EAGAIN;
148 } 149 }
149 ret = copied; 150 ret = copied;
150out: 151out:
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index b607be7236d3..d6e62e90e8d4 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -2084,19 +2084,19 @@ void bpf_program__set_expected_attach_type(struct bpf_program *prog,
2084 prog->expected_attach_type = type; 2084 prog->expected_attach_type = type;
2085} 2085}
2086 2086
2087#define BPF_PROG_SEC_IMPL(string, ptype, eatype, atype) \ 2087#define BPF_PROG_SEC_IMPL(string, ptype, eatype, is_attachable, atype) \
2088 { string, sizeof(string) - 1, ptype, eatype, atype } 2088 { string, sizeof(string) - 1, ptype, eatype, is_attachable, atype }
2089 2089
2090/* Programs that can NOT be attached. */ 2090/* Programs that can NOT be attached. */
2091#define BPF_PROG_SEC(string, ptype) BPF_PROG_SEC_IMPL(string, ptype, 0, -EINVAL) 2091#define BPF_PROG_SEC(string, ptype) BPF_PROG_SEC_IMPL(string, ptype, 0, 0, 0)
2092 2092
2093/* Programs that can be attached. */ 2093/* Programs that can be attached. */
2094#define BPF_APROG_SEC(string, ptype, atype) \ 2094#define BPF_APROG_SEC(string, ptype, atype) \
2095 BPF_PROG_SEC_IMPL(string, ptype, 0, atype) 2095 BPF_PROG_SEC_IMPL(string, ptype, 0, 1, atype)
2096 2096
2097/* Programs that must specify expected attach type at load time. */ 2097/* Programs that must specify expected attach type at load time. */
2098#define BPF_EAPROG_SEC(string, ptype, eatype) \ 2098#define BPF_EAPROG_SEC(string, ptype, eatype) \
2099 BPF_PROG_SEC_IMPL(string, ptype, eatype, eatype) 2099 BPF_PROG_SEC_IMPL(string, ptype, eatype, 1, eatype)
2100 2100
2101/* Programs that can be attached but attach type can't be identified by section 2101/* Programs that can be attached but attach type can't be identified by section
2102 * name. Kept for backward compatibility. 2102 * name. Kept for backward compatibility.
@@ -2108,6 +2108,7 @@ static const struct {
2108 size_t len; 2108 size_t len;
2109 enum bpf_prog_type prog_type; 2109 enum bpf_prog_type prog_type;
2110 enum bpf_attach_type expected_attach_type; 2110 enum bpf_attach_type expected_attach_type;
2111 int is_attachable;
2111 enum bpf_attach_type attach_type; 2112 enum bpf_attach_type attach_type;
2112} section_names[] = { 2113} section_names[] = {
2113 BPF_PROG_SEC("socket", BPF_PROG_TYPE_SOCKET_FILTER), 2114 BPF_PROG_SEC("socket", BPF_PROG_TYPE_SOCKET_FILTER),
@@ -2198,7 +2199,7 @@ int libbpf_attach_type_by_name(const char *name,
2198 for (i = 0; i < ARRAY_SIZE(section_names); i++) { 2199 for (i = 0; i < ARRAY_SIZE(section_names); i++) {
2199 if (strncmp(name, section_names[i].sec, section_names[i].len)) 2200 if (strncmp(name, section_names[i].sec, section_names[i].len))
2200 continue; 2201 continue;
2201 if (section_names[i].attach_type == -EINVAL) 2202 if (!section_names[i].is_attachable)
2202 return -EINVAL; 2203 return -EINVAL;
2203 *attach_type = section_names[i].attach_type; 2204 *attach_type = section_names[i].attach_type;
2204 return 0; 2205 return 0;
diff --git a/tools/testing/selftests/bpf/flow_dissector_load.c b/tools/testing/selftests/bpf/flow_dissector_load.c
index d3273b5b3173..ae8180b11d5f 100644
--- a/tools/testing/selftests/bpf/flow_dissector_load.c
+++ b/tools/testing/selftests/bpf/flow_dissector_load.c
@@ -11,6 +11,8 @@
11#include <bpf/bpf.h> 11#include <bpf/bpf.h>
12#include <bpf/libbpf.h> 12#include <bpf/libbpf.h>
13 13
14#include "bpf_rlimit.h"
15
14const char *cfg_pin_path = "/sys/fs/bpf/flow_dissector"; 16const char *cfg_pin_path = "/sys/fs/bpf/flow_dissector";
15const char *cfg_map_name = "jmp_table"; 17const char *cfg_map_name = "jmp_table";
16bool cfg_attach = true; 18bool cfg_attach = true;
diff --git a/tools/testing/selftests/bpf/test_skb_cgroup_id.sh b/tools/testing/selftests/bpf/test_skb_cgroup_id.sh
index 42544a969abc..a9bc6f82abc1 100755
--- a/tools/testing/selftests/bpf/test_skb_cgroup_id.sh
+++ b/tools/testing/selftests/bpf/test_skb_cgroup_id.sh
@@ -10,7 +10,7 @@ wait_for_ip()
10 echo -n "Wait for testing link-local IP to become available " 10 echo -n "Wait for testing link-local IP to become available "
11 for _i in $(seq ${MAX_PING_TRIES}); do 11 for _i in $(seq ${MAX_PING_TRIES}); do
12 echo -n "." 12 echo -n "."
13 if ping -6 -q -c 1 -W 1 ff02::1%${TEST_IF} >/dev/null 2>&1; then 13 if $PING6 -c 1 -W 1 ff02::1%${TEST_IF} >/dev/null 2>&1; then
14 echo " OK" 14 echo " OK"
15 return 15 return
16 fi 16 fi
@@ -58,5 +58,6 @@ BPF_PROG_OBJ="${DIR}/test_skb_cgroup_id_kern.o"
58BPF_PROG_SECTION="cgroup_id_logger" 58BPF_PROG_SECTION="cgroup_id_logger"
59BPF_PROG_ID=0 59BPF_PROG_ID=0
60PROG="${DIR}/test_skb_cgroup_id_user" 60PROG="${DIR}/test_skb_cgroup_id_user"
61type ping6 >/dev/null 2>&1 && PING6="ping6" || PING6="ping -6"
61 62
62main 63main
diff --git a/tools/testing/selftests/bpf/test_sock_addr.sh b/tools/testing/selftests/bpf/test_sock_addr.sh
index 9832a875a828..3b9fdb8094aa 100755
--- a/tools/testing/selftests/bpf/test_sock_addr.sh
+++ b/tools/testing/selftests/bpf/test_sock_addr.sh
@@ -4,7 +4,8 @@ set -eu
4 4
5ping_once() 5ping_once()
6{ 6{
7 ping -${1} -q -c 1 -W 1 ${2%%/*} >/dev/null 2>&1 7 type ping${1} >/dev/null 2>&1 && PING="ping${1}" || PING="ping -${1}"
8 $PING -q -c 1 -W 1 ${2%%/*} >/dev/null 2>&1
8} 9}
9 10
10wait_for_ip() 11wait_for_ip()
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
index 36f3d3009d1a..6f61df62f690 100644
--- a/tools/testing/selftests/bpf/test_verifier.c
+++ b/tools/testing/selftests/bpf/test_verifier.c
@@ -76,7 +76,7 @@ struct bpf_test {
76 int fixup_percpu_cgroup_storage[MAX_FIXUPS]; 76 int fixup_percpu_cgroup_storage[MAX_FIXUPS];
77 const char *errstr; 77 const char *errstr;
78 const char *errstr_unpriv; 78 const char *errstr_unpriv;
79 uint32_t retval; 79 uint32_t retval, retval_unpriv;
80 enum { 80 enum {
81 UNDEF, 81 UNDEF,
82 ACCEPT, 82 ACCEPT,
@@ -3084,6 +3084,8 @@ static struct bpf_test tests[] = {
3084 .fixup_prog1 = { 2 }, 3084 .fixup_prog1 = { 2 },
3085 .result = ACCEPT, 3085 .result = ACCEPT,
3086 .retval = 42, 3086 .retval = 42,
3087 /* Verifier rewrite for unpriv skips tail call here. */
3088 .retval_unpriv = 2,
3087 }, 3089 },
3088 { 3090 {
3089 "stack pointer arithmetic", 3091 "stack pointer arithmetic",
@@ -6455,6 +6457,256 @@ static struct bpf_test tests[] = {
6455 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 6457 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
6456 }, 6458 },
6457 { 6459 {
6460 "map access: known scalar += value_ptr",
6461 .insns = {
6462 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6463 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6464 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6465 BPF_LD_MAP_FD(BPF_REG_1, 0),
6466 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6467 BPF_FUNC_map_lookup_elem),
6468 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
6469 BPF_MOV64_IMM(BPF_REG_1, 4),
6470 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_0),
6471 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 0),
6472 BPF_MOV64_IMM(BPF_REG_0, 1),
6473 BPF_EXIT_INSN(),
6474 },
6475 .fixup_map_array_48b = { 3 },
6476 .result = ACCEPT,
6477 .retval = 1,
6478 },
6479 {
6480 "map access: value_ptr += known scalar",
6481 .insns = {
6482 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6483 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6484 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6485 BPF_LD_MAP_FD(BPF_REG_1, 0),
6486 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6487 BPF_FUNC_map_lookup_elem),
6488 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
6489 BPF_MOV64_IMM(BPF_REG_1, 4),
6490 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
6491 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
6492 BPF_MOV64_IMM(BPF_REG_0, 1),
6493 BPF_EXIT_INSN(),
6494 },
6495 .fixup_map_array_48b = { 3 },
6496 .result = ACCEPT,
6497 .retval = 1,
6498 },
6499 {
6500 "map access: unknown scalar += value_ptr",
6501 .insns = {
6502 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6503 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6504 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6505 BPF_LD_MAP_FD(BPF_REG_1, 0),
6506 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6507 BPF_FUNC_map_lookup_elem),
6508 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
6509 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
6510 BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0xf),
6511 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_0),
6512 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 0),
6513 BPF_MOV64_IMM(BPF_REG_0, 1),
6514 BPF_EXIT_INSN(),
6515 },
6516 .fixup_map_array_48b = { 3 },
6517 .result = ACCEPT,
6518 .retval = 1,
6519 },
6520 {
6521 "map access: value_ptr += unknown scalar",
6522 .insns = {
6523 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6524 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6525 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6526 BPF_LD_MAP_FD(BPF_REG_1, 0),
6527 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6528 BPF_FUNC_map_lookup_elem),
6529 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
6530 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
6531 BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0xf),
6532 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
6533 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
6534 BPF_MOV64_IMM(BPF_REG_0, 1),
6535 BPF_EXIT_INSN(),
6536 },
6537 .fixup_map_array_48b = { 3 },
6538 .result = ACCEPT,
6539 .retval = 1,
6540 },
6541 {
6542 "map access: value_ptr += value_ptr",
6543 .insns = {
6544 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6545 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6546 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6547 BPF_LD_MAP_FD(BPF_REG_1, 0),
6548 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6549 BPF_FUNC_map_lookup_elem),
6550 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
6551 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_0),
6552 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
6553 BPF_MOV64_IMM(BPF_REG_0, 1),
6554 BPF_EXIT_INSN(),
6555 },
6556 .fixup_map_array_48b = { 3 },
6557 .result = REJECT,
6558 .errstr = "R0 pointer += pointer prohibited",
6559 },
6560 {
6561 "map access: known scalar -= value_ptr",
6562 .insns = {
6563 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6564 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6565 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6566 BPF_LD_MAP_FD(BPF_REG_1, 0),
6567 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6568 BPF_FUNC_map_lookup_elem),
6569 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
6570 BPF_MOV64_IMM(BPF_REG_1, 4),
6571 BPF_ALU64_REG(BPF_SUB, BPF_REG_1, BPF_REG_0),
6572 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 0),
6573 BPF_MOV64_IMM(BPF_REG_0, 1),
6574 BPF_EXIT_INSN(),
6575 },
6576 .fixup_map_array_48b = { 3 },
6577 .result = REJECT,
6578 .errstr = "R1 tried to subtract pointer from scalar",
6579 },
6580 {
6581 "map access: value_ptr -= known scalar",
6582 .insns = {
6583 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6584 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6585 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6586 BPF_LD_MAP_FD(BPF_REG_1, 0),
6587 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6588 BPF_FUNC_map_lookup_elem),
6589 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
6590 BPF_MOV64_IMM(BPF_REG_1, 4),
6591 BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_1),
6592 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
6593 BPF_MOV64_IMM(BPF_REG_0, 1),
6594 BPF_EXIT_INSN(),
6595 },
6596 .fixup_map_array_48b = { 3 },
6597 .result = REJECT,
6598 .errstr = "R0 min value is outside of the array range",
6599 },
6600 {
6601 "map access: value_ptr -= known scalar, 2",
6602 .insns = {
6603 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6604 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6605 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6606 BPF_LD_MAP_FD(BPF_REG_1, 0),
6607 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6608 BPF_FUNC_map_lookup_elem),
6609 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5),
6610 BPF_MOV64_IMM(BPF_REG_1, 6),
6611 BPF_MOV64_IMM(BPF_REG_2, 4),
6612 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
6613 BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_2),
6614 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
6615 BPF_MOV64_IMM(BPF_REG_0, 1),
6616 BPF_EXIT_INSN(),
6617 },
6618 .fixup_map_array_48b = { 3 },
6619 .result = ACCEPT,
6620 .retval = 1,
6621 },
6622 {
6623 "map access: unknown scalar -= value_ptr",
6624 .insns = {
6625 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6626 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6627 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6628 BPF_LD_MAP_FD(BPF_REG_1, 0),
6629 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6630 BPF_FUNC_map_lookup_elem),
6631 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
6632 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
6633 BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0xf),
6634 BPF_ALU64_REG(BPF_SUB, BPF_REG_1, BPF_REG_0),
6635 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 0),
6636 BPF_MOV64_IMM(BPF_REG_0, 1),
6637 BPF_EXIT_INSN(),
6638 },
6639 .fixup_map_array_48b = { 3 },
6640 .result = REJECT,
6641 .errstr = "R1 tried to subtract pointer from scalar",
6642 },
6643 {
6644 "map access: value_ptr -= unknown scalar",
6645 .insns = {
6646 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6647 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6648 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6649 BPF_LD_MAP_FD(BPF_REG_1, 0),
6650 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6651 BPF_FUNC_map_lookup_elem),
6652 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
6653 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
6654 BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0xf),
6655 BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_1),
6656 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
6657 BPF_MOV64_IMM(BPF_REG_0, 1),
6658 BPF_EXIT_INSN(),
6659 },
6660 .fixup_map_array_48b = { 3 },
6661 .result = REJECT,
6662 .errstr = "R0 min value is negative",
6663 },
6664 {
6665 "map access: value_ptr -= unknown scalar, 2",
6666 .insns = {
6667 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6668 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6669 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6670 BPF_LD_MAP_FD(BPF_REG_1, 0),
6671 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6672 BPF_FUNC_map_lookup_elem),
6673 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
6674 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
6675 BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0xf),
6676 BPF_ALU64_IMM(BPF_OR, BPF_REG_1, 0x7),
6677 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
6678 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
6679 BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0x7),
6680 BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_1),
6681 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
6682 BPF_MOV64_IMM(BPF_REG_0, 1),
6683 BPF_EXIT_INSN(),
6684 },
6685 .fixup_map_array_48b = { 3 },
6686 .result = ACCEPT,
6687 .retval = 1,
6688 },
6689 {
6690 "map access: value_ptr -= value_ptr",
6691 .insns = {
6692 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6693 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6694 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6695 BPF_LD_MAP_FD(BPF_REG_1, 0),
6696 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6697 BPF_FUNC_map_lookup_elem),
6698 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
6699 BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_0),
6700 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
6701 BPF_MOV64_IMM(BPF_REG_0, 1),
6702 BPF_EXIT_INSN(),
6703 },
6704 .fixup_map_array_48b = { 3 },
6705 .result = REJECT,
6706 .errstr = "R0 invalid mem access 'inv'",
6707 .errstr_unpriv = "R0 pointer -= pointer prohibited",
6708 },
6709 {
6458 "map lookup helper access to map", 6710 "map lookup helper access to map",
6459 .insns = { 6711 .insns = {
6460 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 6712 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
@@ -13899,6 +14151,33 @@ static void do_test_fixup(struct bpf_test *test, enum bpf_map_type prog_type,
13899 } 14151 }
13900} 14152}
13901 14153
14154static int set_admin(bool admin)
14155{
14156 cap_t caps;
14157 const cap_value_t cap_val = CAP_SYS_ADMIN;
14158 int ret = -1;
14159
14160 caps = cap_get_proc();
14161 if (!caps) {
14162 perror("cap_get_proc");
14163 return -1;
14164 }
14165 if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap_val,
14166 admin ? CAP_SET : CAP_CLEAR)) {
14167 perror("cap_set_flag");
14168 goto out;
14169 }
14170 if (cap_set_proc(caps)) {
14171 perror("cap_set_proc");
14172 goto out;
14173 }
14174 ret = 0;
14175out:
14176 if (cap_free(caps))
14177 perror("cap_free");
14178 return ret;
14179}
14180
13902static void do_test_single(struct bpf_test *test, bool unpriv, 14181static void do_test_single(struct bpf_test *test, bool unpriv,
13903 int *passes, int *errors) 14182 int *passes, int *errors)
13904{ 14183{
@@ -13907,6 +14186,7 @@ static void do_test_single(struct bpf_test *test, bool unpriv,
13907 struct bpf_insn *prog = test->insns; 14186 struct bpf_insn *prog = test->insns;
13908 int map_fds[MAX_NR_MAPS]; 14187 int map_fds[MAX_NR_MAPS];
13909 const char *expected_err; 14188 const char *expected_err;
14189 uint32_t expected_val;
13910 uint32_t retval; 14190 uint32_t retval;
13911 int i, err; 14191 int i, err;
13912 14192
@@ -13926,6 +14206,8 @@ static void do_test_single(struct bpf_test *test, bool unpriv,
13926 test->result_unpriv : test->result; 14206 test->result_unpriv : test->result;
13927 expected_err = unpriv && test->errstr_unpriv ? 14207 expected_err = unpriv && test->errstr_unpriv ?
13928 test->errstr_unpriv : test->errstr; 14208 test->errstr_unpriv : test->errstr;
14209 expected_val = unpriv && test->retval_unpriv ?
14210 test->retval_unpriv : test->retval;
13929 14211
13930 reject_from_alignment = fd_prog < 0 && 14212 reject_from_alignment = fd_prog < 0 &&
13931 (test->flags & F_NEEDS_EFFICIENT_UNALIGNED_ACCESS) && 14213 (test->flags & F_NEEDS_EFFICIENT_UNALIGNED_ACCESS) &&
@@ -13959,16 +14241,20 @@ static void do_test_single(struct bpf_test *test, bool unpriv,
13959 __u8 tmp[TEST_DATA_LEN << 2]; 14241 __u8 tmp[TEST_DATA_LEN << 2];
13960 __u32 size_tmp = sizeof(tmp); 14242 __u32 size_tmp = sizeof(tmp);
13961 14243
14244 if (unpriv)
14245 set_admin(true);
13962 err = bpf_prog_test_run(fd_prog, 1, test->data, 14246 err = bpf_prog_test_run(fd_prog, 1, test->data,
13963 sizeof(test->data), tmp, &size_tmp, 14247 sizeof(test->data), tmp, &size_tmp,
13964 &retval, NULL); 14248 &retval, NULL);
14249 if (unpriv)
14250 set_admin(false);
13965 if (err && errno != 524/*ENOTSUPP*/ && errno != EPERM) { 14251 if (err && errno != 524/*ENOTSUPP*/ && errno != EPERM) {
13966 printf("Unexpected bpf_prog_test_run error\n"); 14252 printf("Unexpected bpf_prog_test_run error\n");
13967 goto fail_log; 14253 goto fail_log;
13968 } 14254 }
13969 if (!err && retval != test->retval && 14255 if (!err && retval != expected_val &&
13970 test->retval != POINTER_VALUE) { 14256 expected_val != POINTER_VALUE) {
13971 printf("FAIL retval %d != %d\n", retval, test->retval); 14257 printf("FAIL retval %d != %d\n", retval, expected_val);
13972 goto fail_log; 14258 goto fail_log;
13973 } 14259 }
13974 } 14260 }
@@ -14011,33 +14297,6 @@ static bool is_admin(void)
14011 return (sysadmin == CAP_SET); 14297 return (sysadmin == CAP_SET);
14012} 14298}
14013 14299
14014static int set_admin(bool admin)
14015{
14016 cap_t caps;
14017 const cap_value_t cap_val = CAP_SYS_ADMIN;
14018 int ret = -1;
14019
14020 caps = cap_get_proc();
14021 if (!caps) {
14022 perror("cap_get_proc");
14023 return -1;
14024 }
14025 if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap_val,
14026 admin ? CAP_SET : CAP_CLEAR)) {
14027 perror("cap_set_flag");
14028 goto out;
14029 }
14030 if (cap_set_proc(caps)) {
14031 perror("cap_set_proc");
14032 goto out;
14033 }
14034 ret = 0;
14035out:
14036 if (cap_free(caps))
14037 perror("cap_free");
14038 return ret;
14039}
14040
14041static void get_unpriv_disabled() 14300static void get_unpriv_disabled()
14042{ 14301{
14043 char buf[2]; 14302 char buf[2];