On Wed, Apr 12, 2023 at 2:50 PM Andrii Nakryiko <andrii.nakryiko@xxxxxxxxx> wrote: > > 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? i think combining it gets confusing in the case where ptr->data is null, as to how the invoked places interpret the return value. I think having the check spelled out more explicitly in the invoked places (eg bpf_dynptr_write, bpf_dynptr_data, ...) makes it more clear as well where the check for null is happening. for v2 I will leave this as is, but also happy to change it if you prefer the two be combined > > 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 > >