History

Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf

Alexei Starovoitov says: ==================== pull-request: bpf 2020-04-24 The following pull-request contains BPF updates for your *net* tree. We've added 17 non-merge commits during the last 5 day(s) which contain a total of 19 files changed, 203 insertions(+), 85 deletions(-). The main changes are: 1) link_update fix, from Andrii. 2) libbpf get_xdp_id fix, from David. 3) xadd verifier fix, from Jann. 4) x86-32 JIT fixes, from Luke and Wang. 5) test_btf fix, from Stanislav. 6) freplace verifier fix, from Toke. ====================

David S. Miller committed 6 years ago

Commit 167ff132 parents 3554e54 e1cebd819 files · +203 −85Browse files

Unified · Split

19 files
  1. arch/x86/net/bpf_jit_comp.c +15 −3
  2. arch/x86/net/bpf_jit_comp32.c +22 −6
  3. include/uapi/linux/bpf.h +1 −1
  4. kernel/bpf/cpumap.c +1 −1
  5. kernel/bpf/syscall.c +10 −3
  6. kernel/bpf/verifier.c +28 −10
  7. tools/bpf/bpftool/struct_ops.c +7 −1
  8. tools/bpf/runqslower/Makefile +1 −1
  9. tools/include/uapi/linux/bpf.h +1 −1
  10. tools/lib/bpf/netlink.c +2 −0
  11. tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c +24 −6
  12. tools/testing/selftests/bpf/progs/connect4_prog.c +16 −12
  13. tools/testing/selftests/bpf/progs/freplace_connect4.c +18 −0
  14. tools/testing/selftests/bpf/progs/test_btf_haskv.c +5 −13
  15. tools/testing/selftests/bpf/progs/test_btf_newkv.c +5 −13
  16. tools/testing/selftests/bpf/progs/test_btf_nokv.c +5 −13
  17. tools/testing/selftests/bpf/test_btf.c +1 −1
  18. tools/testing/selftests/bpf/verifier/stack_ptr.c +40 −0
  19. tools/testing/selftests/bpf/verifier/value_illegal_alu.c +1 −0
arch/x86/net/bpf_jit_comp.c+15−3
@@ -158,6 +158,19 @@ static bool is_ereg(u32 reg) · 157 unmodified lines
158 BIT(BPF_REG_AX));158 BIT(BPF_REG_AX));
159}159}
160 160
161/*
162 * is_ereg_8l() == true if BPF register 'reg' is mapped to access x86-64
163 * lower 8-bit registers dil,sil,bpl,spl,r8b..r15b, which need extra byte
164 * of encoding. al,cl,dl,bl have simpler encoding.
165 */
166static bool is_ereg_8l(u32 reg)
167{
168 return is_ereg(reg) ||
169 (1 << reg) & (BIT(BPF_REG_1) |
170 BIT(BPF_REG_2) |
171 BIT(BPF_REG_FP));
172}
173
161static bool is_axreg(u32 reg)174static bool is_axreg(u32 reg)
162{175{
163 return reg == BPF_REG_0;176 return reg == BPF_REG_0;
@@ -598,9 +611,8 @@ static void emit_stx(u8 **pprog, u32 size, u32 dst_reg, u32 src_reg, int off) · 434 unmodified lines
598 switch (size) {611 switch (size) {
599 case BPF_B:612 case BPF_B:
600 /* Emit 'mov byte ptr [rax + off], al' */613 /* Emit 'mov byte ptr [rax + off], al' */
601 if (is_ereg(dst_reg) || is_ereg(src_reg) ||614 if (is_ereg(dst_reg) || is_ereg_8l(src_reg))
602 /* We have to add extra byte for x86 SIL, DIL regs */615 /* Add extra byte for eregs or SIL,DIL,BPL in src_reg */
603 src_reg == BPF_REG_1 || src_reg == BPF_REG_2)
604 EMIT2(add_2mod(0x40, dst_reg, src_reg), 0x88);616 EMIT2(add_2mod(0x40, dst_reg, src_reg), 0x88);
605 else617 else
606 EMIT1(0x88);618 EMIT1(0x88);
arch/x86/net/bpf_jit_comp32.c+22−6
@@ -1847,14 +1847,16 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, · 1846 unmodified lines
1847 case BPF_B:1847 case BPF_B:
1848 case BPF_H:1848 case BPF_H:
1849 case BPF_W:1849 case BPF_W:
1850 if (!bpf_prog->aux->verifier_zext)1850 if (bpf_prog->aux->verifier_zext)
1851 break;1851 break;
1852 if (dstk) {1852 if (dstk) {
1853 EMIT3(0xC7, add_1reg(0x40, IA32_EBP),1853 EMIT3(0xC7, add_1reg(0x40, IA32_EBP),
1854 STACK_VAR(dst_hi));1854 STACK_VAR(dst_hi));
1855 EMIT(0x0, 4);1855 EMIT(0x0, 4);
1856 } else {1856 } else {
1857 EMIT3(0xC7, add_1reg(0xC0, dst_hi), 0);1857 /* xor dst_hi,dst_hi */
1858 EMIT2(0x33,
1859 add_2reg(0xC0, dst_hi, dst_hi));
1858 }1860 }
1859 break;1861 break;
1860 case BPF_DW:1862 case BPF_DW:
@@ -2013,8 +2015,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, · 152 unmodified lines
2013 case BPF_JMP | BPF_JSET | BPF_X:2015 case BPF_JMP | BPF_JSET | BPF_X:
2014 case BPF_JMP32 | BPF_JSET | BPF_X: {2016 case BPF_JMP32 | BPF_JSET | BPF_X: {
2015 bool is_jmp64 = BPF_CLASS(insn->code) == BPF_JMP;2017 bool is_jmp64 = BPF_CLASS(insn->code) == BPF_JMP;
2016 u8 dreg_lo = dstk ? IA32_EAX : dst_lo;2018 u8 dreg_lo = IA32_EAX;
2017 u8 dreg_hi = dstk ? IA32_EDX : dst_hi;2019 u8 dreg_hi = IA32_EDX;
2018 u8 sreg_lo = sstk ? IA32_ECX : src_lo;2020 u8 sreg_lo = sstk ? IA32_ECX : src_lo;
2019 u8 sreg_hi = sstk ? IA32_EBX : src_hi;2021 u8 sreg_hi = sstk ? IA32_EBX : src_hi;
2020 2022
@@ -2026,6 +2028,13 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, · 5 unmodified lines
2026 add_2reg(0x40, IA32_EBP,2028 add_2reg(0x40, IA32_EBP,
2027 IA32_EDX),2029 IA32_EDX),
2028 STACK_VAR(dst_hi));2030 STACK_VAR(dst_hi));
2031 } else {
2032 /* mov dreg_lo,dst_lo */
2033 EMIT2(0x89, add_2reg(0xC0, dreg_lo, dst_lo));
2034 if (is_jmp64)
2035 /* mov dreg_hi,dst_hi */
2036 EMIT2(0x89,
2037 add_2reg(0xC0, dreg_hi, dst_hi));
2029 }2038 }
2030 2039
2031 if (sstk) {2040 if (sstk) {
@@ -2050,8 +2059,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, · 18 unmodified lines
2050 case BPF_JMP | BPF_JSET | BPF_K:2059 case BPF_JMP | BPF_JSET | BPF_K:
2051 case BPF_JMP32 | BPF_JSET | BPF_K: {2060 case BPF_JMP32 | BPF_JSET | BPF_K: {
2052 bool is_jmp64 = BPF_CLASS(insn->code) == BPF_JMP;2061 bool is_jmp64 = BPF_CLASS(insn->code) == BPF_JMP;
2053 u8 dreg_lo = dstk ? IA32_EAX : dst_lo;2062 u8 dreg_lo = IA32_EAX;
2054 u8 dreg_hi = dstk ? IA32_EDX : dst_hi;2063 u8 dreg_hi = IA32_EDX;
2055 u8 sreg_lo = IA32_ECX;2064 u8 sreg_lo = IA32_ECX;
2056 u8 sreg_hi = IA32_EBX;2065 u8 sreg_hi = IA32_EBX;
2057 u32 hi;2066 u32 hi;
@@ -2064,6 +2073,13 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, · 6 unmodified lines
2064 add_2reg(0x40, IA32_EBP,2073 add_2reg(0x40, IA32_EBP,
2065 IA32_EDX),2074 IA32_EDX),
2066 STACK_VAR(dst_hi));2075 STACK_VAR(dst_hi));
2076 } else {
2077 /* mov dreg_lo,dst_lo */
2078 EMIT2(0x89, add_2reg(0xC0, dreg_lo, dst_lo));
2079 if (is_jmp64)
2080 /* mov dreg_hi,dst_hi */
2081 EMIT2(0x89,
2082 add_2reg(0xC0, dreg_hi, dst_hi));
2067 }2083 }
2068 2084
2069 /* mov ecx,imm32 */2085 /* mov ecx,imm32 */
include/uapi/linux/bpf.h+1−1
@@ -1642,7 +1642,7 @@ union bpf_attr { · 1641 unmodified lines
1642 * ifindex, but doesn't require a map to do so.1642 * ifindex, but doesn't require a map to do so.
1643 * Return1643 * Return
1644 * **XDP_REDIRECT** on success, or the value of the two lower bits1644 * **XDP_REDIRECT** on success, or the value of the two lower bits
1645 * of the **flags* argument on error.1645 * of the *flags* argument on error.
1646 *1646 *
1647 * int bpf_sk_redirect_map(struct sk_buff *skb, struct bpf_map *map, u32 key, u64 flags)1647 * int bpf_sk_redirect_map(struct sk_buff *skb, struct bpf_map *map, u32 key, u64 flags)
1648 * Description1648 * Description
kernel/bpf/cpumap.c+1−1
@@ -469,7 +469,7 @@ static int cpu_map_update_elem(struct bpf_map *map, void *key, void *value, · 468 unmodified lines
469 return -EOVERFLOW;469 return -EOVERFLOW;
470 470
471 /* Make sure CPU is a valid possible cpu */471 /* Make sure CPU is a valid possible cpu */
472 if (!cpu_possible(key_cpu))472 if (key_cpu >= nr_cpumask_bits || !cpu_possible(key_cpu))
473 return -ENODEV;473 return -ENODEV;
474 474
475 if (qsize == 0) {475 if (qsize == 0) {
kernel/bpf/syscall.c+10−3
@@ -2283,7 +2283,7 @@ static void bpf_link_show_fdinfo(struct seq_file *m, struct file *filp) · 2282 unmodified lines
2283}2283}
2284#endif2284#endif
2285 2285
2286const struct file_operations bpf_link_fops = {2286static const struct file_operations bpf_link_fops = {
2287#ifdef CONFIG_PROC_FS2287#ifdef CONFIG_PROC_FS
2288 .show_fdinfo = bpf_link_show_fdinfo,2288 .show_fdinfo = bpf_link_show_fdinfo,
2289#endif2289#endif
@@ -3628,8 +3628,10 @@ static int link_update(union bpf_attr *attr) · 1338 unmodified lines
3628 return PTR_ERR(link);3628 return PTR_ERR(link);
3629 3629
3630 new_prog = bpf_prog_get(attr->link_update.new_prog_fd);3630 new_prog = bpf_prog_get(attr->link_update.new_prog_fd);
3631 if (IS_ERR(new_prog))3631 if (IS_ERR(new_prog)) {
3632 return PTR_ERR(new_prog);3632 ret = PTR_ERR(new_prog);
3633 goto out_put_link;
3634 }
3633 3635
3634 if (flags & BPF_F_REPLACE) {3636 if (flags & BPF_F_REPLACE) {
3635 old_prog = bpf_prog_get(attr->link_update.old_prog_fd);3637 old_prog = bpf_prog_get(attr->link_update.old_prog_fd);
@@ -3638,6 +3640,9 @@ static int link_update(union bpf_attr *attr) · 2 unmodified lines
3638 old_prog = NULL;3640 old_prog = NULL;
3639 goto out_put_progs;3641 goto out_put_progs;
3640 }3642 }
3643 } else if (attr->link_update.old_prog_fd) {
3644 ret = -EINVAL;
3645 goto out_put_progs;
3641 }3646 }
3642 3647
3643#ifdef CONFIG_CGROUP_BPF3648#ifdef CONFIG_CGROUP_BPF
@@ -3653,6 +3658,8 @@ out_put_progs: · 9 unmodified lines
3653 bpf_prog_put(old_prog);3658 bpf_prog_put(old_prog);
3654 if (ret)3659 if (ret)
3655 bpf_prog_put(new_prog);3660 bpf_prog_put(new_prog);
3661out_put_link:
3662 bpf_link_put(link);
3656 return ret;3663 return ret;
3657}3664}
3658 3665
kernel/bpf/verifier.c+28−10
@@ -2118,6 +2118,15 @@ static bool register_is_const(struct bpf_reg_state *reg) · 2117 unmodified lines
2118 return reg->type == SCALAR_VALUE && tnum_is_const(reg->var_off);2118 return reg->type == SCALAR_VALUE && tnum_is_const(reg->var_off);
2119}2119}
2120 2120
2121static bool __is_pointer_value(bool allow_ptr_leaks,
2122 const struct bpf_reg_state *reg)
2123{
2124 if (allow_ptr_leaks)
2125 return false;
2126
2127 return reg->type != SCALAR_VALUE;
2128}
2129
2121static void save_register_state(struct bpf_func_state *state,2130static void save_register_state(struct bpf_func_state *state,
2122 int spi, struct bpf_reg_state *reg)2131 int spi, struct bpf_reg_state *reg)
2123{2132{
@@ -2308,6 +2317,16 @@ static int check_stack_read(struct bpf_verifier_env *env, · 184 unmodified lines
2308 * which resets stack/reg liveness for state transitions2317 * which resets stack/reg liveness for state transitions
2309 */2318 */
2310 state->regs[value_regno].live |= REG_LIVE_WRITTEN;2319 state->regs[value_regno].live |= REG_LIVE_WRITTEN;
2320 } else if (__is_pointer_value(env->allow_ptr_leaks, reg)) {
2321 /* If value_regno==-1, the caller is asking us whether
2322 * it is acceptable to use this value as a SCALAR_VALUE
2323 * (e.g. for XADD).
2324 * We must not allow unprivileged callers to do that
2325 * with spilled pointers.
2326 */
2327 verbose(env, "leaking pointer from stack off %d\n",
2328 off);
2329 return -EACCES;
2311 }2330 }
2312 mark_reg_read(env, reg, reg->parent, REG_LIVE_READ64);2331 mark_reg_read(env, reg, reg->parent, REG_LIVE_READ64);
2313 } else {2332 } else {
@@ -2673,15 +2692,6 @@ static int check_sock_access(struct bpf_verifier_env *env, int insn_idx, · 359 unmodified lines
2673 return -EACCES;2692 return -EACCES;
2674}2693}
2675 2694
2676static bool __is_pointer_value(bool allow_ptr_leaks,
2677 const struct bpf_reg_state *reg)
2678{
2679 if (allow_ptr_leaks)
2680 return false;
2681
2682 return reg->type != SCALAR_VALUE;
2683}
2684
2685static struct bpf_reg_state *reg_state(struct bpf_verifier_env *env, int regno)2695static struct bpf_reg_state *reg_state(struct bpf_verifier_env *env, int regno)
2686{2696{
2687 return cur_regs(env) + regno;2697 return cur_regs(env) + regno;
@@ -3089,7 +3099,7 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env, · 401 unmodified lines
3089 if (ret < 0)3099 if (ret < 0)
3090 return ret;3100 return ret;
3091 3101
3092 if (atype == BPF_READ) {3102 if (atype == BPF_READ && value_regno >= 0) {
3093 if (ret == SCALAR_VALUE) {3103 if (ret == SCALAR_VALUE) {
3094 mark_reg_unknown(env, regs, value_regno);3104 mark_reg_unknown(env, regs, value_regno);
3095 return 0;3105 return 0;
@@ -10487,6 +10497,7 @@ static int check_attach_btf_id(struct bpf_verifier_env *env) · 7391 unmodified lines
10487 return -EINVAL;10497 return -EINVAL;
10488 }10498 }
10489 env->ops = bpf_verifier_ops[tgt_prog->type];10499 env->ops = bpf_verifier_ops[tgt_prog->type];
10500 prog->expected_attach_type = tgt_prog->expected_attach_type;
10490 }10501 }
10491 if (!tgt_prog->jited) {10502 if (!tgt_prog->jited) {
10492 verbose(env, "Can attach to only JITed progs\n");10503 verbose(env, "Can attach to only JITed progs\n");
@@ -10831,6 +10842,13 @@ err_release_maps: · 338 unmodified lines
10831 * them now. Otherwise free_used_maps() will release them.10842 * them now. Otherwise free_used_maps() will release them.
10832 */10843 */
10833 release_maps(env);10844 release_maps(env);
10845
10846 /* extension progs temporarily inherit the attach_type of their targets
10847 for verification purposes, so set it back to zero before returning
10848 */
10849 if (env->prog->type == BPF_PROG_TYPE_EXT)
10850 env->prog->expected_attach_type = 0;
10851
10834 *prog = env->prog;10852 *prog = env->prog;
10835err_unlock:10853err_unlock:
10836 if (!is_priv)10854 if (!is_priv)
tools/bpf/bpftool/struct_ops.c+7−1
@@ -479,6 +479,7 @@ static int do_unregister(int argc, char **argv) · 478 unmodified lines
479 479
480static int do_register(int argc, char **argv)480static int do_register(int argc, char **argv)
481{481{
482 struct bpf_object_load_attr load_attr = {};
482 const struct bpf_map_def *def;483 const struct bpf_map_def *def;
483 struct bpf_map_info info = {};484 struct bpf_map_info info = {};
484 __u32 info_len = sizeof(info);485 __u32 info_len = sizeof(info);
@@ -499,7 +500,12 @@ static int do_register(int argc, char **argv) · 14 unmodified lines
499 500
500 set_max_rlimit();501 set_max_rlimit();
501 502
502 if (bpf_object__load(obj)) {503 load_attr.obj = obj;
504 if (verifier_logs)
505 /* log_level1 + log_level2 + stats, but not stable UAPI */
506 load_attr.log_level = 1 + 2 + 4;
507
508 if (bpf_object__load_xattr(&load_attr)) {
503 bpf_object__close(obj);509 bpf_object__close(obj);
504 return -1;510 return -1;
505 }511 }
tools/bpf/runqslower/Makefile+1−1
@@ -8,7 +8,7 @@ BPFTOOL ?= $(DEFAULT_BPFTOOL) · 7 unmodified lines
8LIBBPF_SRC := $(abspath ../../lib/bpf)8LIBBPF_SRC := $(abspath ../../lib/bpf)
9BPFOBJ := $(OUTPUT)/libbpf.a9BPFOBJ := $(OUTPUT)/libbpf.a
10BPF_INCLUDE := $(OUTPUT)10BPF_INCLUDE := $(OUTPUT)
11INCLUDES := -I$(BPF_INCLUDE) -I$(OUTPUT) -I$(abspath ../../lib)11INCLUDES := -I$(OUTPUT) -I$(BPF_INCLUDE) -I$(abspath ../../lib)
12CFLAGS := -g -Wall12CFLAGS := -g -Wall
13 13
14# Try to detect best kernel BTF source14# Try to detect best kernel BTF source
tools/include/uapi/linux/bpf.h+1−1
@@ -1642,7 +1642,7 @@ union bpf_attr { · 1641 unmodified lines
1642 * ifindex, but doesn't require a map to do so.1642 * ifindex, but doesn't require a map to do so.
1643 * Return1643 * Return
1644 * **XDP_REDIRECT** on success, or the value of the two lower bits1644 * **XDP_REDIRECT** on success, or the value of the two lower bits
1645 * of the **flags* argument on error.1645 * of the *flags* argument on error.
1646 *1646 *
1647 * int bpf_sk_redirect_map(struct sk_buff *skb, struct bpf_map *map, u32 key, u64 flags)1647 * int bpf_sk_redirect_map(struct sk_buff *skb, struct bpf_map *map, u32 key, u64 flags)
1648 * Description1648 * Description
tools/lib/bpf/netlink.c+2−0
@@ -321,6 +321,8 @@ int bpf_get_link_xdp_info(int ifindex, struct xdp_link_info *info, · 320 unmodified lines
321 321
322static __u32 get_xdp_id(struct xdp_link_info *info, __u32 flags)322static __u32 get_xdp_id(struct xdp_link_info *info, __u32 flags)
323{323{
324 flags &= XDP_FLAGS_MODES;
325
324 if (info->attach_mode != XDP_ATTACHED_MULTI && !flags)326 if (info->attach_mode != XDP_ATTACHED_MULTI && !flags)
325 return info->prog_id;327 return info->prog_id;
326 if (flags & XDP_FLAGS_DRV_MODE)328 if (flags & XDP_FLAGS_DRV_MODE)
tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c+24−6
@@ -5,7 +5,8 @@ · 4 unmodified lines
5static void test_fexit_bpf2bpf_common(const char *obj_file,5static void test_fexit_bpf2bpf_common(const char *obj_file,
6 const char *target_obj_file,6 const char *target_obj_file,
7 int prog_cnt,7 int prog_cnt,
8 const char **prog_name)8 const char **prog_name,
9 bool run_prog)
9{10{
10 struct bpf_object *obj = NULL, *pkt_obj;11 struct bpf_object *obj = NULL, *pkt_obj;
11 int err, pkt_fd, i;12 int err, pkt_fd, i;
@@ -18,7 +19,8 @@ static void test_fexit_bpf2bpf_common(const char *obj_file, · 6 unmodified lines
18 19
19 err = bpf_prog_load(target_obj_file, BPF_PROG_TYPE_UNSPEC,20 err = bpf_prog_load(target_obj_file, BPF_PROG_TYPE_UNSPEC,
20 &pkt_obj, &pkt_fd);21 &pkt_obj, &pkt_fd);
21 if (CHECK(err, "prog_load sched cls", "err %d errno %d\n", err, errno))22 if (CHECK(err, "tgt_prog_load", "file %s err %d errno %d\n",
23 target_obj_file, err, errno))
22 return;24 return;
23 DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts,25 DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts,
24 .attach_prog_fd = pkt_fd,26 .attach_prog_fd = pkt_fd,
@@ -33,7 +35,7 @@ static void test_fexit_bpf2bpf_common(const char *obj_file, · 8 unmodified lines
33 35
34 obj = bpf_object__open_file(obj_file, &opts);36 obj = bpf_object__open_file(obj_file, &opts);
35 if (CHECK(IS_ERR_OR_NULL(obj), "obj_open",37 if (CHECK(IS_ERR_OR_NULL(obj), "obj_open",
36 "failed to open fexit_bpf2bpf: %ld\n",38 "failed to open %s: %ld\n", obj_file,
37 PTR_ERR(obj)))39 PTR_ERR(obj)))
38 goto close_prog;40 goto close_prog;
39 41
@@ -49,6 +51,10 @@ static void test_fexit_bpf2bpf_common(const char *obj_file, · 9 unmodified lines
49 if (CHECK(IS_ERR(link[i]), "attach_trace", "failed to link\n"))51 if (CHECK(IS_ERR(link[i]), "attach_trace", "failed to link\n"))
50 goto close_prog;52 goto close_prog;
51 }53 }
54
55 if (!run_prog)
56 goto close_prog;
57
52 data_map = bpf_object__find_map_by_name(obj, "fexit_bp.bss");58 data_map = bpf_object__find_map_by_name(obj, "fexit_bp.bss");
53 if (CHECK(!data_map, "find_data_map", "data map not found\n"))59 if (CHECK(!data_map, "find_data_map", "data map not found\n"))
54 goto close_prog;60 goto close_prog;
@@ -89,7 +95,7 @@ static void test_target_no_callees(void) · 34 unmodified lines
89 test_fexit_bpf2bpf_common("./fexit_bpf2bpf_simple.o",95 test_fexit_bpf2bpf_common("./fexit_bpf2bpf_simple.o",
90 "./test_pkt_md_access.o",96 "./test_pkt_md_access.o",
91 ARRAY_SIZE(prog_name),97 ARRAY_SIZE(prog_name),
92 prog_name);98 prog_name, true);
93}99}
94 100
95static void test_target_yes_callees(void)101static void test_target_yes_callees(void)
@@ -103,7 +109,7 @@ static void test_target_yes_callees(void) · 7 unmodified lines
103 test_fexit_bpf2bpf_common("./fexit_bpf2bpf.o",109 test_fexit_bpf2bpf_common("./fexit_bpf2bpf.o",
104 "./test_pkt_access.o",110 "./test_pkt_access.o",
105 ARRAY_SIZE(prog_name),111 ARRAY_SIZE(prog_name),
106 prog_name);112 prog_name, true);
107}113}
108 114
109static void test_func_replace(void)115static void test_func_replace(void)
@@ -120,7 +126,18 @@ static void test_func_replace(void) · 10 unmodified lines
120 test_fexit_bpf2bpf_common("./fexit_bpf2bpf.o",126 test_fexit_bpf2bpf_common("./fexit_bpf2bpf.o",
121 "./test_pkt_access.o",127 "./test_pkt_access.o",
122 ARRAY_SIZE(prog_name),128 ARRAY_SIZE(prog_name),
123 prog_name);129 prog_name, true);
130}
131
132static void test_func_replace_verify(void)
133{
134 const char *prog_name[] = {
135 "freplace/do_bind",
136 };
137 test_fexit_bpf2bpf_common("./freplace_connect4.o",
138 "./connect4_prog.o",
139 ARRAY_SIZE(prog_name),
140 prog_name, false);
124}141}
125 142
126void test_fexit_bpf2bpf(void)143void test_fexit_bpf2bpf(void)
@@ -128,4 +145,5 @@ void test_fexit_bpf2bpf(void) · 1 unmodified line
128 test_target_no_callees();145 test_target_no_callees();
129 test_target_yes_callees();146 test_target_yes_callees();
130 test_func_replace();147 test_func_replace();
148 test_func_replace_verify();
131}149}
tools/testing/selftests/bpf/progs/connect4_prog.c+16−12
@@ -18,11 +18,25 @@ · 17 unmodified lines
18 18
19int _version SEC("version") = 1;19int _version SEC("version") = 1;
20 20
21__attribute__ ((noinline))
22int do_bind(struct bpf_sock_addr *ctx)
23{
24 struct sockaddr_in sa = {};
25
26 sa.sin_family = AF_INET;
27 sa.sin_port = bpf_htons(0);
28 sa.sin_addr.s_addr = bpf_htonl(SRC_REWRITE_IP4);
29
30 if (bpf_bind(ctx, (struct sockaddr *)&sa, sizeof(sa)) != 0)
31 return 0;
32
33 return 1;
34}
35
21SEC("cgroup/connect4")36SEC("cgroup/connect4")
22int connect_v4_prog(struct bpf_sock_addr *ctx)37int connect_v4_prog(struct bpf_sock_addr *ctx)
23{38{
24 struct bpf_sock_tuple tuple = {};39 struct bpf_sock_tuple tuple = {};
25 struct sockaddr_in sa;
26 struct bpf_sock *sk;40 struct bpf_sock *sk;
27 41
28 /* Verify that new destination is available. */42 /* Verify that new destination is available. */
@@ -56,17 +70,7 @@ int connect_v4_prog(struct bpf_sock_addr *ctx) · 27 unmodified lines
56 ctx->user_ip4 = bpf_htonl(DST_REWRITE_IP4);70 ctx->user_ip4 = bpf_htonl(DST_REWRITE_IP4);
57 ctx->user_port = bpf_htons(DST_REWRITE_PORT4);71 ctx->user_port = bpf_htons(DST_REWRITE_PORT4);
58 72
59 /* Rewrite source. */73 return do_bind(ctx) ? 1 : 0;
60 memset(&sa, 0, sizeof(sa));
61
62 sa.sin_family = AF_INET;
63 sa.sin_port = bpf_htons(0);
64 sa.sin_addr.s_addr = bpf_htonl(SRC_REWRITE_IP4);
65
66 if (bpf_bind(ctx, (struct sockaddr *)&sa, sizeof(sa)) != 0)
67 return 0;
68
69 return 1;
70}74}
71 75
72char _license[] SEC("license") = "GPL";76char _license[] SEC("license") = "GPL";
tools/testing/selftests/bpf/progs/freplace_connect4.c+18−0
@@ -0,0 +1,18 @@
1#include <linux/stddef.h>
2#include <linux/ipv6.h>
3#include <linux/bpf.h>
4#include <linux/in.h>
5#include <sys/socket.h>
6#include <bpf/bpf_helpers.h>
7#include <bpf/bpf_endian.h>
8
9SEC("freplace/do_bind")
10int new_do_bind(struct bpf_sock_addr *ctx)
11{
12 struct sockaddr_in sa = {};
13
14 bpf_bind(ctx, (struct sockaddr *)&sa, sizeof(sa));
15 return 0;
16}
17
18char _license[] SEC("license") = "GPL";
tools/testing/selftests/bpf/progs/test_btf_haskv.c+5−13
@@ -20,20 +20,12 @@ struct bpf_map_def SEC("maps") btf_map = { · 19 unmodified lines
20 20
21BPF_ANNOTATE_KV_PAIR(btf_map, int, struct ipv_counts);21BPF_ANNOTATE_KV_PAIR(btf_map, int, struct ipv_counts);
22 22
23struct dummy_tracepoint_args {
24 unsigned long long pad;
25 struct sock *sock;
26};
27
28__attribute__((noinline))23__attribute__((noinline))
29int test_long_fname_2(struct dummy_tracepoint_args *arg)24int test_long_fname_2(void)
30{25{
31 struct ipv_counts *counts;26 struct ipv_counts *counts;
32 int key = 0;27 int key = 0;
33 28
34 if (!arg->sock)
35 return 0;
36
37 counts = bpf_map_lookup_elem(&btf_map, &key);29 counts = bpf_map_lookup_elem(&btf_map, &key);
38 if (!counts)30 if (!counts)
39 return 0;31 return 0;
@@ -44,15 +36,15 @@ int test_long_fname_2(struct dummy_tracepoint_args *arg) · 4 unmodified lines
44}36}
45 37
46__attribute__((noinline))38__attribute__((noinline))
47int test_long_fname_1(struct dummy_tracepoint_args *arg)39int test_long_fname_1(void)
48{40{
49 return test_long_fname_2(arg);41 return test_long_fname_2();
50}42}
51 43
52SEC("dummy_tracepoint")44SEC("dummy_tracepoint")
53int _dummy_tracepoint(struct dummy_tracepoint_args *arg)45int _dummy_tracepoint(void *arg)
54{46{
55 return test_long_fname_1(arg);47 return test_long_fname_1();
56}48}
57 49
58char _license[] SEC("license") = "GPL";50char _license[] SEC("license") = "GPL";
tools/testing/selftests/bpf/progs/test_btf_newkv.c+5−13
@@ -28,20 +28,12 @@ struct { · 27 unmodified lines
28 __type(value, struct ipv_counts);28 __type(value, struct ipv_counts);
29} btf_map SEC(".maps");29} btf_map SEC(".maps");
30 30
31struct dummy_tracepoint_args {
32 unsigned long long pad;
33 struct sock *sock;
34};
35
36__attribute__((noinline))31__attribute__((noinline))
37int test_long_fname_2(struct dummy_tracepoint_args *arg)32int test_long_fname_2(void)
38{33{
39 struct ipv_counts *counts;34 struct ipv_counts *counts;
40 int key = 0;35 int key = 0;
41 36
42 if (!arg->sock)
43 return 0;
44
45 counts = bpf_map_lookup_elem(&btf_map, &key);37 counts = bpf_map_lookup_elem(&btf_map, &key);
46 if (!counts)38 if (!counts)
47 return 0;39 return 0;
@@ -57,15 +49,15 @@ int test_long_fname_2(struct dummy_tracepoint_args *arg) · 9 unmodified lines
57}49}
58 50
59__attribute__((noinline))51__attribute__((noinline))
60int test_long_fname_1(struct dummy_tracepoint_args *arg)52int test_long_fname_1(void)
61{53{
62 return test_long_fname_2(arg);54 return test_long_fname_2();
63}55}
64 56
65SEC("dummy_tracepoint")57SEC("dummy_tracepoint")
66int _dummy_tracepoint(struct dummy_tracepoint_args *arg)58int _dummy_tracepoint(void *arg)
67{59{
68 return test_long_fname_1(arg);60 return test_long_fname_1();
69}61}
70 62
71char _license[] SEC("license") = "GPL";63char _license[] SEC("license") = "GPL";
tools/testing/selftests/bpf/progs/test_btf_nokv.c+5−13
@@ -17,20 +17,12 @@ struct bpf_map_def SEC("maps") btf_map = { · 16 unmodified lines
17 .max_entries = 4,17 .max_entries = 4,
18};18};
19 19
20struct dummy_tracepoint_args {
21 unsigned long long pad;
22 struct sock *sock;
23};
24
25__attribute__((noinline))20__attribute__((noinline))
26int test_long_fname_2(struct dummy_tracepoint_args *arg)21int test_long_fname_2(void)
27{22{
28 struct ipv_counts *counts;23 struct ipv_counts *counts;
29 int key = 0;24 int key = 0;
30 25
31 if (!arg->sock)
32 return 0;
33
34 counts = bpf_map_lookup_elem(&btf_map, &key);26 counts = bpf_map_lookup_elem(&btf_map, &key);
35 if (!counts)27 if (!counts)
36 return 0;28 return 0;
@@ -41,15 +33,15 @@ int test_long_fname_2(struct dummy_tracepoint_args *arg) · 4 unmodified lines
41}33}
42 34
43__attribute__((noinline))35__attribute__((noinline))
44int test_long_fname_1(struct dummy_tracepoint_args *arg)36int test_long_fname_1(void)
45{37{
46 return test_long_fname_2(arg);38 return test_long_fname_2();
47}39}
48 40
49SEC("dummy_tracepoint")41SEC("dummy_tracepoint")
50int _dummy_tracepoint(struct dummy_tracepoint_args *arg)42int _dummy_tracepoint(void *arg)
51{43{
52 return test_long_fname_1(arg);44 return test_long_fname_1();
53}45}
54 46
55char _license[] SEC("license") = "GPL";47char _license[] SEC("license") = "GPL";
tools/testing/selftests/bpf/test_btf.c+1−1
@@ -2854,7 +2854,7 @@ static struct btf_raw_test raw_tests[] = { · 2853 unmodified lines
2854 .value_type_id = 1,2854 .value_type_id = 1,
2855 .max_entries = 4,2855 .max_entries = 4,
2856 .btf_load_err = true,2856 .btf_load_err = true,
2857 .err_str = "vlen != 0",2857 .err_str = "Invalid func linkage",
2858},2858},
2859 2859
2860{2860{
tools/testing/selftests/bpf/verifier/stack_ptr.c+40−0
@@ -315,3 +315,43 @@ · 314 unmodified lines
315 },315 },
316 .result = ACCEPT,316 .result = ACCEPT,
317},317},
318{
319 "store PTR_TO_STACK in R10 to array map using BPF_B",
320 .insns = {
321 /* Load pointer to map. */
322 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
323 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
324 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
325 BPF_LD_MAP_FD(BPF_REG_1, 0),
326 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
327 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2),
328 BPF_MOV64_IMM(BPF_REG_0, 2),
329 BPF_EXIT_INSN(),
330 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
331 /* Copy R10 to R9. */
332 BPF_MOV64_REG(BPF_REG_9, BPF_REG_10),
333 /* Pollute other registers with unaligned values. */
334 BPF_MOV64_IMM(BPF_REG_2, -1),
335 BPF_MOV64_IMM(BPF_REG_3, -1),
336 BPF_MOV64_IMM(BPF_REG_4, -1),
337 BPF_MOV64_IMM(BPF_REG_5, -1),
338 BPF_MOV64_IMM(BPF_REG_6, -1),
339 BPF_MOV64_IMM(BPF_REG_7, -1),
340 BPF_MOV64_IMM(BPF_REG_8, -1),
341 /* Store both R9 and R10 with BPF_B and read back. */
342 BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_10, 0),
343 BPF_LDX_MEM(BPF_B, BPF_REG_2, BPF_REG_1, 0),
344 BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_9, 0),
345 BPF_LDX_MEM(BPF_B, BPF_REG_3, BPF_REG_1, 0),
346 /* Should read back as same value. */
347 BPF_JMP_REG(BPF_JEQ, BPF_REG_2, BPF_REG_3, 2),
348 BPF_MOV64_IMM(BPF_REG_0, 1),
349 BPF_EXIT_INSN(),
350 BPF_MOV64_IMM(BPF_REG_0, 42),
351 BPF_EXIT_INSN(),
352 },
353 .fixup_map_array_48b = { 3 },
354 .result = ACCEPT,
355 .retval = 42,
356 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
357},
tools/testing/selftests/bpf/verifier/value_illegal_alu.c+1−0
@@ -88,6 +88,7 @@ · 87 unmodified lines
88 BPF_EXIT_INSN(),88 BPF_EXIT_INSN(),
89 },89 },
90 .fixup_map_hash_48b = { 3 },90 .fixup_map_hash_48b = { 3 },
91 .errstr_unpriv = "leaking pointer from stack off -8",
91 .errstr = "R0 invalid mem access 'inv'",92 .errstr = "R0 invalid mem access 'inv'",
92 .result = REJECT,93 .result = REJECT,
93 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,94 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,