aboutsummaryrefslogtreecommitdiffstats
path: root/security
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 /security
parente138a5d2356729b8752e88520cc1525fae9794ac (diff)
parentf26b90440cd74c78fe10c9bd5160809704a9627c (diff)
Merge ../scsi-rc-fixes-2.6
Diffstat (limited to 'security')
-rw-r--r--security/dummy.c3
-rw-r--r--security/selinux/hooks.c8
-rw-r--r--security/selinux/include/selinux_netlabel.h10
-rw-r--r--security/selinux/include/xfrm.h3
-rw-r--r--security/selinux/ss/ebitmap.c8
-rw-r--r--security/selinux/ss/mls.c17
-rw-r--r--security/selinux/ss/policydb.c2
-rw-r--r--security/selinux/ss/services.c119
-rw-r--r--security/selinux/xfrm.c53
9 files changed, 160 insertions, 63 deletions
diff --git a/security/dummy.c b/security/dummy.c
index aeee70565509..43874c1e6e23 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -881,7 +881,8 @@ static int dummy_xfrm_state_pol_flow_match(struct xfrm_state *x,
881 return 1; 881 return 1;
882} 882}
883 883
884static int dummy_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm) 884static int dummy_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm,
885 struct xfrm_policy *xp)
885{ 886{
886 return 1; 887 return 1;
887} 888}
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index e9969a2fc846..8ab5679a37a3 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3313,7 +3313,13 @@ static int selinux_socket_getpeername(struct socket *sock)
3313 3313
3314static int selinux_socket_setsockopt(struct socket *sock,int level,int optname) 3314static int selinux_socket_setsockopt(struct socket *sock,int level,int optname)
3315{ 3315{
3316 return socket_has_perm(current, sock, SOCKET__SETOPT); 3316 int err;
3317
3318 err = socket_has_perm(current, sock, SOCKET__SETOPT);
3319 if (err)
3320 return err;
3321
3322 return selinux_netlbl_socket_setsockopt(sock, level, optname);
3317} 3323}
3318 3324
3319static int selinux_socket_getsockopt(struct socket *sock, int level, 3325static int selinux_socket_getsockopt(struct socket *sock, int level,
diff --git a/security/selinux/include/selinux_netlabel.h b/security/selinux/include/selinux_netlabel.h
index ecab4bddaaf4..9de10cc2cef2 100644
--- a/security/selinux/include/selinux_netlabel.h
+++ b/security/selinux/include/selinux_netlabel.h
@@ -53,6 +53,9 @@ void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
53void selinux_netlbl_sk_clone_security(struct sk_security_struct *ssec, 53void selinux_netlbl_sk_clone_security(struct sk_security_struct *ssec,
54 struct sk_security_struct *newssec); 54 struct sk_security_struct *newssec);
55int selinux_netlbl_inode_permission(struct inode *inode, int mask); 55int selinux_netlbl_inode_permission(struct inode *inode, int mask);
56int selinux_netlbl_socket_setsockopt(struct socket *sock,
57 int level,
58 int optname);
56#else 59#else
57static inline void selinux_netlbl_cache_invalidate(void) 60static inline void selinux_netlbl_cache_invalidate(void)
58{ 61{
@@ -114,6 +117,13 @@ static inline int selinux_netlbl_inode_permission(struct inode *inode,
114{ 117{
115 return 0; 118 return 0;
116} 119}
120
121static inline int selinux_netlbl_socket_setsockopt(struct socket *sock,
122 int level,
123 int optname)
124{
125 return 0;
126}
117#endif /* CONFIG_NETLABEL */ 127#endif /* CONFIG_NETLABEL */
118 128
119#endif 129#endif
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index 81eb59890162..526b28019aca 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -19,7 +19,8 @@ int selinux_xfrm_state_delete(struct xfrm_state *x);
19int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir); 19int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir);
20int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, 20int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
21 struct xfrm_policy *xp, struct flowi *fl); 21 struct xfrm_policy *xp, struct flowi *fl);
22int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm); 22int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm,
23 struct xfrm_policy *xp);
23 24
24 25
25/* 26/*
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index cfed1d30fa6a..d539346ab3a2 100644
--- a/security/selinux/ss/ebitmap.c
+++ b/security/selinux/ss/ebitmap.c
@@ -93,11 +93,15 @@ int ebitmap_export(const struct ebitmap *src,
93 size_t bitmap_byte; 93 size_t bitmap_byte;
94 unsigned char bitmask; 94 unsigned char bitmask;
95 95
96 if (src->highbit == 0) {
97 *dst = NULL;
98 *dst_len = 0;
99 return 0;
100 }
101
96 bitmap_len = src->highbit / 8; 102 bitmap_len = src->highbit / 8;
97 if (src->highbit % 7) 103 if (src->highbit % 7)
98 bitmap_len += 1; 104 bitmap_len += 1;
99 if (bitmap_len == 0)
100 return -EINVAL;
101 105
102 bitmap = kzalloc((bitmap_len & ~(sizeof(MAPTYPE) - 1)) + 106 bitmap = kzalloc((bitmap_len & ~(sizeof(MAPTYPE) - 1)) +
103 sizeof(MAPTYPE), 107 sizeof(MAPTYPE),
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index c713af23250a..2cca8e251624 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -640,8 +640,13 @@ int mls_export_cat(const struct context *context,
640{ 640{
641 int rc = -EPERM; 641 int rc = -EPERM;
642 642
643 if (!selinux_mls_enabled) 643 if (!selinux_mls_enabled) {
644 *low = NULL;
645 *low_len = 0;
646 *high = NULL;
647 *high_len = 0;
644 return 0; 648 return 0;
649 }
645 650
646 if (low != NULL) { 651 if (low != NULL) {
647 rc = ebitmap_export(&context->range.level[0].cat, 652 rc = ebitmap_export(&context->range.level[0].cat,
@@ -661,10 +666,16 @@ int mls_export_cat(const struct context *context,
661 return 0; 666 return 0;
662 667
663export_cat_failure: 668export_cat_failure:
664 if (low != NULL) 669 if (low != NULL) {
665 kfree(*low); 670 kfree(*low);
666 if (high != NULL) 671 *low = NULL;
672 *low_len = 0;
673 }
674 if (high != NULL) {
667 kfree(*high); 675 kfree(*high);
676 *high = NULL;
677 *high_len = 0;
678 }
668 return rc; 679 return rc;
669} 680}
670 681
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index b18895302555..ba48961f9d05 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -618,6 +618,7 @@ void policydb_destroy(struct policydb *p)
618 c = c->next; 618 c = c->next;
619 ocontext_destroy(ctmp,i); 619 ocontext_destroy(ctmp,i);
620 } 620 }
621 p->ocontexts[i] = NULL;
621 } 622 }
622 623
623 g = p->genfs; 624 g = p->genfs;
@@ -633,6 +634,7 @@ void policydb_destroy(struct policydb *p)
633 g = g->next; 634 g = g->next;
634 kfree(gtmp); 635 kfree(gtmp);
635 } 636 }
637 p->genfs = NULL;
636 638
637 cond_policydb_destroy(p); 639 cond_policydb_destroy(p);
638 640
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 0c219a1b3243..bfe122764c98 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -2172,7 +2172,12 @@ struct netlbl_cache {
2172 */ 2172 */
2173static void selinux_netlbl_cache_free(const void *data) 2173static void selinux_netlbl_cache_free(const void *data)
2174{ 2174{
2175 struct netlbl_cache *cache = NETLBL_CACHE(data); 2175 struct netlbl_cache *cache;
2176
2177 if (data == NULL)
2178 return;
2179
2180 cache = NETLBL_CACHE(data);
2176 switch (cache->type) { 2181 switch (cache->type) {
2177 case NETLBL_CACHE_T_MLS: 2182 case NETLBL_CACHE_T_MLS:
2178 ebitmap_destroy(&cache->data.mls_label.level[0].cat); 2183 ebitmap_destroy(&cache->data.mls_label.level[0].cat);
@@ -2197,17 +2202,20 @@ static void selinux_netlbl_cache_add(struct sk_buff *skb, struct context *ctx)
2197 struct netlbl_lsm_secattr secattr; 2202 struct netlbl_lsm_secattr secattr;
2198 2203
2199 netlbl_secattr_init(&secattr); 2204 netlbl_secattr_init(&secattr);
2205 secattr.cache = netlbl_secattr_cache_alloc(GFP_ATOMIC);
2206 if (secattr.cache == NULL)
2207 goto netlbl_cache_add_return;
2200 2208
2201 cache = kzalloc(sizeof(*cache), GFP_ATOMIC); 2209 cache = kzalloc(sizeof(*cache), GFP_ATOMIC);
2202 if (cache == NULL) 2210 if (cache == NULL)
2203 goto netlbl_cache_add_failure; 2211 goto netlbl_cache_add_return;
2204 secattr.cache.free = selinux_netlbl_cache_free; 2212 secattr.cache->free = selinux_netlbl_cache_free;
2205 secattr.cache.data = (void *)cache; 2213 secattr.cache->data = (void *)cache;
2206 2214
2207 cache->type = NETLBL_CACHE_T_MLS; 2215 cache->type = NETLBL_CACHE_T_MLS;
2208 if (ebitmap_cpy(&cache->data.mls_label.level[0].cat, 2216 if (ebitmap_cpy(&cache->data.mls_label.level[0].cat,
2209 &ctx->range.level[0].cat) != 0) 2217 &ctx->range.level[0].cat) != 0)
2210 goto netlbl_cache_add_failure; 2218 goto netlbl_cache_add_return;
2211 cache->data.mls_label.level[1].cat.highbit = 2219 cache->data.mls_label.level[1].cat.highbit =
2212 cache->data.mls_label.level[0].cat.highbit; 2220 cache->data.mls_label.level[0].cat.highbit;
2213 cache->data.mls_label.level[1].cat.node = 2221 cache->data.mls_label.level[1].cat.node =
@@ -2215,13 +2223,10 @@ static void selinux_netlbl_cache_add(struct sk_buff *skb, struct context *ctx)
2215 cache->data.mls_label.level[0].sens = ctx->range.level[0].sens; 2223 cache->data.mls_label.level[0].sens = ctx->range.level[0].sens;
2216 cache->data.mls_label.level[1].sens = ctx->range.level[0].sens; 2224 cache->data.mls_label.level[1].sens = ctx->range.level[0].sens;
2217 2225
2218 if (netlbl_cache_add(skb, &secattr) != 0) 2226 netlbl_cache_add(skb, &secattr);
2219 goto netlbl_cache_add_failure;
2220
2221 return;
2222 2227
2223netlbl_cache_add_failure: 2228netlbl_cache_add_return:
2224 netlbl_secattr_destroy(&secattr, 1); 2229 netlbl_secattr_destroy(&secattr);
2225} 2230}
2226 2231
2227/** 2232/**
@@ -2263,8 +2268,8 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb,
2263 2268
2264 POLICY_RDLOCK; 2269 POLICY_RDLOCK;
2265 2270
2266 if (secattr->cache.data) { 2271 if (secattr->cache) {
2267 cache = NETLBL_CACHE(secattr->cache.data); 2272 cache = NETLBL_CACHE(secattr->cache->data);
2268 switch (cache->type) { 2273 switch (cache->type) {
2269 case NETLBL_CACHE_T_SID: 2274 case NETLBL_CACHE_T_SID:
2270 *sid = cache->data.sid; 2275 *sid = cache->data.sid;
@@ -2331,7 +2336,7 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb,
2331 selinux_netlbl_cache_add(skb, &ctx_new); 2336 selinux_netlbl_cache_add(skb, &ctx_new);
2332 ebitmap_destroy(&ctx_new.range.level[0].cat); 2337 ebitmap_destroy(&ctx_new.range.level[0].cat);
2333 } else { 2338 } else {
2334 *sid = SECINITSID_UNLABELED; 2339 *sid = SECSID_NULL;
2335 rc = 0; 2340 rc = 0;
2336 } 2341 }
2337 2342
@@ -2369,7 +2374,7 @@ static int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
2369 &secattr, 2374 &secattr,
2370 base_sid, 2375 base_sid,
2371 sid); 2376 sid);
2372 netlbl_secattr_destroy(&secattr, 0); 2377 netlbl_secattr_destroy(&secattr);
2373 2378
2374 return rc; 2379 return rc;
2375} 2380}
@@ -2394,31 +2399,33 @@ static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid)
2394 if (!ss_initialized) 2399 if (!ss_initialized)
2395 return 0; 2400 return 0;
2396 2401
2402 netlbl_secattr_init(&secattr);
2403
2397 POLICY_RDLOCK; 2404 POLICY_RDLOCK;
2398 2405
2399 ctx = sidtab_search(&sidtab, sid); 2406 ctx = sidtab_search(&sidtab, sid);
2400 if (ctx == NULL) 2407 if (ctx == NULL)
2401 goto netlbl_socket_setsid_return; 2408 goto netlbl_socket_setsid_return;
2402 2409
2403 netlbl_secattr_init(&secattr);
2404 secattr.domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1], 2410 secattr.domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1],
2405 GFP_ATOMIC); 2411 GFP_ATOMIC);
2406 mls_export_lvl(ctx, &secattr.mls_lvl, NULL); 2412 mls_export_lvl(ctx, &secattr.mls_lvl, NULL);
2407 secattr.mls_lvl_vld = 1; 2413 secattr.mls_lvl_vld = 1;
2408 mls_export_cat(ctx, 2414 rc = mls_export_cat(ctx,
2409 &secattr.mls_cat, 2415 &secattr.mls_cat,
2410 &secattr.mls_cat_len, 2416 &secattr.mls_cat_len,
2411 NULL, 2417 NULL,
2412 NULL); 2418 NULL);
2419 if (rc != 0)
2420 goto netlbl_socket_setsid_return;
2413 2421
2414 rc = netlbl_socket_setattr(sock, &secattr); 2422 rc = netlbl_socket_setattr(sock, &secattr);
2415 if (rc == 0) 2423 if (rc == 0)
2416 sksec->nlbl_state = NLBL_LABELED; 2424 sksec->nlbl_state = NLBL_LABELED;
2417 2425
2418 netlbl_secattr_destroy(&secattr, 0);
2419
2420netlbl_socket_setsid_return: 2426netlbl_socket_setsid_return:
2421 POLICY_RDUNLOCK; 2427 POLICY_RDUNLOCK;
2428 netlbl_secattr_destroy(&secattr);
2422 return rc; 2429 return rc;
2423} 2430}
2424 2431
@@ -2514,10 +2521,10 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
2514 if (netlbl_sock_getattr(sk, &secattr) == 0 && 2521 if (netlbl_sock_getattr(sk, &secattr) == 0 &&
2515 selinux_netlbl_secattr_to_sid(NULL, 2522 selinux_netlbl_secattr_to_sid(NULL,
2516 &secattr, 2523 &secattr,
2517 sksec->sid, 2524 SECINITSID_UNLABELED,
2518 &nlbl_peer_sid) == 0) 2525 &nlbl_peer_sid) == 0)
2519 sksec->peer_sid = nlbl_peer_sid; 2526 sksec->peer_sid = nlbl_peer_sid;
2520 netlbl_secattr_destroy(&secattr, 0); 2527 netlbl_secattr_destroy(&secattr);
2521 2528
2522 sksec->nlbl_state = NLBL_REQUIRE; 2529 sksec->nlbl_state = NLBL_REQUIRE;
2523 2530
@@ -2547,9 +2554,6 @@ u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, u32 sock_sid)
2547 if (rc != 0) 2554 if (rc != 0)
2548 return SECSID_NULL; 2555 return SECSID_NULL;
2549 2556
2550 if (peer_sid == SECINITSID_UNLABELED)
2551 return SECSID_NULL;
2552
2553 return peer_sid; 2557 return peer_sid;
2554} 2558}
2555 2559
@@ -2611,11 +2615,13 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
2611 u32 netlbl_sid; 2615 u32 netlbl_sid;
2612 u32 recv_perm; 2616 u32 recv_perm;
2613 2617
2614 rc = selinux_netlbl_skbuff_getsid(skb, SECINITSID_NETMSG, &netlbl_sid); 2618 rc = selinux_netlbl_skbuff_getsid(skb,
2619 SECINITSID_UNLABELED,
2620 &netlbl_sid);
2615 if (rc != 0) 2621 if (rc != 0)
2616 return rc; 2622 return rc;
2617 2623
2618 if (netlbl_sid == SECINITSID_UNLABELED) 2624 if (netlbl_sid == SECSID_NULL)
2619 return 0; 2625 return 0;
2620 2626
2621 switch (sksec->sclass) { 2627 switch (sksec->sclass) {
@@ -2653,10 +2659,6 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
2653u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock) 2659u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock)
2654{ 2660{
2655 struct sk_security_struct *sksec = sock->sk->sk_security; 2661 struct sk_security_struct *sksec = sock->sk->sk_security;
2656
2657 if (sksec->peer_sid == SECINITSID_UNLABELED)
2658 return SECSID_NULL;
2659
2660 return sksec->peer_sid; 2662 return sksec->peer_sid;
2661} 2663}
2662 2664
@@ -2672,18 +2674,49 @@ u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock)
2672u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb) 2674u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb)
2673{ 2675{
2674 int peer_sid; 2676 int peer_sid;
2675 struct sock *sk = skb->sk;
2676 struct inode_security_struct *isec;
2677 2677
2678 if (sk == NULL || sk->sk_socket == NULL) 2678 if (selinux_netlbl_skbuff_getsid(skb,
2679 return SECSID_NULL; 2679 SECINITSID_UNLABELED,
2680 2680 &peer_sid) != 0)
2681 isec = SOCK_INODE(sk->sk_socket)->i_security;
2682 if (selinux_netlbl_skbuff_getsid(skb, isec->sid, &peer_sid) != 0)
2683 return SECSID_NULL;
2684 if (peer_sid == SECINITSID_UNLABELED)
2685 return SECSID_NULL; 2681 return SECSID_NULL;
2686 2682
2687 return peer_sid; 2683 return peer_sid;
2688} 2684}
2685
2686/**
2687 * selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel
2688 * @sock: the socket
2689 * @level: the socket level or protocol
2690 * @optname: the socket option name
2691 *
2692 * Description:
2693 * Check the setsockopt() call and if the user is trying to replace the IP
2694 * options on a socket and a NetLabel is in place for the socket deny the
2695 * access; otherwise allow the access. Returns zero when the access is
2696 * allowed, -EACCES when denied, and other negative values on error.
2697 *
2698 */
2699int selinux_netlbl_socket_setsockopt(struct socket *sock,
2700 int level,
2701 int optname)
2702{
2703 int rc = 0;
2704 struct inode *inode = SOCK_INODE(sock);
2705 struct sk_security_struct *sksec = sock->sk->sk_security;
2706 struct inode_security_struct *isec = inode->i_security;
2707 struct netlbl_lsm_secattr secattr;
2708
2709 mutex_lock(&isec->lock);
2710 if (level == IPPROTO_IP && optname == IP_OPTIONS &&
2711 sksec->nlbl_state == NLBL_LABELED) {
2712 netlbl_secattr_init(&secattr);
2713 rc = netlbl_socket_getattr(sock, &secattr);
2714 if (rc == 0 && (secattr.cache || secattr.mls_lvl_vld))
2715 rc = -EACCES;
2716 netlbl_secattr_destroy(&secattr);
2717 }
2718 mutex_unlock(&isec->lock);
2719
2720 return rc;
2721}
2689#endif /* CONFIG_NETLABEL */ 2722#endif /* CONFIG_NETLABEL */
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index 3e742b850af6..675b995a67c3 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -77,8 +77,8 @@ static inline int selinux_authorizable_xfrm(struct xfrm_state *x)
77 */ 77 */
78int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir) 78int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir)
79{ 79{
80 int rc = 0; 80 int rc;
81 u32 sel_sid = SECINITSID_UNLABELED; 81 u32 sel_sid;
82 struct xfrm_sec_ctx *ctx; 82 struct xfrm_sec_ctx *ctx;
83 83
84 /* Context sid is either set to label or ANY_ASSOC */ 84 /* Context sid is either set to label or ANY_ASSOC */
@@ -88,11 +88,21 @@ int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir)
88 88
89 sel_sid = ctx->ctx_sid; 89 sel_sid = ctx->ctx_sid;
90 } 90 }
91 else
92 /*
93 * All flows should be treated as polmatch'ing an
94 * otherwise applicable "non-labeled" policy. This
95 * would prevent inadvertent "leaks".
96 */
97 return 0;
91 98
92 rc = avc_has_perm(fl_secid, sel_sid, SECCLASS_ASSOCIATION, 99 rc = avc_has_perm(fl_secid, sel_sid, SECCLASS_ASSOCIATION,
93 ASSOCIATION__POLMATCH, 100 ASSOCIATION__POLMATCH,
94 NULL); 101 NULL);
95 102
103 if (rc == -EACCES)
104 rc = -ESRCH;
105
96 return rc; 106 return rc;
97} 107}
98 108
@@ -108,15 +118,20 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *
108 u32 pol_sid; 118 u32 pol_sid;
109 int err; 119 int err;
110 120
111 if (x->security) 121 if (xp->security) {
112 state_sid = x->security->ctx_sid; 122 if (!x->security)
113 else 123 /* unlabeled SA and labeled policy can't match */
114 state_sid = SECINITSID_UNLABELED; 124 return 0;
115 125 else
116 if (xp->security) 126 state_sid = x->security->ctx_sid;
117 pol_sid = xp->security->ctx_sid; 127 pol_sid = xp->security->ctx_sid;
118 else 128 } else
119 pol_sid = SECINITSID_UNLABELED; 129 if (x->security)
130 /* unlabeled policy and labeled SA can't match */
131 return 0;
132 else
133 /* unlabeled policy and unlabeled SA match all flows */
134 return 1;
120 135
121 err = avc_has_perm(state_sid, pol_sid, SECCLASS_ASSOCIATION, 136 err = avc_has_perm(state_sid, pol_sid, SECCLASS_ASSOCIATION,
122 ASSOCIATION__POLMATCH, 137 ASSOCIATION__POLMATCH,
@@ -125,7 +140,11 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *
125 if (err) 140 if (err)
126 return 0; 141 return 0;
127 142
128 return selinux_xfrm_flow_state_match(fl, x); 143 err = avc_has_perm(fl->secid, state_sid, SECCLASS_ASSOCIATION,
144 ASSOCIATION__SENDTO,
145 NULL)? 0:1;
146
147 return err;
129} 148}
130 149
131/* 150/*
@@ -133,12 +152,22 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *
133 * can use a given security association. 152 * can use a given security association.
134 */ 153 */
135 154
136int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm) 155int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm,
156 struct xfrm_policy *xp)
137{ 157{
138 int rc = 0; 158 int rc = 0;
139 u32 sel_sid = SECINITSID_UNLABELED; 159 u32 sel_sid = SECINITSID_UNLABELED;
140 struct xfrm_sec_ctx *ctx; 160 struct xfrm_sec_ctx *ctx;
141 161
162 if (!xp->security)
163 if (!xfrm->security)
164 return 1;
165 else
166 return 0;
167 else
168 if (!xfrm->security)
169 return 0;
170
142 /* Context sid is either set to label or ANY_ASSOC */ 171 /* Context sid is either set to label or ANY_ASSOC */
143 if ((ctx = xfrm->security)) { 172 if ((ctx = xfrm->security)) {
144 if (!selinux_authorizable_ctx(ctx)) 173 if (!selinux_authorizable_ctx(ctx))