Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5607fff3 authored by John Fastabend's avatar John Fastabend Committed by Daniel Borkmann
Browse files

bpf: sockmap only allow ESTABLISHED sock state



After this patch we only allow socks that are in ESTABLISHED state or
are being added via a sock_ops event that is transitioning into an
ESTABLISHED state. By allowing sock_ops events we allow users to
manage sockmaps directly from sock ops programs. The two supported
sock_ops ops are BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB and
BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB.

Similar to TLS ULP this ensures sk_user_data is correct.

Reported-by: default avatarEric Dumazet <edumazet@google.com>
Fixes: 1aa12bdf ("bpf: sockmap, add sock close() hook to remove socks")
Signed-off-by: default avatarJohn Fastabend <john.fastabend@gmail.com>
Acked-by: default avatarYonghong Song <yhs@fb.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
parent 080220b6
Loading
Loading
Loading
Loading
+30 −1
Original line number Diff line number Diff line
@@ -2097,8 +2097,12 @@ static int sock_map_update_elem(struct bpf_map *map,
		return -EINVAL;
	}

	/* ULPs are currently supported only for TCP sockets in ESTABLISHED
	 * state.
	 */
	if (skops.sk->sk_type != SOCK_STREAM ||
	    skops.sk->sk_protocol != IPPROTO_TCP) {
	    skops.sk->sk_protocol != IPPROTO_TCP ||
	    skops.sk->sk_state != TCP_ESTABLISHED) {
		fput(socket->file);
		return -EOPNOTSUPP;
	}
@@ -2453,6 +2457,16 @@ static int sock_hash_update_elem(struct bpf_map *map,
		return -EINVAL;
	}

	/* ULPs are currently supported only for TCP sockets in ESTABLISHED
	 * state.
	 */
	if (skops.sk->sk_type != SOCK_STREAM ||
	    skops.sk->sk_protocol != IPPROTO_TCP ||
	    skops.sk->sk_state != TCP_ESTABLISHED) {
		fput(socket->file);
		return -EOPNOTSUPP;
	}

	lock_sock(skops.sk);
	preempt_disable();
	rcu_read_lock();
@@ -2543,10 +2557,22 @@ const struct bpf_map_ops sock_hash_ops = {
	.map_check_btf = map_check_no_btf,
};

static bool bpf_is_valid_sock_op(struct bpf_sock_ops_kern *ops)
{
	return ops->op == BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB ||
	       ops->op == BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB;
}
BPF_CALL_4(bpf_sock_map_update, struct bpf_sock_ops_kern *, bpf_sock,
	   struct bpf_map *, map, void *, key, u64, flags)
{
	WARN_ON_ONCE(!rcu_read_lock_held());

	/* ULPs are currently supported only for TCP sockets in ESTABLISHED
	 * state. This checks that the sock ops triggering the update is
	 * one indicating we are (or will be soon) in an ESTABLISHED state.
	 */
	if (!bpf_is_valid_sock_op(bpf_sock))
		return -EOPNOTSUPP;
	return sock_map_ctx_update_elem(bpf_sock, map, key, flags);
}

@@ -2565,6 +2591,9 @@ BPF_CALL_4(bpf_sock_hash_update, struct bpf_sock_ops_kern *, bpf_sock,
	   struct bpf_map *, map, void *, key, u64, flags)
{
	WARN_ON_ONCE(!rcu_read_lock_held());

	if (!bpf_is_valid_sock_op(bpf_sock))
		return -EOPNOTSUPP;
	return sock_hash_ctx_update_elem(bpf_sock, map, key, flags);
}