Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 67f83cbf authored by Venkat Yekkirala's avatar Venkat Yekkirala Committed by David S. Miller
Browse files

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: default avatarVenkat Yekkirala <vyekkirala@TrustedCS.com>
Signed-off-by: default avatarJames Morris <jmorris@namei.org>
parent 6b877699
Loading
Loading
Loading
Loading
+0 −19
Original line number Diff line number Diff line
@@ -886,11 +886,6 @@ struct request_sock;
 *	@xp contains the policy to check for a match.
 *	@fl contains the flow to check for a match.
 *	Return 1 if there is a match.
 * @xfrm_flow_state_match:
 *	@fl contains the flow key to match.
 *	@xfrm points to the xfrm_state to match.
 *	@xp points to the xfrm_policy to match.
 *	Return 1 if there is a match.
 * @xfrm_decode_session:
 *	@skb points to skb to decode.
 *	@secid points to the flow key secid to set.
@@ -1388,8 +1383,6 @@ struct security_operations {
	int (*xfrm_policy_lookup)(struct xfrm_policy *xp, u32 fl_secid, u8 dir);
	int (*xfrm_state_pol_flow_match)(struct xfrm_state *x,
			struct xfrm_policy *xp, struct flowi *fl);
	int (*xfrm_flow_state_match)(struct flowi *fl, struct xfrm_state *xfrm,
			struct xfrm_policy *xp);
	int (*xfrm_decode_session)(struct sk_buff *skb, u32 *secid, int ckall);
#endif	/* CONFIG_SECURITY_NETWORK_XFRM */

@@ -3186,12 +3179,6 @@ static inline int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
	return security_ops->xfrm_state_pol_flow_match(x, xp, fl);
}

static inline int security_xfrm_flow_state_match(struct flowi *fl,
			struct xfrm_state *xfrm, struct xfrm_policy *xp)
{
	return security_ops->xfrm_flow_state_match(fl, xfrm, xp);
}

static inline int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
{
	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,
	return 1;
}

static inline int security_xfrm_flow_state_match(struct flowi *fl,
			struct xfrm_state *xfrm, struct xfrm_policy *xp)
{
	return 1;
}

static inline int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
{
	return 0;
+2 −1
Original line number Diff line number Diff line
@@ -1894,7 +1894,8 @@ int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,

		if (fl && !xfrm_selector_match(&dst->xfrm->sel, fl, family))
			return 0;
		if (fl && !security_xfrm_flow_state_match(fl, dst->xfrm, pol))
		if (fl && pol &&
		    !security_xfrm_state_pol_flow_match(dst->xfrm, pol, fl))
			return 0;
		if (dst->xfrm->km.state != XFRM_STATE_VALID)
			return 0;
+0 −7
Original line number Diff line number Diff line
@@ -886,12 +886,6 @@ static int dummy_xfrm_state_pol_flow_match(struct xfrm_state *x,
	return 1;
}

static int dummy_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm,
				struct xfrm_policy *xp)
{
	return 1;
}

