aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_state.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/xfrm/xfrm_state.c')
-rw-r--r--net/xfrm/xfrm_state.c165
1 files changed, 78 insertions, 87 deletions
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 3459692092ec..ae01bdbcb294 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -158,8 +158,8 @@ out_unlock:
158 mutex_unlock(&hash_resize_mutex); 158 mutex_unlock(&hash_resize_mutex);
159} 159}
160 160
161static DEFINE_RWLOCK(xfrm_state_afinfo_lock); 161static DEFINE_SPINLOCK(xfrm_state_afinfo_lock);
162static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO]; 162static struct xfrm_state_afinfo __rcu *xfrm_state_afinfo[NPROTO];
163 163
164static DEFINE_SPINLOCK(xfrm_state_gc_lock); 164static DEFINE_SPINLOCK(xfrm_state_gc_lock);
165 165
@@ -168,58 +168,45 @@ int __xfrm_state_delete(struct xfrm_state *x);
168int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); 168int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol);
169void km_state_expired(struct xfrm_state *x, int hard, u32 portid); 169void km_state_expired(struct xfrm_state *x, int hard, u32 portid);
170 170
171static struct xfrm_state_afinfo *xfrm_state_lock_afinfo(unsigned int family) 171static DEFINE_SPINLOCK(xfrm_type_lock);
172{
173 struct xfrm_state_afinfo *afinfo;
174 if (unlikely(family >= NPROTO))
175 return NULL;
176 write_lock_bh(&xfrm_state_afinfo_lock);
177 afinfo = xfrm_state_afinfo[family];
178 if (unlikely(!afinfo))
179 write_unlock_bh(&xfrm_state_afinfo_lock);
180 return afinfo;
181}
182
183static void xfrm_state_unlock_afinfo(struct xfrm_state_afinfo *afinfo)
184 __releases(xfrm_state_afinfo_lock)
185{
186 write_unlock_bh(&xfrm_state_afinfo_lock);
187}
188
189int xfrm_register_type(const struct xfrm_type *type, unsigned short family) 172int xfrm_register_type(const struct xfrm_type *type, unsigned short family)
190{ 173{
191 struct xfrm_state_afinfo *afinfo = xfrm_state_lock_afinfo(family); 174 struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
192 const struct xfrm_type **typemap; 175 const struct xfrm_type **typemap;
193 int err = 0; 176 int err = 0;
194 177
195 if (unlikely(afinfo == NULL)) 178 if (unlikely(afinfo == NULL))
196 return -EAFNOSUPPORT; 179 return -EAFNOSUPPORT;
197 typemap = afinfo->type_map; 180 typemap = afinfo->type_map;
181 spin_lock_bh(&xfrm_type_lock);
198 182
199 if (likely(typemap[type->proto] == NULL)) 183 if (likely(typemap[type->proto] == NULL))
200 typemap[type->proto] = type; 184 typemap[type->proto] = type;
201 else 185 else
202 err = -EEXIST; 186 err = -EEXIST;
203 xfrm_state_unlock_afinfo(afinfo); 187 spin_unlock_bh(&xfrm_type_lock);
188 xfrm_state_put_afinfo(afinfo);
204 return err; 189 return err;
205} 190}
206EXPORT_SYMBOL(xfrm_register_type); 191EXPORT_SYMBOL(xfrm_register_type);
207 192
208int xfrm_unregister_type(const struct xfrm_type *type, unsigned short family) 193int xfrm_unregister_type(const struct xfrm_type *type, unsigned short family)
209{ 194{
210 struct xfrm_state_afinfo *afinfo = xfrm_state_lock_afinfo(family); 195 struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
211 const struct xfrm_type **typemap; 196 const struct xfrm_type **typemap;
212 int err = 0; 197 int err = 0;
213 198
214 if (unlikely(afinfo == NULL)) 199 if (unlikely(afinfo == NULL))
215 return -EAFNOSUPPORT; 200 return -EAFNOSUPPORT;
216 typemap = afinfo->type_map; 201 typemap = afinfo->type_map;
202 spin_lock_bh(&xfrm_type_lock);
217 203
218 if (unlikely(typemap[type->proto] != type)) 204 if (unlikely(typemap[type->proto] != type))
219 err = -ENOENT; 205 err = -ENOENT;
220 else 206 else
221 typemap[type->proto] = NULL; 207 typemap[type->proto] = NULL;
222 xfrm_state_unlock_afinfo(afinfo); 208 spin_unlock_bh(&xfrm_type_lock);
209 xfrm_state_put_afinfo(afinfo);
223 return err; 210 return err;
224} 211}
225EXPORT_SYMBOL(xfrm_unregister_type); 212EXPORT_SYMBOL(xfrm_unregister_type);
@@ -256,6 +243,7 @@ static void xfrm_put_type(const struct xfrm_type *type)
256 module_put(type->owner); 243 module_put(type->owner);
257} 244}
258 245
246static DEFINE_SPINLOCK(xfrm_mode_lock);
259int xfrm_register_mode(struct xfrm_mode *mode, int family) 247int xfrm_register_mode(struct xfrm_mode *mode, int family)
260{ 248{
261 struct xfrm_state_afinfo *afinfo; 249 struct xfrm_state_afinfo *afinfo;
@@ -265,12 +253,13 @@ int xfrm_register_mode(struct xfrm_mode *mode, int family)
265 if (unlikely(mode->encap >= XFRM_MODE_MAX)) 253 if (unlikely(mode->encap >= XFRM_MODE_MAX))
266 return -EINVAL; 254 return -EINVAL;
267 255
268 afinfo = xfrm_state_lock_afinfo(family); 256 afinfo = xfrm_state_get_afinfo(family);
269 if (unlikely(afinfo == NULL)) 257 if (unlikely(afinfo == NULL))
270 return -EAFNOSUPPORT; 258 return -EAFNOSUPPORT;
271 259
272 err = -EEXIST; 260 err = -EEXIST;
273 modemap = afinfo->mode_map; 261 modemap = afinfo->mode_map;
262 spin_lock_bh(&xfrm_mode_lock);
274 if (modemap[mode->encap]) 263 if (modemap[mode->encap])
275 goto out; 264 goto out;
276 265
@@ -283,7 +272,8 @@ int xfrm_register_mode(struct xfrm_mode *mode, int family)
283 err = 0; 272 err = 0;
284 273
285out: 274out:
286 xfrm_state_unlock_afinfo(afinfo); 275 spin_unlock_bh(&xfrm_mode_lock);
276 xfrm_state_put_afinfo(afinfo);
287 return err; 277 return err;
288} 278}
289EXPORT_SYMBOL(xfrm_register_mode); 279EXPORT_SYMBOL(xfrm_register_mode);
@@ -297,19 +287,21 @@ int xfrm_unregister_mode(struct xfrm_mode *mode, int family)
297 if (unlikely(mode->encap >= XFRM_MODE_MAX)) 287 if (unlikely(mode->encap >= XFRM_MODE_MAX))
298 return -EINVAL; 288 return -EINVAL;
299 289
300 afinfo = xfrm_state_lock_afinfo(family); 290 afinfo = xfrm_state_get_afinfo(family);
301 if (unlikely(afinfo == NULL)) 291 if (unlikely(afinfo == NULL))
302 return -EAFNOSUPPORT; 292 return -EAFNOSUPPORT;
303 293
304 err = -ENOENT; 294 err = -ENOENT;
305 modemap = afinfo->mode_map; 295 modemap = afinfo->mode_map;
296 spin_lock_bh(&xfrm_mode_lock);
306 if (likely(modemap[mode->encap] == mode)) { 297 if (likely(modemap[mode->encap] == mode)) {
307 modemap[mode->encap] = NULL; 298 modemap[mode->encap] = NULL;
308 module_put(mode->afinfo->owner); 299 module_put(mode->afinfo->owner);
309 err = 0; 300 err = 0;
310 } 301 }
311 302
312 xfrm_state_unlock_afinfo(afinfo); 303 spin_unlock_bh(&xfrm_mode_lock);
304 xfrm_state_put_afinfo(afinfo);
313 return err; 305 return err;
314} 306}
315EXPORT_SYMBOL(xfrm_unregister_mode); 307EXPORT_SYMBOL(xfrm_unregister_mode);
@@ -699,7 +691,7 @@ static struct xfrm_state *__xfrm_state_lookup(struct net *net, u32 mark,
699 if (x->props.family != family || 691 if (x->props.family != family ||
700 x->id.spi != spi || 692 x->id.spi != spi ||
701 x->id.proto != proto || 693 x->id.proto != proto ||
702 xfrm_addr_cmp(&x->id.daddr, daddr, family)) 694 !xfrm_addr_equal(&x->id.daddr, daddr, family))
703 continue; 695 continue;
704 696
705 if ((mark & x->mark.m) != x->mark.v) 697 if ((mark & x->mark.m) != x->mark.v)
@@ -723,8 +715,8 @@ static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, u32 mark,
723 hlist_for_each_entry(x, entry, net->xfrm.state_bysrc+h, bysrc) { 715 hlist_for_each_entry(x, entry, net->xfrm.state_bysrc+h, bysrc) {
724 if (x->props.family != family || 716 if (x->props.family != family ||
725 x->id.proto != proto || 717 x->id.proto != proto ||
726 xfrm_addr_cmp(&x->id.daddr, daddr, family) || 718 !xfrm_addr_equal(&x->id.daddr, daddr, family) ||
727 xfrm_addr_cmp(&x->props.saddr, saddr, family)) 719 !xfrm_addr_equal(&x->props.saddr, saddr, family))
728 continue; 720 continue;
729 721
730 if ((mark & x->mark.m) != x->mark.v) 722 if ((mark & x->mark.m) != x->mark.v)
@@ -989,8 +981,8 @@ static void __xfrm_state_bump_genids(struct xfrm_state *xnew)
989 if (x->props.family == family && 981 if (x->props.family == family &&
990 x->props.reqid == reqid && 982 x->props.reqid == reqid &&
991 (mark & x->mark.m) == x->mark.v && 983 (mark & x->mark.m) == x->mark.v &&
992 !xfrm_addr_cmp(&x->id.daddr, &xnew->id.daddr, family) && 984 xfrm_addr_equal(&x->id.daddr, &xnew->id.daddr, family) &&
993 !xfrm_addr_cmp(&x->props.saddr, &xnew->props.saddr, family)) 985 xfrm_addr_equal(&x->props.saddr, &xnew->props.saddr, family))
994 x->genid++; 986 x->genid++;
995 } 987 }
996} 988}
@@ -1024,8 +1016,8 @@ static struct xfrm_state *__find_acq_core(struct net *net, struct xfrm_mark *m,
1024 x->id.spi != 0 || 1016 x->id.spi != 0 ||
1025 x->id.proto != proto || 1017 x->id.proto != proto ||
1026 (mark & x->mark.m) != x->mark.v || 1018 (mark & x->mark.m) != x->mark.v ||
1027 xfrm_addr_cmp(&x->id.daddr, daddr, family) || 1019 !xfrm_addr_equal(&x->id.daddr, daddr, family) ||
1028 xfrm_addr_cmp(&x->props.saddr, saddr, family)) 1020 !xfrm_addr_equal(&x->props.saddr, saddr, family))
1029 continue; 1021 continue;
1030 1022
1031 xfrm_state_hold(x); 1023 xfrm_state_hold(x);
@@ -1108,7 +1100,7 @@ int xfrm_state_add(struct xfrm_state *x)
1108 if (use_spi && x->km.seq) { 1100 if (use_spi && x->km.seq) {
1109 x1 = __xfrm_find_acq_byseq(net, mark, x->km.seq); 1101 x1 = __xfrm_find_acq_byseq(net, mark, x->km.seq);
1110 if (x1 && ((x1->id.proto != x->id.proto) || 1102 if (x1 && ((x1->id.proto != x->id.proto) ||
1111 xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family))) { 1103 !xfrm_addr_equal(&x1->id.daddr, &x->id.daddr, family))) {
1112 to_put = x1; 1104 to_put = x1;
1113 x1 = NULL; 1105 x1 = NULL;
1114 } 1106 }
@@ -1234,10 +1226,10 @@ struct xfrm_state * xfrm_migrate_state_find(struct xfrm_migrate *m)
1234 continue; 1226 continue;
1235 if (m->reqid && x->props.reqid != m->reqid) 1227 if (m->reqid && x->props.reqid != m->reqid)
1236 continue; 1228 continue;
1237 if (xfrm_addr_cmp(&x->id.daddr, &m->old_daddr, 1229 if (!xfrm_addr_equal(&x->id.daddr, &m->old_daddr,
1238 m->old_family) || 1230 m->old_family) ||
1239 xfrm_addr_cmp(&x->props.saddr, &m->old_saddr, 1231 !xfrm_addr_equal(&x->props.saddr, &m->old_saddr,
1240 m->old_family)) 1232 m->old_family))
1241 continue; 1233 continue;
1242 xfrm_state_hold(x); 1234 xfrm_state_hold(x);
1243 return x; 1235 return x;
@@ -1249,10 +1241,10 @@ struct xfrm_state * xfrm_migrate_state_find(struct xfrm_migrate *m)
1249 if (x->props.mode != m->mode || 1241 if (x->props.mode != m->mode ||
1250 x->id.proto != m->proto) 1242 x->id.proto != m->proto)
1251 continue; 1243 continue;
1252 if (xfrm_addr_cmp(&x->id.daddr, &m->old_daddr, 1244 if (!xfrm_addr_equal(&x->id.daddr, &m->old_daddr,
1253 m->old_family) || 1245 m->old_family) ||
1254 xfrm_addr_cmp(&x->props.saddr, &m->old_saddr, 1246 !xfrm_addr_equal(&x->props.saddr, &m->old_saddr,
1255 m->old_family)) 1247 m->old_family))
1256 continue; 1248 continue;
1257 xfrm_state_hold(x); 1249 xfrm_state_hold(x);
1258 return x; 1250 return x;
@@ -1277,7 +1269,7 @@ struct xfrm_state * xfrm_state_migrate(struct xfrm_state *x,
1277 memcpy(&xc->props.saddr, &m->new_saddr, sizeof(xc->props.saddr)); 1269 memcpy(&xc->props.saddr, &m->new_saddr, sizeof(xc->props.saddr));
1278 1270
1279 /* add state */ 1271 /* add state */
1280 if (!xfrm_addr_cmp(&x->id.daddr, &m->new_daddr, m->new_family)) { 1272 if (xfrm_addr_equal(&x->id.daddr, &m->new_daddr, m->new_family)) {
1281 /* a care is needed when the destination address of the 1273 /* a care is needed when the destination address of the
1282 state is to be updated as it is a part of triplet */ 1274 state is to be updated as it is a part of triplet */
1283 xfrm_state_insert(xc); 1275 xfrm_state_insert(xc);
@@ -1370,9 +1362,6 @@ int xfrm_state_check_expire(struct xfrm_state *x)
1370 if (!x->curlft.use_time) 1362 if (!x->curlft.use_time)
1371 x->curlft.use_time = get_seconds(); 1363 x->curlft.use_time = get_seconds();
1372 1364
1373 if (x->km.state != XFRM_STATE_VALID)
1374 return -EINVAL;
1375
1376 if (x->curlft.bytes >= x->lft.hard_byte_limit || 1365 if (x->curlft.bytes >= x->lft.hard_byte_limit ||
1377 x->curlft.packets >= x->lft.hard_packet_limit) { 1366 x->curlft.packets >= x->lft.hard_packet_limit) {
1378 x->km.state = XFRM_STATE_EXPIRED; 1367 x->km.state = XFRM_STATE_EXPIRED;
@@ -1648,27 +1637,26 @@ static void xfrm_replay_timer_handler(unsigned long data)
1648} 1637}
1649 1638
1650static LIST_HEAD(xfrm_km_list); 1639static LIST_HEAD(xfrm_km_list);
1651static DEFINE_RWLOCK(xfrm_km_lock);
1652 1640
1653void km_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c) 1641void km_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c)
1654{ 1642{
1655 struct xfrm_mgr *km; 1643 struct xfrm_mgr *km;
1656 1644
1657 read_lock(&xfrm_km_lock); 1645 rcu_read_lock();
1658 list_for_each_entry(km, &xfrm_km_list, list) 1646 list_for_each_entry_rcu(km, &xfrm_km_list, list)
1659 if (km->notify_policy) 1647 if (km->notify_policy)
1660 km->notify_policy(xp, dir, c); 1648 km->notify_policy(xp, dir, c);
1661 read_unlock(&xfrm_km_lock); 1649 rcu_read_unlock();
1662} 1650}
1663 1651
1664void km_state_notify(struct xfrm_state *x, const struct km_event *c) 1652void km_state_notify(struct xfrm_state *x, const struct km_event *c)
1665{ 1653{
1666 struct xfrm_mgr *km; 1654 struct xfrm_mgr *km;
1667 read_lock(&xfrm_km_lock); 1655 rcu_read_lock();
1668 list_for_each_entry(km, &xfrm_km_list, list) 1656 list_for_each_entry_rcu(km, &xfrm_km_list, list)
1669 if (km->notify) 1657 if (km->notify)
1670 km->notify(x, c); 1658 km->notify(x, c);
1671 read_unlock(&xfrm_km_lock); 1659 rcu_read_unlock();
1672} 1660}
1673 1661
1674EXPORT_SYMBOL(km_policy_notify); 1662EXPORT_SYMBOL(km_policy_notify);
@@ -1698,13 +1686,13 @@ int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol)
1698 int err = -EINVAL, acqret; 1686 int err = -EINVAL, acqret;
1699 struct xfrm_mgr *km; 1687 struct xfrm_mgr *km;
1700 1688
1701 read_lock(&xfrm_km_lock); 1689 rcu_read_lock();
1702 list_for_each_entry(km, &xfrm_km_list, list) { 1690 list_for_each_entry_rcu(km, &xfrm_km_list, list) {
1703 acqret = km->acquire(x, t, pol); 1691 acqret = km->acquire(x, t, pol);
1704 if (!acqret) 1692 if (!acqret)
1705 err = acqret; 1693 err = acqret;
1706 } 1694 }
1707 read_unlock(&xfrm_km_lock); 1695 rcu_read_unlock();
1708 return err; 1696 return err;
1709} 1697}
1710EXPORT_SYMBOL(km_query); 1698EXPORT_SYMBOL(km_query);
@@ -1714,14 +1702,14 @@ int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport)
1714 int err = -EINVAL; 1702 int err = -EINVAL;
1715 struct xfrm_mgr *km; 1703 struct xfrm_mgr *km;
1716 1704
1717 read_lock(&xfrm_km_lock); 1705 rcu_read_lock();
1718 list_for_each_entry(km, &xfrm_km_list, list) { 1706 list_for_each_entry_rcu(km, &xfrm_km_list, list) {
1719 if (km->new_mapping) 1707 if (km->new_mapping)
1720 err = km->new_mapping(x, ipaddr, sport); 1708 err = km->new_mapping(x, ipaddr, sport);
1721 if (!err) 1709 if (!err)
1722 break; 1710 break;
1723 } 1711 }
1724 read_unlock(&xfrm_km_lock); 1712 rcu_read_unlock();
1725 return err; 1713 return err;
1726} 1714}
1727EXPORT_SYMBOL(km_new_mapping); 1715EXPORT_SYMBOL(km_new_mapping);
@@ -1750,15 +1738,15 @@ int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
1750 int ret; 1738 int ret;
1751 struct xfrm_mgr *km; 1739 struct xfrm_mgr *km;
1752 1740
1753 read_lock(&xfrm_km_lock); 1741 rcu_read_lock();
1754 list_for_each_entry(km, &xfrm_km_list, list) { 1742 list_for_each_entry_rcu(km, &xfrm_km_list, list) {
1755 if (km->migrate) { 1743 if (km->migrate) {
1756 ret = km->migrate(sel, dir, type, m, num_migrate, k); 1744 ret = km->migrate(sel, dir, type, m, num_migrate, k);
1757 if (!ret) 1745 if (!ret)
1758 err = ret; 1746 err = ret;
1759 } 1747 }
1760 } 1748 }
1761 read_unlock(&xfrm_km_lock); 1749 rcu_read_unlock();
1762 return err; 1750 return err;
1763} 1751}
1764EXPORT_SYMBOL(km_migrate); 1752EXPORT_SYMBOL(km_migrate);
@@ -1770,15 +1758,15 @@ int km_report(struct net *net, u8 proto, struct xfrm_selector *sel, xfrm_address
1770 int ret; 1758 int ret;
1771 struct xfrm_mgr *km; 1759 struct xfrm_mgr *km;
1772 1760
1773 read_lock(&xfrm_km_lock); 1761 rcu_read_lock();
1774 list_for_each_entry(km, &xfrm_km_list, list) { 1762 list_for_each_entry_rcu(km, &xfrm_km_list, list) {
1775 if (km->report) { 1763 if (km->report) {
1776 ret = km->report(net, proto, sel, addr); 1764 ret = km->report(net, proto, sel, addr);
1777 if (!ret) 1765 if (!ret)
1778 err = ret; 1766 err = ret;
1779 } 1767 }
1780 } 1768 }
1781 read_unlock(&xfrm_km_lock); 1769 rcu_read_unlock();
1782 return err; 1770 return err;
1783} 1771}
1784EXPORT_SYMBOL(km_report); 1772EXPORT_SYMBOL(km_report);
@@ -1802,14 +1790,14 @@ int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen
1802 goto out; 1790 goto out;
1803 1791
1804 err = -EINVAL; 1792 err = -EINVAL;
1805 read_lock(&xfrm_km_lock); 1793 rcu_read_lock();
1806 list_for_each_entry(km, &xfrm_km_list, list) { 1794 list_for_each_entry_rcu(km, &xfrm_km_list, list) {
1807 pol = km->compile_policy(sk, optname, data, 1795 pol = km->compile_policy(sk, optname, data,
1808 optlen, &err); 1796 optlen, &err);
1809 if (err >= 0) 1797 if (err >= 0)
1810 break; 1798 break;
1811 } 1799 }
1812 read_unlock(&xfrm_km_lock); 1800 rcu_read_unlock();
1813 1801
1814 if (err >= 0) { 1802 if (err >= 0) {
1815 xfrm_sk_policy_insert(sk, err, pol); 1803 xfrm_sk_policy_insert(sk, err, pol);
@@ -1823,20 +1811,23 @@ out:
1823} 1811}
1824EXPORT_SYMBOL(xfrm_user_policy); 1812EXPORT_SYMBOL(xfrm_user_policy);
1825 1813
1814static DEFINE_SPINLOCK(xfrm_km_lock);
1815
1826int xfrm_register_km(struct xfrm_mgr *km) 1816int xfrm_register_km(struct xfrm_mgr *km)
1827{ 1817{
1828 write_lock_bh(&xfrm_km_lock); 1818 spin_lock_bh(&xfrm_km_lock);
1829 list_add_tail(&km->list, &xfrm_km_list); 1819 list_add_tail_rcu(&km->list, &xfrm_km_list);
1830 write_unlock_bh(&xfrm_km_lock); 1820 spin_unlock_bh(&xfrm_km_lock);
1831 return 0; 1821 return 0;
1832} 1822}
1833EXPORT_SYMBOL(xfrm_register_km); 1823EXPORT_SYMBOL(xfrm_register_km);
1834 1824
1835int xfrm_unregister_km(struct xfrm_mgr *km) 1825int xfrm_unregister_km(struct xfrm_mgr *km)
1836{ 1826{
1837 write_lock_bh(&xfrm_km_lock); 1827 spin_lock_bh(&xfrm_km_lock);
1838 list_del(&km->list); 1828 list_del_rcu(&km->list);
1839 write_unlock_bh(&xfrm_km_lock); 1829 spin_unlock_bh(&xfrm_km_lock);
1830 synchronize_rcu();
1840 return 0; 1831 return 0;
1841} 1832}
1842EXPORT_SYMBOL(xfrm_unregister_km); 1833EXPORT_SYMBOL(xfrm_unregister_km);
@@ -1848,12 +1839,12 @@ int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo)
1848 return -EINVAL; 1839 return -EINVAL;
1849 if (unlikely(afinfo->family >= NPROTO)) 1840 if (unlikely(afinfo->family >= NPROTO))
1850 return -EAFNOSUPPORT; 1841 return -EAFNOSUPPORT;
1851 write_lock_bh(&xfrm_state_afinfo_lock); 1842 spin_lock_bh(&xfrm_state_afinfo_lock);
1852 if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL)) 1843 if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL))
1853 err = -ENOBUFS; 1844 err = -ENOBUFS;
1854 else 1845 else
1855 xfrm_state_afinfo[afinfo->family] = afinfo; 1846 rcu_assign_pointer(xfrm_state_afinfo[afinfo->family], afinfo);
1856 write_unlock_bh(&xfrm_state_afinfo_lock); 1847 spin_unlock_bh(&xfrm_state_afinfo_lock);
1857 return err; 1848 return err;
1858} 1849}
1859EXPORT_SYMBOL(xfrm_state_register_afinfo); 1850EXPORT_SYMBOL(xfrm_state_register_afinfo);
@@ -1865,14 +1856,15 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo)
1865 return -EINVAL; 1856 return -EINVAL;
1866 if (unlikely(afinfo->family >= NPROTO)) 1857 if (unlikely(afinfo->family >= NPROTO))
1867 return -EAFNOSUPPORT; 1858 return -EAFNOSUPPORT;
1868 write_lock_bh(&xfrm_state_afinfo_lock); 1859 spin_lock_bh(&xfrm_state_afinfo_lock);
1869 if (likely(xfrm_state_afinfo[afinfo->family] != NULL)) { 1860 if (likely(xfrm_state_afinfo[afinfo->family] != NULL)) {
1870 if (unlikely(xfrm_state_afinfo[afinfo->family] != afinfo)) 1861 if (unlikely(xfrm_state_afinfo[afinfo->family] != afinfo))
1871 err = -EINVAL; 1862 err = -EINVAL;
1872 else 1863 else
1873 xfrm_state_afinfo[afinfo->family] = NULL; 1864 RCU_INIT_POINTER(xfrm_state_afinfo[afinfo->family], NULL);
1874 } 1865 }
1875 write_unlock_bh(&xfrm_state_afinfo_lock); 1866 spin_unlock_bh(&xfrm_state_afinfo_lock);
1867 synchronize_rcu();
1876 return err; 1868 return err;
1877} 1869}
1878EXPORT_SYMBOL(xfrm_state_unregister_afinfo); 1870EXPORT_SYMBOL(xfrm_state_unregister_afinfo);
@@ -1882,17 +1874,16 @@ static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family)
1882 struct xfrm_state_afinfo *afinfo; 1874 struct xfrm_state_afinfo *afinfo;
1883 if (unlikely(family >= NPROTO)) 1875 if (unlikely(family >= NPROTO))
1884 return NULL; 1876 return NULL;
1885 read_lock(&xfrm_state_afinfo_lock); 1877 rcu_read_lock();
1886 afinfo = xfrm_state_afinfo[family]; 1878 afinfo = rcu_dereference(xfrm_state_afinfo[family]);
1887 if (unlikely(!afinfo)) 1879 if (unlikely(!afinfo))
1888 read_unlock(&xfrm_state_afinfo_lock); 1880 rcu_read_unlock();
1889 return afinfo; 1881 return afinfo;
1890} 1882}
1891 1883
1892static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo) 1884static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo)
1893 __releases(xfrm_state_afinfo_lock)
1894{ 1885{
1895 read_unlock(&xfrm_state_afinfo_lock); 1886 rcu_read_unlock();
1896} 1887}
1897 1888
1898/* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */ 1889/* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */