Re: [PATCH] netfilter: ipv4: fix NULL dereference

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I've been running production kernels in production with those changes
and so far I haven't observed a single crash resulting from this.
Furthermore, I  believe that all the call sites of synproxy_build_ip
should have the skb associated with a valid tcp socket, which must have
originated from a particular namespace.

On 03/23/2016 04:27 PM, Liping Zhang wrote:
> From: Liping Zhang <liping.zhang@xxxxxxxxxxxxxx>
> 
> Commit fa50d974d104 ("ipv4: Namespaceify ip_default_ttl sysctl knob")
> introduce the namespaceify ip_default_ttl, but sk_buff->sk maybe NULL,
> so sock_net(skb->sk) will dereference the NULL pointer and oops will
> happen.
> 
> Signed-off-by: Liping Zhang <liping.zhang@xxxxxxxxxxxxxx>
> ---
>  net/bridge/netfilter/nft_reject_bridge.c |   20 ++++++++++----------
>  net/ipv4/netfilter/ipt_SYNPROXY.c        |   16 ++++++++++------
>  2 files changed, 20 insertions(+), 16 deletions(-)
> 
> diff --git a/net/bridge/netfilter/nft_reject_bridge.c b/net/bridge/netfilter/nft_reject_bridge.c
> index adc8d72..77f7e7a 100644
> --- a/net/bridge/netfilter/nft_reject_bridge.c
> +++ b/net/bridge/netfilter/nft_reject_bridge.c
> @@ -40,7 +40,8 @@ static void nft_reject_br_push_etherhdr(struct sk_buff *oldskb,
>  /* We cannot use oldskb->dev, it can be either bridge device (NF_BRIDGE INPUT)
>   * or the bridge port (NF_BRIDGE PREROUTING).
>   */
> -static void nft_reject_br_send_v4_tcp_reset(struct sk_buff *oldskb,
> +static void nft_reject_br_send_v4_tcp_reset(struct net *net,
> +					    struct sk_buff *oldskb,
>  					    const struct net_device *dev,
>  					    int hook)
>  {
> @@ -48,7 +49,6 @@ static void nft_reject_br_send_v4_tcp_reset(struct sk_buff *oldskb,
>  	struct iphdr *niph;
>  	const struct tcphdr *oth;
>  	struct tcphdr _oth;
> -	struct net *net = sock_net(oldskb->sk);
>  
>  	if (!nft_bridge_iphdr_validate(oldskb))
>  		return;
> @@ -75,7 +75,8 @@ static void nft_reject_br_send_v4_tcp_reset(struct sk_buff *oldskb,
>  	br_deliver(br_port_get_rcu(dev), nskb);
>  }
>  
> -static void nft_reject_br_send_v4_unreach(struct sk_buff *oldskb,
> +static void nft_reject_br_send_v4_unreach(struct net *net,
> +					  struct sk_buff *oldskb,
>  					  const struct net_device *dev,
>  					  int hook, u8 code)
>  {
> @@ -86,7 +87,6 @@ static void nft_reject_br_send_v4_unreach(struct sk_buff *oldskb,
>  	void *payload;
>  	__wsum csum;
>  	u8 proto;
> -	struct net *net = sock_net(oldskb->sk);
>  
>  	if (oldskb->csum_bad || !nft_bridge_iphdr_validate(oldskb))
>  		return;
> @@ -273,17 +273,17 @@ static void nft_reject_bridge_eval(const struct nft_expr *expr,
>  	case htons(ETH_P_IP):
>  		switch (priv->type) {
>  		case NFT_REJECT_ICMP_UNREACH:
> -			nft_reject_br_send_v4_unreach(pkt->skb, pkt->in,
> -						      pkt->hook,
> +			nft_reject_br_send_v4_unreach(pkt->net, pkt->skb,
> +						      pkt->in, pkt->hook,
>  						      priv->icmp_code);
>  			break;
>  		case NFT_REJECT_TCP_RST:
> -			nft_reject_br_send_v4_tcp_reset(pkt->skb, pkt->in,
> -							pkt->hook);
> +			nft_reject_br_send_v4_tcp_reset(pkt->net, pkt->skb,
> +							pkt->in, pkt->hook);
>  			break;
>  		case NFT_REJECT_ICMPX_UNREACH:
> -			nft_reject_br_send_v4_unreach(pkt->skb, pkt->in,
> -						      pkt->hook,
> +			nft_reject_br_send_v4_unreach(pkt->net, pkt->skb,
> +						      pkt->in, pkt->hook,
>  						      nft_reject_icmp_code(priv->icmp_code));
>  			break;
>  		}
> diff --git a/net/ipv4/netfilter/ipt_SYNPROXY.c b/net/ipv4/netfilter/ipt_SYNPROXY.c
> index 7b8fbb3..6b4f501 100644
> --- a/net/ipv4/netfilter/ipt_SYNPROXY.c
> +++ b/net/ipv4/netfilter/ipt_SYNPROXY.c
> @@ -18,10 +18,10 @@
>  #include <net/netfilter/nf_conntrack_synproxy.h>
>  
>  static struct iphdr *
> -synproxy_build_ip(struct sk_buff *skb, __be32 saddr, __be32 daddr)
> +synproxy_build_ip(struct net *net, struct sk_buff *skb, __be32 saddr,
> +		  __be32 daddr)
>  {
>  	struct iphdr *iph;
> -	struct net *net = sock_net(skb->sk);
>  
>  	skb_reset_network_header(skb);
>  	iph = (struct iphdr *)skb_put(skb, sizeof(*iph));
> @@ -91,7 +91,8 @@ synproxy_send_client_synack(const struct synproxy_net *snet,
>  		return;
>  	skb_reserve(nskb, MAX_TCP_HEADER);
>  
> -	niph = synproxy_build_ip(nskb, iph->daddr, iph->saddr);
> +	niph = synproxy_build_ip(nf_ct_net(snet->tmpl), nskb, iph->daddr,
> +				 iph->saddr);
>  
>  	skb_reset_transport_header(nskb);
>  	nth = (struct tcphdr *)skb_put(nskb, tcp_hdr_size);
> @@ -132,7 +133,8 @@ synproxy_send_server_syn(const struct synproxy_net *snet,
>  		return;
>  	skb_reserve(nskb, MAX_TCP_HEADER);
>  
> -	niph = synproxy_build_ip(nskb, iph->saddr, iph->daddr);
> +	niph = synproxy_build_ip(nf_ct_net(snet->tmpl), nskb, iph->saddr,
> +				 iph->daddr);
>  
>  	skb_reset_transport_header(nskb);
>  	nth = (struct tcphdr *)skb_put(nskb, tcp_hdr_size);
> @@ -177,7 +179,8 @@ synproxy_send_server_ack(const struct synproxy_net *snet,
>  		return;
>  	skb_reserve(nskb, MAX_TCP_HEADER);
>  
> -	niph = synproxy_build_ip(nskb, iph->daddr, iph->saddr);
> +	niph = synproxy_build_ip(nf_ct_net(snet->tmpl), nskb, iph->daddr,
> +				 iph->saddr);
>  
>  	skb_reset_transport_header(nskb);
>  	nth = (struct tcphdr *)skb_put(nskb, tcp_hdr_size);
> @@ -215,7 +218,8 @@ synproxy_send_client_ack(const struct synproxy_net *snet,
>  		return;
>  	skb_reserve(nskb, MAX_TCP_HEADER);
>  
> -	niph = synproxy_build_ip(nskb, iph->saddr, iph->daddr);
> +	niph = synproxy_build_ip(nf_ct_net(snet->tmpl), nskb, iph->saddr,
> +				 iph->daddr);
>  
>  	skb_reset_transport_header(nskb);
>  	nth = (struct tcphdr *)skb_put(nskb, tcp_hdr_size);
> 
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux