diff options
Diffstat (limited to 'net/tls/tls_main.c')
| -rw-r--r-- | net/tls/tls_main.c | 98 | 
1 files changed, 50 insertions, 48 deletions
| diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c index 93c0c225ab34..311cec8e533d 100644 --- a/net/tls/tls_main.c +++ b/net/tls/tls_main.c @@ -141,7 +141,6 @@ retry:  		size = sg->length;  	} -	clear_bit(TLS_PENDING_CLOSED_RECORD, &ctx->flags);  	ctx->in_tcp_sendpages = false;  	ctx->sk_write_space(sk); @@ -193,15 +192,12 @@ int tls_proccess_cmsg(struct sock *sk, struct msghdr *msg,  	return rc;  } -int tls_push_pending_closed_record(struct sock *sk, struct tls_context *ctx, -				   int flags, long *timeo) +int tls_push_partial_record(struct sock *sk, struct tls_context *ctx, +			    int flags)  {  	struct scatterlist *sg;  	u16 offset; -	if (!tls_is_partially_sent_record(ctx)) -		return ctx->push_pending_record(sk, flags); -  	sg = ctx->partially_sent_record;  	offset = ctx->partially_sent_offset; @@ -209,33 +205,53 @@ int tls_push_pending_closed_record(struct sock *sk, struct tls_context *ctx,  	return tls_push_sg(sk, ctx, sg, offset, flags);  } +int tls_push_pending_closed_record(struct sock *sk, +				   struct tls_context *tls_ctx, +				   int flags, long *timeo) +{ +	struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx); + +	if (tls_is_partially_sent_record(tls_ctx) || +	    !list_empty(&ctx->tx_list)) +		return tls_tx_records(sk, flags); +	else +		return tls_ctx->push_pending_record(sk, flags); +} +  static void tls_write_space(struct sock *sk)  {  	struct tls_context *ctx = tls_get_ctx(sk); +	struct tls_sw_context_tx *tx_ctx = tls_sw_ctx_tx(ctx); -	/* We are already sending pages, ignore notification */ -	if (ctx->in_tcp_sendpages) +	/* If in_tcp_sendpages call lower protocol write space handler +	 * to ensure we wake up any waiting operations there. For example +	 * if do_tcp_sendpages where to call sk_wait_event. +	 */ +	if (ctx->in_tcp_sendpages) { +		ctx->sk_write_space(sk);  		return; +	} -	if (!sk->sk_write_pending && tls_is_pending_closed_record(ctx)) { -		gfp_t sk_allocation = sk->sk_allocation; -		int rc; -		long timeo = 0; - -		sk->sk_allocation = GFP_ATOMIC; -		rc = tls_push_pending_closed_record(sk, ctx, -						    MSG_DONTWAIT | -						    MSG_NOSIGNAL, -						    &timeo); -		sk->sk_allocation = sk_allocation; - -		if (rc < 0) -			return; +	/* Schedule the transmission if tx list is ready */ +	if (is_tx_ready(tx_ctx) && !sk->sk_write_pending) { +		/* Schedule the transmission */ +		if (!test_and_set_bit(BIT_TX_SCHEDULED, &tx_ctx->tx_bitmask)) +			schedule_delayed_work(&tx_ctx->tx_work.work, 0);  	}  	ctx->sk_write_space(sk);  } +static void tls_ctx_free(struct tls_context *ctx) +{ +	if (!ctx) +		return; + +	memzero_explicit(&ctx->crypto_send, sizeof(ctx->crypto_send)); +	memzero_explicit(&ctx->crypto_recv, sizeof(ctx->crypto_recv)); +	kfree(ctx); +} +  static void tls_sk_proto_close(struct sock *sk, long timeout)  {  	struct tls_context *ctx = tls_get_ctx(sk); @@ -255,19 +271,6 @@ static void tls_sk_proto_close(struct sock *sk, long timeout)  	if (!tls_complete_pending_work(sk, ctx, 0, &timeo))  		tls_handle_open_record(sk, 0); -	if (ctx->partially_sent_record) { -		struct scatterlist *sg = ctx->partially_sent_record; - -		while (1) { -			put_page(sg_page(sg)); -			sk_mem_uncharge(sk, sg->length); - -			if (sg_is_last(sg)) -				break; -			sg++; -		} -	} -  	/* We need these for tls_sw_fallback handling of other packets */  	if (ctx->tx_conf == TLS_SW) {  		kfree(ctx->tx.rec_seq); @@ -289,7 +292,7 @@ static void tls_sk_proto_close(struct sock *sk, long timeout)  #else  	{  #endif -		kfree(ctx); +		tls_ctx_free(ctx);  		ctx = NULL;  	} @@ -300,7 +303,7 @@ skip_tx_cleanup:  	 * for sk->sk_prot->unhash [tls_hw_unhash]  	 */  	if (free_ctx) -		kfree(ctx); +		tls_ctx_free(ctx);  }  static int do_tls_getsockopt_tx(struct sock *sk, char __user *optval, @@ -325,7 +328,7 @@ static int do_tls_getsockopt_tx(struct sock *sk, char __user *optval,  	}  	/* get user crypto info */ -	crypto_info = &ctx->crypto_send; +	crypto_info = &ctx->crypto_send.info;  	if (!TLS_CRYPTO_INFO_READY(crypto_info)) {  		rc = -EBUSY; @@ -412,9 +415,9 @@ static int do_tls_setsockopt_conf(struct sock *sk, char __user *optval,  	}  	if (tx) -		crypto_info = &ctx->crypto_send; +		crypto_info = &ctx->crypto_send.info;  	else -		crypto_info = &ctx->crypto_recv; +		crypto_info = &ctx->crypto_recv.info;  	/* Currently we don't support set crypto info more than one time */  	if (TLS_CRYPTO_INFO_READY(crypto_info)) { @@ -494,7 +497,7 @@ static int do_tls_setsockopt_conf(struct sock *sk, char __user *optval,  	goto out;  err_crypto_info: -	memset(crypto_info, 0, sizeof(*crypto_info)); +	memzero_explicit(crypto_info, sizeof(union tls_crypto_context));  out:  	return rc;  } @@ -617,12 +620,14 @@ static void build_protos(struct proto prot[TLS_NUM_CONFIG][TLS_NUM_CONFIG],  	prot[TLS_SW][TLS_BASE].sendpage		= tls_sw_sendpage;  	prot[TLS_BASE][TLS_SW] = prot[TLS_BASE][TLS_BASE]; -	prot[TLS_BASE][TLS_SW].recvmsg		= tls_sw_recvmsg; -	prot[TLS_BASE][TLS_SW].close		= tls_sk_proto_close; +	prot[TLS_BASE][TLS_SW].recvmsg		  = tls_sw_recvmsg; +	prot[TLS_BASE][TLS_SW].stream_memory_read = tls_sw_stream_read; +	prot[TLS_BASE][TLS_SW].close		  = tls_sk_proto_close;  	prot[TLS_SW][TLS_SW] = prot[TLS_SW][TLS_BASE]; -	prot[TLS_SW][TLS_SW].recvmsg	= tls_sw_recvmsg; -	prot[TLS_SW][TLS_SW].close	= tls_sk_proto_close; +	prot[TLS_SW][TLS_SW].recvmsg		= tls_sw_recvmsg; +	prot[TLS_SW][TLS_SW].stream_memory_read	= tls_sw_stream_read; +	prot[TLS_SW][TLS_SW].close		= tls_sk_proto_close;  #ifdef CONFIG_TLS_DEVICE  	prot[TLS_HW][TLS_BASE] = prot[TLS_BASE][TLS_BASE]; @@ -710,8 +715,6 @@ EXPORT_SYMBOL(tls_unregister_device);  static struct tcp_ulp_ops tcp_tls_ulp_ops __read_mostly = {  	.name			= "tls", -	.uid			= TCP_ULP_TLS, -	.user_visible		= true,  	.owner			= THIS_MODULE,  	.init			= tls_init,  }; @@ -721,7 +724,6 @@ static int __init tls_register(void)  	build_protos(tls_prots[TLSV4], &tcp_prot);  	tls_sw_proto_ops = inet_stream_ops; -	tls_sw_proto_ops.poll = tls_sw_poll;  	tls_sw_proto_ops.splice_read = tls_sw_splice_read;  #ifdef CONFIG_TLS_DEVICE |