aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_policy.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/xfrm/xfrm_policy.c')
-rw-r--r--net/xfrm/xfrm_policy.c127
1 files changed, 99 insertions, 28 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index cb81ca35b0d6..843e066649cb 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -469,16 +469,16 @@ static inline int xfrm_byidx_should_resize(struct net *net, int total)
469 return 0; 469 return 0;
470} 470}
471 471
472void xfrm_spd_getinfo(struct xfrmk_spdinfo *si) 472void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si)
473{ 473{
474 read_lock_bh(&xfrm_policy_lock); 474 read_lock_bh(&xfrm_policy_lock);
475 si->incnt = init_net.xfrm.policy_count[XFRM_POLICY_IN]; 475 si->incnt = net->xfrm.policy_count[XFRM_POLICY_IN];
476 si->outcnt = init_net.xfrm.policy_count[XFRM_POLICY_OUT]; 476 si->outcnt = net->xfrm.policy_count[XFRM_POLICY_OUT];
477 si->fwdcnt = init_net.xfrm.policy_count[XFRM_POLICY_FWD]; 477 si->fwdcnt = net->xfrm.policy_count[XFRM_POLICY_FWD];
478 si->inscnt = init_net.xfrm.policy_count[XFRM_POLICY_IN+XFRM_POLICY_MAX]; 478 si->inscnt = net->xfrm.policy_count[XFRM_POLICY_IN+XFRM_POLICY_MAX];
479 si->outscnt = init_net.xfrm.policy_count[XFRM_POLICY_OUT+XFRM_POLICY_MAX]; 479 si->outscnt = net->xfrm.policy_count[XFRM_POLICY_OUT+XFRM_POLICY_MAX];
480 si->fwdscnt = init_net.xfrm.policy_count[XFRM_POLICY_FWD+XFRM_POLICY_MAX]; 480 si->fwdscnt = net->xfrm.policy_count[XFRM_POLICY_FWD+XFRM_POLICY_MAX];
481 si->spdhcnt = init_net.xfrm.policy_idx_hmask; 481 si->spdhcnt = net->xfrm.policy_idx_hmask;
482 si->spdhmcnt = xfrm_policy_hashmax; 482 si->spdhmcnt = xfrm_policy_hashmax;
483 read_unlock_bh(&xfrm_policy_lock); 483 read_unlock_bh(&xfrm_policy_lock);
484} 484}
@@ -556,6 +556,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
556 struct hlist_head *chain; 556 struct hlist_head *chain;
557 struct hlist_node *entry, *newpos; 557 struct hlist_node *entry, *newpos;
558 struct dst_entry *gc_list; 558 struct dst_entry *gc_list;
559 u32 mark = policy->mark.v & policy->mark.m;
559 560
560 write_lock_bh(&xfrm_policy_lock); 561 write_lock_bh(&xfrm_policy_lock);
561 chain = policy_hash_bysel(net, &policy->selector, policy->family, dir); 562 chain = policy_hash_bysel(net, &policy->selector, policy->family, dir);
@@ -564,6 +565,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
564 hlist_for_each_entry(pol, entry, chain, bydst) { 565 hlist_for_each_entry(pol, entry, chain, bydst) {
565 if (pol->type == policy->type && 566 if (pol->type == policy->type &&
566 !selector_cmp(&pol->selector, &policy->selector) && 567 !selector_cmp(&pol->selector, &policy->selector) &&
568 (mark & pol->mark.m) == pol->mark.v &&
567 xfrm_sec_ctx_match(pol->security, policy->security) && 569 xfrm_sec_ctx_match(pol->security, policy->security) &&
568 !WARN_ON(delpol)) { 570 !WARN_ON(delpol)) {
569 if (excl) { 571 if (excl) {
@@ -635,8 +637,8 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
635} 637}
636EXPORT_SYMBOL(xfrm_policy_insert); 638EXPORT_SYMBOL(xfrm_policy_insert);
637 639
638struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u8 type, int dir, 640struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u8 type,
639 struct xfrm_selector *sel, 641 int dir, struct xfrm_selector *sel,
640 struct xfrm_sec_ctx *ctx, int delete, 642 struct xfrm_sec_ctx *ctx, int delete,
641 int *err) 643 int *err)
642{ 644{
@@ -650,6 +652,7 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u8 type, int dir,
650 ret = NULL; 652 ret = NULL;
651 hlist_for_each_entry(pol, entry, chain, bydst) { 653 hlist_for_each_entry(pol, entry, chain, bydst) {
652 if (pol->type == type && 654 if (pol->type == type &&
655 (mark & pol->mark.m) == pol->mark.v &&
653 !selector_cmp(sel, &pol->selector) && 656 !selector_cmp(sel, &pol->selector) &&
654 xfrm_sec_ctx_match(ctx, pol->security)) { 657 xfrm_sec_ctx_match(ctx, pol->security)) {
655 xfrm_pol_hold(pol); 658 xfrm_pol_hold(pol);
@@ -676,8 +679,8 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u8 type, int dir,
676} 679}
677EXPORT_SYMBOL(xfrm_policy_bysel_ctx); 680EXPORT_SYMBOL(xfrm_policy_bysel_ctx);
678 681
679struct xfrm_policy *xfrm_policy_byid(struct net *net, u8 type, int dir, u32 id, 682struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8 type,
680 int delete, int *err) 683 int dir, u32 id, int delete, int *err)
681{ 684{
682 struct xfrm_policy *pol, *ret; 685 struct xfrm_policy *pol, *ret;
683 struct hlist_head *chain; 686 struct hlist_head *chain;
@@ -692,7 +695,8 @@ struct xfrm_policy *xfrm_policy_byid(struct net *net, u8 type, int dir, u32 id,
692 chain = net->xfrm.policy_byidx + idx_hash(net, id); 695 chain = net->xfrm.policy_byidx + idx_hash(net, id);
693 ret = NULL; 696 ret = NULL;
694 hlist_for_each_entry(pol, entry, chain, byidx) { 697 hlist_for_each_entry(pol, entry, chain, byidx) {
695 if (pol->type == type && pol->index == id) { 698 if (pol->type == type && pol->index == id &&
699 (mark & pol->mark.m) == pol->mark.v) {
696 xfrm_pol_hold(pol); 700 xfrm_pol_hold(pol);
697 if (delete) { 701 if (delete) {
698 *err = security_xfrm_policy_delete( 702 *err = security_xfrm_policy_delete(
@@ -771,7 +775,8 @@ xfrm_policy_flush_secctx_check(struct net *net, u8 type, struct xfrm_audit *audi
771 775
772int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) 776int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info)
773{ 777{
774 int dir, err = 0; 778 int dir, err = 0, cnt = 0;
779 struct xfrm_policy *dp;
775 780
776 write_lock_bh(&xfrm_policy_lock); 781 write_lock_bh(&xfrm_policy_lock);
777 782
@@ -789,8 +794,10 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info)
789 &net->xfrm.policy_inexact[dir], bydst) { 794 &net->xfrm.policy_inexact[dir], bydst) {
790 if (pol->type != type) 795 if (pol->type != type)
791 continue; 796 continue;
792 __xfrm_policy_unlink(pol, dir); 797 dp = __xfrm_policy_unlink(pol, dir);
793 write_unlock_bh(&xfrm_policy_lock); 798 write_unlock_bh(&xfrm_policy_lock);
799 if (dp)
800 cnt++;
794 801
795 xfrm_audit_policy_delete(pol, 1, audit_info->loginuid, 802 xfrm_audit_policy_delete(pol, 1, audit_info->loginuid,
796 audit_info->sessionid, 803 audit_info->sessionid,
@@ -809,8 +816,10 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info)
809 bydst) { 816 bydst) {
810 if (pol->type != type) 817 if (pol->type != type)
811 continue; 818 continue;
812 __xfrm_policy_unlink(pol, dir); 819 dp = __xfrm_policy_unlink(pol, dir);
813 write_unlock_bh(&xfrm_policy_lock); 820 write_unlock_bh(&xfrm_policy_lock);
821 if (dp)
822 cnt++;
814 823
815 xfrm_audit_policy_delete(pol, 1, 824 xfrm_audit_policy_delete(pol, 1,
816 audit_info->loginuid, 825 audit_info->loginuid,
@@ -824,6 +833,8 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info)
824 } 833 }
825 834
826 } 835 }
836 if (!cnt)
837 err = -ESRCH;
827 atomic_inc(&flow_cache_genid); 838 atomic_inc(&flow_cache_genid);
828out: 839out:
829 write_unlock_bh(&xfrm_policy_lock); 840 write_unlock_bh(&xfrm_policy_lock);
@@ -909,6 +920,7 @@ static int xfrm_policy_match(struct xfrm_policy *pol, struct flowi *fl,
909 int match, ret = -ESRCH; 920 int match, ret = -ESRCH;
910 921
911 if (pol->family != family || 922 if (pol->family != family ||
923 (fl->mark & pol->mark.m) != pol->mark.v ||
912 pol->type != type) 924 pol->type != type)
913 return ret; 925 return ret;
914 926
@@ -1033,6 +1045,10 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struc
1033 int err = 0; 1045 int err = 0;
1034 1046
1035 if (match) { 1047 if (match) {
1048 if ((sk->sk_mark & pol->mark.m) != pol->mark.v) {
1049 pol = NULL;
1050 goto out;
1051 }
1036 err = security_xfrm_policy_lookup(pol->security, 1052 err = security_xfrm_policy_lookup(pol->security,
1037 fl->secid, 1053 fl->secid,
1038 policy_to_flow_dir(dir)); 1054 policy_to_flow_dir(dir));
@@ -1045,6 +1061,7 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struc
1045 } else 1061 } else
1046 pol = NULL; 1062 pol = NULL;
1047 } 1063 }
1064out:
1048 read_unlock_bh(&xfrm_policy_lock); 1065 read_unlock_bh(&xfrm_policy_lock);
1049 return pol; 1066 return pol;
1050} 1067}
@@ -1137,6 +1154,7 @@ static struct xfrm_policy *clone_policy(struct xfrm_policy *old, int dir)
1137 } 1154 }
1138 newp->lft = old->lft; 1155 newp->lft = old->lft;
1139 newp->curlft = old->curlft; 1156 newp->curlft = old->curlft;
1157 newp->mark = old->mark;
1140 newp->action = old->action; 1158 newp->action = old->action;
1141 newp->flags = old->flags; 1159 newp->flags = old->flags;
1142 newp->xfrm_nr = old->xfrm_nr; 1160 newp->xfrm_nr = old->xfrm_nr;
@@ -1309,15 +1327,28 @@ static inline int xfrm_get_tos(struct flowi *fl, int family)
1309 return tos; 1327 return tos;
1310} 1328}
1311 1329
1312static inline struct xfrm_dst *xfrm_alloc_dst(int family) 1330static inline struct xfrm_dst *xfrm_alloc_dst(struct net *net, int family)
1313{ 1331{
1314 struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); 1332 struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
1333 struct dst_ops *dst_ops;
1315 struct xfrm_dst *xdst; 1334 struct xfrm_dst *xdst;
1316 1335
1317 if (!afinfo) 1336 if (!afinfo)
1318 return ERR_PTR(-EINVAL); 1337 return ERR_PTR(-EINVAL);
1319 1338
1320 xdst = dst_alloc(afinfo->dst_ops) ?: ERR_PTR(-ENOBUFS); 1339 switch (family) {
1340 case AF_INET:
1341 dst_ops = &net->xfrm.xfrm4_dst_ops;
1342 break;
1343#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
1344 case AF_INET6:
1345 dst_ops = &net->xfrm.xfrm6_dst_ops;
1346 break;
1347#endif
1348 default:
1349 BUG();
1350 }
1351 xdst = dst_alloc(dst_ops) ?: ERR_PTR(-ENOBUFS);
1321 1352
1322 xfrm_policy_put_afinfo(afinfo); 1353 xfrm_policy_put_afinfo(afinfo);
1323 1354
@@ -1341,7 +1372,8 @@ static inline int xfrm_init_path(struct xfrm_dst *path, struct dst_entry *dst,
1341 return err; 1372 return err;
1342} 1373}
1343 1374
1344static inline int xfrm_fill_dst(struct xfrm_dst *xdst, struct net_device *dev) 1375static inline int xfrm_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
1376 struct flowi *fl)
1345{ 1377{
1346 struct xfrm_policy_afinfo *afinfo = 1378 struct xfrm_policy_afinfo *afinfo =
1347 xfrm_policy_get_afinfo(xdst->u.dst.ops->family); 1379 xfrm_policy_get_afinfo(xdst->u.dst.ops->family);
@@ -1350,7 +1382,7 @@ static inline int xfrm_fill_dst(struct xfrm_dst *xdst, struct net_device *dev)
1350 if (!afinfo) 1382 if (!afinfo)
1351 return -EINVAL; 1383 return -EINVAL;
1352 1384
1353 err = afinfo->fill_dst(xdst, dev); 1385 err = afinfo->fill_dst(xdst, dev, fl);
1354 1386
1355 xfrm_policy_put_afinfo(afinfo); 1387 xfrm_policy_put_afinfo(afinfo);
1356 1388
@@ -1366,6 +1398,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
1366 struct flowi *fl, 1398 struct flowi *fl,
1367 struct dst_entry *dst) 1399 struct dst_entry *dst)
1368{ 1400{
1401 struct net *net = xp_net(policy);
1369 unsigned long now = jiffies; 1402 unsigned long now = jiffies;
1370 struct net_device *dev; 1403 struct net_device *dev;
1371 struct dst_entry *dst_prev = NULL; 1404 struct dst_entry *dst_prev = NULL;
@@ -1389,7 +1422,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
1389 dst_hold(dst); 1422 dst_hold(dst);
1390 1423
1391 for (; i < nx; i++) { 1424 for (; i < nx; i++) {
1392 struct xfrm_dst *xdst = xfrm_alloc_dst(family); 1425 struct xfrm_dst *xdst = xfrm_alloc_dst(net, family);
1393 struct dst_entry *dst1 = &xdst->u.dst; 1426 struct dst_entry *dst1 = &xdst->u.dst;
1394 1427
1395 err = PTR_ERR(xdst); 1428 err = PTR_ERR(xdst);
@@ -1445,7 +1478,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
1445 if (!dev) 1478 if (!dev)
1446 goto free_dst; 1479 goto free_dst;
1447 1480
1448 /* Copy neighbout for reachability confirmation */ 1481 /* Copy neighbour for reachability confirmation */
1449 dst0->neighbour = neigh_clone(dst->neighbour); 1482 dst0->neighbour = neigh_clone(dst->neighbour);
1450 1483
1451 xfrm_init_path((struct xfrm_dst *)dst0, dst, nfheader_len); 1484 xfrm_init_path((struct xfrm_dst *)dst0, dst, nfheader_len);
@@ -1454,7 +1487,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
1454 for (dst_prev = dst0; dst_prev != dst; dst_prev = dst_prev->child) { 1487 for (dst_prev = dst0; dst_prev != dst; dst_prev = dst_prev->child) {
1455 struct xfrm_dst *xdst = (struct xfrm_dst *)dst_prev; 1488 struct xfrm_dst *xdst = (struct xfrm_dst *)dst_prev;
1456 1489
1457 err = xfrm_fill_dst(xdst, dev); 1490 err = xfrm_fill_dst(xdst, dev, fl);
1458 if (err) 1491 if (err)
1459 goto free_dst; 1492 goto free_dst;
1460 1493
@@ -2031,8 +2064,7 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family)
2031 int res; 2064 int res;
2032 2065
2033 if (xfrm_decode_session(skb, &fl, family) < 0) { 2066 if (xfrm_decode_session(skb, &fl, family) < 0) {
2034 /* XXX: we should have something like FWDHDRERROR here. */ 2067 XFRM_INC_STATS(net, LINUX_MIB_XFRMFWDHDRERROR);
2035 XFRM_INC_STATS(net, LINUX_MIB_XFRMINHDRERROR);
2036 return 0; 2068 return 0;
2037 } 2069 }
2038 2070
@@ -2279,6 +2311,7 @@ EXPORT_SYMBOL(xfrm_bundle_ok);
2279 2311
2280int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) 2312int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
2281{ 2313{
2314 struct net *net;
2282 int err = 0; 2315 int err = 0;
2283 if (unlikely(afinfo == NULL)) 2316 if (unlikely(afinfo == NULL))
2284 return -EINVAL; 2317 return -EINVAL;
@@ -2302,6 +2335,27 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
2302 xfrm_policy_afinfo[afinfo->family] = afinfo; 2335 xfrm_policy_afinfo[afinfo->family] = afinfo;
2303 } 2336 }
2304 write_unlock_bh(&xfrm_policy_afinfo_lock); 2337 write_unlock_bh(&xfrm_policy_afinfo_lock);
2338
2339 rtnl_lock();
2340 for_each_net(net) {
2341 struct dst_ops *xfrm_dst_ops;
2342
2343 switch (afinfo->family) {
2344 case AF_INET:
2345 xfrm_dst_ops = &net->xfrm.xfrm4_dst_ops;
2346 break;
2347#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
2348 case AF_INET6:
2349 xfrm_dst_ops = &net->xfrm.xfrm6_dst_ops;
2350 break;
2351#endif
2352 default:
2353 BUG();
2354 }
2355 *xfrm_dst_ops = *afinfo->dst_ops;
2356 }
2357 rtnl_unlock();
2358
2305 return err; 2359 return err;
2306} 2360}
2307EXPORT_SYMBOL(xfrm_policy_register_afinfo); 2361EXPORT_SYMBOL(xfrm_policy_register_afinfo);
@@ -2332,6 +2386,22 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo)
2332} 2386}
2333EXPORT_SYMBOL(xfrm_policy_unregister_afinfo); 2387EXPORT_SYMBOL(xfrm_policy_unregister_afinfo);
2334 2388
2389static void __net_init xfrm_dst_ops_init(struct net *net)
2390{
2391 struct xfrm_policy_afinfo *afinfo;
2392
2393 read_lock_bh(&xfrm_policy_afinfo_lock);
2394 afinfo = xfrm_policy_afinfo[AF_INET];
2395 if (afinfo)
2396 net->xfrm.xfrm4_dst_ops = *afinfo->dst_ops;
2397#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
2398 afinfo = xfrm_policy_afinfo[AF_INET6];
2399 if (afinfo)
2400 net->xfrm.xfrm6_dst_ops = *afinfo->dst_ops;
2401#endif
2402 read_unlock_bh(&xfrm_policy_afinfo_lock);
2403}
2404
2335static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family) 2405static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family)
2336{ 2406{
2337 struct xfrm_policy_afinfo *afinfo; 2407 struct xfrm_policy_afinfo *afinfo;
@@ -2369,19 +2439,19 @@ static int __net_init xfrm_statistics_init(struct net *net)
2369{ 2439{
2370 int rv; 2440 int rv;
2371 2441
2372 if (snmp_mib_init((void **)net->mib.xfrm_statistics, 2442 if (snmp_mib_init((void __percpu **)net->mib.xfrm_statistics,
2373 sizeof(struct linux_xfrm_mib)) < 0) 2443 sizeof(struct linux_xfrm_mib)) < 0)
2374 return -ENOMEM; 2444 return -ENOMEM;
2375 rv = xfrm_proc_init(net); 2445 rv = xfrm_proc_init(net);
2376 if (rv < 0) 2446 if (rv < 0)
2377 snmp_mib_free((void **)net->mib.xfrm_statistics); 2447 snmp_mib_free((void __percpu **)net->mib.xfrm_statistics);
2378 return rv; 2448 return rv;
2379} 2449}
2380 2450
2381static void xfrm_statistics_fini(struct net *net) 2451static void xfrm_statistics_fini(struct net *net)
2382{ 2452{
2383 xfrm_proc_fini(net); 2453 xfrm_proc_fini(net);
2384 snmp_mib_free((void **)net->mib.xfrm_statistics); 2454 snmp_mib_free((void __percpu **)net->mib.xfrm_statistics);
2385} 2455}
2386#else 2456#else
2387static int __net_init xfrm_statistics_init(struct net *net) 2457static int __net_init xfrm_statistics_init(struct net *net)
@@ -2494,6 +2564,7 @@ static int __net_init xfrm_net_init(struct net *net)
2494 rv = xfrm_policy_init(net); 2564 rv = xfrm_policy_init(net);
2495 if (rv < 0) 2565 if (rv < 0)
2496 goto out_policy; 2566 goto out_policy;
2567 xfrm_dst_ops_init(net);
2497 rv = xfrm_sysctl_init(net); 2568 rv = xfrm_sysctl_init(net);
2498 if (rv < 0) 2569 if (rv < 0)
2499 goto out_sysctl; 2570 goto out_sysctl;