On Wed, Jul 24, 2019 at 10:11 AM Stanislav Fomichev <sdf@xxxxxxxxxx> wrote: > > This will allow us to write tests for those flags. > > Cc: Willem de Bruijn <willemb@xxxxxxxxxx> > Cc: Petar Penkov <ppenkov@xxxxxxxxxx> > Signed-off-by: Stanislav Fomichev <sdf@xxxxxxxxxx> Acked-by: Song Liu <songliubraving@xxxxxx> > --- > net/bpf/test_run.c | 39 +++++++++++++++++++++++++++++++++++---- > 1 file changed, 35 insertions(+), 4 deletions(-) > > diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c > index 4e41d15a1098..444a7baed791 100644 > --- a/net/bpf/test_run.c > +++ b/net/bpf/test_run.c > @@ -377,6 +377,22 @@ int bpf_prog_test_run_xdp(struct bpf_prog *prog, const union bpf_attr *kattr, > return ret; > } > > +static int verify_user_bpf_flow_keys(struct bpf_flow_keys *ctx) > +{ > + /* make sure the fields we don't use are zeroed */ > + if (!range_is_zero(ctx, 0, offsetof(struct bpf_flow_keys, flags))) > + return -EINVAL; > + > + /* flags is allowed */ > + > + if (!range_is_zero(ctx, offsetof(struct bpf_flow_keys, flags) + > + FIELD_SIZEOF(struct bpf_flow_keys, flags), > + sizeof(struct bpf_flow_keys))) > + return -EINVAL; > + > + return 0; > +} > + > int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog, > const union bpf_attr *kattr, > union bpf_attr __user *uattr) > @@ -384,9 +400,11 @@ int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog, > u32 size = kattr->test.data_size_in; > struct bpf_flow_dissector ctx = {}; > u32 repeat = kattr->test.repeat; > + struct bpf_flow_keys *user_ctx; > struct bpf_flow_keys flow_keys; > u64 time_start, time_spent = 0; > const struct ethhdr *eth; > + unsigned int flags = 0; > u32 retval, duration; > void *data; > int ret; > @@ -395,9 +413,6 @@ int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog, > if (prog->type != BPF_PROG_TYPE_FLOW_DISSECTOR) > return -EINVAL; > > - if (kattr->test.ctx_in || kattr->test.ctx_out) > - return -EINVAL; > - > if (size < ETH_HLEN) > return -EINVAL; > > @@ -410,6 +425,18 @@ int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog, > if (!repeat) > repeat = 1; > > + user_ctx = bpf_ctx_init(kattr, sizeof(struct bpf_flow_keys)); > + if (IS_ERR(user_ctx)) { > + kfree(data); > + return PTR_ERR(user_ctx); > + } > + if (user_ctx) { > + ret = verify_user_bpf_flow_keys(user_ctx); > + if (ret) > + goto out; > + flags = user_ctx->flags; > + } > + > ctx.flow_keys = &flow_keys; > ctx.data = data; > ctx.data_end = (__u8 *)data + size; > @@ -419,7 +446,7 @@ int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog, > time_start = ktime_get_ns(); > for (i = 0; i < repeat; i++) { > retval = bpf_flow_dissect(prog, &ctx, eth->h_proto, ETH_HLEN, > - size, 0); > + size, flags); > > if (signal_pending(current)) { > preempt_enable(); > @@ -450,8 +477,12 @@ int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog, > > ret = bpf_test_finish(kattr, uattr, &flow_keys, sizeof(flow_keys), > retval, duration); > + if (!ret) > + ret = bpf_ctx_finish(kattr, uattr, user_ctx, > + sizeof(struct bpf_flow_keys)); > > out: > kfree(data); > + kfree(user_ctx); nit: it is not really necessary now, but maybe put kfree(user_ctx) before kfree(data). > return ret; > } > -- > 2.22.0.657.g960e92d24f-goog >