aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2005-05-03 18:30:05 -0400
committerDavid S. Miller <davem@davemloft.net>2005-05-03 18:30:05 -0400
commit09e14305982efc2f3b509d3c50ef5dcbff64a998 (patch)
tree7829c8b212a84e793ebf2d5bd0ceb68283c7b79e
parent2a0a6ebee1d68552152ae8d4aeda91d806995dec (diff)
[NETLINK]: Fix infinite loops in synchronous netlink changes.
The qlen should continue to decrement, even if we pop partially processed SKBs back onto the receive queue. Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/core/rtnetlink.c7
-rw-r--r--net/decnet/netfilter/dn_rtmsg.c2
-rw-r--r--net/xfrm/xfrm_user.c7
3 files changed, 7 insertions, 9 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 6e1ab1e34b2e..75b6d33b5292 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -626,14 +626,13 @@ static void rtnetlink_rcv(struct sock *sk, int len)
626 if (qlen > skb_queue_len(&sk->sk_receive_queue)) 626 if (qlen > skb_queue_len(&sk->sk_receive_queue))
627 qlen = skb_queue_len(&sk->sk_receive_queue); 627 qlen = skb_queue_len(&sk->sk_receive_queue);
628 628
629 while (qlen--) { 629 for (; qlen; qlen--) {
630 skb = skb_dequeue(&sk->sk_receive_queue); 630 skb = skb_dequeue(&sk->sk_receive_queue);
631 if (rtnetlink_rcv_skb(skb)) { 631 if (rtnetlink_rcv_skb(skb)) {
632 if (skb->len) { 632 if (skb->len)
633 skb_queue_head(&sk->sk_receive_queue, 633 skb_queue_head(&sk->sk_receive_queue,
634 skb); 634 skb);
635 qlen++; 635 else
636 } else
637 kfree_skb(skb); 636 kfree_skb(skb);
638 break; 637 break;
639 } 638 }
diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c
index 101ddef9ba9a..284a9998e53d 100644
--- a/net/decnet/netfilter/dn_rtmsg.c
+++ b/net/decnet/netfilter/dn_rtmsg.c
@@ -121,7 +121,7 @@ static void dnrmg_receive_user_sk(struct sock *sk, int len)
121 struct sk_buff *skb; 121 struct sk_buff *skb;
122 unsigned int qlen = skb_queue_len(&sk->sk_receive_queue); 122 unsigned int qlen = skb_queue_len(&sk->sk_receive_queue);
123 123
124 while (qlen-- && (skb = skb_dequeue(&sk->sk_receive_queue))) { 124 for (; qlen && (skb = skb_dequeue(&sk->sk_receive_queue)); qlen--) {
125 dnrmg_receive_user_skb(skb); 125 dnrmg_receive_user_skb(skb);
126 kfree_skb(skb); 126 kfree_skb(skb);
127 } 127 }
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index dab112f1dd8a..e8740a4a1d78 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -1018,14 +1018,13 @@ static void xfrm_netlink_rcv(struct sock *sk, int len)
1018 if (qlen > skb_queue_len(&sk->sk_receive_queue)) 1018 if (qlen > skb_queue_len(&sk->sk_receive_queue))
1019 qlen = skb_queue_len(&sk->sk_receive_queue); 1019 qlen = skb_queue_len(&sk->sk_receive_queue);
1020 1020
1021 while (qlen--) { 1021 for (; qlen; qlen--) {
1022 skb = skb_dequeue(&sk->sk_receive_queue); 1022 skb = skb_dequeue(&sk->sk_receive_queue);
1023 if (xfrm_user_rcv_skb(skb)) { 1023 if (xfrm_user_rcv_skb(skb)) {
1024 if (skb->len) { 1024 if (skb->len)
1025 skb_queue_head(&sk->sk_receive_queue, 1025 skb_queue_head(&sk->sk_receive_queue,
1026 skb); 1026 skb);
1027 qlen++; 1027 else
1028 } else
1029 kfree_skb(skb); 1028 kfree_skb(skb);
1030 break; 1029 break;
1031 } 1030 }