Skip to content

Commit d08b419

Browse files
ameryhunggregkh
authored andcommitted
bpf: Support specifying linear xdp packet data size for BPF_PROG_TEST_RUN
[ Upstream commit fe9544e ] To test bpf_xdp_pull_data(), an xdp packet containing fragments as well as free linear data area after xdp->data_end needs to be created. However, bpf_prog_test_run_xdp() always fills the linear area with data_in before creating fragments, leaving no space to pull data. This patch will allow users to specify the linear data size through ctx->data_end. Currently, ctx_in->data_end must match data_size_in and will not be the final ctx->data_end seen by xdp programs. This is because ctx->data_end is populated according to the xdp_buff passed to test_run. The linear data area available in an xdp_buff, max_linear_sz, is alawys filled up before copying data_in into fragments. This patch will allow users to specify the size of data that goes into the linear area. When ctx_in->data_end is different from data_size_in, only ctx_in->data_end bytes of data will be put into the linear area when creating the xdp_buff. While ctx_in->data_end will be allowed to be different from data_size_in, it cannot be larger than the data_size_in as there will be no data to copy from user space. If it is larger than the maximum linear data area size, the layout suggested by the user will not be honored. Data beyond max_linear_sz bytes will still be copied into fragments. Finally, since it is possible for a NIC to produce a xdp_buff with empty linear data area, allow it when calling bpf_test_init() from bpf_prog_test_run_xdp() so that we can test XDP kfuncs with such xdp_buff. This is done by moving lower-bound check to callers as most of them already do except bpf_prog_test_run_skb(). The change also fixes a bug that allows passing an xdp_buff with data < ETH_HLEN. This can happen when ctx is used and metadata is at least ETH_HLEN. Signed-off-by: Amery Hung <ameryhung@gmail.com> Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org> Link: https://patch.msgid.link/20250922233356.3356453-7-ameryhung@gmail.com Stable-dep-of: e558cca21779 ("bpf, test_run: Subtract size of xdp_frame from allowed metadata size") Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 875d7cb commit d08b419

2 files changed

Lines changed: 13 additions & 6 deletions

File tree

net/bpf/test_run.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,7 @@ static void *bpf_test_init(const union bpf_attr *kattr, u32 user_size,
630630
void __user *data_in = u64_to_user_ptr(kattr->test.data_in);
631631
void *data;
632632

633-
if (user_size < ETH_HLEN || user_size > PAGE_SIZE - headroom - tailroom)
633+
if (user_size > PAGE_SIZE - headroom - tailroom)
634634
return ERR_PTR(-EINVAL);
635635

636636
size = SKB_DATA_ALIGN(size);
@@ -964,6 +964,9 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr,
964964
if (kattr->test.flags || kattr->test.cpu || kattr->test.batch_size)
965965
return -EINVAL;
966966

967+
if (size < ETH_HLEN)
968+
return -EINVAL;
969+
967970
data = bpf_test_init(kattr, kattr->test.data_size_in,
968971
size, NET_SKB_PAD + NET_IP_ALIGN,
969972
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)));
@@ -1144,7 +1147,7 @@ int bpf_prog_test_run_xdp(struct bpf_prog *prog, const union bpf_attr *kattr,
11441147
{
11451148
bool do_live = (kattr->test.flags & BPF_F_TEST_XDP_LIVE_FRAMES);
11461149
u32 tailroom = SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
1147-
u32 retval = 0, duration, max_linear_sz, size;
1150+
u32 retval = 0, meta_sz = 0, duration, max_linear_sz, size;
11481151
u32 linear_sz = kattr->test.data_size_in;
11491152
u32 batch_size = kattr->test.batch_size;
11501153
u32 headroom = XDP_PACKET_HEADROOM;
@@ -1183,13 +1186,16 @@ int bpf_prog_test_run_xdp(struct bpf_prog *prog, const union bpf_attr *kattr,
11831186

11841187
if (ctx) {
11851188
/* There can't be user provided data before the meta data */
1186-
if (ctx->data_meta || ctx->data_end != kattr->test.data_size_in ||
1189+
if (ctx->data_meta || ctx->data_end > kattr->test.data_size_in ||
11871190
ctx->data > ctx->data_end ||
11881191
unlikely(xdp_metalen_invalid(ctx->data)) ||
11891192
(do_live && (kattr->test.data_out || kattr->test.ctx_out)))
11901193
goto free_ctx;
11911194
/* Meta data is allocated from the headroom */
11921195
headroom -= ctx->data;
1196+
1197+
meta_sz = ctx->data;
1198+
linear_sz = ctx->data_end;
11931199
}
11941200

11951201
max_linear_sz = PAGE_SIZE - headroom - tailroom;
@@ -1199,6 +1205,9 @@ int bpf_prog_test_run_xdp(struct bpf_prog *prog, const union bpf_attr *kattr,
11991205
if (do_live && kattr->test.data_size_in > linear_sz)
12001206
goto free_ctx;
12011207

1208+
if (kattr->test.data_size_in - meta_sz < ETH_HLEN)
1209+
return -EINVAL;
1210+
12021211
data = bpf_test_init(kattr, linear_sz, max_linear_sz, headroom, tailroom);
12031212
if (IS_ERR(data)) {
12041213
ret = PTR_ERR(data);

tools/testing/selftests/bpf/prog_tests/xdp_context_test_run.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,7 @@ void test_xdp_context_test_run(void)
8080
/* Meta data must be 32 bytes or smaller */
8181
test_xdp_context_error(prog_fd, opts, 0, 36, sizeof(data), 0, 0, 0);
8282

83-
/* Total size of data must match data_end - data_meta */
84-
test_xdp_context_error(prog_fd, opts, 0, sizeof(__u32),
85-
sizeof(data) - 1, 0, 0, 0);
83+
/* Total size of data must be data_end - data_meta or larger */
8684
test_xdp_context_error(prog_fd, opts, 0, sizeof(__u32),
8785
sizeof(data) + 1, 0, 0, 0);
8886

0 commit comments

Comments
 (0)