diff options
author | Ursula Braun <ubraun@linux.ibm.com> | 2018-05-02 10:53:56 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-05-02 13:27:19 -0400 |
commit | 784813aed6ba24a1f24e7e11d9d0f208cee37a7d (patch) | |
tree | dbcd307055b4f0361d8b426306746b0aa09181ea /net | |
parent | af3e0fcf78879f718c5f73df0814951bd7057d34 (diff) |
net/smc: restrict non-blocking connect finish
The smc_poll code tries to finish connect() if the socket is in
state SMC_INIT and polling of the internal CLC-socket returns with
EPOLLOUT. This makes sense for a select/poll call following a connect
call, but not without preceding connect().
With this patch smc_poll starts connect logic only, if the CLC-socket
is no longer in its initial state TCP_CLOSE.
In addition, a poll error on the internal CLC-socket is always
propagated to the SMC socket.
With this patch the code path mentioned by syzbot
https://syzkaller.appspot.com/bug?extid=03faa2dc16b8b64be396
is no longer possible.
Signed-off-by: Ursula Braun <ubraun@linux.ibm.com>
Reported-by: syzbot+03faa2dc16b8b64be396@syzkaller.appspotmail.com
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/smc/af_smc.c | 14 |
1 files changed, 8 insertions, 6 deletions
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c index 4470501374bf..8b4c059bd13b 100644 --- a/net/smc/af_smc.c +++ b/net/smc/af_smc.c | |||
@@ -1166,13 +1166,15 @@ static __poll_t smc_poll(struct file *file, struct socket *sock, | |||
1166 | /* delegate to CLC child sock */ | 1166 | /* delegate to CLC child sock */ |
1167 | release_sock(sk); | 1167 | release_sock(sk); |
1168 | mask = smc->clcsock->ops->poll(file, smc->clcsock, wait); | 1168 | mask = smc->clcsock->ops->poll(file, smc->clcsock, wait); |
1169 | /* if non-blocking connect finished ... */ | ||
1170 | lock_sock(sk); | 1169 | lock_sock(sk); |
1171 | if ((sk->sk_state == SMC_INIT) && (mask & EPOLLOUT)) { | 1170 | sk->sk_err = smc->clcsock->sk->sk_err; |
1172 | sk->sk_err = smc->clcsock->sk->sk_err; | 1171 | if (sk->sk_err) { |
1173 | if (sk->sk_err) { | 1172 | mask |= EPOLLERR; |
1174 | mask |= EPOLLERR; | 1173 | } else { |
1175 | } else { | 1174 | /* if non-blocking connect finished ... */ |
1175 | if (sk->sk_state == SMC_INIT && | ||
1176 | mask & EPOLLOUT && | ||
1177 | smc->clcsock->sk->sk_state != TCP_CLOSE) { | ||
1176 | rc = smc_connect_rdma(smc); | 1178 | rc = smc_connect_rdma(smc); |
1177 | if (rc < 0) | 1179 | if (rc < 0) |
1178 | mask |= EPOLLERR; | 1180 | mask |= EPOLLERR; |