aboutsummaryrefslogtreecommitdiffstats
path: root/net/smc
diff options
context:
space:
mode:
authorUrsula Braun <ursula.braun@linux.ibm.com>2018-07-16 07:56:52 -0400
committerDavid S. Miller <davem@davemloft.net>2018-07-16 17:45:13 -0400
commit1992d99882afda6dc17f9d49c06150856a91282f (patch)
treeaa249871b27d3e80f1148d7d481419bad67a7586 /net/smc
parentbd598d205055dfe32698261efe1b1b736d9a7173 (diff)
net/smc: take sock lock in smc_ioctl()
SMC ioctl processing requires the sock lock to work properly in all thinkable scenarios. Problem has been found with RaceFuzzer and fixes: KASAN: null-ptr-deref Read in smc_ioctl Reported-by: Byoungyoung Lee <lifeasageek@gmail.com> Reported-by: syzbot+35b2c5aa76fd398b9fd4@syzkaller.appspotmail.com Signed-off-by: Ursula Braun <ubraun@linux.ibm.com> Reviewed-by: Stefano Brivio <sbrivio@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/smc')
-rw-r--r--net/smc/af_smc.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index 5334157f5065..c12a7fc18f56 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -1524,10 +1524,13 @@ static int smc_ioctl(struct socket *sock, unsigned int cmd,
1524 return -EBADF; 1524 return -EBADF;
1525 return smc->clcsock->ops->ioctl(smc->clcsock, cmd, arg); 1525 return smc->clcsock->ops->ioctl(smc->clcsock, cmd, arg);
1526 } 1526 }
1527 lock_sock(&smc->sk);
1527 switch (cmd) { 1528 switch (cmd) {
1528 case SIOCINQ: /* same as FIONREAD */ 1529 case SIOCINQ: /* same as FIONREAD */
1529 if (smc->sk.sk_state == SMC_LISTEN) 1530 if (smc->sk.sk_state == SMC_LISTEN) {
1531 release_sock(&smc->sk);
1530 return -EINVAL; 1532 return -EINVAL;
1533 }
1531 if (smc->sk.sk_state == SMC_INIT || 1534 if (smc->sk.sk_state == SMC_INIT ||
1532 smc->sk.sk_state == SMC_CLOSED) 1535 smc->sk.sk_state == SMC_CLOSED)
1533 answ = 0; 1536 answ = 0;
@@ -1536,8 +1539,10 @@ static int smc_ioctl(struct socket *sock, unsigned int cmd,
1536 break; 1539 break;
1537 case SIOCOUTQ: 1540 case SIOCOUTQ:
1538 /* output queue size (not send + not acked) */ 1541 /* output queue size (not send + not acked) */
1539 if (smc->sk.sk_state == SMC_LISTEN) 1542 if (smc->sk.sk_state == SMC_LISTEN) {
1543 release_sock(&smc->sk);
1540 return -EINVAL; 1544 return -EINVAL;
1545 }
1541 if (smc->sk.sk_state == SMC_INIT || 1546 if (smc->sk.sk_state == SMC_INIT ||
1542 smc->sk.sk_state == SMC_CLOSED) 1547 smc->sk.sk_state == SMC_CLOSED)
1543 answ = 0; 1548 answ = 0;
@@ -1547,8 +1552,10 @@ static int smc_ioctl(struct socket *sock, unsigned int cmd,
1547 break; 1552 break;
1548 case SIOCOUTQNSD: 1553 case SIOCOUTQNSD:
1549 /* output queue size (not send only) */ 1554 /* output queue size (not send only) */
1550 if (smc->sk.sk_state == SMC_LISTEN) 1555 if (smc->sk.sk_state == SMC_LISTEN) {
1556 release_sock(&smc->sk);
1551 return -EINVAL; 1557 return -EINVAL;
1558 }
1552 if (smc->sk.sk_state == SMC_INIT || 1559 if (smc->sk.sk_state == SMC_INIT ||
1553 smc->sk.sk_state == SMC_CLOSED) 1560 smc->sk.sk_state == SMC_CLOSED)
1554 answ = 0; 1561 answ = 0;
@@ -1556,8 +1563,10 @@ static int smc_ioctl(struct socket *sock, unsigned int cmd,
1556 answ = smc_tx_prepared_sends(&smc->conn); 1563 answ = smc_tx_prepared_sends(&smc->conn);
1557 break; 1564 break;
1558 case SIOCATMARK: 1565 case SIOCATMARK:
1559 if (smc->sk.sk_state == SMC_LISTEN) 1566 if (smc->sk.sk_state == SMC_LISTEN) {
1567 release_sock(&smc->sk);
1560 return -EINVAL; 1568 return -EINVAL;
1569 }
1561 if (smc->sk.sk_state == SMC_INIT || 1570 if (smc->sk.sk_state == SMC_INIT ||
1562 smc->sk.sk_state == SMC_CLOSED) { 1571 smc->sk.sk_state == SMC_CLOSED) {
1563 answ = 0; 1572 answ = 0;
@@ -1573,8 +1582,10 @@ static int smc_ioctl(struct socket *sock, unsigned int cmd,
1573 } 1582 }
1574 break; 1583 break;
1575 default: 1584 default:
1585 release_sock(&smc->sk);
1576 return -ENOIOCTLCMD; 1586 return -ENOIOCTLCMD;
1577 } 1587 }
1588 release_sock(&smc->sk);
1578 1589
1579 return put_user(answ, (int __user *)arg); 1590 return put_user(answ, (int __user *)arg);
1580} 1591}