On 4/24/19 8:07 PM, Jakub Kicinski wrote: > On Wed, 24 Apr 2019 12:21:03 -0700, John Fastabend wrote: >> It is possible (via shutdown()) for TCP socks to go through TCP_CLOSE >> state via tcp_disconnect() without calling into close callback. This >> would allow a kTLS enabled socket to exist outside of ESTABLISHED >> state which is not supported. >> >> Solve this the same way we solved the sock{map|hash} case by adding >> an unhash hook to remove tear down the TLS state. >> >> In the process we also make the close hook more robust. We add a put >> call into the close path, also in the unhash path, to remove the >> reference to ulp data after free. Its no longer valid and may confuse >> things later if the socket (re)enters kTLS code paths. Second we add >> an 'if(ctx)' check to ensure the ctx is still valid and not released >> from a previous unhash/close path. >> >> Fixes: d91c3e17f75f2 ("net/tls: Only attach to sockets in ESTABLISHED state") >> Reported-by: Eric Dumazet <edumazet@xxxxxxxxxx> >> Signed-off-by: John Fastabend <john.fastabend@xxxxxxxxx> > > Ah, EDOESNTBUILD, now I get to nitpick too? :) > Oops messed up a merge conflict. nitpicks seems like a fair enough punishment. # CONFIG_TLS_DEVICE is not set [...] >> static inline struct tls_sw_context_rx *tls_sw_ctx_rx( >> const struct tls_context *tls_ctx) >> diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c >> index 7e546b8ec000..2973048957bd 100644 >> --- a/net/tls/tls_main.c >> +++ b/net/tls/tls_main.c >> @@ -261,23 +261,16 @@ static void tls_ctx_free(struct tls_context *ctx) >> kfree(ctx); >> } >> >> -static void tls_sk_proto_close(struct sock *sk, long timeout) >> +static bool tls_sk_proto_destroy(struct sock *sk, >> + struct tls_context *ctx, bool destroy) > > perhaps this destroy should rather be called locked? It doesn't really > control destroying AFACT.. > Sure we can call it locked. >> { >> - struct tls_context *ctx = tls_get_ctx(sk); >> long timeo = sock_sndtimeo(sk, 0); >> - void (*sk_proto_close)(struct sock *sk, long timeout); >> - bool free_ctx = false; >> - >> - lock_sock(sk); >> - sk_proto_close = ctx->sk_proto_close; >> >> if (ctx->tx_conf == TLS_HW_RECORD && ctx->rx_conf == TLS_HW_RECORD) >> - goto skip_tx_cleanup; >> + return false; >> >> - if (ctx->tx_conf == TLS_BASE && ctx->rx_conf == TLS_BASE) { >> - free_ctx = true; >> - goto skip_tx_cleanup; >> - } >> + if (ctx->tx_conf == TLS_BASE && ctx->rx_conf == TLS_BASE) >> + return true; >> >> if (!tls_complete_pending_work(sk, ctx, 0, &timeo)) >> tls_handle_open_record(sk, 0); >> @@ -286,10 +279,10 @@ static void tls_sk_proto_close(struct sock *sk, long timeout) >> if (ctx->tx_conf == TLS_SW) { >> kfree(ctx->tx.rec_seq); >> kfree(ctx->tx.iv); >> - tls_sw_free_resources_tx(sk); >> + tls_sw_free_resources_tx(sk, destroy); >> #ifdef CONFIG_TLS_DEVICE >> } else if (ctx->tx_conf == TLS_HW) { >> - tls_device_free_resources_tx(sk); >> + tls_device_free_resources_tx(sk, destroy); > > this part breaks the build tls_device_free_resources_tx() doesn't need > changes. tls_device_offload_cleanup_rx() will though, cause it sleeps. OK will touch that path as well. > >> #endif >> } >> >> @@ -310,8 +303,39 @@ static void tls_sk_proto_close(struct sock *sk, long timeout) >> tls_ctx_free(ctx); >> ctx = NULL; >> } >> + return false; >> +} >> + >> +static void tls_sk_proto_unhash(struct sock *sk) >> +{ >> + struct tls_context *ctx = tls_get_ctx(sk); >> + void (*sk_proto_unhash)(struct sock *sk); >> + bool free_ctx; >> + >> + if (!ctx) >> + return sk->sk_prot->unhash(sk); >> + sk_proto_unhash = ctx->sk_proto_unhash; >> + free_ctx = tls_sk_proto_destroy(sk, ctx, false); >> + tls_put_ctx(sk); >> + if (sk_proto_unhash) >> + sk_proto_unhash(sk); >> + if (free_ctx) >> + tls_ctx_free(ctx); >> +} >> >> -skip_tx_cleanup: >> +static void tls_sk_proto_close(struct sock *sk, long timeout) >> +{ >> + struct tls_context *ctx = tls_get_ctx(sk); >> + void (*sk_proto_close)(struct sock *sk, long timeout); > > reverse xmas tree > +1 >> + bool free_ctx; >> + >> + if (!ctx) >> + return sk->sk_prot->destroy(sk); >> + >> + lock_sock(sk); >> + sk_proto_close = ctx->sk_proto_close; >> + free_ctx = tls_sk_proto_destroy(sk, ctx, true); >> + tls_put_ctx(sk); >> release_sock(sk); >> sk_proto_close(sk, timeout); >> /* free ctx for TLS_HW_RECORD, used by tcp_set_state Thanks for reviewing.