Browse Source

net/smc: return 0 for ioctl calls in states INIT and CLOSED

A connected SMC-socket contains addresses of descriptors for the
send buffer and the rmb (receive buffer). Fields of these descriptors
are used to determine the answer for certain ioctl requests.
Add extra handling for unconnected SMC socket states without valid
buffer descriptor addresses.

Signed-off-by: Ursula Braun <ubraun@linux.ibm.com>
Reported-by: syzbot+e6714328fda813fc670f@syzkaller.appspotmail.com
Signed-off-by: David S. Miller <davem@davemloft.net>
Ursula Braun 7 years ago
parent
commit
2351abe6f8
1 changed files with 15 additions and 3 deletions
  1. 15 3
      net/smc/af_smc.c

+ 15 - 3
net/smc/af_smc.c

@@ -1490,20 +1490,32 @@ static int smc_ioctl(struct socket *sock, unsigned int cmd,
 	case SIOCINQ: /* same as FIONREAD */
 	case SIOCINQ: /* same as FIONREAD */
 		if (smc->sk.sk_state == SMC_LISTEN)
 		if (smc->sk.sk_state == SMC_LISTEN)
 			return -EINVAL;
 			return -EINVAL;
-		answ = atomic_read(&smc->conn.bytes_to_rcv);
+		if (smc->sk.sk_state == SMC_INIT ||
+		    smc->sk.sk_state == SMC_CLOSED)
+			answ = 0;
+		else
+			answ = atomic_read(&smc->conn.bytes_to_rcv);
 		break;
 		break;
 	case SIOCOUTQ:
 	case SIOCOUTQ:
 		/* output queue size (not send + not acked) */
 		/* output queue size (not send + not acked) */
 		if (smc->sk.sk_state == SMC_LISTEN)
 		if (smc->sk.sk_state == SMC_LISTEN)
 			return -EINVAL;
 			return -EINVAL;
-		answ = smc->conn.sndbuf_desc->len -
+		if (smc->sk.sk_state == SMC_INIT ||
+		    smc->sk.sk_state == SMC_CLOSED)
+			answ = 0;
+		else
+			answ = smc->conn.sndbuf_desc->len -
 					atomic_read(&smc->conn.sndbuf_space);
 					atomic_read(&smc->conn.sndbuf_space);
 		break;
 		break;
 	case SIOCOUTQNSD:
 	case SIOCOUTQNSD:
 		/* output queue size (not send only) */
 		/* output queue size (not send only) */
 		if (smc->sk.sk_state == SMC_LISTEN)
 		if (smc->sk.sk_state == SMC_LISTEN)
 			return -EINVAL;
 			return -EINVAL;
-		answ = smc_tx_prepared_sends(&smc->conn);
+		if (smc->sk.sk_state == SMC_INIT ||
+		    smc->sk.sk_state == SMC_CLOSED)
+			answ = 0;
+		else
+			answ = smc_tx_prepared_sends(&smc->conn);
 		break;
 		break;
 	default:
 	default:
 		return -ENOIOCTLCMD;
 		return -ENOIOCTLCMD;