]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
tls: fix sw_ctx leak
authorSabrina Dubroca <sd@queasysnail.net>
Tue, 16 Jan 2018 15:04:26 +0000 (16:04 +0100)
committerDavid S. Miller <davem@davemloft.net>
Wed, 17 Jan 2018 21:16:03 +0000 (16:16 -0500)
During setsockopt(SOL_TCP, TLS_TX), if initialization of the software
context fails in tls_set_sw_offload(), we leak sw_ctx. We also don't
reassign ctx->priv_ctx to NULL, so we can't even do another attempt to
set it up on the same socket, as it will fail with -EEXIST.

Fixes: 3c4d7559159b ('tls: kernel TLS support')
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/tls/tls_sw.c

index 9773571b6a3489d5a3474403493e1474f02e32bd..61f394d369bf86d69c44b84950632cd5c3519905 100644 (file)
@@ -681,18 +681,17 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx)
        }
        default:
                rc = -EINVAL;
-               goto out;
+               goto free_priv;
        }
 
        ctx->prepend_size = TLS_HEADER_SIZE + nonce_size;
        ctx->tag_size = tag_size;
        ctx->overhead_size = ctx->prepend_size + ctx->tag_size;
        ctx->iv_size = iv_size;
-       ctx->iv = kmalloc(iv_size + TLS_CIPHER_AES_GCM_128_SALT_SIZE,
-                         GFP_KERNEL);
+       ctx->iv = kmalloc(iv_size + TLS_CIPHER_AES_GCM_128_SALT_SIZE, GFP_KERNEL);
        if (!ctx->iv) {
                rc = -ENOMEM;
-               goto out;
+               goto free_priv;
        }
        memcpy(ctx->iv, gcm_128_info->salt, TLS_CIPHER_AES_GCM_128_SALT_SIZE);
        memcpy(ctx->iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE, iv, iv_size);
@@ -740,7 +739,7 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx)
 
        rc = crypto_aead_setauthsize(sw_ctx->aead_send, ctx->tag_size);
        if (!rc)
-               goto out;
+               return 0;
 
 free_aead:
        crypto_free_aead(sw_ctx->aead_send);
@@ -751,6 +750,9 @@ free_rec_seq:
 free_iv:
        kfree(ctx->iv);
        ctx->iv = NULL;
+free_priv:
+       kfree(ctx->priv_ctx);
+       ctx->priv_ctx = NULL;
 out:
        return rc;
 }