tls: Fix TLS ulp context leak, when TLS_TX setsockopt is not used.
Previously the TLS ulp context would leak if we attached a TLS ulp
to a socket but did not use the TLS_TX setsockopt,
or did use it but it failed.
This patch solves the issue by overriding prot[TLS_BASE_TX].close
and fixing tls_sk_proto_close to work properly
when its called with ctx->tx_conf == TLS_BASE_TX.
This patch also removes ctx->free_resources as we can use ctx->tx_conf
to obtain the relevant information.
Fixes: 3c4d755915
('tls: kernel TLS support')
Signed-off-by: Ilya Lesokhin <ilyal@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
6d88207fcf
Коммит
ff45d820a2
|
@ -99,7 +99,6 @@ struct tls_context {
|
||||||
|
|
||||||
u16 pending_open_record_frags;
|
u16 pending_open_record_frags;
|
||||||
int (*push_pending_record)(struct sock *sk, int flags);
|
int (*push_pending_record)(struct sock *sk, int flags);
|
||||||
void (*free_resources)(struct sock *sk);
|
|
||||||
|
|
||||||
void (*sk_write_space)(struct sock *sk);
|
void (*sk_write_space)(struct sock *sk);
|
||||||
void (*sk_proto_close)(struct sock *sk, long timeout);
|
void (*sk_proto_close)(struct sock *sk, long timeout);
|
||||||
|
@ -124,6 +123,7 @@ int tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size);
|
||||||
int tls_sw_sendpage(struct sock *sk, struct page *page,
|
int tls_sw_sendpage(struct sock *sk, struct page *page,
|
||||||
int offset, size_t size, int flags);
|
int offset, size_t size, int flags);
|
||||||
void tls_sw_close(struct sock *sk, long timeout);
|
void tls_sw_close(struct sock *sk, long timeout);
|
||||||
|
void tls_sw_free_tx_resources(struct sock *sk);
|
||||||
|
|
||||||
void tls_sk_destruct(struct sock *sk, struct tls_context *ctx);
|
void tls_sk_destruct(struct sock *sk, struct tls_context *ctx);
|
||||||
void tls_icsk_clean_acked(struct sock *sk);
|
void tls_icsk_clean_acked(struct sock *sk);
|
||||||
|
|
|
@ -226,6 +226,12 @@ static void tls_sk_proto_close(struct sock *sk, long timeout)
|
||||||
void (*sk_proto_close)(struct sock *sk, long timeout);
|
void (*sk_proto_close)(struct sock *sk, long timeout);
|
||||||
|
|
||||||
lock_sock(sk);
|
lock_sock(sk);
|
||||||
|
sk_proto_close = ctx->sk_proto_close;
|
||||||
|
|
||||||
|
if (ctx->tx_conf == TLS_BASE_TX) {
|
||||||
|
kfree(ctx);
|
||||||
|
goto skip_tx_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
if (!tls_complete_pending_work(sk, ctx, 0, &timeo))
|
if (!tls_complete_pending_work(sk, ctx, 0, &timeo))
|
||||||
tls_handle_open_record(sk, 0);
|
tls_handle_open_record(sk, 0);
|
||||||
|
@ -242,13 +248,14 @@ static void tls_sk_proto_close(struct sock *sk, long timeout)
|
||||||
sg++;
|
sg++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx->free_resources(sk);
|
|
||||||
kfree(ctx->rec_seq);
|
kfree(ctx->rec_seq);
|
||||||
kfree(ctx->iv);
|
kfree(ctx->iv);
|
||||||
|
|
||||||
sk_proto_close = ctx->sk_proto_close;
|
if (ctx->tx_conf == TLS_SW_TX)
|
||||||
kfree(ctx);
|
tls_sw_free_tx_resources(sk);
|
||||||
|
|
||||||
|
skip_tx_cleanup:
|
||||||
release_sock(sk);
|
release_sock(sk);
|
||||||
sk_proto_close(sk, timeout);
|
sk_proto_close(sk, timeout);
|
||||||
}
|
}
|
||||||
|
@ -402,8 +409,6 @@ static int do_tls_setsockopt_tx(struct sock *sk, char __user *optval,
|
||||||
ctx->sk_write_space = sk->sk_write_space;
|
ctx->sk_write_space = sk->sk_write_space;
|
||||||
sk->sk_write_space = tls_write_space;
|
sk->sk_write_space = tls_write_space;
|
||||||
|
|
||||||
ctx->sk_proto_close = sk->sk_prot->close;
|
|
||||||
|
|
||||||
/* currently SW is default, we will have ethtool in future */
|
/* currently SW is default, we will have ethtool in future */
|
||||||
rc = tls_set_sw_offload(sk, ctx);
|
rc = tls_set_sw_offload(sk, ctx);
|
||||||
tx_conf = TLS_SW_TX;
|
tx_conf = TLS_SW_TX;
|
||||||
|
@ -464,6 +469,7 @@ static int tls_init(struct sock *sk)
|
||||||
icsk->icsk_ulp_data = ctx;
|
icsk->icsk_ulp_data = ctx;
|
||||||
ctx->setsockopt = sk->sk_prot->setsockopt;
|
ctx->setsockopt = sk->sk_prot->setsockopt;
|
||||||
ctx->getsockopt = sk->sk_prot->getsockopt;
|
ctx->getsockopt = sk->sk_prot->getsockopt;
|
||||||
|
ctx->sk_proto_close = sk->sk_prot->close;
|
||||||
|
|
||||||
ctx->tx_conf = TLS_BASE_TX;
|
ctx->tx_conf = TLS_BASE_TX;
|
||||||
update_sk_prot(sk, ctx);
|
update_sk_prot(sk, ctx);
|
||||||
|
@ -480,11 +486,11 @@ static struct tcp_ulp_ops tcp_tls_ulp_ops __read_mostly = {
|
||||||
static void build_protos(struct proto *prot, struct proto *base)
|
static void build_protos(struct proto *prot, struct proto *base)
|
||||||
{
|
{
|
||||||
prot[TLS_BASE_TX] = *base;
|
prot[TLS_BASE_TX] = *base;
|
||||||
prot[TLS_BASE_TX].setsockopt = tls_setsockopt;
|
prot[TLS_BASE_TX].setsockopt = tls_setsockopt;
|
||||||
prot[TLS_BASE_TX].getsockopt = tls_getsockopt;
|
prot[TLS_BASE_TX].getsockopt = tls_getsockopt;
|
||||||
|
prot[TLS_BASE_TX].close = tls_sk_proto_close;
|
||||||
|
|
||||||
prot[TLS_SW_TX] = prot[TLS_BASE_TX];
|
prot[TLS_SW_TX] = prot[TLS_BASE_TX];
|
||||||
prot[TLS_SW_TX].close = tls_sk_proto_close;
|
|
||||||
prot[TLS_SW_TX].sendmsg = tls_sw_sendmsg;
|
prot[TLS_SW_TX].sendmsg = tls_sw_sendmsg;
|
||||||
prot[TLS_SW_TX].sendpage = tls_sw_sendpage;
|
prot[TLS_SW_TX].sendpage = tls_sw_sendpage;
|
||||||
}
|
}
|
||||||
|
|
|
@ -639,7 +639,7 @@ sendpage_end:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tls_sw_free_resources(struct sock *sk)
|
void tls_sw_free_tx_resources(struct sock *sk)
|
||||||
{
|
{
|
||||||
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
||||||
struct tls_sw_context *ctx = tls_sw_ctx(tls_ctx);
|
struct tls_sw_context *ctx = tls_sw_ctx(tls_ctx);
|
||||||
|
@ -650,6 +650,7 @@ static void tls_sw_free_resources(struct sock *sk)
|
||||||
tls_free_both_sg(sk);
|
tls_free_both_sg(sk);
|
||||||
|
|
||||||
kfree(ctx);
|
kfree(ctx);
|
||||||
|
kfree(tls_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx)
|
int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx)
|
||||||
|
@ -679,7 +680,6 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->priv_ctx = (struct tls_offload_context *)sw_ctx;
|
ctx->priv_ctx = (struct tls_offload_context *)sw_ctx;
|
||||||
ctx->free_resources = tls_sw_free_resources;
|
|
||||||
|
|
||||||
crypto_info = &ctx->crypto_send;
|
crypto_info = &ctx->crypto_send;
|
||||||
switch (crypto_info->cipher_type) {
|
switch (crypto_info->cipher_type) {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче