diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2016-01-15 09:02:20 -0500 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2016-01-18 05:16:34 -0500 |
commit | 1822793a523e5d5730b19cc21160ff1717421bc8 (patch) | |
tree | 32a11267ee28dc0f2b22d4748b0c40788ed99fc1 /crypto/algif_skcipher.c | |
parent | ad46d7e33219218605ea619e32553daf4f346b9f (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.c | 9 |
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 | ||
756 | static int skcipher_check_key(struct socket *sock) | 756 | static 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 | ||
785 | unlock: | 786 | unlock: |
786 | release_sock(psk); | 787 | release_sock(psk); |
788 | unlock_child: | ||
789 | release_sock(sk); | ||
787 | 790 | ||
788 | return err; | 791 | return err; |
789 | } | 792 | } |