Skip to content

Commit

Permalink
sock: redo the psock vs ULP protection check
Browse files Browse the repository at this point in the history
Commit 8a59f9d ("sock: Introduce sk->sk_prot->psock_update_sk_prot()")
has moved the inet_csk_has_ulp(sk) check from sk_psock_init() to
the new tcp_bpf_update_proto() function. I'm guessing that this
was done to allow creating psocks for non-inet sockets.

Unfortunately the destruction path for psock includes the ULP
unwind, so we need to fail the sk_psock_init() itself.
Otherwise if ULP is already present we'll notice that later,
and call tcp_update_ulp() with the sk_proto of the ULP
itself, which will most likely result in the ULP looping
its callbacks.

Fixes: 8a59f9d ("sock: Introduce sk->sk_prot->psock_update_sk_prot()")
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Reviewed-by: John Fastabend <john.fastabend@gmail.com>
Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com>
Tested-by: Jakub Sitnicki <jakub@cloudflare.com>
Link: https://lore.kernel.org/r/20220620191353.1184629-2-kuba@kernel.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
  • Loading branch information
Jakub Kicinski authored and Paolo Abeni committed Jun 23, 2022
1 parent 1b205d9 commit e34a07c
Show file tree
Hide file tree
Showing 4 changed files with 12 additions and 3 deletions.
5 changes: 5 additions & 0 deletions include/net/inet_sock.h
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,11 @@ struct inet_sock {
#define IP_CMSG_CHECKSUM BIT(7)
#define IP_CMSG_RECVFRAGSIZE BIT(8)

static inline bool sk_is_inet(struct sock *sk)
{
return sk->sk_family == AF_INET || sk->sk_family == AF_INET6;
}

/**
* sk_to_full_sk - Access to a full socket
* @sk: pointer to a socket
Expand Down
5 changes: 5 additions & 0 deletions net/core/skmsg.c
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,11 @@ struct sk_psock *sk_psock_init(struct sock *sk, int node)

write_lock_bh(&sk->sk_callback_lock);

if (sk_is_inet(sk) && inet_csk_has_ulp(sk)) {
psock = ERR_PTR(-EINVAL);
goto out;
}

if (sk->sk_user_data) {
psock = ERR_PTR(-EBUSY);
goto out;
Expand Down
3 changes: 0 additions & 3 deletions net/ipv4/tcp_bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -611,9 +611,6 @@ int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore)
return 0;
}

if (inet_csk_has_ulp(sk))
return -EINVAL;

if (sk->sk_family == AF_INET6) {
if (tcp_bpf_assert_proto_ops(psock->sk_proto))
return -EINVAL;
Expand Down
2 changes: 2 additions & 0 deletions net/tls/tls_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,8 @@ static void tls_update(struct sock *sk, struct proto *p,
{
struct tls_context *ctx;

WARN_ON_ONCE(sk->sk_prot == p);

ctx = tls_get_ctx(sk);
if (likely(ctx)) {
ctx->sk_write_space = write_space;
Expand Down

0 comments on commit e34a07c

Please sign in to comment.