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

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

[MLSXFRM]: Add flow labeling



This labels the flows that could utilize IPSec xfrms at the points the
flows are defined so that IPSec policy and SAs at the right label can
be used.

The following protos are currently not handled, but they should
continue to be able to use single-labeled IPSec like they currently
do.

ipmr
ip_gre
ipip
igmp
sit
sctp
ip6_tunnel (IPv6 over IPv6 tunnel device)
decnet

Signed-off-by: default avatarVenkat Yekkirala <vyekkirala@TrustedCS.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4e2ba18e
Loading
Loading
Loading
Loading
+25 −13
Original line number Original line Diff line number Diff line
@@ -32,6 +32,7 @@
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/key.h>
#include <linux/key.h>
#include <linux/xfrm.h>
#include <linux/xfrm.h>
#include <net/flow.h>


struct ctl_table;
struct ctl_table;


@@ -815,8 +816,8 @@ struct swap_info_struct;
 *	Deallocate security structure.
 *	Deallocate security structure.
 * @sk_clone_security:
 * @sk_clone_security:
 *	Clone/copy security structure.
 *	Clone/copy security structure.
 * @sk_getsid:
 * @sk_getsecid:
 *	Retrieve the LSM-specific sid for the sock to enable caching of network
 *	Retrieve the LSM-specific secid for the sock to enable caching of network
 *	authorizations.
 *	authorizations.
 *
 *
 * Security hooks for XFRM operations.
 * Security hooks for XFRM operations.
@@ -882,8 +883,9 @@ struct swap_info_struct;
 *	Return 1 if there is a match.
 *	Return 1 if there is a match.
 * @xfrm_decode_session:
 * @xfrm_decode_session:
 *	@skb points to skb to decode.
 *	@skb points to skb to decode.
 *	@fl points to the flow key to set.
 *	@secid points to the flow key secid to set.
 *	Return 0 if successful decoding.
 *	@ckall says if all xfrms used should be checked for same secid.
 *	Return 0 if ckall is zero or all xfrms used have the same secid.
 *
 *
 * Security hooks affecting all Key Management operations
 * Security hooks affecting all Key Management operations
 *
 *
@@ -1353,7 +1355,7 @@ struct security_operations {
	int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority);
	int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority);
	void (*sk_free_security) (struct sock *sk);
	void (*sk_free_security) (struct sock *sk);
	void (*sk_clone_security) (const struct sock *sk, struct sock *newsk);
	void (*sk_clone_security) (const struct sock *sk, struct sock *newsk);
	unsigned int (*sk_getsid) (struct sock *sk, struct flowi *fl, u8 dir);
	void (*sk_getsecid) (struct sock *sk, u32 *secid);
#endif	/* CONFIG_SECURITY_NETWORK */
#endif	/* CONFIG_SECURITY_NETWORK */


#ifdef CONFIG_SECURITY_NETWORK_XFRM
#ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -1370,7 +1372,7 @@ struct security_operations {
	int (*xfrm_state_pol_flow_match)(struct xfrm_state *x,
	int (*xfrm_state_pol_flow_match)(struct xfrm_state *x,
			struct xfrm_policy *xp, struct flowi *fl);
			struct xfrm_policy *xp, struct flowi *fl);
	int (*xfrm_flow_state_match)(struct flowi *fl, struct xfrm_state *xfrm);
	int (*xfrm_flow_state_match)(struct flowi *fl, struct xfrm_state *xfrm);
	int (*xfrm_decode_session)(struct sk_buff *skb, struct flowi *fl);
	int (*xfrm_decode_session)(struct sk_buff *skb, u32 *secid, int ckall);
#endif	/* CONFIG_SECURITY_NETWORK_XFRM */
#endif	/* CONFIG_SECURITY_NETWORK_XFRM */


	/* key management security hooks */
	/* key management security hooks */
@@ -2917,9 +2919,9 @@ static inline void security_sk_clone(const struct sock *sk, struct sock *newsk)
	return security_ops->sk_clone_security(sk, newsk);
	return security_ops->sk_clone_security(sk, newsk);
}
}


static inline unsigned int security_sk_sid(struct sock *sk, struct flowi *fl, u8 dir)
static inline void security_sk_classify_flow(struct sock *sk, struct flowi *fl)
{
{
	return security_ops->sk_getsid(sk, fl, dir);
	security_ops->sk_getsecid(sk, &fl->secid);
}
}
#else	/* CONFIG_SECURITY_NETWORK */
#else	/* CONFIG_SECURITY_NETWORK */
static inline int security_unix_stream_connect(struct socket * sock,
static inline int security_unix_stream_connect(struct socket * sock,
@@ -3047,9 +3049,8 @@ static inline void security_sk_clone(const struct sock *sk, struct sock *newsk)
{
{
}
}


static inline unsigned int security_sk_sid(struct sock *sk, struct flowi *fl, u8 dir)
static inline void security_sk_classify_flow(struct sock *sk, struct flowi *fl)
{
{
	return 0;
}
}
#endif	/* CONFIG_SECURITY_NETWORK */
#endif	/* CONFIG_SECURITY_NETWORK */


@@ -3114,9 +3115,16 @@ static inline int security_xfrm_flow_state_match(struct flowi *fl, struct xfrm_s
	return security_ops->xfrm_flow_state_match(fl, xfrm);
	return security_ops->xfrm_flow_state_match(fl, xfrm);
}
}


static inline int security_xfrm_decode_session(struct sk_buff *skb, struct flowi *fl)
static inline int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
{
	return security_ops->xfrm_decode_session(skb, secid, 1);
}

static inline void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl)
{
{
	return security_ops->xfrm_decode_session(skb, fl);
	int rc = security_ops->xfrm_decode_session(skb, &fl->secid, 0);

	BUG_ON(rc);
}
}
#else	/* CONFIG_SECURITY_NETWORK_XFRM */
#else	/* CONFIG_SECURITY_NETWORK_XFRM */
static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx)
static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx)
@@ -3176,11 +3184,15 @@ static inline int security_xfrm_flow_state_match(struct flowi *fl,
	return 1;
	return 1;
}
}


static inline int security_xfrm_decode_session(struct sk_buff *skb, struct flowi *fl)
static inline int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
{
{
	return 0;
	return 0;
}
}


static inline void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl)
{
}

#endif	/* CONFIG_SECURITY_NETWORK_XFRM */
#endif	/* CONFIG_SECURITY_NETWORK_XFRM */


#ifdef CONFIG_KEYS
#ifdef CONFIG_KEYS
+3 −0
Original line number Original line Diff line number Diff line
@@ -32,6 +32,7 @@
#include <linux/route.h>
#include <linux/route.h>
#include <linux/ip.h>
#include <linux/ip.h>
#include <linux/cache.h>
#include <linux/cache.h>
#include <linux/security.h>


#ifndef __KERNEL__
#ifndef __KERNEL__
#warning This file is not supposed to be used outside of kernel.
#warning This file is not supposed to be used outside of kernel.
@@ -166,6 +167,7 @@ static inline int ip_route_connect(struct rtable **rp, u32 dst,
		ip_rt_put(*rp);
		ip_rt_put(*rp);
		*rp = NULL;
		*rp = NULL;
	}
	}
	security_sk_classify_flow(sk, &fl);
	return ip_route_output_flow(rp, &fl, sk, 0);
	return ip_route_output_flow(rp, &fl, sk, 0);
}
}


@@ -182,6 +184,7 @@ static inline int ip_route_newports(struct rtable **rp, u8 protocol,
		fl.proto = protocol;
		fl.proto = protocol;
		ip_rt_put(*rp);
		ip_rt_put(*rp);
		*rp = NULL;
		*rp = NULL;
		security_sk_classify_flow(sk, &fl);
		return ip_route_output_flow(rp, &fl, sk, 0);
		return ip_route_output_flow(rp, &fl, sk, 0);
	}
	}
	return 0;
	return 0;
+1 −0
Original line number Original line Diff line number Diff line
@@ -678,6 +678,7 @@ static struct dst_entry* dccp_v4_route_skb(struct sock *sk,
			   	     }
			   	     }
			  };
			  };


	security_skb_classify_flow(skb, &fl);
	if (ip_route_output_flow(&rt, &fl, sk, 0)) {
	if (ip_route_output_flow(&rt, &fl, sk, 0)) {
		IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
		IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
		return NULL;
		return NULL;
+6 −0
Original line number Original line Diff line number Diff line
@@ -201,6 +201,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
	fl.oif = sk->sk_bound_dev_if;
	fl.oif = sk->sk_bound_dev_if;
	fl.fl_ip_dport = usin->sin6_port;
	fl.fl_ip_dport = usin->sin6_port;
	fl.fl_ip_sport = inet->sport;
	fl.fl_ip_sport = inet->sport;
	security_sk_classify_flow(sk, &fl);


	if (np->opt != NULL && np->opt->srcrt != NULL) {
	if (np->opt != NULL && np->opt->srcrt != NULL) {
		const struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
		const struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
@@ -322,6 +323,7 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
			fl.oif = sk->sk_bound_dev_if;
			fl.oif = sk->sk_bound_dev_if;
			fl.fl_ip_dport = inet->dport;
			fl.fl_ip_dport = inet->dport;
			fl.fl_ip_sport = inet->sport;
			fl.fl_ip_sport = inet->sport;
			security_sk_classify_flow(sk, &fl);


			err = ip6_dst_lookup(sk, &dst, &fl);
			err = ip6_dst_lookup(sk, &dst, &fl);
			if (err) {
			if (err) {
@@ -422,6 +424,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,
	fl.oif = ireq6->iif;
	fl.oif = ireq6->iif;
	fl.fl_ip_dport = inet_rsk(req)->rmt_port;
	fl.fl_ip_dport = inet_rsk(req)->rmt_port;
	fl.fl_ip_sport = inet_sk(sk)->sport;
	fl.fl_ip_sport = inet_sk(sk)->sport;
	security_sk_classify_flow(sk, &fl);


	if (dst == NULL) {
	if (dst == NULL) {
		opt = np->opt;
		opt = np->opt;
@@ -566,6 +569,7 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb)
	fl.oif = inet6_iif(rxskb);
	fl.oif = inet6_iif(rxskb);
	fl.fl_ip_dport = dh->dccph_dport;
	fl.fl_ip_dport = dh->dccph_dport;
	fl.fl_ip_sport = dh->dccph_sport;
	fl.fl_ip_sport = dh->dccph_sport;
	security_skb_classify_flow(rxskb, &fl);


	/* sk = NULL, but it is safe for now. RST socket required. */
	/* sk = NULL, but it is safe for now. RST socket required. */
	if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
	if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
@@ -622,6 +626,7 @@ static void dccp_v6_reqsk_send_ack(struct sk_buff *rxskb,
	fl.oif = inet6_iif(rxskb);
	fl.oif = inet6_iif(rxskb);
	fl.fl_ip_dport = dh->dccph_dport;
	fl.fl_ip_dport = dh->dccph_dport;
	fl.fl_ip_sport = dh->dccph_sport;
	fl.fl_ip_sport = dh->dccph_sport;
	security_skb_classify_flow(rxskb, &fl);


	if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
	if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
		if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) {
		if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) {
@@ -842,6 +847,7 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
		fl.oif = sk->sk_bound_dev_if;
		fl.oif = sk->sk_bound_dev_if;
		fl.fl_ip_dport = inet_rsk(req)->rmt_port;
		fl.fl_ip_dport = inet_rsk(req)->rmt_port;
		fl.fl_ip_sport = inet_sk(sk)->sport;
		fl.fl_ip_sport = inet_sk(sk)->sport;
		security_sk_classify_flow(sk, &fl);


		if (ip6_dst_lookup(sk, &dst, &fl))
		if (ip6_dst_lookup(sk, &dst, &fl))
			goto out;
			goto out;
+1 −0
Original line number Original line Diff line number Diff line
@@ -1074,6 +1074,7 @@ int inet_sk_rebuild_header(struct sock *sk)
		},
		},
	};
	};
						
						
	security_sk_classify_flow(sk, &fl);
	err = ip_route_output_flow(&rt, &fl, sk, 0);
	err = ip_route_output_flow(&rt, &fl, sk, 0);
}
}
	if (!err)
	if (!err)
Loading