aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorVenkat Yekkirala <vyekkirala@TrustedCS.com>2006-07-25 02:29:07 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-22 17:53:24 -0400
commite0d1caa7b0d5f02e4f34aa09c695d04251310c6c (patch)
treebf023c17abf6813f2694ebf5fafff82edd6a1023 /net
parentb6340fcd761acf9249b3acbc95c4dc555d9beb07 (diff)
[MLSXFRM]: Flow based matching of xfrm policy and state
This implements a seemless mechanism for xfrm policy selection and state matching based on the flow sid. This also includes the necessary SELinux enforcement pieces. Signed-off-by: Venkat Yekkirala <vyekkirala@TrustedCS.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/flow.c7
-rw-r--r--net/xfrm/xfrm_policy.c28
-rw-r--r--net/xfrm/xfrm_state.c12
3 files changed, 27 insertions, 20 deletions
diff --git a/net/core/flow.c b/net/core/flow.c
index 2191af5f26ac..645241165e6c 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -32,7 +32,6 @@ struct flow_cache_entry {
32 u8 dir; 32 u8 dir;
33 struct flowi key; 33 struct flowi key;
34 u32 genid; 34 u32 genid;
35 u32 sk_sid;
36 void *object; 35 void *object;
37 atomic_t *object_ref; 36 atomic_t *object_ref;
38}; 37};
@@ -165,7 +164,7 @@ static int flow_key_compare(struct flowi *key1, struct flowi *key2)
165 return 0; 164 return 0;
166} 165}
167 166
168void *flow_cache_lookup(struct flowi *key, u32 sk_sid, u16 family, u8 dir, 167void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir,
169 flow_resolve_t resolver) 168 flow_resolve_t resolver)
170{ 169{
171 struct flow_cache_entry *fle, **head; 170 struct flow_cache_entry *fle, **head;
@@ -189,7 +188,6 @@ void *flow_cache_lookup(struct flowi *key, u32 sk_sid, u16 family, u8 dir,
189 for (fle = *head; fle; fle = fle->next) { 188 for (fle = *head; fle; fle = fle->next) {
190 if (fle->family == family && 189 if (fle->family == family &&
191 fle->dir == dir && 190 fle->dir == dir &&
192 fle->sk_sid == sk_sid &&
193 flow_key_compare(key, &fle->key) == 0) { 191 flow_key_compare(key, &fle->key) == 0) {
194 if (fle->genid == atomic_read(&flow_cache_genid)) { 192 if (fle->genid == atomic_read(&flow_cache_genid)) {
195 void *ret = fle->object; 193 void *ret = fle->object;
@@ -214,7 +212,6 @@ void *flow_cache_lookup(struct flowi *key, u32 sk_sid, u16 family, u8 dir,
214 *head = fle; 212 *head = fle;
215 fle->family = family; 213 fle->family = family;
216 fle->dir = dir; 214 fle->dir = dir;
217 fle->sk_sid = sk_sid;
218 memcpy(&fle->key, key, sizeof(*key)); 215 memcpy(&fle->key, key, sizeof(*key));
219 fle->object = NULL; 216 fle->object = NULL;
220 flow_count(cpu)++; 217 flow_count(cpu)++;
@@ -226,7 +223,7 @@ nocache:
226 void *obj; 223 void *obj;
227 atomic_t *obj_ref; 224 atomic_t *obj_ref;
228 225
229 resolver(key, sk_sid, family, dir, &obj, &obj_ref); 226 resolver(key, family, dir, &obj, &obj_ref);
230 227
231 if (fle) { 228 if (fle) {
232 fle->genid = atomic_read(&flow_cache_genid); 229 fle->genid = atomic_read(&flow_cache_genid);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 3da67ca2c3ce..79405daadc52 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -597,7 +597,7 @@ EXPORT_SYMBOL(xfrm_policy_walk);
597 597
598/* Find policy to apply to this flow. */ 598/* Find policy to apply to this flow. */
599 599
600static void xfrm_policy_lookup(struct flowi *fl, u32 sk_sid, u16 family, u8 dir, 600static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir,
601 void **objp, atomic_t **obj_refp) 601 void **objp, atomic_t **obj_refp)
602{ 602{
603 struct xfrm_policy *pol; 603 struct xfrm_policy *pol;
@@ -613,7 +613,7 @@ static void xfrm_policy_lookup(struct flowi *fl, u32 sk_sid, u16 family, u8 dir,
613 match = xfrm_selector_match(sel, fl, family); 613 match = xfrm_selector_match(sel, fl, family);
614 614
615 if (match) { 615 if (match) {
616 if (!security_xfrm_policy_lookup(pol, sk_sid, dir)) { 616 if (!security_xfrm_policy_lookup(pol, fl->secid, dir)) {
617 xfrm_pol_hold(pol); 617 xfrm_pol_hold(pol);
618 break; 618 break;
619 } 619 }
@@ -641,7 +641,7 @@ static inline int policy_to_flow_dir(int dir)
641 }; 641 };
642} 642}
643 643
644static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struct flowi *fl, u32 sk_sid) 644static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struct flowi *fl)
645{ 645{
646 struct xfrm_policy *pol; 646 struct xfrm_policy *pol;
647 647
@@ -652,7 +652,7 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struc
652 int err = 0; 652 int err = 0;
653 653
654 if (match) 654 if (match)
655 err = security_xfrm_policy_lookup(pol, sk_sid, policy_to_flow_dir(dir)); 655 err = security_xfrm_policy_lookup(pol, fl->secid, policy_to_flow_dir(dir));
656 656
657 if (match && !err) 657 if (match && !err)
658 xfrm_pol_hold(pol); 658 xfrm_pol_hold(pol);
@@ -862,19 +862,20 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl,
862 u32 genid; 862 u32 genid;
863 u16 family; 863 u16 family;
864 u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT); 864 u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT);
865 u32 sk_sid = security_sk_sid(sk, fl, dir); 865
866 fl->secid = security_sk_sid(sk, fl, dir);
866restart: 867restart:
867 genid = atomic_read(&flow_cache_genid); 868 genid = atomic_read(&flow_cache_genid);
868 policy = NULL; 869 policy = NULL;
869 if (sk && sk->sk_policy[1]) 870 if (sk && sk->sk_policy[1])
870 policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl, sk_sid); 871 policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl);
871 872
872 if (!policy) { 873 if (!policy) {
873 /* To accelerate a bit... */ 874 /* To accelerate a bit... */
874 if ((dst_orig->flags & DST_NOXFRM) || !xfrm_policy_list[XFRM_POLICY_OUT]) 875 if ((dst_orig->flags & DST_NOXFRM) || !xfrm_policy_list[XFRM_POLICY_OUT])
875 return 0; 876 return 0;
876 877
877 policy = flow_cache_lookup(fl, sk_sid, dst_orig->ops->family, 878 policy = flow_cache_lookup(fl, dst_orig->ops->family,
878 dir, xfrm_policy_lookup); 879 dir, xfrm_policy_lookup);
879 } 880 }
880 881
@@ -1032,13 +1033,15 @@ int
1032xfrm_decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short family) 1033xfrm_decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short family)
1033{ 1034{
1034 struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); 1035 struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
1036 int err;
1035 1037
1036 if (unlikely(afinfo == NULL)) 1038 if (unlikely(afinfo == NULL))
1037 return -EAFNOSUPPORT; 1039 return -EAFNOSUPPORT;
1038 1040
1039 afinfo->decode_session(skb, fl); 1041 afinfo->decode_session(skb, fl);
1042 err = security_xfrm_decode_session(skb, fl);
1040 xfrm_policy_put_afinfo(afinfo); 1043 xfrm_policy_put_afinfo(afinfo);
1041 return 0; 1044 return err;
1042} 1045}
1043EXPORT_SYMBOL(xfrm_decode_session); 1046EXPORT_SYMBOL(xfrm_decode_session);
1044 1047
@@ -1058,14 +1061,11 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
1058 struct xfrm_policy *pol; 1061 struct xfrm_policy *pol;
1059 struct flowi fl; 1062 struct flowi fl;
1060 u8 fl_dir = policy_to_flow_dir(dir); 1063 u8 fl_dir = policy_to_flow_dir(dir);
1061 u32 sk_sid;
1062 1064
1063 if (xfrm_decode_session(skb, &fl, family) < 0) 1065 if (xfrm_decode_session(skb, &fl, family) < 0)
1064 return 0; 1066 return 0;
1065 nf_nat_decode_session(skb, &fl, family); 1067 nf_nat_decode_session(skb, &fl, family);
1066 1068
1067 sk_sid = security_sk_sid(sk, &fl, fl_dir);
1068
1069 /* First, check used SA against their selectors. */ 1069 /* First, check used SA against their selectors. */
1070 if (skb->sp) { 1070 if (skb->sp) {
1071 int i; 1071 int i;
@@ -1079,10 +1079,10 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
1079 1079
1080 pol = NULL; 1080 pol = NULL;
1081 if (sk && sk->sk_policy[dir]) 1081 if (sk && sk->sk_policy[dir])
1082 pol = xfrm_sk_policy_lookup(sk, dir, &fl, sk_sid); 1082 pol = xfrm_sk_policy_lookup(sk, dir, &fl);
1083 1083
1084 if (!pol) 1084 if (!pol)
1085 pol = flow_cache_lookup(&fl, sk_sid, family, fl_dir, 1085 pol = flow_cache_lookup(&fl, family, fl_dir,
1086 xfrm_policy_lookup); 1086 xfrm_policy_lookup);
1087 1087
1088 if (!pol) 1088 if (!pol)
@@ -1298,6 +1298,8 @@ int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family)
1298 1298
1299 if (fl && !xfrm_selector_match(&dst->xfrm->sel, fl, family)) 1299 if (fl && !xfrm_selector_match(&dst->xfrm->sel, fl, family))
1300 return 0; 1300 return 0;
1301 if (fl && !security_xfrm_flow_state_match(fl, dst->xfrm))
1302 return 0;
1301 if (dst->xfrm->km.state != XFRM_STATE_VALID) 1303 if (dst->xfrm->km.state != XFRM_STATE_VALID)
1302 return 0; 1304 return 0;
1303 1305
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 0021aad5db43..be02bd981d12 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -367,7 +367,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
367 */ 367 */
368 if (x->km.state == XFRM_STATE_VALID) { 368 if (x->km.state == XFRM_STATE_VALID) {
369 if (!xfrm_selector_match(&x->sel, fl, family) || 369 if (!xfrm_selector_match(&x->sel, fl, family) ||
370 !xfrm_sec_ctx_match(pol->security, x->security)) 370 !security_xfrm_state_pol_flow_match(x, pol, fl))
371 continue; 371 continue;
372 if (!best || 372 if (!best ||
373 best->km.dying > x->km.dying || 373 best->km.dying > x->km.dying ||
@@ -379,7 +379,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
379 } else if (x->km.state == XFRM_STATE_ERROR || 379 } else if (x->km.state == XFRM_STATE_ERROR ||
380 x->km.state == XFRM_STATE_EXPIRED) { 380 x->km.state == XFRM_STATE_EXPIRED) {
381 if (xfrm_selector_match(&x->sel, fl, family) && 381 if (xfrm_selector_match(&x->sel, fl, family) &&
382 xfrm_sec_ctx_match(pol->security, x->security)) 382 security_xfrm_state_pol_flow_match(x, pol, fl))
383 error = -ESRCH; 383 error = -ESRCH;
384 } 384 }
385 } 385 }
@@ -403,6 +403,14 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
403 * to current session. */ 403 * to current session. */
404 xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family); 404 xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family);
405 405
406 error = security_xfrm_state_alloc_acquire(x, pol->security, fl->secid);
407 if (error) {
408 x->km.state = XFRM_STATE_DEAD;
409 xfrm_state_put(x);
410 x = NULL;
411 goto out;
412 }
413
406 if (km_query(x, tmpl, pol) == 0) { 414 if (km_query(x, tmpl, pol) == 0) {
407 x->km.state = XFRM_STATE_ACQ; 415 x->km.state = XFRM_STATE_ACQ;
408 list_add_tail(&x->bydst, xfrm_state_bydst+h); 416 list_add_tail(&x->bydst, xfrm_state_bydst+h);