Commit af57d2b7 authored by David S. Miller's avatar David S. Miller

Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf

Pablo Neira Ayuso says:

====================
Netfilter fixes for net

The following patchset contains Netfilter fixes for your net tree,
they are:

1) Fix use after free of struct proc_dir_entry in ipt_CLUSTERIP, patch
   from Sabrina Dubroca.

2) Fix spurious EINVAL errors from iptables over nft compatibility layer.

3) Reload pointer to ip header only if there is non-terminal verdict,
   ie. XT_CONTINUE, otherwise invalid memory access may happen, patch
   from Taehee Yoo.

4) Fix interaction between SYNPROXY and NAT, SYNPROXY adds sequence
   adjustment already, however from nf_nat_setup() assumes there's not.
   Patch from Xin Long.

5) Fix burst arithmetics in nft_limit as Joe Stringer mentioned during
   NFWS in Faro. Patch from Andy Zhou.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents d0273ef3 c26844ed
...@@ -268,14 +268,14 @@ unsigned int arpt_do_table(struct sk_buff *skb, ...@@ -268,14 +268,14 @@ unsigned int arpt_do_table(struct sk_buff *skb,
acpar.targinfo = t->data; acpar.targinfo = t->data;
verdict = t->u.kernel.target->target(skb, &acpar); verdict = t->u.kernel.target->target(skb, &acpar);
/* Target might have changed stuff. */ if (verdict == XT_CONTINUE) {
arp = arp_hdr(skb); /* Target might have changed stuff. */
arp = arp_hdr(skb);
if (verdict == XT_CONTINUE)
e = arpt_next_entry(e); e = arpt_next_entry(e);
else } else {
/* Verdict */ /* Verdict */
break; break;
}
} while (!acpar.hotdrop); } while (!acpar.hotdrop);
xt_write_recseq_end(addend); xt_write_recseq_end(addend);
local_bh_enable(); local_bh_enable();
......
...@@ -352,13 +352,14 @@ ipt_do_table(struct sk_buff *skb, ...@@ -352,13 +352,14 @@ ipt_do_table(struct sk_buff *skb,
acpar.targinfo = t->data; acpar.targinfo = t->data;
verdict = t->u.kernel.target->target(skb, &acpar); verdict = t->u.kernel.target->target(skb, &acpar);
/* Target might have changed stuff. */ if (verdict == XT_CONTINUE) {
ip = ip_hdr(skb); /* Target might have changed stuff. */
if (verdict == XT_CONTINUE) ip = ip_hdr(skb);
e = ipt_next_entry(e); e = ipt_next_entry(e);
else } else {
/* Verdict */ /* Verdict */
break; break;
}
} while (!acpar.hotdrop); } while (!acpar.hotdrop);
xt_write_recseq_end(addend); xt_write_recseq_end(addend);
......
...@@ -117,7 +117,8 @@ clusterip_config_entry_put(struct net *net, struct clusterip_config *c) ...@@ -117,7 +117,8 @@ clusterip_config_entry_put(struct net *net, struct clusterip_config *c)
* functions are also incrementing the refcount on their own, * functions are also incrementing the refcount on their own,
* so it's safe to remove the entry even if it's in use. */ * so it's safe to remove the entry even if it's in use. */
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
proc_remove(c->pde); if (cn->procdir)
proc_remove(c->pde);
#endif #endif
return; return;
} }
...@@ -815,6 +816,7 @@ static void clusterip_net_exit(struct net *net) ...@@ -815,6 +816,7 @@ static void clusterip_net_exit(struct net *net)
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
struct clusterip_net *cn = net_generic(net, clusterip_net_id); struct clusterip_net *cn = net_generic(net, clusterip_net_id);
proc_remove(cn->procdir); proc_remove(cn->procdir);
cn->procdir = NULL;
#endif #endif
nf_unregister_net_hook(net, &cip_arp_ops); nf_unregister_net_hook(net, &cip_arp_ops);
} }
......
...@@ -441,7 +441,7 @@ nf_nat_setup_info(struct nf_conn *ct, ...@@ -441,7 +441,7 @@ nf_nat_setup_info(struct nf_conn *ct,
else else
ct->status |= IPS_DST_NAT; ct->status |= IPS_DST_NAT;
if (nfct_help(ct)) if (nfct_help(ct) && !nfct_seqadj(ct))
if (!nfct_seqadj_ext_add(ct)) if (!nfct_seqadj_ext_add(ct))
return NF_DROP; return NF_DROP;
} }
......
...@@ -305,7 +305,7 @@ static int nft_target_validate(const struct nft_ctx *ctx, ...@@ -305,7 +305,7 @@ static int nft_target_validate(const struct nft_ctx *ctx,
const struct nf_hook_ops *ops = &basechain->ops[0]; const struct nf_hook_ops *ops = &basechain->ops[0];
hook_mask = 1 << ops->hooknum; hook_mask = 1 << ops->hooknum;
if (!(hook_mask & target->hooks)) if (target->hooks && !(hook_mask & target->hooks))
return -EINVAL; return -EINVAL;
ret = nft_compat_chain_validate_dependency(target->table, ret = nft_compat_chain_validate_dependency(target->table,
...@@ -484,7 +484,7 @@ static int nft_match_validate(const struct nft_ctx *ctx, ...@@ -484,7 +484,7 @@ static int nft_match_validate(const struct nft_ctx *ctx,
const struct nf_hook_ops *ops = &basechain->ops[0]; const struct nf_hook_ops *ops = &basechain->ops[0];
hook_mask = 1 << ops->hooknum; hook_mask = 1 << ops->hooknum;
if (!(hook_mask & match->hooks)) if (match->hooks && !(hook_mask & match->hooks))
return -EINVAL; return -EINVAL;
ret = nft_compat_chain_validate_dependency(match->table, ret = nft_compat_chain_validate_dependency(match->table,
......
...@@ -65,19 +65,23 @@ static int nft_limit_init(struct nft_limit *limit, ...@@ -65,19 +65,23 @@ static int nft_limit_init(struct nft_limit *limit,
limit->nsecs = unit * NSEC_PER_SEC; limit->nsecs = unit * NSEC_PER_SEC;
if (limit->rate == 0 || limit->nsecs < unit) if (limit->rate == 0 || limit->nsecs < unit)
return -EOVERFLOW; return -EOVERFLOW;
limit->tokens = limit->tokens_max = limit->nsecs;
if (tb[NFTA_LIMIT_BURST]) {
u64 rate;
if (tb[NFTA_LIMIT_BURST])
limit->burst = ntohl(nla_get_be32(tb[NFTA_LIMIT_BURST])); limit->burst = ntohl(nla_get_be32(tb[NFTA_LIMIT_BURST]));
else
limit->burst = 0;
if (limit->rate + limit->burst < limit->rate)
return -EOVERFLOW;
rate = limit->rate + limit->burst; /* The token bucket size limits the number of tokens can be
if (rate < limit->rate) * accumulated. tokens_max specifies the bucket size.
return -EOVERFLOW; * tokens_max = unit * (rate + burst) / rate.
*/
limit->tokens = div_u64(limit->nsecs * (limit->rate + limit->burst),
limit->rate);
limit->tokens_max = limit->tokens;
limit->rate = rate;
}
if (tb[NFTA_LIMIT_FLAGS]) { if (tb[NFTA_LIMIT_FLAGS]) {
u32 flags = ntohl(nla_get_be32(tb[NFTA_LIMIT_FLAGS])); u32 flags = ntohl(nla_get_be32(tb[NFTA_LIMIT_FLAGS]));
...@@ -95,9 +99,8 @@ static int nft_limit_dump(struct sk_buff *skb, const struct nft_limit *limit, ...@@ -95,9 +99,8 @@ static int nft_limit_dump(struct sk_buff *skb, const struct nft_limit *limit,
{ {
u32 flags = limit->invert ? NFT_LIMIT_F_INV : 0; u32 flags = limit->invert ? NFT_LIMIT_F_INV : 0;
u64 secs = div_u64(limit->nsecs, NSEC_PER_SEC); u64 secs = div_u64(limit->nsecs, NSEC_PER_SEC);
u64 rate = limit->rate - limit->burst;
if (nla_put_be64(skb, NFTA_LIMIT_RATE, cpu_to_be64(rate), if (nla_put_be64(skb, NFTA_LIMIT_RATE, cpu_to_be64(limit->rate),
NFTA_LIMIT_PAD) || NFTA_LIMIT_PAD) ||
nla_put_be64(skb, NFTA_LIMIT_UNIT, cpu_to_be64(secs), nla_put_be64(skb, NFTA_LIMIT_UNIT, cpu_to_be64(secs),
NFTA_LIMIT_PAD) || NFTA_LIMIT_PAD) ||
......
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