]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
tls: Fix TLS ulp context leak, when TLS_TX setsockopt is not used.
authorIlya Lesokhin <ilyal@mellanox.com>
Mon, 13 Nov 2017 08:22:46 +0000 (10:22 +0200)
committerDavid S. Miller <davem@davemloft.net>
Tue, 14 Nov 2017 07:26:34 +0000 (16:26 +0900)
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: 3c4d7559159b ('tls: kernel TLS support')
Signed-off-by: Ilya Lesokhin <ilyal@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/tls.h
net/tls/tls_main.c
net/tls/tls_sw.c

index f058a6e08eaadba3c4eaefa95c7dc7acbcab2136..7cb58a6b8fd0cc3fb936c353974ea69a7204d0a0 100644 (file)
@@ -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);
index de6a1416bc41a14d32fcd57a88eba8eb7776fa75..13427ee7c582118bc28a0febfa79fd38ccc02591 100644 (file)
@@ -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);
@@ -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)
 {
        prot[TLS_BASE_TX] = *base;
-       prot[TLS_BASE_TX].setsockopt = tls_setsockopt;
-       prot[TLS_BASE_TX].getsockopt = tls_getsockopt;
+       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;
 }
index f00383a37622051f3a9cfc63e28f7f4b6644a757..fcd92a9c2d063a9714ef20db7e643f04b0f35957 100644 (file)
@@ -639,7 +639,7 @@ sendpage_end:
        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) {