Commit e15e5027 authored by Florian Westphal's avatar Florian Westphal

netfilter: xt_mangle: only check verdict part of return value

These checks assume that the caller only returns NF_DROP without
any errno embedded in the upper bits.

This is fine right now, but followup patches will start to propagate
such errors to allow kfree_skb_drop_reason() in the called functions,
those would then indicate 'errno << 8 | NF_STOLEN'.

To not break things we have to mask those parts out.
Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
parent a0a86022
...@@ -36,12 +36,12 @@ static const struct xt_table packet_mangler = { ...@@ -36,12 +36,12 @@ static const struct xt_table packet_mangler = {
static unsigned int static unsigned int
ipt_mangle_out(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) ipt_mangle_out(void *priv, struct sk_buff *skb, const struct nf_hook_state *state)
{ {
unsigned int ret; unsigned int ret, verdict;
const struct iphdr *iph; const struct iphdr *iph;
u_int8_t tos;
__be32 saddr, daddr; __be32 saddr, daddr;
u_int32_t mark; u32 mark;
int err; int err;
u8 tos;
/* Save things which could affect route */ /* Save things which could affect route */
mark = skb->mark; mark = skb->mark;
...@@ -51,8 +51,9 @@ ipt_mangle_out(void *priv, struct sk_buff *skb, const struct nf_hook_state *stat ...@@ -51,8 +51,9 @@ ipt_mangle_out(void *priv, struct sk_buff *skb, const struct nf_hook_state *stat
tos = iph->tos; tos = iph->tos;
ret = ipt_do_table(priv, skb, state); ret = ipt_do_table(priv, skb, state);
verdict = ret & NF_VERDICT_MASK;
/* Reroute for ANY change. */ /* Reroute for ANY change. */
if (ret != NF_DROP && ret != NF_STOLEN) { if (verdict != NF_DROP && verdict != NF_STOLEN) {
iph = ip_hdr(skb); iph = ip_hdr(skb);
if (iph->saddr != saddr || if (iph->saddr != saddr ||
......
...@@ -31,10 +31,10 @@ static const struct xt_table packet_mangler = { ...@@ -31,10 +31,10 @@ static const struct xt_table packet_mangler = {
static unsigned int static unsigned int
ip6t_mangle_out(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) ip6t_mangle_out(void *priv, struct sk_buff *skb, const struct nf_hook_state *state)
{ {
unsigned int ret;
struct in6_addr saddr, daddr; struct in6_addr saddr, daddr;
u_int8_t hop_limit; unsigned int ret, verdict;
u_int32_t flowlabel, mark; u32 flowlabel, mark;
u8 hop_limit;
int err; int err;
/* save source/dest address, mark, hoplimit, flowlabel, priority, */ /* save source/dest address, mark, hoplimit, flowlabel, priority, */
...@@ -47,8 +47,9 @@ ip6t_mangle_out(void *priv, struct sk_buff *skb, const struct nf_hook_state *sta ...@@ -47,8 +47,9 @@ ip6t_mangle_out(void *priv, struct sk_buff *skb, const struct nf_hook_state *sta
flowlabel = *((u_int32_t *)ipv6_hdr(skb)); flowlabel = *((u_int32_t *)ipv6_hdr(skb));
ret = ip6t_do_table(priv, skb, state); ret = ip6t_do_table(priv, skb, state);
verdict = ret & NF_VERDICT_MASK;
if (ret != NF_DROP && ret != NF_STOLEN && if (verdict != NF_DROP && verdict != NF_STOLEN &&
(!ipv6_addr_equal(&ipv6_hdr(skb)->saddr, &saddr) || (!ipv6_addr_equal(&ipv6_hdr(skb)->saddr, &saddr) ||
!ipv6_addr_equal(&ipv6_hdr(skb)->daddr, &daddr) || !ipv6_addr_equal(&ipv6_hdr(skb)->daddr, &daddr) ||
skb->mark != mark || skb->mark != mark ||
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment