aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVenkat Yekkirala <vyekkirala@trustedcs.com>2006-11-08 18:04:26 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-12-03 00:21:34 -0500
commit67f83cbf081a70426ff667e8d14f94e13ed3bdca (patch)
tree776a40733eacb9071478f865e6791daa3f6fd602
parent6b877699c6f1efede4545bcecc367786a472eedb (diff)
SELinux: Fix SA selection semantics
Fix the selection of an SA for an outgoing packet to be at the same context as the originating socket/flow. This eliminates the SELinux policy's ability to use/sendto SAs with contexts other than the socket's. With this patch applied, the SELinux policy will require one or more of the following for a socket to be able to communicate with/without SAs: 1. To enable a socket to communicate without using labeled-IPSec SAs: allow socket_t unlabeled_t:association { sendto recvfrom } 2. To enable a socket to communicate with labeled-IPSec SAs: allow socket_t self:association { sendto }; allow socket_t peer_sa_t:association { recvfrom }; Signed-off-by: Venkat Yekkirala <vyekkirala@TrustedCS.com> Signed-off-by: James Morris <jmorris@namei.org>
-rw-r--r--include/linux/security.h19
-rw-r--r--net/xfrm/xfrm_policy.c3
-rw-r--r--security/dummy.c7
-rw-r--r--security/selinux/hooks.c26
-rw-r--r--security/selinux/include/xfrm.h7
-rw-r--r--security/selinux/xfrm.c101
6 files changed, 70 insertions, 93 deletions
diff --git a/include/linux/security.h b/include/linux/security.h
index 84cebcdb3f83..83cdefae9931 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -886,11 +886,6 @@ struct request_sock;
886 * @xp contains the policy to check for a match. 886 * @xp contains the policy to check for a match.
887 * @fl contains the flow to check for a match. 887 * @fl contains the flow to check for a match.
888 * Return 1 if there is a match. 888 * Return 1 if there is a match.
889 * @xfrm_flow_state_match:
890 * @fl contains the flow key to match.
891 * @xfrm points to the xfrm_state to match.
892 * @xp points to the xfrm_policy to match.
893 * Return 1 if there is a match.
894 * @xfrm_decode_session: 889 * @xfrm_decode_session:
895 * @skb points to skb to decode. 890 * @skb points to skb to decode.
896 * @secid points to the flow key secid to set. 891 * @secid points to the flow key secid to set.
@@ -1388,8 +1383,6 @@ struct security_operations {
1388 int (*xfrm_policy_lookup)(struct xfrm_policy *xp, u32 fl_secid, u8 dir); 1383 int (*xfrm_policy_lookup)(struct xfrm_policy *xp, u32 fl_secid, u8 dir);
1389 int (*xfrm_state_pol_flow_match)(struct xfrm_state *x, 1384 int (*xfrm_state_pol_flow_match)(struct xfrm_state *x,
1390 struct xfrm_policy *xp, struct flowi *fl); 1385 struct xfrm_policy *xp, struct flowi *fl);
1391 int (*xfrm_flow_state_match)(struct flowi *fl, struct xfrm_state *xfrm,
1392 struct xfrm_policy *xp);
1393 int (*xfrm_decode_session)(struct sk_buff *skb, u32 *secid, int ckall); 1386 int (*xfrm_decode_session)(struct sk_buff *skb, u32 *secid, int ckall);
1394#endif /* CONFIG_SECURITY_NETWORK_XFRM */ 1387#endif /* CONFIG_SECURITY_NETWORK_XFRM */
1395 1388
@@ -3186,12 +3179,6 @@ static inline int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
3186 return security_ops->xfrm_state_pol_flow_match(x, xp, fl); 3179 return security_ops->xfrm_state_pol_flow_match(x, xp, fl);
3187} 3180}
3188 3181
3189static inline int security_xfrm_flow_state_match(struct flowi *fl,
3190 struct xfrm_state *xfrm, struct xfrm_policy *xp)
3191{
3192 return security_ops->xfrm_flow_state_match(fl, xfrm, xp);
3193}
3194
3195static inline int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid) 3182static inline int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
3196{ 3183{
3197 return security_ops->xfrm_decode_session(skb, secid, 1); 3184 return security_ops->xfrm_decode_session(skb, secid, 1);
@@ -3255,12 +3242,6 @@ static inline int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
3255 return 1; 3242 return 1;
3256} 3243}
3257 3244
3258static inline int security_xfrm_flow_state_match(struct flowi *fl,
3259 struct xfrm_state *xfrm, struct xfrm_policy *xp)
3260{
3261 return 1;
3262}
3263
3264static inline int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid) 3245static inline int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
3265{ 3246{
3266 return 0; 3247 return 0;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 7736b23c3f03..b88b038530c9 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1894,7 +1894,8 @@ int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,
1894 1894
1895 if (fl && !xfrm_selector_match(&dst->xfrm->sel, fl, family)) 1895 if (fl && !xfrm_selector_match(&dst->xfrm->sel, fl, family))
1896 return 0; 1896 return 0;
1897 if (fl && !security_xfrm_flow_state_match(fl, dst->xfrm, pol)) 1897 if (fl && pol &&
1898 !security_xfrm_state_pol_flow_match(dst->xfrm, pol, fl))
1898 return 0; 1899 return 0;
1899 if (dst->xfrm->km.state != XFRM_STATE_VALID) 1900 if (dst->xfrm->km.state != XFRM_STATE_VALID)
1900 return 0; 1901 return 0;
diff --git a/security/dummy.c b/security/dummy.c
index 0148d1518dd1..558795b237d6 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -886,12 +886,6 @@ static int dummy_xfrm_state_pol_flow_match(struct xfrm_state *x,
886 return 1; 886 return 1;
887} 887}
888 888
889static int dummy_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm,
890 struct xfrm_policy *xp)
891{
892 return 1;
893}
894
895static int dummy_xfrm_decode_session(struct sk_buff *skb, u32 *fl, int ckall) 889static int dummy_xfrm_decode_session(struct sk_buff *skb, u32 *fl, int ckall)
896{ 890{
897 return 0; 891 return 0;
@@ -1126,7 +1120,6 @@ void security_fixup_ops (struct security_operations *ops)
1126 set_to_dummy_if_null(ops, xfrm_state_delete_security); 1120 set_to_dummy_if_null(ops, xfrm_state_delete_security);
1127 set_to_dummy_if_null(ops, xfrm_policy_lookup); 1121 set_to_dummy_if_null(ops, xfrm_policy_lookup);
1128 set_to_dummy_if_null(ops, xfrm_state_pol_flow_match); 1122 set_to_dummy_if_null(ops, xfrm_state_pol_flow_match);
1129 set_to_dummy_if_null(ops, xfrm_flow_state_match);
1130 set_to_dummy_if_null(ops, xfrm_decode_session); 1123 set_to_dummy_if_null(ops, xfrm_decode_session);
1131#endif /* CONFIG_SECURITY_NETWORK_XFRM */ 1124#endif /* CONFIG_SECURITY_NETWORK_XFRM */
1132#ifdef CONFIG_KEYS 1125#ifdef CONFIG_KEYS
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 5bbd599a4471..956137baf3e7 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2889,7 +2889,8 @@ static void selinux_task_to_inode(struct task_struct *p,
2889} 2889}
2890 2890
2891/* Returns error only if unable to parse addresses */ 2891/* Returns error only if unable to parse addresses */
2892static int selinux_parse_skb_ipv4(struct sk_buff *skb, struct avc_audit_data *ad) 2892static int selinux_parse_skb_ipv4(struct sk_buff *skb,
2893 struct avc_audit_data *ad, u8 *proto)
2893{ 2894{
2894 int offset, ihlen, ret = -EINVAL; 2895 int offset, ihlen, ret = -EINVAL;
2895 struct iphdr _iph, *ih; 2896 struct iphdr _iph, *ih;
@@ -2907,6 +2908,9 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb, struct avc_audit_data *ad
2907 ad->u.net.v4info.daddr = ih->daddr; 2908 ad->u.net.v4info.daddr = ih->daddr;
2908 ret = 0; 2909 ret = 0;
2909 2910
2911 if (proto)
2912 *proto = ih->protocol;
2913
2910 switch (ih->protocol) { 2914 switch (ih->protocol) {
2911 case IPPROTO_TCP: { 2915 case IPPROTO_TCP: {
2912 struct tcphdr _tcph, *th; 2916 struct tcphdr _tcph, *th;
@@ -2950,7 +2954,8 @@ out:
2950#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 2954#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
2951 2955
2952/* Returns error only if unable to parse addresses */ 2956/* Returns error only if unable to parse addresses */
2953static int selinux_parse_skb_ipv6(struct sk_buff *skb, struct avc_audit_data *ad) 2957static int selinux_parse_skb_ipv6(struct sk_buff *skb,
2958 struct avc_audit_data *ad, u8 *proto)
2954{ 2959{
2955 u8 nexthdr; 2960 u8 nexthdr;
2956 int ret = -EINVAL, offset; 2961 int ret = -EINVAL, offset;
@@ -2971,6 +2976,9 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb, struct avc_audit_data *ad
2971 if (offset < 0) 2976 if (offset < 0)
2972 goto out; 2977 goto out;
2973 2978
2979 if (proto)
2980 *proto = nexthdr;
2981
2974 switch (nexthdr) { 2982 switch (nexthdr) {
2975 case IPPROTO_TCP: { 2983 case IPPROTO_TCP: {
2976 struct tcphdr _tcph, *th; 2984 struct tcphdr _tcph, *th;
@@ -3007,13 +3015,13 @@ out:
3007#endif /* IPV6 */ 3015#endif /* IPV6 */
3008 3016
3009static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, 3017static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
3010 char **addrp, int *len, int src) 3018 char **addrp, int *len, int src, u8 *proto)
3011{ 3019{
3012 int ret = 0; 3020 int ret = 0;
3013 3021
3014 switch (ad->u.net.family) { 3022 switch (ad->u.net.family) {
3015 case PF_INET: 3023 case PF_INET:
3016 ret = selinux_parse_skb_ipv4(skb, ad); 3024 ret = selinux_parse_skb_ipv4(skb, ad, proto);
3017 if (ret || !addrp) 3025 if (ret || !addrp)
3018 break; 3026 break;
3019 *len = 4; 3027 *len = 4;
@@ -3023,7 +3031,7 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
3023 3031
3024#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 3032#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3025 case PF_INET6: 3033 case PF_INET6:
3026 ret = selinux_parse_skb_ipv6(skb, ad); 3034 ret = selinux_parse_skb_ipv6(skb, ad, proto);
3027 if (ret || !addrp) 3035 if (ret || !addrp)
3028 break; 3036 break;
3029 *len = 16; 3037 *len = 16;
@@ -3494,7 +3502,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
3494 ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]"; 3502 ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]";
3495 ad.u.net.family = family; 3503 ad.u.net.family = family;
3496 3504
3497 err = selinux_parse_skb(skb, &ad, &addrp, &len, 1); 3505 err = selinux_parse_skb(skb, &ad, &addrp, &len, 1, NULL);
3498 if (err) 3506 if (err)
3499 goto out; 3507 goto out;
3500 3508
@@ -3820,6 +3828,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
3820 struct avc_audit_data ad; 3828 struct avc_audit_data ad;
3821 struct net_device *dev = (struct net_device *)out; 3829 struct net_device *dev = (struct net_device *)out;
3822 struct sk_security_struct *sksec; 3830 struct sk_security_struct *sksec;
3831 u8 proto;
3823 3832
3824 sk = skb->sk; 3833 sk = skb->sk;
3825 if (!sk) 3834 if (!sk)
@@ -3831,7 +3840,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
3831 ad.u.net.netif = dev->name; 3840 ad.u.net.netif = dev->name;
3832 ad.u.net.family = family; 3841 ad.u.net.family = family;
3833 3842
3834 err = selinux_parse_skb(skb, &ad, &addrp, &len, 0); 3843 err = selinux_parse_skb(skb, &ad, &addrp, &len, 0, &proto);
3835 if (err) 3844 if (err)
3836 goto out; 3845 goto out;
3837 3846
@@ -3845,7 +3854,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
3845 if (err) 3854 if (err)
3846 goto out; 3855 goto out;
3847 3856
3848 err = selinux_xfrm_postroute_last(sksec->sid, skb, &ad); 3857 err = selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto);
3849out: 3858out:
3850 return err ? NF_DROP : NF_ACCEPT; 3859 return err ? NF_DROP : NF_ACCEPT;
3851} 3860}
@@ -4764,7 +4773,6 @@ static struct security_operations selinux_ops = {
4764 .xfrm_state_delete_security = selinux_xfrm_state_delete, 4773 .xfrm_state_delete_security = selinux_xfrm_state_delete,
4765 .xfrm_policy_lookup = selinux_xfrm_policy_lookup, 4774 .xfrm_policy_lookup = selinux_xfrm_policy_lookup,
4766 .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match, 4775 .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match,
4767 .xfrm_flow_state_match = selinux_xfrm_flow_state_match,
4768 .xfrm_decode_session = selinux_xfrm_decode_session, 4776 .xfrm_decode_session = selinux_xfrm_decode_session,
4769#endif 4777#endif
4770 4778
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index 27502365d706..ebd7246a4be5 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -19,9 +19,6 @@ 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,
23 struct xfrm_policy *xp);
24
25 22
26/* 23/*
27 * Extract the security blob from the sock (it's actually on the socket) 24 * Extract the security blob from the sock (it's actually on the socket)
@@ -38,7 +35,7 @@ static inline struct inode_security_struct *get_sock_isec(struct sock *sk)
38int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb, 35int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb,
39 struct avc_audit_data *ad); 36 struct avc_audit_data *ad);
40int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, 37int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
41 struct avc_audit_data *ad); 38 struct avc_audit_data *ad, u8 proto);
42u32 selinux_socket_getpeer_dgram(struct sk_buff *skb); 39u32 selinux_socket_getpeer_dgram(struct sk_buff *skb);
43int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); 40int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall);
44#else 41#else
@@ -49,7 +46,7 @@ static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
49} 46}
50 47
51static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, 48static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
52 struct avc_audit_data *ad) 49 struct avc_audit_data *ad, u8 proto)
53{ 50{
54 return 0; 51 return 0;
55} 52}
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index 8fef74271f22..9b777140068f 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -115,71 +115,40 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *
115 struct flowi *fl) 115 struct flowi *fl)
116{ 116{
117 u32 state_sid; 117 u32 state_sid;
118 u32 pol_sid; 118 int rc;
119 int err;
120 119
121 if (xp->security) { 120 if (!xp->security)
122 if (!x->security)
123 /* unlabeled SA and labeled policy can't match */
124 return 0;
125 else
126 state_sid = x->security->ctx_sid;
127 pol_sid = xp->security->ctx_sid;
128 } else
129 if (x->security) 121 if (x->security)
130 /* unlabeled policy and labeled SA can't match */ 122 /* unlabeled policy and labeled SA can't match */
131 return 0; 123 return 0;
132 else 124 else
133 /* unlabeled policy and unlabeled SA match all flows */ 125 /* unlabeled policy and unlabeled SA match all flows */
134 return 1; 126 return 1;
135
136 err = avc_has_perm(state_sid, pol_sid, SECCLASS_ASSOCIATION,
137 ASSOCIATION__POLMATCH,
138 NULL);
139
140 if (err)
141 return 0;
142
143 err = avc_has_perm(fl->secid, state_sid, SECCLASS_ASSOCIATION,
144 ASSOCIATION__SENDTO,
145 NULL)? 0:1;
146
147 return err;
148}
149
150/*
151 * LSM hook implementation that authorizes that a particular outgoing flow
152 * can use a given security association.
153 */
154
155int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm,
156 struct xfrm_policy *xp)
157{
158 int rc = 0;
159 u32 sel_sid = SECINITSID_UNLABELED;
160 struct xfrm_sec_ctx *ctx;
161
162 if (!xp->security)
163 if (!xfrm->security)
164 return 1;
165 else
166 return 0;
167 else 127 else
168 if (!xfrm->security) 128 if (!x->security)
129 /* unlabeled SA and labeled policy can't match */
169 return 0; 130 return 0;
131 else
132 if (!selinux_authorizable_xfrm(x))
133 /* Not a SELinux-labeled SA */
134 return 0;
170 135
171 /* Context sid is either set to label or ANY_ASSOC */ 136 state_sid = x->security->ctx_sid;
172 if ((ctx = xfrm->security)) {
173 if (!selinux_authorizable_ctx(ctx))
174 return 0;
175 137
176 sel_sid = ctx->ctx_sid; 138 if (fl->secid != state_sid)
177 } 139 return 0;
178 140
179 rc = avc_has_perm(fl->secid, sel_sid, SECCLASS_ASSOCIATION, 141 rc = avc_has_perm(fl->secid, state_sid, SECCLASS_ASSOCIATION,
180 ASSOCIATION__SENDTO, 142 ASSOCIATION__SENDTO,
181 NULL)? 0:1; 143 NULL)? 0:1;
182 144
145 /*
146 * We don't need a separate SA Vs. policy polmatch check
147 * since the SA is now of the same label as the flow and
148 * a flow Vs. policy polmatch check had already happened
149 * in selinux_xfrm_policy_lookup() above.
150 */
151
183 return rc; 152 return rc;
184} 153}
185 154
@@ -481,6 +450,13 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
481 } 450 }
482 } 451 }
483 452
453 /*
454 * This check even when there's no association involved is
455 * intended, according to Trent Jaeger, to make sure a
456 * process can't engage in non-ipsec communication unless
457 * explicitly allowed by policy.
458 */
459
484 rc = avc_has_perm(isec_sid, sel_sid, SECCLASS_ASSOCIATION, 460 rc = avc_has_perm(isec_sid, sel_sid, SECCLASS_ASSOCIATION,
485 ASSOCIATION__RECVFROM, ad); 461 ASSOCIATION__RECVFROM, ad);
486 462
@@ -492,10 +468,10 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
492 * If we have no security association, then we need to determine 468 * If we have no security association, then we need to determine
493 * whether the socket is allowed to send to an unlabelled destination. 469 * whether the socket is allowed to send to an unlabelled destination.
494 * If we do have a authorizable security association, then it has already been 470 * If we do have a authorizable security association, then it has already been
495 * checked in xfrm_policy_lookup hook. 471 * checked in the selinux_xfrm_state_pol_flow_match hook above.
496 */ 472 */
497int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, 473int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
498 struct avc_audit_data *ad) 474 struct avc_audit_data *ad, u8 proto)
499{ 475{
500 struct dst_entry *dst; 476 struct dst_entry *dst;
501 int rc = 0; 477 int rc = 0;
@@ -514,6 +490,27 @@ int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
514 } 490 }
515 } 491 }
516 492
493 switch (proto) {
494 case IPPROTO_AH:
495 case IPPROTO_ESP:
496 case IPPROTO_COMP:
497 /*
498 * We should have already seen this packet once before
499 * it underwent xfrm(s). No need to subject it to the
500 * unlabeled check.
501 */
502 goto out;
503 default:
504 break;
505 }
506
507 /*
508 * This check even when there's no association involved is
509 * intended, according to Trent Jaeger, to make sure a
510 * process can't engage in non-ipsec communication unless
511 * explicitly allowed by policy.
512 */
513
517 rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION, 514 rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION,
518 ASSOCIATION__SENDTO, ad); 515 ASSOCIATION__SENDTO, ad);
519out: 516out: