summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2016-01-13 02:03:32 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2016-01-18 05:16:33 -0500
commita6a48c565f6f112c6983e2a02b1602189ed6e26e (patch)
tree50c78dffdeaba445cf12b3c3027f4f8e3a3ad759 /crypto
parentd7b65aee1e7b4c87922b0232eaba56a8a143a4a0 (diff)
crypto: af_alg - Forbid bind(2) when nokey child sockets are present
This patch forbids the calling of bind(2) when there are child sockets created by accept(2) in existence, even if they are created on the nokey path. This is needed as those child sockets have references to the tfm object which bind(2) will destroy. Cc: stable@vger.kernel.org Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto')
-rw-r--r--crypto/af_alg.c16
1 files changed, 7 insertions, 9 deletions
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index e7cb8367771d..f5e18c2a4852 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -130,19 +130,16 @@ EXPORT_SYMBOL_GPL(af_alg_release);
130void af_alg_release_parent(struct sock *sk) 130void af_alg_release_parent(struct sock *sk)
131{ 131{
132 struct alg_sock *ask = alg_sk(sk); 132 struct alg_sock *ask = alg_sk(sk);
133 bool last; 133 unsigned int nokey = ask->nokey_refcnt;
134 bool last = nokey && !ask->refcnt;
134 135
135 sk = ask->parent; 136 sk = ask->parent;
136
137 if (ask->nokey_refcnt && !ask->refcnt) {
138 sock_put(sk);
139 return;
140 }
141
142 ask = alg_sk(sk); 137 ask = alg_sk(sk);
143 138
144 lock_sock(sk); 139 lock_sock(sk);
145 last = !--ask->refcnt; 140 ask->nokey_refcnt -= nokey;
141 if (!last)
142 last = !--ask->refcnt;
146 release_sock(sk); 143 release_sock(sk);
147 144
148 if (last) 145 if (last)
@@ -188,7 +185,7 @@ static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
188 185
189 err = -EBUSY; 186 err = -EBUSY;
190 lock_sock(sk); 187 lock_sock(sk);
191 if (ask->refcnt) 188 if (ask->refcnt | ask->nokey_refcnt)
192 goto unlock; 189 goto unlock;
193 190
194 swap(ask->type, type); 191 swap(ask->type, type);
@@ -306,6 +303,7 @@ int af_alg_accept(struct sock *sk, struct socket *newsock)
306 303
307 if (nokey || !ask->refcnt++) 304 if (nokey || !ask->refcnt++)
308 sock_hold(sk); 305 sock_hold(sk);
306 ask->nokey_refcnt += nokey;
309 alg_sk(sk2)->parent = sk; 307 alg_sk(sk2)->parent = sk;
310 alg_sk(sk2)->type = type; 308 alg_sk(sk2)->type = type;
311 alg_sk(sk2)->nokey_refcnt = nokey; 309 alg_sk(sk2)->nokey_refcnt = nokey;