diff options
Diffstat (limited to 'net/xfrm')
| -rw-r--r-- | net/xfrm/xfrm_output.c | 12 | ||||
| -rw-r--r-- | net/xfrm/xfrm_policy.c | 7 | ||||
| -rw-r--r-- | net/xfrm/xfrm_state.c | 34 |
3 files changed, 36 insertions, 17 deletions
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index ac25b4c0e982..dc50f1e71f76 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c | |||
| @@ -27,10 +27,14 @@ static int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb) | |||
| 27 | - skb_headroom(skb); | 27 | - skb_headroom(skb); |
| 28 | int ntail = dst->dev->needed_tailroom - skb_tailroom(skb); | 28 | int ntail = dst->dev->needed_tailroom - skb_tailroom(skb); |
| 29 | 29 | ||
| 30 | if (nhead > 0 || ntail > 0) | 30 | if (nhead <= 0) { |
| 31 | return pskb_expand_head(skb, nhead, ntail, GFP_ATOMIC); | 31 | if (ntail <= 0) |
| 32 | 32 | return 0; | |
| 33 | return 0; | 33 | nhead = 0; |
| 34 | } else if (ntail < 0) | ||
| 35 | ntail = 0; | ||
| 36 | |||
| 37 | return pskb_expand_head(skb, nhead, ntail, GFP_ATOMIC); | ||
| 34 | } | 38 | } |
| 35 | 39 | ||
| 36 | static int xfrm_output_one(struct sk_buff *skb, int err) | 40 | static int xfrm_output_one(struct sk_buff *skb, int err) |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 841b32a2e680..b7754b1b73a4 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
| @@ -1077,6 +1077,7 @@ static void __xfrm_policy_link(struct xfrm_policy *pol, int dir) | |||
| 1077 | struct hlist_head *chain = policy_hash_bysel(&pol->selector, | 1077 | struct hlist_head *chain = policy_hash_bysel(&pol->selector, |
| 1078 | pol->family, dir); | 1078 | pol->family, dir); |
| 1079 | 1079 | ||
| 1080 | list_add_tail(&pol->bytype, &xfrm_policy_bytype[pol->type]); | ||
| 1080 | hlist_add_head(&pol->bydst, chain); | 1081 | hlist_add_head(&pol->bydst, chain); |
| 1081 | hlist_add_head(&pol->byidx, xfrm_policy_byidx+idx_hash(pol->index)); | 1082 | hlist_add_head(&pol->byidx, xfrm_policy_byidx+idx_hash(pol->index)); |
| 1082 | xfrm_policy_count[dir]++; | 1083 | xfrm_policy_count[dir]++; |
| @@ -1731,8 +1732,7 @@ restart: | |||
| 1731 | * We can't enlist stable bundles either. | 1732 | * We can't enlist stable bundles either. |
| 1732 | */ | 1733 | */ |
| 1733 | write_unlock_bh(&policy->lock); | 1734 | write_unlock_bh(&policy->lock); |
| 1734 | if (dst) | 1735 | dst_free(dst); |
| 1735 | dst_free(dst); | ||
| 1736 | 1736 | ||
| 1737 | if (pol_dead) | 1737 | if (pol_dead) |
| 1738 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLDEAD); | 1738 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLDEAD); |
| @@ -1748,8 +1748,7 @@ restart: | |||
| 1748 | err = xfrm_dst_update_origin(dst, fl); | 1748 | err = xfrm_dst_update_origin(dst, fl); |
| 1749 | if (unlikely(err)) { | 1749 | if (unlikely(err)) { |
| 1750 | write_unlock_bh(&policy->lock); | 1750 | write_unlock_bh(&policy->lock); |
| 1751 | if (dst) | 1751 | dst_free(dst); |
| 1752 | dst_free(dst); | ||
| 1753 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTBUNDLECHECKERROR); | 1752 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTBUNDLECHECKERROR); |
| 1754 | goto error; | 1753 | goto error; |
| 1755 | } | 1754 | } |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 4c6914ef7d92..0a8f09c3144c 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
| @@ -780,11 +780,13 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
| 780 | { | 780 | { |
| 781 | unsigned int h; | 781 | unsigned int h; |
| 782 | struct hlist_node *entry; | 782 | struct hlist_node *entry; |
| 783 | struct xfrm_state *x, *x0; | 783 | struct xfrm_state *x, *x0, *to_put; |
| 784 | int acquire_in_progress = 0; | 784 | int acquire_in_progress = 0; |
| 785 | int error = 0; | 785 | int error = 0; |
| 786 | struct xfrm_state *best = NULL; | 786 | struct xfrm_state *best = NULL; |
| 787 | 787 | ||
| 788 | to_put = NULL; | ||
| 789 | |||
| 788 | spin_lock_bh(&xfrm_state_lock); | 790 | spin_lock_bh(&xfrm_state_lock); |
| 789 | h = xfrm_dst_hash(daddr, saddr, tmpl->reqid, family); | 791 | h = xfrm_dst_hash(daddr, saddr, tmpl->reqid, family); |
| 790 | hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) { | 792 | hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) { |
| @@ -833,7 +835,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
| 833 | if (tmpl->id.spi && | 835 | if (tmpl->id.spi && |
| 834 | (x0 = __xfrm_state_lookup(daddr, tmpl->id.spi, | 836 | (x0 = __xfrm_state_lookup(daddr, tmpl->id.spi, |
| 835 | tmpl->id.proto, family)) != NULL) { | 837 | tmpl->id.proto, family)) != NULL) { |
| 836 | xfrm_state_put(x0); | 838 | to_put = x0; |
| 837 | error = -EEXIST; | 839 | error = -EEXIST; |
| 838 | goto out; | 840 | goto out; |
| 839 | } | 841 | } |
| @@ -849,13 +851,14 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
| 849 | error = security_xfrm_state_alloc_acquire(x, pol->security, fl->secid); | 851 | error = security_xfrm_state_alloc_acquire(x, pol->security, fl->secid); |
| 850 | if (error) { | 852 | if (error) { |
| 851 | x->km.state = XFRM_STATE_DEAD; | 853 | x->km.state = XFRM_STATE_DEAD; |
| 852 | xfrm_state_put(x); | 854 | to_put = x; |
| 853 | x = NULL; | 855 | x = NULL; |
| 854 | goto out; | 856 | goto out; |
| 855 | } | 857 | } |
| 856 | 858 | ||
| 857 | if (km_query(x, tmpl, pol) == 0) { | 859 | if (km_query(x, tmpl, pol) == 0) { |
| 858 | x->km.state = XFRM_STATE_ACQ; | 860 | x->km.state = XFRM_STATE_ACQ; |
| 861 | list_add_tail(&x->all, &xfrm_state_all); | ||
| 859 | hlist_add_head(&x->bydst, xfrm_state_bydst+h); | 862 | hlist_add_head(&x->bydst, xfrm_state_bydst+h); |
| 860 | h = xfrm_src_hash(daddr, saddr, family); | 863 | h = xfrm_src_hash(daddr, saddr, family); |
| 861 | hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); | 864 | hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); |
| @@ -870,7 +873,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
| 870 | xfrm_hash_grow_check(x->bydst.next != NULL); | 873 | xfrm_hash_grow_check(x->bydst.next != NULL); |
| 871 | } else { | 874 | } else { |
| 872 | x->km.state = XFRM_STATE_DEAD; | 875 | x->km.state = XFRM_STATE_DEAD; |
| 873 | xfrm_state_put(x); | 876 | to_put = x; |
| 874 | x = NULL; | 877 | x = NULL; |
| 875 | error = -ESRCH; | 878 | error = -ESRCH; |
| 876 | } | 879 | } |
| @@ -881,6 +884,8 @@ out: | |||
| 881 | else | 884 | else |
| 882 | *err = acquire_in_progress ? -EAGAIN : error; | 885 | *err = acquire_in_progress ? -EAGAIN : error; |
| 883 | spin_unlock_bh(&xfrm_state_lock); | 886 | spin_unlock_bh(&xfrm_state_lock); |
| 887 | if (to_put) | ||
| 888 | xfrm_state_put(to_put); | ||
| 884 | return x; | 889 | return x; |
| 885 | } | 890 | } |
| 886 | 891 | ||
| @@ -1051,6 +1056,7 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re | |||
| 1051 | xfrm_state_hold(x); | 1056 | xfrm_state_hold(x); |
| 1052 | x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ; | 1057 | x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ; |
| 1053 | add_timer(&x->timer); | 1058 | add_timer(&x->timer); |
| 1059 | list_add_tail(&x->all, &xfrm_state_all); | ||
| 1054 | hlist_add_head(&x->bydst, xfrm_state_bydst+h); | 1060 | hlist_add_head(&x->bydst, xfrm_state_bydst+h); |
| 1055 | h = xfrm_src_hash(daddr, saddr, family); | 1061 | h = xfrm_src_hash(daddr, saddr, family); |
| 1056 | hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); | 1062 | hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); |
| @@ -1067,18 +1073,20 @@ static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq); | |||
| 1067 | 1073 | ||
| 1068 | int xfrm_state_add(struct xfrm_state *x) | 1074 | int xfrm_state_add(struct xfrm_state *x) |
| 1069 | { | 1075 | { |
| 1070 | struct xfrm_state *x1; | 1076 | struct xfrm_state *x1, *to_put; |
| 1071 | int family; | 1077 | int family; |
| 1072 | int err; | 1078 | int err; |
| 1073 | int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY); | 1079 | int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY); |
| 1074 | 1080 | ||
| 1075 | family = x->props.family; | 1081 | family = x->props.family; |
| 1076 | 1082 | ||
| 1083 | to_put = NULL; | ||
| 1084 | |||
| 1077 | spin_lock_bh(&xfrm_state_lock); | 1085 | spin_lock_bh(&xfrm_state_lock); |
| 1078 | 1086 | ||
| 1079 | x1 = __xfrm_state_locate(x, use_spi, family); | 1087 | x1 = __xfrm_state_locate(x, use_spi, family); |
| 1080 | if (x1) { | 1088 | if (x1) { |
| 1081 | xfrm_state_put(x1); | 1089 | to_put = x1; |
| 1082 | x1 = NULL; | 1090 | x1 = NULL; |
| 1083 | err = -EEXIST; | 1091 | err = -EEXIST; |
| 1084 | goto out; | 1092 | goto out; |
| @@ -1088,7 +1096,7 @@ int xfrm_state_add(struct xfrm_state *x) | |||
| 1088 | x1 = __xfrm_find_acq_byseq(x->km.seq); | 1096 | x1 = __xfrm_find_acq_byseq(x->km.seq); |
| 1089 | if (x1 && ((x1->id.proto != x->id.proto) || | 1097 | if (x1 && ((x1->id.proto != x->id.proto) || |
| 1090 | xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family))) { | 1098 | xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family))) { |
| 1091 | xfrm_state_put(x1); | 1099 | to_put = x1; |
| 1092 | x1 = NULL; | 1100 | x1 = NULL; |
| 1093 | } | 1101 | } |
| 1094 | } | 1102 | } |
| @@ -1110,6 +1118,9 @@ out: | |||
| 1110 | xfrm_state_put(x1); | 1118 | xfrm_state_put(x1); |
| 1111 | } | 1119 | } |
| 1112 | 1120 | ||
| 1121 | if (to_put) | ||
| 1122 | xfrm_state_put(to_put); | ||
| 1123 | |||
| 1113 | return err; | 1124 | return err; |
| 1114 | } | 1125 | } |
| 1115 | EXPORT_SYMBOL(xfrm_state_add); | 1126 | EXPORT_SYMBOL(xfrm_state_add); |
| @@ -1269,10 +1280,12 @@ EXPORT_SYMBOL(xfrm_state_migrate); | |||
| 1269 | 1280 | ||
| 1270 | int xfrm_state_update(struct xfrm_state *x) | 1281 | int xfrm_state_update(struct xfrm_state *x) |
| 1271 | { | 1282 | { |
| 1272 | struct xfrm_state *x1; | 1283 | struct xfrm_state *x1, *to_put; |
| 1273 | int err; | 1284 | int err; |
| 1274 | int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY); | 1285 | int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY); |
| 1275 | 1286 | ||
| 1287 | to_put = NULL; | ||
| 1288 | |||
| 1276 | spin_lock_bh(&xfrm_state_lock); | 1289 | spin_lock_bh(&xfrm_state_lock); |
| 1277 | x1 = __xfrm_state_locate(x, use_spi, x->props.family); | 1290 | x1 = __xfrm_state_locate(x, use_spi, x->props.family); |
| 1278 | 1291 | ||
| @@ -1281,7 +1294,7 @@ int xfrm_state_update(struct xfrm_state *x) | |||
| 1281 | goto out; | 1294 | goto out; |
| 1282 | 1295 | ||
| 1283 | if (xfrm_state_kern(x1)) { | 1296 | if (xfrm_state_kern(x1)) { |
| 1284 | xfrm_state_put(x1); | 1297 | to_put = x1; |
| 1285 | err = -EEXIST; | 1298 | err = -EEXIST; |
| 1286 | goto out; | 1299 | goto out; |
| 1287 | } | 1300 | } |
| @@ -1295,6 +1308,9 @@ int xfrm_state_update(struct xfrm_state *x) | |||
| 1295 | out: | 1308 | out: |
| 1296 | spin_unlock_bh(&xfrm_state_lock); | 1309 | spin_unlock_bh(&xfrm_state_lock); |
| 1297 | 1310 | ||
| 1311 | if (to_put) | ||
| 1312 | xfrm_state_put(to_put); | ||
| 1313 | |||
| 1298 | if (err) | 1314 | if (err) |
| 1299 | return err; | 1315 | return err; |
| 1300 | 1316 | ||
