tls: Use correct sk->sk_prot for IPV6

The tls ulp overrides sk->prot with a new tls specific proto structs.
The tls specific structs were previously based on the ipv4 specific
tcp_prot sturct.
As a result, attaching the tls ulp to an ipv6 tcp socket replaced
some ipv6 callback with the ipv4 equivalents.

This patch adds ipv6 tls proto structs and uses them when
attached to ipv6 sockets.

Fixes: 3c4d755915 ('tls: kernel TLS support')
Signed-off-by: Boris Pismenny <borisp@mellanox.com>
Signed-off-by: Ilya Lesokhin <ilyal@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Boris Pismenny 2018-02-27 14:18:39 +02:00 committed by David S. Miller
parent 55ea874306
commit c113187d38

View File

@ -45,17 +45,27 @@ MODULE_AUTHOR("Mellanox Technologies");
MODULE_DESCRIPTION("Transport Layer Security Support"); MODULE_DESCRIPTION("Transport Layer Security Support");
MODULE_LICENSE("Dual BSD/GPL"); MODULE_LICENSE("Dual BSD/GPL");
enum {
TLSV4,
TLSV6,
TLS_NUM_PROTS,
};
enum { enum {
TLS_BASE_TX, TLS_BASE_TX,
TLS_SW_TX, TLS_SW_TX,
TLS_NUM_CONFIG, TLS_NUM_CONFIG,
}; };
static struct proto tls_prots[TLS_NUM_CONFIG]; static struct proto *saved_tcpv6_prot;
static DEFINE_MUTEX(tcpv6_prot_mutex);
static struct proto tls_prots[TLS_NUM_PROTS][TLS_NUM_CONFIG];
static inline void update_sk_prot(struct sock *sk, struct tls_context *ctx) static inline void update_sk_prot(struct sock *sk, struct tls_context *ctx)
{ {
sk->sk_prot = &tls_prots[ctx->tx_conf]; int ip_ver = sk->sk_family == AF_INET6 ? TLSV6 : TLSV4;
sk->sk_prot = &tls_prots[ip_ver][ctx->tx_conf];
} }
int wait_on_pending_writer(struct sock *sk, long *timeo) int wait_on_pending_writer(struct sock *sk, long *timeo)
@ -453,8 +463,21 @@ static int tls_setsockopt(struct sock *sk, int level, int optname,
return do_tls_setsockopt(sk, optname, optval, optlen); return do_tls_setsockopt(sk, optname, optval, optlen);
} }
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].sendmsg = tls_sw_sendmsg;
prot[TLS_SW_TX].sendpage = tls_sw_sendpage;
}
static int tls_init(struct sock *sk) static int tls_init(struct sock *sk)
{ {
int ip_ver = sk->sk_family == AF_INET6 ? TLSV6 : TLSV4;
struct inet_connection_sock *icsk = inet_csk(sk); struct inet_connection_sock *icsk = inet_csk(sk);
struct tls_context *ctx; struct tls_context *ctx;
int rc = 0; int rc = 0;
@ -479,6 +502,17 @@ static int tls_init(struct sock *sk)
ctx->getsockopt = sk->sk_prot->getsockopt; ctx->getsockopt = sk->sk_prot->getsockopt;
ctx->sk_proto_close = sk->sk_prot->close; ctx->sk_proto_close = sk->sk_prot->close;
/* Build IPv6 TLS whenever the address of tcpv6_prot changes */
if (ip_ver == TLSV6 &&
unlikely(sk->sk_prot != smp_load_acquire(&saved_tcpv6_prot))) {
mutex_lock(&tcpv6_prot_mutex);
if (likely(sk->sk_prot != saved_tcpv6_prot)) {
build_protos(tls_prots[TLSV6], sk->sk_prot);
smp_store_release(&saved_tcpv6_prot, sk->sk_prot);
}
mutex_unlock(&tcpv6_prot_mutex);
}
ctx->tx_conf = TLS_BASE_TX; ctx->tx_conf = TLS_BASE_TX;
update_sk_prot(sk, ctx); update_sk_prot(sk, ctx);
out: out:
@ -493,21 +527,9 @@ static struct tcp_ulp_ops tcp_tls_ulp_ops __read_mostly = {
.init = tls_init, .init = tls_init,
}; };
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].sendmsg = tls_sw_sendmsg;
prot[TLS_SW_TX].sendpage = tls_sw_sendpage;
}
static int __init tls_register(void) static int __init tls_register(void)
{ {
build_protos(tls_prots, &tcp_prot); build_protos(tls_prots[TLSV4], &tcp_prot);
tcp_register_ulp(&tcp_tls_ulp_ops); tcp_register_ulp(&tcp_tls_ulp_ops);