mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	netrom: Decrease sock refcount when sock timers expire
Commit63346650c1("netrom: switch to sock timer API") switched to use sock timer API. It replaces mod_timer() by sk_reset_timer(), and del_timer() by sk_stop_timer(). Function sk_reset_timer() will increase the refcount of sock if it is called on an inactive timer, hence, in case the timer expires, we need to decrease the refcount ourselves in the handler, otherwise, the sock refcount will be unbalanced and the sock will never be freed. Signed-off-by: Nguyen Dinh Phi <phind.uet@gmail.com> Reported-by: syzbot+10f1194569953b72f1ae@syzkaller.appspotmail.com Fixes:63346650c1("netrom: switch to sock timer API") Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									2f3fdd8d48
								
							
						
					
					
						commit
						517a16b1a8
					
				
					 1 changed files with 11 additions and 9 deletions
				
			
		| 
						 | 
				
			
			@ -121,11 +121,9 @@ static void nr_heartbeat_expiry(struct timer_list *t)
 | 
			
		|||
		   is accepted() it isn't 'dead' so doesn't get removed. */
 | 
			
		||||
		if (sock_flag(sk, SOCK_DESTROY) ||
 | 
			
		||||
		    (sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_DEAD))) {
 | 
			
		||||
			sock_hold(sk);
 | 
			
		||||
			bh_unlock_sock(sk);
 | 
			
		||||
			nr_destroy_socket(sk);
 | 
			
		||||
			sock_put(sk);
 | 
			
		||||
			return;
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -146,6 +144,8 @@ static void nr_heartbeat_expiry(struct timer_list *t)
 | 
			
		|||
 | 
			
		||||
	nr_start_heartbeat(sk);
 | 
			
		||||
	bh_unlock_sock(sk);
 | 
			
		||||
out:
 | 
			
		||||
	sock_put(sk);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void nr_t2timer_expiry(struct timer_list *t)
 | 
			
		||||
| 
						 | 
				
			
			@ -159,6 +159,7 @@ static void nr_t2timer_expiry(struct timer_list *t)
 | 
			
		|||
		nr_enquiry_response(sk);
 | 
			
		||||
	}
 | 
			
		||||
	bh_unlock_sock(sk);
 | 
			
		||||
	sock_put(sk);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void nr_t4timer_expiry(struct timer_list *t)
 | 
			
		||||
| 
						 | 
				
			
			@ -169,6 +170,7 @@ static void nr_t4timer_expiry(struct timer_list *t)
 | 
			
		|||
	bh_lock_sock(sk);
 | 
			
		||||
	nr_sk(sk)->condition &= ~NR_COND_PEER_RX_BUSY;
 | 
			
		||||
	bh_unlock_sock(sk);
 | 
			
		||||
	sock_put(sk);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void nr_idletimer_expiry(struct timer_list *t)
 | 
			
		||||
| 
						 | 
				
			
			@ -197,6 +199,7 @@ static void nr_idletimer_expiry(struct timer_list *t)
 | 
			
		|||
		sock_set_flag(sk, SOCK_DEAD);
 | 
			
		||||
	}
 | 
			
		||||
	bh_unlock_sock(sk);
 | 
			
		||||
	sock_put(sk);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void nr_t1timer_expiry(struct timer_list *t)
 | 
			
		||||
| 
						 | 
				
			
			@ -209,8 +212,7 @@ static void nr_t1timer_expiry(struct timer_list *t)
 | 
			
		|||
	case NR_STATE_1:
 | 
			
		||||
		if (nr->n2count == nr->n2) {
 | 
			
		||||
			nr_disconnect(sk, ETIMEDOUT);
 | 
			
		||||
			bh_unlock_sock(sk);
 | 
			
		||||
			return;
 | 
			
		||||
			goto out;
 | 
			
		||||
		} else {
 | 
			
		||||
			nr->n2count++;
 | 
			
		||||
			nr_write_internal(sk, NR_CONNREQ);
 | 
			
		||||
| 
						 | 
				
			
			@ -220,8 +222,7 @@ static void nr_t1timer_expiry(struct timer_list *t)
 | 
			
		|||
	case NR_STATE_2:
 | 
			
		||||
		if (nr->n2count == nr->n2) {
 | 
			
		||||
			nr_disconnect(sk, ETIMEDOUT);
 | 
			
		||||
			bh_unlock_sock(sk);
 | 
			
		||||
			return;
 | 
			
		||||
			goto out;
 | 
			
		||||
		} else {
 | 
			
		||||
			nr->n2count++;
 | 
			
		||||
			nr_write_internal(sk, NR_DISCREQ);
 | 
			
		||||
| 
						 | 
				
			
			@ -231,8 +232,7 @@ static void nr_t1timer_expiry(struct timer_list *t)
 | 
			
		|||
	case NR_STATE_3:
 | 
			
		||||
		if (nr->n2count == nr->n2) {
 | 
			
		||||
			nr_disconnect(sk, ETIMEDOUT);
 | 
			
		||||
			bh_unlock_sock(sk);
 | 
			
		||||
			return;
 | 
			
		||||
			goto out;
 | 
			
		||||
		} else {
 | 
			
		||||
			nr->n2count++;
 | 
			
		||||
			nr_requeue_frames(sk);
 | 
			
		||||
| 
						 | 
				
			
			@ -241,5 +241,7 @@ static void nr_t1timer_expiry(struct timer_list *t)
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	nr_start_t1timer(sk);
 | 
			
		||||
out:
 | 
			
		||||
	bh_unlock_sock(sk);
 | 
			
		||||
	sock_put(sk);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue