diff options
Diffstat (limited to 'net/ipv4/ip_output.c')
| -rw-r--r-- | net/ipv4/ip_output.c | 33 | 
1 files changed, 29 insertions, 4 deletions
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 105908d841a3..9ffc2625cddd 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -74,6 +74,7 @@  #include <net/checksum.h>  #include <net/inetpeer.h>  #include <net/lwtunnel.h> +#include <linux/bpf-cgroup.h>  #include <linux/igmp.h>  #include <linux/netfilter_ipv4.h>  #include <linux/netfilter_bridge.h> @@ -107,6 +108,8 @@ int __ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)  	if (unlikely(!skb))  		return 0; +	skb->protocol = htons(ETH_P_IP); +  	return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT,  		       net, sk, skb, NULL, skb_dst(skb)->dev,  		       dst_output); @@ -285,6 +288,13 @@ static int ip_finish_output_gso(struct net *net, struct sock *sk,  static int ip_finish_output(struct net *net, struct sock *sk, struct sk_buff *skb)  {  	unsigned int mtu; +	int ret; + +	ret = BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb); +	if (ret) { +		kfree_skb(skb); +		return ret; +	}  #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM)  	/* Policy lookup after SNAT yielded a new policy */ @@ -303,6 +313,20 @@ static int ip_finish_output(struct net *net, struct sock *sk, struct sk_buff *sk  	return ip_finish_output2(net, sk, skb);  } +static int ip_mc_finish_output(struct net *net, struct sock *sk, +			       struct sk_buff *skb) +{ +	int ret; + +	ret = BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb); +	if (ret) { +		kfree_skb(skb); +		return ret; +	} + +	return dev_loopback_xmit(net, sk, skb); +} +  int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb)  {  	struct rtable *rt = skb_rtable(skb); @@ -340,7 +364,7 @@ int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb)  			if (newskb)  				NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING,  					net, sk, newskb, NULL, newskb->dev, -					dev_loopback_xmit); +					ip_mc_finish_output);  		}  		/* Multicasts with ttl 0 must not go beyond the host */ @@ -356,7 +380,7 @@ int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb)  		if (newskb)  			NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING,  				net, sk, newskb, NULL, newskb->dev, -				dev_loopback_xmit); +				ip_mc_finish_output);  	}  	return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, @@ -581,7 +605,7 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,  	 */  	if (skb_has_frag_list(skb)) {  		struct sk_buff *frag, *frag2; -		int first_len = skb_pagelen(skb); +		unsigned int first_len = skb_pagelen(skb);  		if (first_len - hlen > mtu ||  		    ((first_len - hlen) & 7) || @@ -1592,7 +1616,8 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb,  			   RT_SCOPE_UNIVERSE, ip_hdr(skb)->protocol,  			   ip_reply_arg_flowi_flags(arg),  			   daddr, saddr, -			   tcp_hdr(skb)->source, tcp_hdr(skb)->dest); +			   tcp_hdr(skb)->source, tcp_hdr(skb)->dest, +			   arg->uid);  	security_skb_classify_flow(skb, flowi4_to_flowi(&fl4));  	rt = ip_route_output_key(net, &fl4);  	if (IS_ERR(rt))  |