aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm
diff options
context:
space:
mode:
authorJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-11-22 13:06:44 -0500
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-11-22 13:06:44 -0500
commit0bd2af46839ad6262d25714a6ec0365db9d6b98f (patch)
treedcced72d230d69fd0c5816ac6dd03ab84799a93e /net/xfrm
parente138a5d2356729b8752e88520cc1525fae9794ac (diff)
parentf26b90440cd74c78fe10c9bd5160809704a9627c (diff)
Merge ../scsi-rc-fixes-2.6
Diffstat (limited to 'net/xfrm')
-rw-r--r--net/xfrm/xfrm_policy.c101
-rw-r--r--net/xfrm/xfrm_state.c19
-rw-r--r--net/xfrm/xfrm_user.c26
3 files changed, 104 insertions, 42 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;
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 39b8bf3a9ded..899de9ed22a6 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -505,6 +505,14 @@ __xfrm_state_locate(struct xfrm_state *x, int use_spi, int family)
505 x->id.proto, family); 505 x->id.proto, family);
506} 506}
507 507
508static void xfrm_hash_grow_check(int have_hash_collision)
509{
510 if (have_hash_collision &&
511 (xfrm_state_hmask + 1) < xfrm_state_hashmax &&
512 xfrm_state_num > xfrm_state_hmask)
513 schedule_work(&xfrm_hash_work);
514}
515
508struct xfrm_state * 516struct xfrm_state *
509xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, 517xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
510 struct flowi *fl, struct xfrm_tmpl *tmpl, 518 struct flowi *fl, struct xfrm_tmpl *tmpl,
@@ -598,6 +606,8 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
598 x->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES; 606 x->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES;
599 x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ; 607 x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ;
600 add_timer(&x->timer); 608 add_timer(&x->timer);
609 xfrm_state_num++;
610 xfrm_hash_grow_check(x->bydst.next != NULL);
601 } else { 611 } else {
602 x->km.state = XFRM_STATE_DEAD; 612 x->km.state = XFRM_STATE_DEAD;
603 xfrm_state_put(x); 613 xfrm_state_put(x);
@@ -642,10 +652,7 @@ static void __xfrm_state_insert(struct xfrm_state *x)
642 652
643 xfrm_state_num++; 653 xfrm_state_num++;
644 654
645 if (x->bydst.next != NULL && 655 xfrm_hash_grow_check(x->bydst.next != NULL);
646 (xfrm_state_hmask + 1) < xfrm_state_hashmax &&
647 xfrm_state_num > xfrm_state_hmask)
648 schedule_work(&xfrm_hash_work);
649} 656}
650 657
651/* xfrm_state_lock is held */ 658/* xfrm_state_lock is held */
@@ -753,6 +760,10 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re
753 h = xfrm_src_hash(daddr, saddr, family); 760 h = xfrm_src_hash(daddr, saddr, family);
754 hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); 761 hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
755 wake_up(&km_waitq); 762 wake_up(&km_waitq);
763
764 xfrm_state_num++;
765
766 xfrm_hash_grow_check(x->bydst.next != NULL);
756 } 767 }
757 768
758 return x; 769 return x;
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index d54b3a70d5df..c4cde57d9216 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -323,7 +323,7 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *
323 x->props.replay_window = p->replay_window; 323 x->props.replay_window = p->replay_window;
324 x->props.reqid = p->reqid; 324 x->props.reqid = p->reqid;
325 x->props.family = p->family; 325 x->props.family = p->family;
326 x->props.saddr = p->saddr; 326 memcpy(&x->props.saddr, &p->saddr, sizeof(x->props.saddr));
327 x->props.flags = p->flags; 327 x->props.flags = p->flags;
328} 328}
329 329
@@ -545,7 +545,7 @@ static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p)
545 memcpy(&p->lft, &x->lft, sizeof(p->lft)); 545 memcpy(&p->lft, &x->lft, sizeof(p->lft));
546 memcpy(&p->curlft, &x->curlft, sizeof(p->curlft)); 546 memcpy(&p->curlft, &x->curlft, sizeof(p->curlft));
547 memcpy(&p->stats, &x->stats, sizeof(p->stats)); 547 memcpy(&p->stats, &x->stats, sizeof(p->stats));
548 p->saddr = x->props.saddr; 548 memcpy(&p->saddr, &x->props.saddr, sizeof(p->saddr));
549 p->mode = x->props.mode; 549 p->mode = x->props.mode;
550 p->replay_window = x->props.replay_window; 550 p->replay_window = x->props.replay_window;
551 p->reqid = x->props.reqid; 551 p->reqid = x->props.reqid;
@@ -1927,6 +1927,9 @@ static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt,
1927 len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr); 1927 len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr);
1928 len += NLMSG_SPACE(sizeof(struct xfrm_user_acquire)); 1928 len += NLMSG_SPACE(sizeof(struct xfrm_user_acquire));
1929 len += RTA_SPACE(xfrm_user_sec_ctx_size(xp)); 1929 len += RTA_SPACE(xfrm_user_sec_ctx_size(xp));
1930#ifdef CONFIG_XFRM_SUB_POLICY
1931 len += RTA_SPACE(sizeof(struct xfrm_userpolicy_type));
1932#endif
1930 skb = alloc_skb(len, GFP_ATOMIC); 1933 skb = alloc_skb(len, GFP_ATOMIC);
1931 if (skb == NULL) 1934 if (skb == NULL)
1932 return -ENOMEM; 1935 return -ENOMEM;
@@ -1992,15 +1995,6 @@ static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt,
1992 xp->type = XFRM_POLICY_TYPE_MAIN; 1995 xp->type = XFRM_POLICY_TYPE_MAIN;
1993 copy_templates(xp, ut, nr); 1996 copy_templates(xp, ut, nr);
1994 1997
1995 if (!xp->security) {
1996 int err = security_xfrm_sock_policy_alloc(xp, sk);
1997 if (err) {
1998 kfree(xp);
1999 *dir = err;
2000 return NULL;
2001 }
2002 }
2003
2004 *dir = p->dir; 1998 *dir = p->dir;
2005 1999
2006 return xp; 2000 return xp;
@@ -2043,6 +2037,9 @@ static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_eve
2043 len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr); 2037 len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr);
2044 len += NLMSG_SPACE(sizeof(struct xfrm_user_polexpire)); 2038 len += NLMSG_SPACE(sizeof(struct xfrm_user_polexpire));
2045 len += RTA_SPACE(xfrm_user_sec_ctx_size(xp)); 2039 len += RTA_SPACE(xfrm_user_sec_ctx_size(xp));
2040#ifdef CONFIG_XFRM_SUB_POLICY
2041 len += RTA_SPACE(sizeof(struct xfrm_userpolicy_type));
2042#endif
2046 skb = alloc_skb(len, GFP_ATOMIC); 2043 skb = alloc_skb(len, GFP_ATOMIC);
2047 if (skb == NULL) 2044 if (skb == NULL)
2048 return -ENOMEM; 2045 return -ENOMEM;
@@ -2069,6 +2066,9 @@ static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *
2069 len += RTA_SPACE(headlen); 2066 len += RTA_SPACE(headlen);
2070 headlen = sizeof(*id); 2067 headlen = sizeof(*id);
2071 } 2068 }
2069#ifdef CONFIG_XFRM_SUB_POLICY
2070 len += RTA_SPACE(sizeof(struct xfrm_userpolicy_type));
2071#endif
2072 len += NLMSG_SPACE(headlen); 2072 len += NLMSG_SPACE(headlen);
2073 2073
2074 skb = alloc_skb(len, GFP_ATOMIC); 2074 skb = alloc_skb(len, GFP_ATOMIC);
@@ -2115,10 +2115,12 @@ static int xfrm_notify_policy_flush(struct km_event *c)
2115 struct nlmsghdr *nlh; 2115 struct nlmsghdr *nlh;
2116 struct sk_buff *skb; 2116 struct sk_buff *skb;
2117 unsigned char *b; 2117 unsigned char *b;
2118 int len = 0;
2118#ifdef CONFIG_XFRM_SUB_POLICY 2119#ifdef CONFIG_XFRM_SUB_POLICY
2119 struct xfrm_userpolicy_type upt; 2120 struct xfrm_userpolicy_type upt;
2121 len += RTA_SPACE(sizeof(struct xfrm_userpolicy_type));
2120#endif 2122#endif
2121 int len = NLMSG_LENGTH(0); 2123 len += NLMSG_LENGTH(0);
2122 2124
2123 skb = alloc_skb(len, GFP_ATOMIC); 2125 skb = alloc_skb(len, GFP_ATOMIC);
2124 if (skb == NULL) 2126 if (skb == NULL)