Skip to content

Commit e558cca

Browse files
tohojoAlexei Starovoitov
authored andcommitted
bpf, test_run: Subtract size of xdp_frame from allowed metadata size
The xdp_frame structure takes up part of the XDP frame headroom, limiting the size of the metadata. However, in bpf_test_run, we don't take this into account, which makes it possible for userspace to supply a metadata size that is too large (taking up the entire headroom). If userspace supplies such a large metadata size in live packet mode, the xdp_update_frame_from_buff() call in xdp_test_run_init_page() call will fail, after which packet transmission proceeds with an uninitialised frame structure, leading to the usual Bad Stuff. The commit in the Fixes tag fixed a related bug where the second check in xdp_update_frame_from_buff() could fail, but did not add any additional constraints on the metadata size. Complete the fix by adding an additional check on the metadata size. Reorder the checks slightly to make the logic clearer and add a comment. Link: https://lore.kernel.org/r/[email protected] Fixes: b6f1f78 ("bpf, test_run: Fix packet size check for live packet mode") Reported-by: Yinhao Hu <[email protected]> Reported-by: Kaiyan Mei <[email protected]> Signed-off-by: Toke Høiland-Jørgensen <[email protected]> Reviewed-by: Amery Hung <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 8f3e00a commit e558cca

1 file changed

Lines changed: 13 additions & 5 deletions

File tree

net/bpf/test_run.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,8 +1294,6 @@ int bpf_prog_test_run_xdp(struct bpf_prog *prog, const union bpf_attr *kattr,
12941294
batch_size = NAPI_POLL_WEIGHT;
12951295
else if (batch_size > TEST_XDP_MAX_BATCH)
12961296
return -E2BIG;
1297-
1298-
headroom += sizeof(struct xdp_page_head);
12991297
} else if (batch_size) {
13001298
return -EINVAL;
13011299
}
@@ -1308,16 +1306,26 @@ int bpf_prog_test_run_xdp(struct bpf_prog *prog, const union bpf_attr *kattr,
13081306
/* There can't be user provided data before the meta data */
13091307
if (ctx->data_meta || ctx->data_end > kattr->test.data_size_in ||
13101308
ctx->data > ctx->data_end ||
1311-
unlikely(xdp_metalen_invalid(ctx->data)) ||
13121309
(do_live && (kattr->test.data_out || kattr->test.ctx_out)))
13131310
goto free_ctx;
1314-
/* Meta data is allocated from the headroom */
1315-
headroom -= ctx->data;
13161311

13171312
meta_sz = ctx->data;
1313+
if (xdp_metalen_invalid(meta_sz) || meta_sz > headroom - sizeof(struct xdp_frame))
1314+
goto free_ctx;
1315+
1316+
/* Meta data is allocated from the headroom */
1317+
headroom -= meta_sz;
13181318
linear_sz = ctx->data_end;
13191319
}
13201320

1321+
/* The xdp_page_head structure takes up space in each page, limiting the
1322+
* size of the packet data; add the extra size to headroom here to make
1323+
* sure it's accounted in the length checks below, but not in the
1324+
* metadata size check above.
1325+
*/
1326+
if (do_live)
1327+
headroom += sizeof(struct xdp_page_head);
1328+
13211329
max_linear_sz = PAGE_SIZE - headroom - tailroom;
13221330
linear_sz = min_t(u32, linear_sz, max_linear_sz);
13231331

0 commit comments

Comments
 (0)