On Sat, Apr 8, 2023 at 8:34 PM Joanne Koong <joannelkoong@xxxxxxxxx> wrote: > > bpf_dynptr_is_null returns true if the dynptr is null / invalid > (determined by whether ptr->data is NULL), else false if > the dynptr is a valid dynptr. > > bpf_dynptr_is_rdonly returns true if the dynptr is read-only, > else false if the dynptr is read-writable. > > Signed-off-by: Joanne Koong <joannelkoong@xxxxxxxxx> > --- > kernel/bpf/helpers.c | 23 +++++++++++++++++++---- > 1 file changed, 19 insertions(+), 4 deletions(-) > > diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c > index 51b4c4b5dbed..e4e84e92a4c6 100644 > --- a/kernel/bpf/helpers.c > +++ b/kernel/bpf/helpers.c > @@ -1423,7 +1423,7 @@ static const struct bpf_func_proto bpf_kptr_xchg_proto = { > #define DYNPTR_SIZE_MASK 0xFFFFFF > #define DYNPTR_RDONLY_BIT BIT(31) > > -static bool bpf_dynptr_is_rdonly(const struct bpf_dynptr_kern *ptr) > +static bool __bpf_dynptr_is_rdonly(const struct bpf_dynptr_kern *ptr) > { > return ptr->size & DYNPTR_RDONLY_BIT; > } > @@ -1570,7 +1570,7 @@ BPF_CALL_5(bpf_dynptr_write, const struct bpf_dynptr_kern *, dst, u32, offset, v > enum bpf_dynptr_type type; > int err; > > - if (!dst->data || bpf_dynptr_is_rdonly(dst)) > + if (!dst->data || __bpf_dynptr_is_rdonly(dst)) > return -EINVAL; > > err = bpf_dynptr_check_off_len(dst, offset, len); > @@ -1626,7 +1626,7 @@ BPF_CALL_3(bpf_dynptr_data, const struct bpf_dynptr_kern *, ptr, u32, offset, u3 > if (err) > return 0; > > - if (bpf_dynptr_is_rdonly(ptr)) > + if (__bpf_dynptr_is_rdonly(ptr)) > return 0; > > type = bpf_dynptr_get_type(ptr); > @@ -2254,7 +2254,7 @@ __bpf_kfunc void *bpf_dynptr_slice(const struct bpf_dynptr_kern *ptr, u32 offset > __bpf_kfunc void *bpf_dynptr_slice_rdwr(const struct bpf_dynptr_kern *ptr, u32 offset, > void *buffer, u32 buffer__szk) > { > - if (!ptr->data || bpf_dynptr_is_rdonly(ptr)) > + if (!ptr->data || __bpf_dynptr_is_rdonly(ptr)) seems like all the uses of __bpf_dynptr_is_rdonly check !ptr->data explicitly, so maybe move that ptr->data check inside and simplify all the callers? Regardless, looks good: Acked-by: Andrii Nakryiko <andrii@xxxxxxxxxx> > return NULL; > > /* bpf_dynptr_slice_rdwr is the same logic as bpf_dynptr_slice. > @@ -2322,6 +2322,19 @@ __bpf_kfunc int bpf_dynptr_trim(struct bpf_dynptr_kern *ptr, u32 len) > return bpf_dynptr_adjust(ptr, 0, len); > } > > +__bpf_kfunc bool bpf_dynptr_is_null(struct bpf_dynptr_kern *ptr) > +{ > + return !ptr->data; > +} > + > +__bpf_kfunc bool bpf_dynptr_is_rdonly(struct bpf_dynptr_kern *ptr) > +{ > + if (!ptr->data) > + return false; > + > + return __bpf_dynptr_is_rdonly(ptr); > +} > + > __bpf_kfunc void *bpf_cast_to_kern_ctx(void *obj) > { > return obj; > @@ -2396,6 +2409,8 @@ BTF_ID_FLAGS(func, bpf_iter_num_next, KF_ITER_NEXT | KF_RET_NULL) > BTF_ID_FLAGS(func, bpf_iter_num_destroy, KF_ITER_DESTROY) > BTF_ID_FLAGS(func, bpf_dynptr_trim) > BTF_ID_FLAGS(func, bpf_dynptr_advance) > +BTF_ID_FLAGS(func, bpf_dynptr_is_null) > +BTF_ID_FLAGS(func, bpf_dynptr_is_rdonly) > BTF_SET8_END(common_btf_ids) > > static const struct btf_kfunc_id_set common_kfunc_set = { > -- > 2.34.1 >