aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm
diff options
context:
space:
mode:
authorSteffen Klassert <steffen.klassert@secunet.com>2013-10-08 04:49:45 -0400
committerSteffen Klassert <steffen.klassert@secunet.com>2013-10-08 04:49:45 -0400
commite7d8f6cb2f8735693396872f4608bbe305e8baee (patch)
treeec1e047b8f4a584cea14b3b9dc876b7caf3c5851 /net/xfrm
parentcd808fc9a6c7cd3a4311d9d2cffc4adbeaef5f6c (diff)
xfrm: Add refcount handling to queued policies
We need to ensure that policies can't go away as long as the hold timer is armed, so take a refcont when we arm the timer and drop one if we delete it. Bug was introduced with git commit a0073fe18 ("xfrm: Add a state resolution packet queue") Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Diffstat (limited to 'net/xfrm')
-rw-r--r--net/xfrm/xfrm_policy.c24
1 files changed, 17 insertions, 7 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index ed38d5d81f9e..5f9be976770e 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -334,7 +334,8 @@ static void xfrm_policy_kill(struct xfrm_policy *policy)
334 334
335 atomic_inc(&policy->genid); 335 atomic_inc(&policy->genid);
336 336
337 del_timer(&policy->polq.hold_timer); 337 if (del_timer(&policy->polq.hold_timer))
338 xfrm_pol_put(policy);
338 xfrm_queue_purge(&policy->polq.hold_queue); 339 xfrm_queue_purge(&policy->polq.hold_queue);
339 340
340 if (del_timer(&policy->timer)) 341 if (del_timer(&policy->timer))
@@ -589,7 +590,8 @@ static void xfrm_policy_requeue(struct xfrm_policy *old,
589 590
590 spin_lock_bh(&pq->hold_queue.lock); 591 spin_lock_bh(&pq->hold_queue.lock);
591 skb_queue_splice_init(&pq->hold_queue, &list); 592 skb_queue_splice_init(&pq->hold_queue, &list);
592 del_timer(&pq->hold_timer); 593 if (del_timer(&pq->hold_timer))
594 xfrm_pol_put(old);
593 spin_unlock_bh(&pq->hold_queue.lock); 595 spin_unlock_bh(&pq->hold_queue.lock);
594 596
595 if (skb_queue_empty(&list)) 597 if (skb_queue_empty(&list))
@@ -600,7 +602,8 @@ static void xfrm_policy_requeue(struct xfrm_policy *old,
600 spin_lock_bh(&pq->hold_queue.lock); 602 spin_lock_bh(&pq->hold_queue.lock);
601 skb_queue_splice(&list, &pq->hold_queue); 603 skb_queue_splice(&list, &pq->hold_queue);
602 pq->timeout = XFRM_QUEUE_TMO_MIN; 604 pq->timeout = XFRM_QUEUE_TMO_MIN;
603 mod_timer(&pq->hold_timer, jiffies); 605 if (!mod_timer(&pq->hold_timer, jiffies))
606 xfrm_pol_hold(new);
604 spin_unlock_bh(&pq->hold_queue.lock); 607 spin_unlock_bh(&pq->hold_queue.lock);
605} 608}
606 609
@@ -1787,8 +1790,9 @@ static void xfrm_policy_queue_process(unsigned long arg)
1787 goto purge_queue; 1790 goto purge_queue;
1788 1791
1789 pq->timeout = pq->timeout << 1; 1792 pq->timeout = pq->timeout << 1;
1790 mod_timer(&pq->hold_timer, jiffies + pq->timeout); 1793 if (!mod_timer(&pq->hold_timer, jiffies + pq->timeout))
1791 return; 1794 xfrm_pol_hold(pol);
1795 goto out;
1792 } 1796 }
1793 1797
1794 dst_release(dst); 1798 dst_release(dst);
@@ -1819,11 +1823,14 @@ static void xfrm_policy_queue_process(unsigned long arg)
1819 err = dst_output(skb); 1823 err = dst_output(skb);
1820 } 1824 }
1821 1825
1826out:
1827 xfrm_pol_put(pol);
1822 return; 1828 return;
1823 1829
1824purge_queue: 1830purge_queue:
1825 pq->timeout = 0; 1831 pq->timeout = 0;
1826 xfrm_queue_purge(&pq->hold_queue); 1832 xfrm_queue_purge(&pq->hold_queue);
1833 xfrm_pol_put(pol);
1827} 1834}
1828 1835
1829static int xdst_queue_output(struct sk_buff *skb) 1836static int xdst_queue_output(struct sk_buff *skb)
@@ -1831,7 +1838,8 @@ static int xdst_queue_output(struct sk_buff *skb)
1831 unsigned long sched_next; 1838 unsigned long sched_next;
1832 struct dst_entry *dst = skb_dst(skb); 1839 struct dst_entry *dst = skb_dst(skb);
1833 struct xfrm_dst *xdst = (struct xfrm_dst *) dst; 1840 struct xfrm_dst *xdst = (struct xfrm_dst *) dst;
1834 struct xfrm_policy_queue *pq = &xdst->pols[0]->polq; 1841 struct xfrm_policy *pol = xdst->pols[0];
1842 struct xfrm_policy_queue *pq = &pol->polq;
1835 1843
1836 if (pq->hold_queue.qlen > XFRM_MAX_QUEUE_LEN) { 1844 if (pq->hold_queue.qlen > XFRM_MAX_QUEUE_LEN) {
1837 kfree_skb(skb); 1845 kfree_skb(skb);
@@ -1850,10 +1858,12 @@ static int xdst_queue_output(struct sk_buff *skb)
1850 if (del_timer(&pq->hold_timer)) { 1858 if (del_timer(&pq->hold_timer)) {
1851 if (time_before(pq->hold_timer.expires, sched_next)) 1859 if (time_before(pq->hold_timer.expires, sched_next))
1852 sched_next = pq->hold_timer.expires; 1860 sched_next = pq->hold_timer.expires;
1861 xfrm_pol_put(pol);
1853 } 1862 }
1854 1863
1855 __skb_queue_tail(&pq->hold_queue, skb); 1864 __skb_queue_tail(&pq->hold_queue, skb);
1856 mod_timer(&pq->hold_timer, sched_next); 1865 if (!mod_timer(&pq->hold_timer, sched_next))
1866 xfrm_pol_hold(pol);
1857 1867
1858 spin_unlock_bh(&pq->hold_queue.lock); 1868 spin_unlock_bh(&pq->hold_queue.lock);
1859 1869