diff options
Diffstat (limited to 'net/xfrm')
| -rw-r--r-- | net/xfrm/xfrm_policy.c | 28 | ||||
| -rw-r--r-- | net/xfrm/xfrm_replay.c | 54 | ||||
| -rw-r--r-- | net/xfrm/xfrm_user.c | 5 |
3 files changed, 52 insertions, 35 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index ed38d5d81f9e..76e1873811d4 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 | ||
| @@ -1769,6 +1772,10 @@ static void xfrm_policy_queue_process(unsigned long arg) | |||
| 1769 | 1772 | ||
| 1770 | spin_lock(&pq->hold_queue.lock); | 1773 | spin_lock(&pq->hold_queue.lock); |
| 1771 | skb = skb_peek(&pq->hold_queue); | 1774 | skb = skb_peek(&pq->hold_queue); |
| 1775 | if (!skb) { | ||
| 1776 | spin_unlock(&pq->hold_queue.lock); | ||
| 1777 | goto out; | ||
| 1778 | } | ||
| 1772 | dst = skb_dst(skb); | 1779 | dst = skb_dst(skb); |
| 1773 | sk = skb->sk; | 1780 | sk = skb->sk; |
| 1774 | xfrm_decode_session(skb, &fl, dst->ops->family); | 1781 | xfrm_decode_session(skb, &fl, dst->ops->family); |
| @@ -1787,8 +1794,9 @@ static void xfrm_policy_queue_process(unsigned long arg) | |||
| 1787 | goto purge_queue; | 1794 | goto purge_queue; |
| 1788 | 1795 | ||
| 1789 | pq->timeout = pq->timeout << 1; | 1796 | pq->timeout = pq->timeout << 1; |
| 1790 | mod_timer(&pq->hold_timer, jiffies + pq->timeout); | 1797 | if (!mod_timer(&pq->hold_timer, jiffies + pq->timeout)) |
| 1791 | return; | 1798 | xfrm_pol_hold(pol); |
| 1799 | goto out; | ||
| 1792 | } | 1800 | } |
| 1793 | 1801 | ||
| 1794 | dst_release(dst); | 1802 | dst_release(dst); |
| @@ -1819,11 +1827,14 @@ static void xfrm_policy_queue_process(unsigned long arg) | |||
| 1819 | err = dst_output(skb); | 1827 | err = dst_output(skb); |
| 1820 | } | 1828 | } |
| 1821 | 1829 | ||
| 1830 | out: | ||
| 1831 | xfrm_pol_put(pol); | ||
| 1822 | return; | 1832 | return; |
| 1823 | 1833 | ||
| 1824 | purge_queue: | 1834 | purge_queue: |
| 1825 | pq->timeout = 0; | 1835 | pq->timeout = 0; |
| 1826 | xfrm_queue_purge(&pq->hold_queue); | 1836 | xfrm_queue_purge(&pq->hold_queue); |
| 1837 | xfrm_pol_put(pol); | ||
| 1827 | } | 1838 | } |
| 1828 | 1839 | ||
| 1829 | static int xdst_queue_output(struct sk_buff *skb) | 1840 | static int xdst_queue_output(struct sk_buff *skb) |
| @@ -1831,7 +1842,8 @@ static int xdst_queue_output(struct sk_buff *skb) | |||
| 1831 | unsigned long sched_next; | 1842 | unsigned long sched_next; |
| 1832 | struct dst_entry *dst = skb_dst(skb); | 1843 | struct dst_entry *dst = skb_dst(skb); |
| 1833 | struct xfrm_dst *xdst = (struct xfrm_dst *) dst; | 1844 | struct xfrm_dst *xdst = (struct xfrm_dst *) dst; |
| 1834 | struct xfrm_policy_queue *pq = &xdst->pols[0]->polq; | 1845 | struct xfrm_policy *pol = xdst->pols[0]; |
| 1846 | struct xfrm_policy_queue *pq = &pol->polq; | ||
| 1835 | 1847 | ||
| 1836 | if (pq->hold_queue.qlen > XFRM_MAX_QUEUE_LEN) { | 1848 | if (pq->hold_queue.qlen > XFRM_MAX_QUEUE_LEN) { |
| 1837 | kfree_skb(skb); | 1849 | kfree_skb(skb); |
| @@ -1850,10 +1862,12 @@ static int xdst_queue_output(struct sk_buff *skb) | |||
| 1850 | if (del_timer(&pq->hold_timer)) { | 1862 | if (del_timer(&pq->hold_timer)) { |
| 1851 | if (time_before(pq->hold_timer.expires, sched_next)) | 1863 | if (time_before(pq->hold_timer.expires, sched_next)) |
| 1852 | sched_next = pq->hold_timer.expires; | 1864 | sched_next = pq->hold_timer.expires; |
| 1865 | xfrm_pol_put(pol); | ||
| 1853 | } | 1866 | } |
| 1854 | 1867 | ||
| 1855 | __skb_queue_tail(&pq->hold_queue, skb); | 1868 | __skb_queue_tail(&pq->hold_queue, skb); |
| 1856 | mod_timer(&pq->hold_timer, sched_next); | 1869 | if (!mod_timer(&pq->hold_timer, sched_next)) |
| 1870 | xfrm_pol_hold(pol); | ||
| 1857 | 1871 | ||
| 1858 | spin_unlock_bh(&pq->hold_queue.lock); | 1872 | spin_unlock_bh(&pq->hold_queue.lock); |
| 1859 | 1873 | ||
diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c index 8dafe6d3c6e4..dab57daae408 100644 --- a/net/xfrm/xfrm_replay.c +++ b/net/xfrm/xfrm_replay.c | |||
| @@ -61,9 +61,9 @@ static void xfrm_replay_notify(struct xfrm_state *x, int event) | |||
| 61 | 61 | ||
| 62 | switch (event) { | 62 | switch (event) { |
| 63 | case XFRM_REPLAY_UPDATE: | 63 | case XFRM_REPLAY_UPDATE: |
| 64 | if (x->replay_maxdiff && | 64 | if (!x->replay_maxdiff || |
| 65 | (x->replay.seq - x->preplay.seq < x->replay_maxdiff) && | 65 | ((x->replay.seq - x->preplay.seq < x->replay_maxdiff) && |
| 66 | (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff)) { | 66 | (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff))) { |
| 67 | if (x->xflags & XFRM_TIME_DEFER) | 67 | if (x->xflags & XFRM_TIME_DEFER) |
| 68 | event = XFRM_REPLAY_TIMEOUT; | 68 | event = XFRM_REPLAY_TIMEOUT; |
| 69 | else | 69 | else |
| @@ -129,8 +129,7 @@ static int xfrm_replay_check(struct xfrm_state *x, | |||
| 129 | return 0; | 129 | return 0; |
| 130 | 130 | ||
| 131 | diff = x->replay.seq - seq; | 131 | diff = x->replay.seq - seq; |
| 132 | if (diff >= min_t(unsigned int, x->props.replay_window, | 132 | if (diff >= x->props.replay_window) { |
| 133 | sizeof(x->replay.bitmap) * 8)) { | ||
| 134 | x->stats.replay_window++; | 133 | x->stats.replay_window++; |
| 135 | goto err; | 134 | goto err; |
| 136 | } | 135 | } |
| @@ -302,9 +301,10 @@ static void xfrm_replay_notify_bmp(struct xfrm_state *x, int event) | |||
| 302 | 301 | ||
| 303 | switch (event) { | 302 | switch (event) { |
| 304 | case XFRM_REPLAY_UPDATE: | 303 | case XFRM_REPLAY_UPDATE: |
| 305 | if (x->replay_maxdiff && | 304 | if (!x->replay_maxdiff || |
| 306 | (replay_esn->seq - preplay_esn->seq < x->replay_maxdiff) && | 305 | ((replay_esn->seq - preplay_esn->seq < x->replay_maxdiff) && |
| 307 | (replay_esn->oseq - preplay_esn->oseq < x->replay_maxdiff)) { | 306 | (replay_esn->oseq - preplay_esn->oseq |
| 307 | < x->replay_maxdiff))) { | ||
| 308 | if (x->xflags & XFRM_TIME_DEFER) | 308 | if (x->xflags & XFRM_TIME_DEFER) |
| 309 | event = XFRM_REPLAY_TIMEOUT; | 309 | event = XFRM_REPLAY_TIMEOUT; |
| 310 | else | 310 | else |
| @@ -353,28 +353,30 @@ static void xfrm_replay_notify_esn(struct xfrm_state *x, int event) | |||
| 353 | 353 | ||
| 354 | switch (event) { | 354 | switch (event) { |
| 355 | case XFRM_REPLAY_UPDATE: | 355 | case XFRM_REPLAY_UPDATE: |
| 356 | if (!x->replay_maxdiff) | 356 | if (x->replay_maxdiff) { |
| 357 | break; | 357 | if (replay_esn->seq_hi == preplay_esn->seq_hi) |
| 358 | 358 | seq_diff = replay_esn->seq - preplay_esn->seq; | |
| 359 | if (replay_esn->seq_hi == preplay_esn->seq_hi) | 359 | else |
| 360 | seq_diff = replay_esn->seq - preplay_esn->seq; | 360 | seq_diff = ~preplay_esn->seq + replay_esn->seq |
| 361 | else | 361 | + 1; |
| 362 | seq_diff = ~preplay_esn->seq + replay_esn->seq + 1; | ||
| 363 | |||
| 364 | if (replay_esn->oseq_hi == preplay_esn->oseq_hi) | ||
| 365 | oseq_diff = replay_esn->oseq - preplay_esn->oseq; | ||
| 366 | else | ||
| 367 | oseq_diff = ~preplay_esn->oseq + replay_esn->oseq + 1; | ||
| 368 | |||
| 369 | if (seq_diff < x->replay_maxdiff && | ||
| 370 | oseq_diff < x->replay_maxdiff) { | ||
| 371 | 362 | ||
| 372 | if (x->xflags & XFRM_TIME_DEFER) | 363 | if (replay_esn->oseq_hi == preplay_esn->oseq_hi) |
| 373 | event = XFRM_REPLAY_TIMEOUT; | 364 | oseq_diff = replay_esn->oseq |
| 365 | - preplay_esn->oseq; | ||
| 374 | else | 366 | else |
| 375 | return; | 367 | oseq_diff = ~preplay_esn->oseq |
| 368 | + replay_esn->oseq + 1; | ||
| 369 | |||
| 370 | if (seq_diff >= x->replay_maxdiff || | ||
| 371 | oseq_diff >= x->replay_maxdiff) | ||
| 372 | break; | ||
| 376 | } | 373 | } |
| 377 | 374 | ||
| 375 | if (x->xflags & XFRM_TIME_DEFER) | ||
| 376 | event = XFRM_REPLAY_TIMEOUT; | ||
| 377 | else | ||
| 378 | return; | ||
| 379 | |||
| 378 | break; | 380 | break; |
| 379 | 381 | ||
| 380 | case XFRM_REPLAY_TIMEOUT: | 382 | case XFRM_REPLAY_TIMEOUT: |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 3f565e495ac6..f964d4c00ffb 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
| @@ -446,7 +446,8 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info * | |||
| 446 | memcpy(&x->sel, &p->sel, sizeof(x->sel)); | 446 | memcpy(&x->sel, &p->sel, sizeof(x->sel)); |
| 447 | memcpy(&x->lft, &p->lft, sizeof(x->lft)); | 447 | memcpy(&x->lft, &p->lft, sizeof(x->lft)); |
| 448 | x->props.mode = p->mode; | 448 | x->props.mode = p->mode; |
| 449 | x->props.replay_window = p->replay_window; | 449 | x->props.replay_window = min_t(unsigned int, p->replay_window, |
| 450 | sizeof(x->replay.bitmap) * 8); | ||
| 450 | x->props.reqid = p->reqid; | 451 | x->props.reqid = p->reqid; |
| 451 | x->props.family = p->family; | 452 | x->props.family = p->family; |
| 452 | memcpy(&x->props.saddr, &p->saddr, sizeof(x->props.saddr)); | 453 | memcpy(&x->props.saddr, &p->saddr, sizeof(x->props.saddr)); |
| @@ -1856,7 +1857,7 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
| 1856 | if (x->km.state != XFRM_STATE_VALID) | 1857 | if (x->km.state != XFRM_STATE_VALID) |
| 1857 | goto out; | 1858 | goto out; |
| 1858 | 1859 | ||
| 1859 | err = xfrm_replay_verify_len(x->replay_esn, rp); | 1860 | err = xfrm_replay_verify_len(x->replay_esn, re); |
| 1860 | if (err) | 1861 | if (err) |
| 1861 | goto out; | 1862 | goto out; |
| 1862 | 1863 | ||
