summaryrefslogtreecommitdiffstats
path: root/crypto/algif_skcipher.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2016-01-15 09:02:20 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2016-01-18 05:16:34 -0500
commit1822793a523e5d5730b19cc21160ff1717421bc8 (patch)
tree32a11267ee28dc0f2b22d4748b0c40788ed99fc1 /crypto/algif_skcipher.c
parentad46d7e33219218605ea619e32553daf4f346b9f (diff)
crypto: algif_skcipher - Fix race condition in skcipher_check_key
We need to lock the child socket in skcipher_check_key as otherwise two simultaneous calls can cause the parent socket to be freed. Cc: stable@vger.kernel.org Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/algif_skcipher.c')
-rw-r--r--crypto/algif_skcipher.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index 1f99d2d47715..dfff8b0b56df 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -755,22 +755,23 @@ static struct proto_ops algif_skcipher_ops = {
755 755
756static int skcipher_check_key(struct socket *sock) 756static int skcipher_check_key(struct socket *sock)
757{ 757{
758 int err; 758 int err = 0;
759 struct sock *psk; 759 struct sock *psk;
760 struct alg_sock *pask; 760 struct alg_sock *pask;
761 struct skcipher_tfm *tfm; 761 struct skcipher_tfm *tfm;
762 struct sock *sk = sock->sk; 762 struct sock *sk = sock->sk;
763 struct alg_sock *ask = alg_sk(sk); 763 struct alg_sock *ask = alg_sk(sk);
764 764
765 lock_sock(sk);
765 if (ask->refcnt) 766 if (ask->refcnt)
766 return 0; 767 goto unlock_child;
767 768
768 psk = ask->parent; 769 psk = ask->parent;
769 pask = alg_sk(ask->parent); 770 pask = alg_sk(ask->parent);
770 tfm = pask->private; 771 tfm = pask->private;
771 772
772 err = -ENOKEY; 773 err = -ENOKEY;
773 lock_sock(psk); 774 lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
774 if (!tfm->has_key) 775 if (!tfm->has_key)
775 goto unlock; 776 goto unlock;
776 777
@@ -784,6 +785,8 @@ static int skcipher_check_key(struct socket *sock)
784 785
785unlock: 786unlock:
786 release_sock(psk); 787 release_sock(psk);
788unlock_child:
789 release_sock(sk);
787 790
788 return err; 791 return err;
789} 792}