Skip to content

Commit 7314f54

Browse files
congwangdavem330
authored andcommitted
netrom: fix locking in nr_find_socket()
nr_find_socket(), nr_find_peer() and nr_find_listener() lock the sock after finding it in the global list. However, the call path requires BH disabled for the sock lock consistently. Actually the locking is unnecessary at this point, we can just hold the sock refcnt to make sure it is not gone after we unlock the global list, and lock it later only when needed. Reported-and-tested-by: syzbot+f621cda8b7e598908efa@syzkaller.appspotmail.com Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent d5c7c74 commit 7314f54

File tree

1 file changed

+10
-5
lines changed

1 file changed

+10
-5
lines changed

net/netrom/af_netrom.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ static struct sock *nr_find_listener(ax25_address *addr)
153153
sk_for_each(s, &nr_list)
154154
if (!ax25cmp(&nr_sk(s)->source_addr, addr) &&
155155
s->sk_state == TCP_LISTEN) {
156-
bh_lock_sock(s);
156+
sock_hold(s);
157157
goto found;
158158
}
159159
s = NULL;
@@ -174,7 +174,7 @@ static struct sock *nr_find_socket(unsigned char index, unsigned char id)
174174
struct nr_sock *nr = nr_sk(s);
175175

176176
if (nr->my_index == index && nr->my_id == id) {
177-
bh_lock_sock(s);
177+
sock_hold(s);
178178
goto found;
179179
}
180180
}
@@ -198,7 +198,7 @@ static struct sock *nr_find_peer(unsigned char index, unsigned char id,
198198

199199
if (nr->your_index == index && nr->your_id == id &&
200200
!ax25cmp(&nr->dest_addr, dest)) {
201-
bh_lock_sock(s);
201+
sock_hold(s);
202202
goto found;
203203
}
204204
}
@@ -224,7 +224,7 @@ static unsigned short nr_find_next_circuit(void)
224224
if (i != 0 && j != 0) {
225225
if ((sk=nr_find_socket(i, j)) == NULL)
226226
break;
227-
bh_unlock_sock(sk);
227+
sock_put(sk);
228228
}
229229

230230
id++;
@@ -920,6 +920,7 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev)
920920
}
921921

922922
if (sk != NULL) {
923+
bh_lock_sock(sk);
923924
skb_reset_transport_header(skb);
924925

925926
if (frametype == NR_CONNACK && skb->len == 22)
@@ -929,6 +930,7 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev)
929930

930931
ret = nr_process_rx_frame(sk, skb);
931932
bh_unlock_sock(sk);
933+
sock_put(sk);
932934
return ret;
933935
}
934936

@@ -960,10 +962,12 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev)
960962
(make = nr_make_new(sk)) == NULL) {
961963
nr_transmit_refusal(skb, 0);
962964
if (sk)
963-
bh_unlock_sock(sk);
965+
sock_put(sk);
964966
return 0;
965967
}
966968

969+
bh_lock_sock(sk);
970+
967971
window = skb->data[20];
968972

969973
skb->sk = make;
@@ -1016,6 +1020,7 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev)
10161020
sk->sk_data_ready(sk);
10171021

10181022
bh_unlock_sock(sk);
1023+
sock_put(sk);
10191024

10201025
nr_insert_socket(make);
10211026

0 commit comments

Comments
 (0)