Commit 94bbbdfb authored by Alexei Starovoitov's avatar Alexei Starovoitov
Browse files

Merge branch 'double-fix bpf_test_run + XDP_PASS recycling'



Alexander Lobakin says:

====================

Enabling skb PP recycling revealed a couple issues in the bpf_test_run
code. Recycling broke the assumption that the headroom won't ever be
touched during the test_run execution: xdp_scrub_frame() invalidates the
XDP frame at the headroom start, while neigh xmit code overwrites 2 bytes
to the left of the Ethernet header. The first makes the kernel panic in
certain cases, while the second breaks xdp_do_redirect selftest on BE.
test_run is a limited-scope entity, so let's hope no more corner cases
will happen here or at least they will be as easy and pleasant to fix
as those two.
====================

Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parents 082cdc69 5640b6d8
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -208,6 +208,16 @@ static void xdp_test_run_teardown(struct xdp_test_data *xdp)
	kfree(xdp->skbs);
}

static bool frame_was_changed(const struct xdp_page_head *head)
{
	/* xdp_scrub_frame() zeroes the data pointer, flags is the last field,
	 * i.e. has the highest chances to be overwritten. If those two are
	 * untouched, it's most likely safe to skip the context reset.
	 */
	return head->frm.data != head->orig_ctx.data ||
	       head->frm.flags != head->orig_ctx.flags;
}

static bool ctx_was_changed(struct xdp_page_head *head)
{
	return head->orig_ctx.data != head->ctx.data ||
@@ -217,7 +227,7 @@ static bool ctx_was_changed(struct xdp_page_head *head)

static void reset_ctx(struct xdp_page_head *head)
{
	if (likely(!ctx_was_changed(head)))
	if (likely(!frame_was_changed(head) && !ctx_was_changed(head)))
		return;

	head->ctx.data = head->orig_ctx.data;
+4 −3
Original line number Diff line number Diff line
@@ -86,12 +86,12 @@ static void test_max_pkt_size(int fd)
void test_xdp_do_redirect(void)
{
	int err, xdp_prog_fd, tc_prog_fd, ifindex_src, ifindex_dst;
	char data[sizeof(pkt_udp) + sizeof(__u32)];
	char data[sizeof(pkt_udp) + sizeof(__u64)];
	struct test_xdp_do_redirect *skel = NULL;
	struct nstoken *nstoken = NULL;
	struct bpf_link *link;
	LIBBPF_OPTS(bpf_xdp_query_opts, query_opts);
	struct xdp_md ctx_in = { .data = sizeof(__u32),
	struct xdp_md ctx_in = { .data = sizeof(__u64),
				 .data_end = sizeof(data) };
	DECLARE_LIBBPF_OPTS(bpf_test_run_opts, opts,
			    .data_in = &data,
@@ -105,8 +105,9 @@ void test_xdp_do_redirect(void)
	DECLARE_LIBBPF_OPTS(bpf_tc_hook, tc_hook,
			    .attach_point = BPF_TC_INGRESS);

	memcpy(&data[sizeof(__u32)], &pkt_udp, sizeof(pkt_udp));
	memcpy(&data[sizeof(__u64)], &pkt_udp, sizeof(pkt_udp));
	*((__u32 *)data) = 0x42; /* metadata test value */
	*((__u32 *)data + 4) = 0;

	skel = test_xdp_do_redirect__open();
	if (!ASSERT_OK_PTR(skel, "skel"))
+1 −1
Original line number Diff line number Diff line
@@ -52,7 +52,7 @@ int xdp_redirect(struct xdp_md *xdp)

	*payload = MARK_IN;

	if (bpf_xdp_adjust_meta(xdp, 4))
	if (bpf_xdp_adjust_meta(xdp, sizeof(__u64)))
		return XDP_ABORTED;

	if (retcode > XDP_PASS)