aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorUrsula Braun <ubraun@linux.ibm.com>2018-05-02 10:53:56 -0400
committerDavid S. Miller <davem@davemloft.net>2018-05-02 13:27:19 -0400
commit784813aed6ba24a1f24e7e11d9d0f208cee37a7d (patch)
treedbcd307055b4f0361d8b426306746b0aa09181ea /net
parentaf3e0fcf78879f718c5f73df0814951bd7057d34 (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.c14
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;