llc: Fix double accounting of received packets

llc_sap_rcv was being preceded by skb_set_owner_r, then calling
llc_state_process that calls sock_queue_rcv_skb, that in turn calls
skb_set_owner_r again making the space allowed to be used by the socket to be
leaked, making the socket to get stuck.

Fix it by setting skb->sk at llc_sap_rcv and leave the accounting to be done
only at sock_queue_rcv_skb.

Reported-by: Dmitry Petukhov <dmgenp@gmail.com>
Tested-by: Dmitry Petukhov <dmgenp@gmail.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Arnaldo Carvalho de Melo 2008-05-30 02:57:29 -07:00 коммит произвёл David S. Miller
Родитель 12293bf911
Коммит 3446b9d57e
1 изменённых файлов: 5 добавлений и 5 удалений

Просмотреть файл

@ -286,12 +286,14 @@ void llc_build_and_send_xid_pkt(struct llc_sap *sap, struct sk_buff *skb,
* *
* Sends received pdus to the sap state machine. * Sends received pdus to the sap state machine.
*/ */
static void llc_sap_rcv(struct llc_sap *sap, struct sk_buff *skb) static void llc_sap_rcv(struct llc_sap *sap, struct sk_buff *skb,
struct sock *sk)
{ {
struct llc_sap_state_ev *ev = llc_sap_ev(skb); struct llc_sap_state_ev *ev = llc_sap_ev(skb);
ev->type = LLC_SAP_EV_TYPE_PDU; ev->type = LLC_SAP_EV_TYPE_PDU;
ev->reason = 0; ev->reason = 0;
skb->sk = sk;
llc_sap_state_process(sap, skb); llc_sap_state_process(sap, skb);
} }
@ -360,8 +362,7 @@ static void llc_sap_mcast(struct llc_sap *sap,
break; break;
sock_hold(sk); sock_hold(sk);
skb_set_owner_r(skb1, sk); llc_sap_rcv(sap, skb1, sk);
llc_sap_rcv(sap, skb1);
sock_put(sk); sock_put(sk);
} }
read_unlock_bh(&sap->sk_list.lock); read_unlock_bh(&sap->sk_list.lock);
@ -381,8 +382,7 @@ void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb)
} else { } else {
struct sock *sk = llc_lookup_dgram(sap, &laddr); struct sock *sk = llc_lookup_dgram(sap, &laddr);
if (sk) { if (sk) {
skb_set_owner_r(skb, sk); llc_sap_rcv(sap, skb, sk);
llc_sap_rcv(sap, skb);
sock_put(sk); sock_put(sk);
} else } else
kfree_skb(skb); kfree_skb(skb);