diff options
author | Ursula Braun <ursula.braun@linux.ibm.com> | 2018-07-16 07:56:52 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-07-16 17:45:13 -0400 |
commit | 1992d99882afda6dc17f9d49c06150856a91282f (patch) | |
tree | aa249871b27d3e80f1148d7d481419bad67a7586 /net/smc | |
parent | bd598d205055dfe32698261efe1b1b736d9a7173 (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.c | 19 |
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 | } |