static int dummy_xfrm_decode_session(struct sk_buff *skb, u32 *fl, int ckall)
{
	return 0;
@@ -1126,7 +1120,6 @@ void security_fixup_ops (struct security_operations *ops)
	set_to_dummy_if_null(ops, xfrm_state_delete_security);
	set_to_dummy_if_null(ops, xfrm_policy_lookup);
	set_to_dummy_if_null(ops, xfrm_state_pol_flow_match);
	set_to_dummy_if_null(ops, xfrm_flow_state_match);
	set_to_dummy_if_null(ops, xfrm_decode_session);
#endif	/* CONFIG_SECURITY_NETWORK_XFRM */
#ifdef CONFIG_KEYS
+17 −9
Original line number Diff line number Diff line
@@ -2889,7 +2889,8 @@ static void selinux_task_to_inode(struct task_struct *p,
}

/* Returns error only if unable to parse addresses */
static int selinux_parse_skb_ipv4(struct sk_buff *skb, struct avc_audit_data *ad)
static int selinux_parse_skb_ipv4(struct sk_buff *skb,
			struct avc_audit_data *ad, u8 *proto)
{
	int offset, ihlen, ret = -EINVAL;
	struct iphdr _iph, *ih;
@@ -2907,6 +2908,9 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb, struct avc_audit_data *ad
	ad->u.net.v4info.daddr = ih->daddr;
	ret = 0;

	if (proto)
		*proto = ih->protocol;

	switch (ih->protocol) {
        case IPPROTO_TCP: {
        	struct tcphdr _tcph, *th;
@@ -2950,7 +2954,8 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb, struct avc_audit_data *ad
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)

/* Returns error only if unable to parse addresses */
static int selinux_parse_skb_ipv6(struct sk_buff *skb, struct avc_audit_data *ad)
static int selinux_parse_skb_ipv6(struct sk_buff *skb,
			struct avc_audit_data *ad, u8 *proto)
{
	u8 nexthdr;
	int ret = -EINVAL, offset;
@@ -2971,6 +2976,9 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb, struct avc_audit_data *ad
	if (offset < 0)
		goto out;

	if (proto)
		*proto = nexthdr;

	switch (nexthdr) {
	case IPPROTO_TCP: {
        	struct tcphdr _tcph, *th;
@@ -3007,13 +3015,13 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb, struct avc_audit_data *ad
#endif /* IPV6 */

static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
			     char **addrp, int *len, int src)
			     char **addrp, int *len, int src, u8 *proto)
{
	int ret = 0;

	switch (ad->u.net.family) {
	case PF_INET:
		ret = selinux_parse_skb_ipv4(skb, ad);
		ret = selinux_parse_skb_ipv4(skb, ad, proto);
		if (ret || !addrp)
			break;
		*len = 4;
@@ -3023,7 +3031,7 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,

#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
	case PF_INET6:
		ret = selinux_parse_skb_ipv6(skb, ad);
		ret = selinux_parse_skb_ipv6(skb, ad, proto);
		if (ret || !addrp)
			break;
		*len = 16;
@@ -3494,7 +3502,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
	ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]";
	ad.u.net.family = family;

	err = selinux_parse_skb(skb, &ad, &addrp, &len, 1);
	err = selinux_parse_skb(skb, &ad, &addrp, &len, 1, NULL);
	if (err)
		goto out;

@@ -3820,6 +3828,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
	struct avc_audit_data ad;
	struct net_device *dev = (struct net_device *)out;
	struct sk_security_struct *sksec;
	u8 proto;

	sk = skb->sk;
	if (!sk)
@@ -3831,7 +3840,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
	ad.u.net.netif = dev->name;
	ad.u.net.family = family;

	err = selinux_parse_skb(skb, &ad, &addrp, &len, 0);
	err = selinux_parse_skb(skb, &ad, &addrp, &len, 0, &proto);
	if (err)
		goto out;

@@ -3845,7 +3854,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
	if (err)
		goto out;

	err = selinux_xfrm_postroute_last(sksec->sid, skb, &ad);
	err = selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto);
out:
	return err ? NF_DROP : NF_ACCEPT;
}
@@ -4764,7 +4773,6 @@ static struct security_operations selinux_ops = {
	.xfrm_state_delete_security =	selinux_xfrm_state_delete,
	.xfrm_policy_lookup = 		selinux_xfrm_policy_lookup,
	.xfrm_state_pol_flow_match =	selinux_xfrm_state_pol_flow_match,
	.xfrm_flow_state_match =	selinux_xfrm_flow_state_match,
	.xfrm_decode_session =		selinux_xfrm_decode_session,
#endif

+2 −5
Original line number Diff line number Diff line
@@ -19,9 +19,6 @@ int selinux_xfrm_state_delete(struct xfrm_state *x);
int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir);
int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
			struct xfrm_policy *xp, struct flowi *fl);
int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm,
			struct xfrm_policy *xp);


/*
 * 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)
int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb,
			struct avc_audit_data *ad);
int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
			struct avc_audit_data *ad);
			struct avc_audit_data *ad, u8 proto);
u32 selinux_socket_getpeer_dgram(struct sk_buff *skb);
int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall);
#else
@@ -49,7 +46,7 @@ static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
}

static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
			struct avc_audit_data *ad)
			struct avc_audit_data *ad, u8 proto)
{
	return 0;
}
Loading