diff options
author | Daniel Borkmann <dborkman@redhat.com> | 2014-11-19 11:13:11 -0500 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2014-11-25 09:50:39 -0500 |
commit | 79e886599e6416d0de26e8562e4464577d081c3d (patch) | |
tree | 83a545d589f1bb7ba5de28cc768ce549598fd0b2 | |
parent | 5d26a105b5a73e5635eae0629b42fa0a90e07b7b (diff) |
crypto: algif - add and use sock_kzfree_s() instead of memzero_explicit()
Commit e1bd95bf7c25 ("crypto: algif - zeroize IV buffer") and
2a6af25befd0 ("crypto: algif - zeroize message digest buffer")
added memzero_explicit() calls on buffers that are later on
passed back to sock_kfree_s().
This is a discussed follow-up that, instead, extends the sock
API and adds sock_kzfree_s(), which internally uses kzfree()
instead of kfree() for passing the buffers back to slab.
Having sock_kzfree_s() allows to keep the changes more minimal
by just having a drop-in replacement instead of adding
memzero_explicit() calls everywhere before sock_kfree_s().
In kzfree(), the compiler is not allowed to optimize the memset()
away and thus there's no need for memzero_explicit(). Both,
sock_kfree_s() and sock_kzfree_s() are wrappers for
__sock_kfree_s() and call into kfree() resp. kzfree(); here,
__sock_kfree_s() needs to be explicitly inlined as we want the
compiler to optimize the call and condition away and thus it
produces e.g. on x86_64 the _same_ assembler output for
sock_kfree_s() before and after, and thus also allows for
avoiding code duplication.
Cc: David S. Miller <davem@davemloft.net>
Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r-- | crypto/algif_hash.c | 6 | ||||
-rw-r--r-- | crypto/algif_skcipher.c | 3 | ||||
-rw-r--r-- | include/net/sock.h | 1 | ||||
-rw-r--r-- | net/core/sock.c | 24 |
4 files changed, 24 insertions, 10 deletions
diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c index f75db4ce48bf..e6050396a3b3 100644 --- a/crypto/algif_hash.c +++ b/crypto/algif_hash.c | |||
@@ -258,10 +258,8 @@ static void hash_sock_destruct(struct sock *sk) | |||
258 | struct alg_sock *ask = alg_sk(sk); | 258 | struct alg_sock *ask = alg_sk(sk); |
259 | struct hash_ctx *ctx = ask->private; | 259 | struct hash_ctx *ctx = ask->private; |
260 | 260 | ||
261 | memzero_explicit(ctx->result, | 261 | sock_kzfree_s(sk, ctx->result, |
262 | crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req))); | 262 | crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req))); |
263 | sock_kfree_s(sk, ctx->result, | ||
264 | crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req))); | ||
265 | sock_kfree_s(sk, ctx, ctx->len); | 263 | sock_kfree_s(sk, ctx, ctx->len); |
266 | af_alg_release_parent(sk); | 264 | af_alg_release_parent(sk); |
267 | } | 265 | } |
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c index 85e3bdbe214c..34389964000d 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c | |||
@@ -566,8 +566,7 @@ static void skcipher_sock_destruct(struct sock *sk) | |||
566 | struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(&ctx->req); | 566 | struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(&ctx->req); |
567 | 567 | ||
568 | skcipher_free_sgl(sk); | 568 | skcipher_free_sgl(sk); |
569 | memzero_explicit(ctx->iv, crypto_ablkcipher_ivsize(tfm)); | 569 | sock_kzfree_s(sk, ctx->iv, crypto_ablkcipher_ivsize(tfm)); |
570 | sock_kfree_s(sk, ctx->iv, crypto_ablkcipher_ivsize(tfm)); | ||
571 | sock_kfree_s(sk, ctx, ctx->len); | 570 | sock_kfree_s(sk, ctx, ctx->len); |
572 | af_alg_release_parent(sk); | 571 | af_alg_release_parent(sk); |
573 | } | 572 | } |
diff --git a/include/net/sock.h b/include/net/sock.h index 7db3db112baa..37d6cc5dcf33 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -1588,6 +1588,7 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len, | |||
1588 | int *errcode, int max_page_order); | 1588 | int *errcode, int max_page_order); |
1589 | void *sock_kmalloc(struct sock *sk, int size, gfp_t priority); | 1589 | void *sock_kmalloc(struct sock *sk, int size, gfp_t priority); |
1590 | void sock_kfree_s(struct sock *sk, void *mem, int size); | 1590 | void sock_kfree_s(struct sock *sk, void *mem, int size); |
1591 | void sock_kzfree_s(struct sock *sk, void *mem, int size); | ||
1591 | void sk_send_sigurg(struct sock *sk); | 1592 | void sk_send_sigurg(struct sock *sk); |
1592 | 1593 | ||
1593 | /* | 1594 | /* |
diff --git a/net/core/sock.c b/net/core/sock.c index 15e0c67b1069..04ce26a996bd 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -1713,18 +1713,34 @@ void *sock_kmalloc(struct sock *sk, int size, gfp_t priority) | |||
1713 | } | 1713 | } |
1714 | EXPORT_SYMBOL(sock_kmalloc); | 1714 | EXPORT_SYMBOL(sock_kmalloc); |
1715 | 1715 | ||
1716 | /* | 1716 | /* Free an option memory block. Note, we actually want the inline |
1717 | * Free an option memory block. | 1717 | * here as this allows gcc to detect the nullify and fold away the |
1718 | * condition entirely. | ||
1718 | */ | 1719 | */ |
1719 | void sock_kfree_s(struct sock *sk, void *mem, int size) | 1720 | static inline void __sock_kfree_s(struct sock *sk, void *mem, int size, |
1721 | const bool nullify) | ||
1720 | { | 1722 | { |
1721 | if (WARN_ON_ONCE(!mem)) | 1723 | if (WARN_ON_ONCE(!mem)) |
1722 | return; | 1724 | return; |
1723 | kfree(mem); | 1725 | if (nullify) |
1726 | kzfree(mem); | ||
1727 | else | ||
1728 | kfree(mem); | ||
1724 | atomic_sub(size, &sk->sk_omem_alloc); | 1729 | atomic_sub(size, &sk->sk_omem_alloc); |
1725 | } | 1730 | } |
1731 | |||
1732 | void sock_kfree_s(struct sock *sk, void *mem, int size) | ||
1733 | { | ||
1734 | __sock_kfree_s(sk, mem, size, false); | ||
1735 | } | ||
1726 | EXPORT_SYMBOL(sock_kfree_s); | 1736 | EXPORT_SYMBOL(sock_kfree_s); |
1727 | 1737 | ||
1738 | void sock_kzfree_s(struct sock *sk, void *mem, int size) | ||
1739 | { | ||
1740 | __sock_kfree_s(sk, mem, size, true); | ||
1741 | } | ||
1742 | EXPORT_SYMBOL(sock_kzfree_s); | ||
1743 | |||
1728 | /* It is almost wait_for_tcp_memory minus release_sock/lock_sock. | 1744 | /* It is almost wait_for_tcp_memory minus release_sock/lock_sock. |
1729 | I think, these locks should be removed for datagram sockets. | 1745 | I think, these locks should be removed for datagram sockets. |
1730 | */ | 1746 | */ |