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.c101
1 files changed, 75 insertions, 26 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 2a7861661f14..7736b23c3f03 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -883,30 +883,32 @@ out:
883} 883}
884EXPORT_SYMBOL(xfrm_policy_walk); 884EXPORT_SYMBOL(xfrm_policy_walk);
885 885
886/* Find policy to apply to this flow. */ 886/*
887 887 * Find policy to apply to this flow.
888 *
889 * Returns 0 if policy found, else an -errno.
890 */
888static int xfrm_policy_match(struct xfrm_policy *pol, struct flowi *fl, 891static int xfrm_policy_match(struct xfrm_policy *pol, struct flowi *fl,
889 u8 type, u16 family, int dir) 892 u8 type, u16 family, int dir)
890{ 893{
891 struct xfrm_selector *sel = &pol->selector; 894 struct xfrm_selector *sel = &pol->selector;
892 int match; 895 int match, ret = -ESRCH;
893 896
894 if (pol->family != family || 897 if (pol->family != family ||
895 pol->type != type) 898 pol->type != type)
896 return 0; 899 return ret;
897 900
898 match = xfrm_selector_match(sel, fl, family); 901 match = xfrm_selector_match(sel, fl, family);
899 if (match) { 902 if (match)
900 if (!security_xfrm_policy_lookup(pol, fl->secid, dir)) 903 ret = security_xfrm_policy_lookup(pol, fl->secid, dir);
901 return 1;
902 }
903 904
904 return 0; 905 return ret;
905} 906}
906 907
907static struct xfrm_policy *xfrm_policy_lookup_bytype(u8 type, struct flowi *fl, 908static struct xfrm_policy *xfrm_policy_lookup_bytype(u8 type, struct flowi *fl,
908 u16 family, u8 dir) 909 u16 family, u8 dir)
909{ 910{
911 int err;
910 struct xfrm_policy *pol, *ret; 912 struct xfrm_policy *pol, *ret;
911 xfrm_address_t *daddr, *saddr; 913 xfrm_address_t *daddr, *saddr;
912 struct hlist_node *entry; 914 struct hlist_node *entry;
@@ -922,7 +924,15 @@ static struct xfrm_policy *xfrm_policy_lookup_bytype(u8 type, struct flowi *fl,
922 chain = policy_hash_direct(daddr, saddr, family, dir); 924 chain = policy_hash_direct(daddr, saddr, family, dir);
923 ret = NULL; 925 ret = NULL;
924 hlist_for_each_entry(pol, entry, chain, bydst) { 926 hlist_for_each_entry(pol, entry, chain, bydst) {
925 if (xfrm_policy_match(pol, fl, type, family, dir)) { 927 err = xfrm_policy_match(pol, fl, type, family, dir);
928 if (err) {
929 if (err == -ESRCH)
930 continue;
931 else {
932 ret = ERR_PTR(err);
933 goto fail;
934 }
935 } else {
926 ret = pol; 936 ret = pol;
927 priority = ret->priority; 937 priority = ret->priority;
928 break; 938 break;
@@ -930,36 +940,53 @@ static struct xfrm_policy *xfrm_policy_lookup_bytype(u8 type, struct flowi *fl,
930 } 940 }
931 chain = &xfrm_policy_inexact[dir]; 941 chain = &xfrm_policy_inexact[dir];
932 hlist_for_each_entry(pol, entry, chain, bydst) { 942 hlist_for_each_entry(pol, entry, chain, bydst) {
933 if (xfrm_policy_match(pol, fl, type, family, dir) && 943 err = xfrm_policy_match(pol, fl, type, family, dir);
934 pol->priority < priority) { 944 if (err) {
945 if (err == -ESRCH)
946 continue;
947 else {
948 ret = ERR_PTR(err);
949 goto fail;
950 }
951 } else if (pol->priority < priority) {
935 ret = pol; 952 ret = pol;
936 break; 953 break;
937 } 954 }
938 } 955 }
939 if (ret) 956 if (ret)
940 xfrm_pol_hold(ret); 957 xfrm_pol_hold(ret);
958fail:
941 read_unlock_bh(&xfrm_policy_lock); 959 read_unlock_bh(&xfrm_policy_lock);
942 960
943 return ret; 961 return ret;
944} 962}
945 963
946static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir, 964static int xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir,
947 void **objp, atomic_t **obj_refp) 965 void **objp, atomic_t **obj_refp)
948{ 966{
949 struct xfrm_policy *pol; 967 struct xfrm_policy *pol;
968 int err = 0;
950 969
951#ifdef CONFIG_XFRM_SUB_POLICY 970#ifdef CONFIG_XFRM_SUB_POLICY
952 pol = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_SUB, fl, family, dir); 971 pol = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_SUB, fl, family, dir);
953 if (pol) 972 if (IS_ERR(pol)) {
973 err = PTR_ERR(pol);
974 pol = NULL;
975 }
976 if (pol || err)
954 goto end; 977 goto end;
955#endif 978#endif
956 pol = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_MAIN, fl, family, dir); 979 pol = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_MAIN, fl, family, dir);
957 980 if (IS_ERR(pol)) {
981 err = PTR_ERR(pol);
982 pol = NULL;
983 }
958#ifdef CONFIG_XFRM_SUB_POLICY 984#ifdef CONFIG_XFRM_SUB_POLICY
959end: 985end:
960#endif 986#endif
961 if ((*objp = (void *) pol) != NULL) 987 if ((*objp = (void *) pol) != NULL)
962 *obj_refp = &pol->refcnt; 988 *obj_refp = &pol->refcnt;
989 return err;
963} 990}
964 991
965static inline int policy_to_flow_dir(int dir) 992static inline int policy_to_flow_dir(int dir)
@@ -989,12 +1016,16 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struc
989 sk->sk_family); 1016 sk->sk_family);
990 int err = 0; 1017 int err = 0;
991 1018
992 if (match) 1019 if (match) {
993 err = security_xfrm_policy_lookup(pol, fl->secid, policy_to_flow_dir(dir)); 1020 err = security_xfrm_policy_lookup(pol, fl->secid,
994 1021 policy_to_flow_dir(dir));
995 if (match && !err) 1022 if (!err)
996 xfrm_pol_hold(pol); 1023 xfrm_pol_hold(pol);
997 else 1024 else if (err == -ESRCH)
1025 pol = NULL;
1026 else
1027 pol = ERR_PTR(err);
1028 } else
998 pol = NULL; 1029 pol = NULL;
999 } 1030 }
1000 read_unlock_bh(&xfrm_policy_lock); 1031 read_unlock_bh(&xfrm_policy_lock);
@@ -1286,8 +1317,11 @@ restart:
1286 pol_dead = 0; 1317 pol_dead = 0;
1287 xfrm_nr = 0; 1318 xfrm_nr = 0;
1288 1319
1289 if (sk && sk->sk_policy[1]) 1320 if (sk && sk->sk_policy[1]) {
1290 policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl); 1321 policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl);
1322 if (IS_ERR(policy))
1323 return PTR_ERR(policy);
1324 }
1291 1325
1292 if (!policy) { 1326 if (!policy) {
1293 /* To accelerate a bit... */ 1327 /* To accelerate a bit... */
@@ -1297,6 +1331,8 @@ restart:
1297 1331
1298 policy = flow_cache_lookup(fl, dst_orig->ops->family, 1332 policy = flow_cache_lookup(fl, dst_orig->ops->family,
1299 dir, xfrm_policy_lookup); 1333 dir, xfrm_policy_lookup);
1334 if (IS_ERR(policy))
1335 return PTR_ERR(policy);
1300 } 1336 }
1301 1337
1302 if (!policy) 1338 if (!policy)
@@ -1343,6 +1379,10 @@ restart:
1343 fl, family, 1379 fl, family,
1344 XFRM_POLICY_OUT); 1380 XFRM_POLICY_OUT);
1345 if (pols[1]) { 1381 if (pols[1]) {
1382 if (IS_ERR(pols[1])) {
1383 err = PTR_ERR(pols[1]);
1384 goto error;
1385 }
1346 if (pols[1]->action == XFRM_POLICY_BLOCK) { 1386 if (pols[1]->action == XFRM_POLICY_BLOCK) {
1347 err = -EPERM; 1387 err = -EPERM;
1348 goto error; 1388 goto error;
@@ -1574,13 +1614,19 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
1574 } 1614 }
1575 1615
1576 pol = NULL; 1616 pol = NULL;
1577 if (sk && sk->sk_policy[dir]) 1617 if (sk && sk->sk_policy[dir]) {
1578 pol = xfrm_sk_policy_lookup(sk, dir, &fl); 1618 pol = xfrm_sk_policy_lookup(sk, dir, &fl);
1619 if (IS_ERR(pol))
1620 return 0;
1621 }
1579 1622
1580 if (!pol) 1623 if (!pol)
1581 pol = flow_cache_lookup(&fl, family, fl_dir, 1624 pol = flow_cache_lookup(&fl, family, fl_dir,
1582 xfrm_policy_lookup); 1625 xfrm_policy_lookup);
1583 1626
1627 if (IS_ERR(pol))
1628 return 0;
1629
1584 if (!pol) { 1630 if (!pol) {
1585 if (skb->sp && secpath_has_nontransport(skb->sp, 0, &xerr_idx)) { 1631 if (skb->sp && secpath_has_nontransport(skb->sp, 0, &xerr_idx)) {
1586 xfrm_secpath_reject(xerr_idx, skb, &fl); 1632 xfrm_secpath_reject(xerr_idx, skb, &fl);
@@ -1599,6 +1645,8 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
1599 &fl, family, 1645 &fl, family,
1600 XFRM_POLICY_IN); 1646 XFRM_POLICY_IN);
1601 if (pols[1]) { 1647 if (pols[1]) {
1648 if (IS_ERR(pols[1]))
1649 return 0;
1602 pols[1]->curlft.use_time = (unsigned long)xtime.tv_sec; 1650 pols[1]->curlft.use_time = (unsigned long)xtime.tv_sec;
1603 npols ++; 1651 npols ++;
1604 } 1652 }
@@ -1706,7 +1754,7 @@ static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie)
1706 1754
1707static int stale_bundle(struct dst_entry *dst) 1755static int stale_bundle(struct dst_entry *dst)
1708{ 1756{
1709 return !xfrm_bundle_ok((struct xfrm_dst *)dst, NULL, AF_UNSPEC, 0); 1757 return !xfrm_bundle_ok(NULL, (struct xfrm_dst *)dst, NULL, AF_UNSPEC, 0);
1710} 1758}
1711 1759
1712void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev) 1760void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev)
@@ -1828,7 +1876,8 @@ EXPORT_SYMBOL(xfrm_init_pmtu);
1828 * still valid. 1876 * still valid.
1829 */ 1877 */
1830 1878
1831int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family, int strict) 1879int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,
1880 struct flowi *fl, int family, int strict)
1832{ 1881{
1833 struct dst_entry *dst = &first->u.dst; 1882 struct dst_entry *dst = &first->u.dst;
1834 struct xfrm_dst *last; 1883 struct xfrm_dst *last;
@@ -1845,7 +1894,7 @@ int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family, int str
1845 1894
1846 if (fl && !xfrm_selector_match(&dst->xfrm->sel, fl, family)) 1895 if (fl && !xfrm_selector_match(&dst->xfrm->sel, fl, family))
1847 return 0; 1896 return 0;
1848 if (fl && !security_xfrm_flow_state_match(fl, dst->xfrm)) 1897 if (fl && !security_xfrm_flow_state_match(fl, dst->xfrm, pol))
1849 return 0; 1898 return 0;
1850 if (dst->xfrm->km.state != XFRM_STATE_VALID) 1899 if (dst->xfrm->km.state != XFRM_STATE_VALID)
1851 return 0; 1900 return 0;