diff options
author | David S. Miller <davem@davemloft.net> | 2018-10-31 20:34:08 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-10-31 20:34:08 -0400 |
commit | df975da4e578eb06453f41a3ecd73c2a4c28044d (patch) | |
tree | 74dd370bd058feb814e2303bcc4999b8210d42de | |
parent | e2acdddde01511c74e4f6f1d5951a0f5d9bea14a (diff) | |
parent | dfeb8f4c9692fd5e6c3eef19c2e4ae5338dbdb01 (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.h | 3 | ||||
-rw-r--r-- | kernel/bpf/verifier.c | 21 | ||||
-rw-r--r-- | net/ipv4/tcp_bpf.c | 1 | ||||
-rw-r--r-- | tools/lib/bpf/libbpf.c | 13 | ||||
-rw-r--r-- | tools/testing/selftests/bpf/flow_dissector_load.c | 2 | ||||
-rwxr-xr-x | tools/testing/selftests/bpf/test_skb_cgroup_id.sh | 3 | ||||
-rwxr-xr-x | tools/testing/selftests/bpf/test_sock_addr.sh | 3 | ||||
-rw-r--r-- | tools/testing/selftests/bpf/test_verifier.c | 321 |
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; |
150 | out: | 151 | out: |
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 | |||
14 | const char *cfg_pin_path = "/sys/fs/bpf/flow_dissector"; | 16 | const char *cfg_pin_path = "/sys/fs/bpf/flow_dissector"; |
15 | const char *cfg_map_name = "jmp_table"; | 17 | const char *cfg_map_name = "jmp_table"; |
16 | bool cfg_attach = true; | 18 | bool 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" | |||
58 | BPF_PROG_SECTION="cgroup_id_logger" | 58 | BPF_PROG_SECTION="cgroup_id_logger" |
59 | BPF_PROG_ID=0 | 59 | BPF_PROG_ID=0 |
60 | PROG="${DIR}/test_skb_cgroup_id_user" | 60 | PROG="${DIR}/test_skb_cgroup_id_user" |
61 | type ping6 >/dev/null 2>&1 && PING6="ping6" || PING6="ping -6" | ||
61 | 62 | ||
62 | main | 63 | main |
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 | ||
5 | ping_once() | 5 | ping_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 | ||
10 | wait_for_ip() | 11 | wait_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 | ||
14154 | static 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; | ||
14175 | out: | ||
14176 | if (cap_free(caps)) | ||
14177 | perror("cap_free"); | ||
14178 | return ret; | ||
14179 | } | ||
14180 | |||
13902 | static void do_test_single(struct bpf_test *test, bool unpriv, | 14181 | static 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 | ||
14014 | static 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; | ||
14035 | out: | ||
14036 | if (cap_free(caps)) | ||
14037 | perror("cap_free"); | ||
14038 | return ret; | ||
14039 | } | ||
14040 | |||
14041 | static void get_unpriv_disabled() | 14300 | static void get_unpriv_disabled() |
14042 | { | 14301 | { |
14043 | char buf[2]; | 14302 | char buf[2]; |