netfilter: nf_tables: ensure proper initialization of nft_pktinfo fields
This patch introduces nft_set_pktinfo_unspec() that ensures proper initialization all of pktinfo fields for non-IP traffic. This is used by the bridge, netdev and arp families. This new function relies on nft_set_pktinfo_proto_unspec() to set a new tprot_set field that indicates if transport protocol information is available. Remain fields are zeroed. The meta expression has been also updated to check to tprot_set in first place given that zero is a valid tprot value. Even a handcrafted packet may come with the IPPROTO_RAW (255) protocol number so we can't rely on this value as tprot unset. Reported-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
dbd2be0646
commit
beac5afa2d
@ -19,6 +19,7 @@ struct nft_pktinfo {
|
|||||||
const struct net_device *out;
|
const struct net_device *out;
|
||||||
u8 pf;
|
u8 pf;
|
||||||
u8 hook;
|
u8 hook;
|
||||||
|
bool tprot_set;
|
||||||
u8 tprot;
|
u8 tprot;
|
||||||
/* for x_tables compatibility */
|
/* for x_tables compatibility */
|
||||||
struct xt_action_param xt;
|
struct xt_action_param xt;
|
||||||
@ -36,6 +37,23 @@ static inline void nft_set_pktinfo(struct nft_pktinfo *pkt,
|
|||||||
pkt->pf = pkt->xt.family = state->pf;
|
pkt->pf = pkt->xt.family = state->pf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void nft_set_pktinfo_proto_unspec(struct nft_pktinfo *pkt,
|
||||||
|
struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
pkt->tprot_set = false;
|
||||||
|
pkt->tprot = 0;
|
||||||
|
pkt->xt.thoff = 0;
|
||||||
|
pkt->xt.fragoff = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void nft_set_pktinfo_unspec(struct nft_pktinfo *pkt,
|
||||||
|
struct sk_buff *skb,
|
||||||
|
const struct nf_hook_state *state)
|
||||||
|
{
|
||||||
|
nft_set_pktinfo(pkt, skb, state);
|
||||||
|
nft_set_pktinfo_proto_unspec(pkt, skb);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct nft_verdict - nf_tables verdict
|
* struct nft_verdict - nf_tables verdict
|
||||||
*
|
*
|
||||||
|
@ -14,6 +14,7 @@ nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt,
|
|||||||
nft_set_pktinfo(pkt, skb, state);
|
nft_set_pktinfo(pkt, skb, state);
|
||||||
|
|
||||||
ip = ip_hdr(pkt->skb);
|
ip = ip_hdr(pkt->skb);
|
||||||
|
pkt->tprot_set = true;
|
||||||
pkt->tprot = ip->protocol;
|
pkt->tprot = ip->protocol;
|
||||||
pkt->xt.thoff = ip_hdrlen(pkt->skb);
|
pkt->xt.thoff = ip_hdrlen(pkt->skb);
|
||||||
pkt->xt.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
|
pkt->xt.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
|
||||||
|
@ -19,6 +19,7 @@ nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt,
|
|||||||
if (protohdr < 0)
|
if (protohdr < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
pkt->tprot_set = true;
|
||||||
pkt->tprot = protohdr;
|
pkt->tprot = protohdr;
|
||||||
pkt->xt.thoff = thoff;
|
pkt->xt.thoff = thoff;
|
||||||
pkt->xt.fragoff = frag_off;
|
pkt->xt.fragoff = frag_off;
|
||||||
|
@ -71,7 +71,7 @@ static inline void nft_bridge_set_pktinfo_ipv4(struct nft_pktinfo *pkt,
|
|||||||
if (nft_bridge_iphdr_validate(skb))
|
if (nft_bridge_iphdr_validate(skb))
|
||||||
nft_set_pktinfo_ipv4(pkt, skb, state);
|
nft_set_pktinfo_ipv4(pkt, skb, state);
|
||||||
else
|
else
|
||||||
nft_set_pktinfo(pkt, skb, state);
|
nft_set_pktinfo_unspec(pkt, skb, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void nft_bridge_set_pktinfo_ipv6(struct nft_pktinfo *pkt,
|
static inline void nft_bridge_set_pktinfo_ipv6(struct nft_pktinfo *pkt,
|
||||||
@ -83,7 +83,7 @@ static inline void nft_bridge_set_pktinfo_ipv6(struct nft_pktinfo *pkt,
|
|||||||
nft_set_pktinfo_ipv6(pkt, skb, state) == 0)
|
nft_set_pktinfo_ipv6(pkt, skb, state) == 0)
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
nft_set_pktinfo(pkt, skb, state);
|
nft_set_pktinfo_unspec(pkt, skb, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
@ -101,7 +101,7 @@ nft_do_chain_bridge(void *priv,
|
|||||||
nft_bridge_set_pktinfo_ipv6(&pkt, skb, state);
|
nft_bridge_set_pktinfo_ipv6(&pkt, skb, state);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
nft_set_pktinfo(&pkt, skb, state);
|
nft_set_pktinfo_unspec(&pkt, skb, state);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ nft_do_chain_arp(void *priv,
|
|||||||
{
|
{
|
||||||
struct nft_pktinfo pkt;
|
struct nft_pktinfo pkt;
|
||||||
|
|
||||||
nft_set_pktinfo(&pkt, skb, state);
|
nft_set_pktinfo_unspec(&pkt, skb, state);
|
||||||
|
|
||||||
return nft_do_chain(&pkt, priv);
|
return nft_do_chain(&pkt, priv);
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,7 @@ nft_netdev_set_pktinfo_ipv4(struct nft_pktinfo *pkt,
|
|||||||
else if (len < thoff)
|
else if (len < thoff)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
pkt->tprot_set = true;
|
||||||
pkt->tprot = iph->protocol;
|
pkt->tprot = iph->protocol;
|
||||||
pkt->xt.thoff = thoff;
|
pkt->xt.thoff = thoff;
|
||||||
pkt->xt.fragoff = ntohs(iph->frag_off) & IP_OFFSET;
|
pkt->xt.fragoff = ntohs(iph->frag_off) & IP_OFFSET;
|
||||||
@ -74,6 +75,7 @@ __nft_netdev_set_pktinfo_ipv6(struct nft_pktinfo *pkt,
|
|||||||
if (protohdr < 0)
|
if (protohdr < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
pkt->tprot_set = true;
|
||||||
pkt->tprot = protohdr;
|
pkt->tprot = protohdr;
|
||||||
pkt->xt.thoff = thoff;
|
pkt->xt.thoff = thoff;
|
||||||
pkt->xt.fragoff = frag_off;
|
pkt->xt.fragoff = frag_off;
|
||||||
@ -102,7 +104,7 @@ nft_do_chain_netdev(void *priv, struct sk_buff *skb,
|
|||||||
nft_netdev_set_pktinfo_ipv6(&pkt, skb, state);
|
nft_netdev_set_pktinfo_ipv6(&pkt, skb, state);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
nft_set_pktinfo(&pkt, skb, state);
|
nft_set_pktinfo_unspec(&pkt, skb, state);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,6 +52,8 @@ void nft_meta_get_eval(const struct nft_expr *expr,
|
|||||||
*dest = pkt->pf;
|
*dest = pkt->pf;
|
||||||
break;
|
break;
|
||||||
case NFT_META_L4PROTO:
|
case NFT_META_L4PROTO:
|
||||||
|
if (!pkt->tprot_set)
|
||||||
|
goto err;
|
||||||
*dest = pkt->tprot;
|
*dest = pkt->tprot;
|
||||||
break;
|
break;
|
||||||
case NFT_META_PRIORITY:
|
case NFT_META_PRIORITY:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user