forked from mirrors/linux
		
	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>
This commit is contained in:
		
							parent
							
								
									bd598d2050
								
							
						
					
					
						commit
						1992d99882
					
				
					 1 changed files with 15 additions and 4 deletions
				
			
		| 
						 | 
				
			
			@ -1524,10 +1524,13 @@ static int smc_ioctl(struct socket *sock, unsigned int cmd,
 | 
			
		|||
			return -EBADF;
 | 
			
		||||
		return smc->clcsock->ops->ioctl(smc->clcsock, cmd, arg);
 | 
			
		||||
	}
 | 
			
		||||
	lock_sock(&smc->sk);
 | 
			
		||||
	switch (cmd) {
 | 
			
		||||
	case SIOCINQ: /* same as FIONREAD */
 | 
			
		||||
		if (smc->sk.sk_state == SMC_LISTEN)
 | 
			
		||||
		if (smc->sk.sk_state == SMC_LISTEN) {
 | 
			
		||||
			release_sock(&smc->sk);
 | 
			
		||||
			return -EINVAL;
 | 
			
		||||
		}
 | 
			
		||||
		if (smc->sk.sk_state == SMC_INIT ||
 | 
			
		||||
		    smc->sk.sk_state == SMC_CLOSED)
 | 
			
		||||
			answ = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -1536,8 +1539,10 @@ static int smc_ioctl(struct socket *sock, unsigned int cmd,
 | 
			
		|||
		break;
 | 
			
		||||
	case SIOCOUTQ:
 | 
			
		||||
		/* output queue size (not send + not acked) */
 | 
			
		||||
		if (smc->sk.sk_state == SMC_LISTEN)
 | 
			
		||||
		if (smc->sk.sk_state == SMC_LISTEN) {
 | 
			
		||||
			release_sock(&smc->sk);
 | 
			
		||||
			return -EINVAL;
 | 
			
		||||
		}
 | 
			
		||||
		if (smc->sk.sk_state == SMC_INIT ||
 | 
			
		||||
		    smc->sk.sk_state == SMC_CLOSED)
 | 
			
		||||
			answ = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -1547,8 +1552,10 @@ static int smc_ioctl(struct socket *sock, unsigned int cmd,
 | 
			
		|||
		break;
 | 
			
		||||
	case SIOCOUTQNSD:
 | 
			
		||||
		/* output queue size (not send only) */
 | 
			
		||||
		if (smc->sk.sk_state == SMC_LISTEN)
 | 
			
		||||
		if (smc->sk.sk_state == SMC_LISTEN) {
 | 
			
		||||
			release_sock(&smc->sk);
 | 
			
		||||
			return -EINVAL;
 | 
			
		||||
		}
 | 
			
		||||
		if (smc->sk.sk_state == SMC_INIT ||
 | 
			
		||||
		    smc->sk.sk_state == SMC_CLOSED)
 | 
			
		||||
			answ = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -1556,8 +1563,10 @@ static int smc_ioctl(struct socket *sock, unsigned int cmd,
 | 
			
		|||
			answ = smc_tx_prepared_sends(&smc->conn);
 | 
			
		||||
		break;
 | 
			
		||||
	case SIOCATMARK:
 | 
			
		||||
		if (smc->sk.sk_state == SMC_LISTEN)
 | 
			
		||||
		if (smc->sk.sk_state == SMC_LISTEN) {
 | 
			
		||||
			release_sock(&smc->sk);
 | 
			
		||||
			return -EINVAL;
 | 
			
		||||
		}
 | 
			
		||||
		if (smc->sk.sk_state == SMC_INIT ||
 | 
			
		||||
		    smc->sk.sk_state == SMC_CLOSED) {
 | 
			
		||||
			answ = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -1573,8 +1582,10 @@ static int smc_ioctl(struct socket *sock, unsigned int cmd,
 | 
			
		|||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		release_sock(&smc->sk);
 | 
			
		||||
		return -ENOIOCTLCMD;
 | 
			
		||||
	}
 | 
			
		||||
	release_sock(&smc->sk);
 | 
			
		||||
 | 
			
		||||
	return put_user(answ, (int __user *)arg);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue