Commit 62d02fca authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files
Martin KaFai Lau says:

====================
pull-request: bpf 2023-08-09

We've added 5 non-merge commits during the last 7 day(s) which contain
a total of 6 files changed, 102 insertions(+), 8 deletions(-).

The main changes are:

1) A bpf sockmap memleak fix and a fix in accessing the programs of
   a sockmap under the incorrect map type from Xu Kuohai.

2) A refcount underflow fix in xsk from Magnus Karlsson.

* tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf:
  selftests/bpf: Add sockmap test for redirecting partial skb data
  selftests/bpf: fix a CI failure caused by vsock sockmap test
  bpf, sockmap: Fix bug that strp_done cannot be called
  bpf, sockmap: Fix map type error in sock_map_del_link
  xsk: fix refcount underflow in error path
====================

Link: https://lore.kernel.org/r/20230810055303.120917-1-martin.lau@linux.dev


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 6db541ae b734f02c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ struct sk_psock_progs {

enum sk_psock_state_bits {
	SK_PSOCK_TX_ENABLED,
	SK_PSOCK_RX_STRP_ENABLED,
};

struct sk_psock_link {
+8 −2
Original line number Diff line number Diff line
@@ -1120,13 +1120,19 @@ static void sk_psock_strp_data_ready(struct sock *sk)

int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock)
{
	int ret;

	static const struct strp_callbacks cb = {
		.rcv_msg	= sk_psock_strp_read,
		.read_sock_done	= sk_psock_strp_read_done,
		.parse_msg	= sk_psock_strp_parse,
	};

	return strp_init(&psock->strp, sk, &cb);
	ret = strp_init(&psock->strp, sk, &cb);
	if (!ret)
		sk_psock_set_state(psock, SK_PSOCK_RX_STRP_ENABLED);

	return ret;
}

void sk_psock_start_strp(struct sock *sk, struct sk_psock *psock)
@@ -1154,7 +1160,7 @@ void sk_psock_stop_strp(struct sock *sk, struct sk_psock *psock)
static void sk_psock_done_strp(struct sk_psock *psock)
{
	/* Parser has been stopped */
	if (psock->progs.stream_parser)
	if (sk_psock_test_state(psock, SK_PSOCK_RX_STRP_ENABLED))
		strp_done(&psock->strp);
}
#else
+5 −5
Original line number Diff line number Diff line
@@ -146,13 +146,13 @@ static void sock_map_del_link(struct sock *sk,
	list_for_each_entry_safe(link, tmp, &psock->link, list) {
		if (link->link_raw == link_raw) {
			struct bpf_map *map = link->map;
			struct bpf_stab *stab = container_of(map, struct bpf_stab,
							     map);
			if (psock->saved_data_ready && stab->progs.stream_parser)
			struct sk_psock_progs *progs = sock_map_progs(map);

			if (psock->saved_data_ready && progs->stream_parser)
				strp_stop = true;
			if (psock->saved_data_ready && stab->progs.stream_verdict)
			if (psock->saved_data_ready && progs->stream_verdict)
				verdict_stop = true;
			if (psock->saved_data_ready && stab->progs.skb_verdict)
			if (psock->saved_data_ready && progs->skb_verdict)
				verdict_stop = true;
			list_del(&link->list);
			sk_psock_free_link(link);
+1 −0
Original line number Diff line number Diff line
@@ -994,6 +994,7 @@ static int xsk_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
				err = xp_alloc_tx_descs(xs->pool, xs);
				if (err) {
					xp_put_pool(xs->pool);
					xs->pool = NULL;
					sockfd_put(sock);
					goto out_unlock;
				}
+73 −1
Original line number Diff line number Diff line
@@ -869,6 +869,77 @@ static void test_msg_redir_to_listening(struct test_sockmap_listen *skel,
	xbpf_prog_detach2(verdict, sock_map, BPF_SK_MSG_VERDICT);
}

static void redir_partial(int family, int sotype, int sock_map, int parser_map)
{
	int s, c0, c1, p0, p1;
	int err, n, key, value;
	char buf[] = "abc";

	key = 0;
	value = sizeof(buf) - 1;
	err = xbpf_map_update_elem(parser_map, &key, &value, 0);
	if (err)
		return;

	s = socket_loopback(family, sotype | SOCK_NONBLOCK);
	if (s < 0)
		goto clean_parser_map;

	err = create_socket_pairs(s, family, sotype, &c0, &c1, &p0, &p1);
	if (err)
		goto close_srv;

	err = add_to_sockmap(sock_map, p0, p1);
	if (err)
		goto close;

	n = xsend(c1, buf, sizeof(buf), 0);
	if (n < sizeof(buf))
		FAIL("incomplete write");

	n = xrecv_nonblock(c0, buf, sizeof(buf), 0);
	if (n != sizeof(buf) - 1)
		FAIL("expect %zu, received %d", sizeof(buf) - 1, n);

close:
	xclose(c0);
	xclose(p0);
	xclose(c1);
	xclose(p1);
close_srv:
	xclose(s);

clean_parser_map:
	key = 0;
	value = 0;
	xbpf_map_update_elem(parser_map, &key, &value, 0);
}

static void test_skb_redir_partial(struct test_sockmap_listen *skel,
				   struct bpf_map *inner_map, int family,
				   int sotype)
{
	int verdict = bpf_program__fd(skel->progs.prog_stream_verdict);
	int parser = bpf_program__fd(skel->progs.prog_stream_parser);
	int parser_map = bpf_map__fd(skel->maps.parser_map);
	int sock_map = bpf_map__fd(inner_map);
	int err;

	err = xbpf_prog_attach(parser, sock_map, BPF_SK_SKB_STREAM_PARSER, 0);
	if (err)
		return;

	err = xbpf_prog_attach(verdict, sock_map, BPF_SK_SKB_STREAM_VERDICT, 0);
	if (err)
		goto detach;

	redir_partial(family, sotype, sock_map, parser_map);

	xbpf_prog_detach2(verdict, sock_map, BPF_SK_SKB_STREAM_VERDICT);
detach:
	xbpf_prog_detach2(parser, sock_map, BPF_SK_SKB_STREAM_PARSER);
}

static void test_reuseport_select_listening(int family, int sotype,
					    int sock_map, int verd_map,
					    int reuseport_prog)
@@ -1243,6 +1314,7 @@ static void test_redir(struct test_sockmap_listen *skel, struct bpf_map *map,
	} tests[] = {
		TEST(test_skb_redir_to_connected),
		TEST(test_skb_redir_to_listening),
		TEST(test_skb_redir_partial),
		TEST(test_msg_redir_to_connected),
		TEST(test_msg_redir_to_listening),
	};
@@ -1432,7 +1504,7 @@ static void vsock_unix_redir_connectible(int sock_mapfd, int verd_mapfd,
	if (n < 1)
		goto out;

	n = recv(mode == REDIR_INGRESS ? u0 : u1, &b, sizeof(b), MSG_DONTWAIT);
	n = xrecv_nonblock(mode == REDIR_INGRESS ? u0 : u1, &b, sizeof(b), 0);
	if (n < 0)
		FAIL("%s: recv() err, errno=%d", log_prefix, errno);
	if (n == 0)
Loading