mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
[PPPOL2TP]: Fix SMP issues in skb reorder queue handling
When walking a session's packet reorder queue, use skb_queue_walk_safe() since the list could be modified inside the loop. Rearrange the unlinking skbs from the reorder queue such that it is done while the queue lock is held in pppol2tp_recv_dequeue() when walking the skb list. A version of this patch was suggested by Jarek Poplawski. Signed-off-by: James Chapman <jchapman@katalix.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
cf3752e2d2
commit
e653181dd6
1 changed files with 8 additions and 3 deletions
|
@ -342,10 +342,11 @@ static struct pppol2tp_tunnel *pppol2tp_tunnel_find(u16 tunnel_id)
|
|||
static void pppol2tp_recv_queue_skb(struct pppol2tp_session *session, struct sk_buff *skb)
|
||||
{
|
||||
struct sk_buff *skbp;
|
||||
struct sk_buff *tmp;
|
||||
u16 ns = PPPOL2TP_SKB_CB(skb)->ns;
|
||||
|
||||
spin_lock_bh(&session->reorder_q.lock);
|
||||
skb_queue_walk(&session->reorder_q, skbp) {
|
||||
skb_queue_walk_safe(&session->reorder_q, skbp, tmp) {
|
||||
if (PPPOL2TP_SKB_CB(skbp)->ns > ns) {
|
||||
__skb_insert(skb, skbp->prev, skbp, &session->reorder_q);
|
||||
PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG,
|
||||
|
@ -371,10 +372,9 @@ static void pppol2tp_recv_dequeue_skb(struct pppol2tp_session *session, struct s
|
|||
int length = PPPOL2TP_SKB_CB(skb)->length;
|
||||
struct sock *session_sock = NULL;
|
||||
|
||||
/* We're about to requeue the skb, so unlink it and return resources
|
||||
/* We're about to requeue the skb, so return resources
|
||||
* to its current owner (a socket receive buffer).
|
||||
*/
|
||||
skb_unlink(skb, &session->reorder_q);
|
||||
skb_orphan(skb);
|
||||
|
||||
tunnel->stats.rx_packets++;
|
||||
|
@ -470,6 +470,11 @@ static void pppol2tp_recv_dequeue(struct pppol2tp_session *session)
|
|||
goto out;
|
||||
}
|
||||
}
|
||||
__skb_unlink(skb, &session->reorder_q);
|
||||
|
||||
/* Process the skb. We release the queue lock while we
|
||||
* do so to let other contexts process the queue.
|
||||
*/
|
||||
spin_unlock_bh(&session->reorder_q.lock);
|
||||
pppol2tp_recv_dequeue_skb(session, skb);
|
||||
spin_lock_bh(&session->reorder_q.lock);
|
||||
|
|
Loading…
Reference in a new issue