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

Commit ff45d820 authored by Ilya Lesokhin's avatar Ilya Lesokhin Committed by David S. Miller
Browse files

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: 3c4d7559 ('tls: kernel TLS support')
Signed-off-by: default avatarIlya Lesokhin <ilyal@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6d88207f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -99,7 +99,6 @@ struct tls_context {

	u16 pending_open_record_frags;
	int (*push_pending_record)(struct sock *sk, int flags);
	void (*free_resources)(struct sock *sk);

	void (*sk_write_space)(struct sock *sk);
	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 offset, size_t size, int flags);
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_icsk_clean_acked(struct sock *sk);
+14 −8
Original line number Diff line number Diff line
@@ -226,6 +226,12 @@ static void tls_sk_proto_close(struct sock *sk, long timeout)
	void (*sk_proto_close)(struct sock *sk, long timeout);

	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))
		tls_handle_open_record(sk, 0);
@@ -242,13 +248,14 @@ static void tls_sk_proto_close(struct sock *sk, long timeout)
			sg++;
		}
	}
	ctx->free_resources(sk);

	kfree(ctx->rec_seq);
	kfree(ctx->iv);

	sk_proto_close = ctx->sk_proto_close;
	kfree(ctx);
	if (ctx->tx_conf == TLS_SW_TX)
		tls_sw_free_tx_resources(sk);

skip_tx_cleanup:
	release_sock(sk);
	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;
	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 */
	rc = tls_set_sw_offload(sk, ctx);
	tx_conf = TLS_SW_TX;
@@ -464,6 +469,7 @@ static int tls_init(struct sock *sk)
	icsk->icsk_ulp_data = ctx;
	ctx->setsockopt = sk->sk_prot->setsockopt;
	ctx->getsockopt = sk->sk_prot->getsockopt;
	ctx->sk_proto_close = sk->sk_prot->close;

	ctx->tx_conf = TLS_BASE_TX;
	update_sk_prot(sk, ctx);
@@ -482,9 +488,9 @@ static void build_protos(struct proto *prot, struct proto *base)
	prot[TLS_BASE_TX] = *base;
	prot[TLS_BASE_TX].setsockopt	= tls_setsockopt;
	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].close		= tls_sk_proto_close;
	prot[TLS_SW_TX].sendmsg		= tls_sw_sendmsg;
	prot[TLS_SW_TX].sendpage	= tls_sw_sendpage;
}
+2 −2
Original line number Diff line number Diff line
@@ -639,7 +639,7 @@ int tls_sw_sendpage(struct sock *sk, struct page *page,
	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_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);

	kfree(ctx);
	kfree(tls_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->free_resources = tls_sw_free_resources;

	crypto_info = &ctx->crypto_send;
	switch (crypto_info->cipher_type) {