aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Borkmann <dborkman@redhat.com>2014-11-19 11:13:11 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2014-11-25 09:50:39 -0500
commit79e886599e6416d0de26e8562e4464577d081c3d (patch)
tree83a545d589f1bb7ba5de28cc768ce549598fd0b2
parent5d26a105b5a73e5635eae0629b42fa0a90e07b7b (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.c6
-rw-r--r--crypto/algif_skcipher.c3
-rw-r--r--include/net/sock.h1
-rw-r--r--net/core/sock.c24
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);
1589void *sock_kmalloc(struct sock *sk, int size, gfp_t priority); 1589void *sock_kmalloc(struct sock *sk, int size, gfp_t priority);
1590void sock_kfree_s(struct sock *sk, void *mem, int size); 1590void sock_kfree_s(struct sock *sk, void *mem, int size);
1591void sock_kzfree_s(struct sock *sk, void *mem, int size);
1591void sk_send_sigurg(struct sock *sk); 1592void 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}
1714EXPORT_SYMBOL(sock_kmalloc); 1714EXPORT_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 */
1719void sock_kfree_s(struct sock *sk, void *mem, int size) 1720static 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
1732void sock_kfree_s(struct sock *sk, void *mem, int size)
1733{
1734 __sock_kfree_s(sk, mem, size, false);
1735}
1726EXPORT_SYMBOL(sock_kfree_s); 1736EXPORT_SYMBOL(sock_kfree_s);
1727 1737
1738void sock_kzfree_s(struct sock *sk, void *mem, int size)
1739{
1740 __sock_kfree_s(sk, mem, size, true);
1741}
1742EXPORT_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 */