Skip to content

Commit

Permalink
bpf: Use btf_kfunc_id_set.remap logic for bpf_dynptr_from_skb
Browse files Browse the repository at this point in the history
btf_kfunc_id_set.remap can pick proper version of a kfunc for the calling
context. Use this logic to select bpf_dynptr_from_skb or
bpf_dynptr_from_skb_rdonly. This will make the verifier simpler.

Unfortunately, btf_kfunc_id_set.remap cannot cover the DYNPTR_TYPE_SKB
logic in check_kfunc_args(). This can be addressed later.

Signed-off-by: Song Liu <song@kernel.org>
  • Loading branch information
liu-song-6 authored and Kernel Patches Daemon committed Jan 16, 2025
1 parent 83b8a67 commit e4dac21
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 23 deletions.
25 changes: 6 additions & 19 deletions kernel/bpf/verifier.c
Original file line number Diff line number Diff line change
Expand Up @@ -11677,6 +11677,7 @@ enum special_kfunc_type {
KF_bpf_rbtree_add_impl,
KF_bpf_rbtree_first,
KF_bpf_dynptr_from_skb,
KF_bpf_dynptr_from_skb_rdonly,
KF_bpf_dynptr_from_xdp,
KF_bpf_dynptr_slice,
KF_bpf_dynptr_slice_rdwr,
Expand Down Expand Up @@ -11712,6 +11713,7 @@ BTF_ID(func, bpf_rbtree_add_impl)
BTF_ID(func, bpf_rbtree_first)
#ifdef CONFIG_NET
BTF_ID(func, bpf_dynptr_from_skb)
BTF_ID(func, bpf_dynptr_from_skb_rdonly)
BTF_ID(func, bpf_dynptr_from_xdp)
#endif
BTF_ID(func, bpf_dynptr_slice)
Expand Down Expand Up @@ -11743,10 +11745,12 @@ BTF_ID(func, bpf_rbtree_add_impl)
BTF_ID(func, bpf_rbtree_first)
#ifdef CONFIG_NET
BTF_ID(func, bpf_dynptr_from_skb)
BTF_ID(func, bpf_dynptr_from_skb_rdonly)
BTF_ID(func, bpf_dynptr_from_xdp)
#else
BTF_ID_UNUSED
BTF_ID_UNUSED
BTF_ID_UNUSED
#endif
BTF_ID(func, bpf_dynptr_slice)
BTF_ID(func, bpf_dynptr_slice_rdwr)
Expand Down Expand Up @@ -12668,7 +12672,8 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
if (is_kfunc_arg_uninit(btf, &args[i]))
dynptr_arg_type |= MEM_UNINIT;

if (meta->func_id == special_kfunc_list[KF_bpf_dynptr_from_skb]) {
if (meta->func_id == special_kfunc_list[KF_bpf_dynptr_from_skb] ||
meta->func_id == special_kfunc_list[KF_bpf_dynptr_from_skb_rdonly]) {
dynptr_arg_type |= DYNPTR_TYPE_SKB;
} else if (meta->func_id == special_kfunc_list[KF_bpf_dynptr_from_xdp]) {
dynptr_arg_type |= DYNPTR_TYPE_XDP;
Expand Down Expand Up @@ -20821,9 +20826,7 @@ static void specialize_kfunc(struct bpf_verifier_env *env,
u32 func_id, u16 offset, unsigned long *addr)
{
struct bpf_prog *prog = env->prog;
bool seen_direct_write;
void *xdp_kfunc;
bool is_rdonly;

if (bpf_dev_bound_kfunc_id(func_id)) {
xdp_kfunc = bpf_dev_bound_resolve_kfunc(prog, func_id);
Expand All @@ -20833,22 +20836,6 @@ static void specialize_kfunc(struct bpf_verifier_env *env,
}
/* fallback to default kfunc when not supported by netdev */
}

if (offset)
return;

if (func_id == special_kfunc_list[KF_bpf_dynptr_from_skb]) {
seen_direct_write = env->seen_direct_write;
is_rdonly = !may_access_direct_pkt_data(env, NULL, BPF_WRITE);

if (is_rdonly)
*addr = (unsigned long)bpf_dynptr_from_skb_rdonly;

/* restore env->seen_direct_write to its original value, since
* may_access_direct_pkt_data mutates it
*/
env->seen_direct_write = seen_direct_write;
}
}

static void __fixup_collection_insert_kfunc(struct bpf_insn_aux_data *insn_aux,
Expand Down
49 changes: 45 additions & 4 deletions net/core/filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -12047,10 +12047,8 @@ __bpf_kfunc int bpf_sk_assign_tcp_reqsk(struct __sk_buff *s, struct sock *sk,
#endif
}

__bpf_kfunc_end_defs();

int bpf_dynptr_from_skb_rdonly(struct __sk_buff *skb, u64 flags,
struct bpf_dynptr *ptr__uninit)
__bpf_kfunc int bpf_dynptr_from_skb_rdonly(struct __sk_buff *skb, u64 flags,
struct bpf_dynptr *ptr__uninit)
{
struct bpf_dynptr_kern *ptr = (struct bpf_dynptr_kern *)ptr__uninit;
int err;
Expand All @@ -12064,10 +12062,16 @@ int bpf_dynptr_from_skb_rdonly(struct __sk_buff *skb, u64 flags,
return 0;
}

__bpf_kfunc_end_defs();

BTF_KFUNCS_START(bpf_kfunc_check_set_skb)
BTF_ID_FLAGS(func, bpf_dynptr_from_skb, KF_TRUSTED_ARGS)
BTF_KFUNCS_END(bpf_kfunc_check_set_skb)

BTF_HIDDEN_KFUNCS_START(bpf_kfunc_check_hidden_set_skb)
BTF_ID_FLAGS(func, bpf_dynptr_from_skb_rdonly, KF_TRUSTED_ARGS)
BTF_KFUNCS_END(bpf_kfunc_check_hidden_set_skb)

BTF_KFUNCS_START(bpf_kfunc_check_set_xdp)
BTF_ID_FLAGS(func, bpf_dynptr_from_xdp)
BTF_KFUNCS_END(bpf_kfunc_check_set_xdp)
Expand All @@ -12080,9 +12084,46 @@ BTF_KFUNCS_START(bpf_kfunc_check_set_tcp_reqsk)
BTF_ID_FLAGS(func, bpf_sk_assign_tcp_reqsk, KF_TRUSTED_ARGS)
BTF_KFUNCS_END(bpf_kfunc_check_set_tcp_reqsk)

BTF_ID_LIST(bpf_dynptr_from_skb_list)
BTF_ID(func, bpf_dynptr_from_skb)
BTF_ID(func, bpf_dynptr_from_skb_rdonly)

static u32 bpf_kfunc_set_skb_remap(const struct bpf_prog *prog, u32 kfunc_id)
{
if (kfunc_id != bpf_dynptr_from_skb_list[0])
return 0;

switch (resolve_prog_type(prog)) {
/* Program types only with direct read access go here! */
case BPF_PROG_TYPE_LWT_IN:
case BPF_PROG_TYPE_LWT_OUT:
case BPF_PROG_TYPE_LWT_SEG6LOCAL:
case BPF_PROG_TYPE_SK_REUSEPORT:
case BPF_PROG_TYPE_FLOW_DISSECTOR:
case BPF_PROG_TYPE_CGROUP_SKB:
return bpf_dynptr_from_skb_list[1];

/* Program types with direct read + write access go here! */
case BPF_PROG_TYPE_SCHED_CLS:
case BPF_PROG_TYPE_SCHED_ACT:
case BPF_PROG_TYPE_XDP:
case BPF_PROG_TYPE_LWT_XMIT:
case BPF_PROG_TYPE_SK_SKB:
case BPF_PROG_TYPE_SK_MSG:
case BPF_PROG_TYPE_CGROUP_SOCKOPT:
return kfunc_id;

default:
break;
}
return bpf_dynptr_from_skb_list[1];
}

static const struct btf_kfunc_id_set bpf_kfunc_set_skb = {
.owner = THIS_MODULE,
.set = &bpf_kfunc_check_set_skb,
.hidden_set = &bpf_kfunc_check_hidden_set_skb,
.remap = &bpf_kfunc_set_skb_remap,
};

static const struct btf_kfunc_id_set bpf_kfunc_set_xdp = {
Expand Down

0 comments on commit e4dac21

Please sign in to comment.