Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
Pablo Neira Ayuso says: ==================== netfilter/ipvs fixes for net The following patchset contains netfilter/ipvs fixes, they are: 1) Small fix for the FTP helper in IPVS, a diff variable may be left unset when CONFIG_IP_VS_IPV6 is set. Patch from Dan Carpenter. 2) Fix nf_tables port NAT in little endian archs, patch from leroy christophe. 3) Fix race condition between conntrack confirmation and flush from userspace. This is the second reincarnation to resolve this problem. 4) Make sure inner messages in the batch come with the nfnetlink header. 5) Relax strict check from nfnetlink_bind() that may break old userspace applications using all 1s group mask. 6) Schedule removal of chains once no sets and rules refer to them in the new nf_tables ruleset flush command. Reported by Asbjoern Sloth Toennesen. Note that this batch comes later than usual because of the short winter holidays. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
2bd8221804
@ -27,10 +27,10 @@ static void nft_redir_ipv4_eval(const struct nft_expr *expr,
|
||||
|
||||
memset(&mr, 0, sizeof(mr));
|
||||
if (priv->sreg_proto_min) {
|
||||
mr.range[0].min.all = (__force __be16)
|
||||
data[priv->sreg_proto_min].data[0];
|
||||
mr.range[0].max.all = (__force __be16)
|
||||
data[priv->sreg_proto_max].data[0];
|
||||
mr.range[0].min.all =
|
||||
*(__be16 *)&data[priv->sreg_proto_min].data[0];
|
||||
mr.range[0].max.all =
|
||||
*(__be16 *)&data[priv->sreg_proto_max].data[0];
|
||||
mr.range[0].flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
|
||||
}
|
||||
|
||||
|
@ -27,10 +27,10 @@ static void nft_redir_ipv6_eval(const struct nft_expr *expr,
|
||||
|
||||
memset(&range, 0, sizeof(range));
|
||||
if (priv->sreg_proto_min) {
|
||||
range.min_proto.all = (__force __be16)
|
||||
data[priv->sreg_proto_min].data[0];
|
||||
range.max_proto.all = (__force __be16)
|
||||
data[priv->sreg_proto_max].data[0];
|
||||
range.min_proto.all =
|
||||
*(__be16 *)&data[priv->sreg_proto_min].data[0];
|
||||
range.max_proto.all =
|
||||
*(__be16 *)&data[priv->sreg_proto_max].data[0];
|
||||
range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
|
||||
}
|
||||
|
||||
|
@ -183,6 +183,8 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp,
|
||||
struct nf_conn *ct;
|
||||
struct net *net;
|
||||
|
||||
*diff = 0;
|
||||
|
||||
#ifdef CONFIG_IP_VS_IPV6
|
||||
/* This application helper doesn't work with IPv6 yet,
|
||||
* so turn this into a no-op for IPv6 packets
|
||||
@ -191,8 +193,6 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp,
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
*diff = 0;
|
||||
|
||||
/* Only useful for established sessions */
|
||||
if (cp->state != IP_VS_TCP_S_ESTABLISHED)
|
||||
return 1;
|
||||
@ -322,6 +322,9 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp,
|
||||
struct ip_vs_conn *n_cp;
|
||||
struct net *net;
|
||||
|
||||
/* no diff required for incoming packets */
|
||||
*diff = 0;
|
||||
|
||||
#ifdef CONFIG_IP_VS_IPV6
|
||||
/* This application helper doesn't work with IPv6 yet,
|
||||
* so turn this into a no-op for IPv6 packets
|
||||
@ -330,9 +333,6 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp,
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
/* no diff required for incoming packets */
|
||||
*diff = 0;
|
||||
|
||||
/* Only useful for established sessions */
|
||||
if (cp->state != IP_VS_TCP_S_ESTABLISHED)
|
||||
return 1;
|
||||
|
@ -611,16 +611,15 @@ __nf_conntrack_confirm(struct sk_buff *skb)
|
||||
*/
|
||||
NF_CT_ASSERT(!nf_ct_is_confirmed(ct));
|
||||
pr_debug("Confirming conntrack %p\n", ct);
|
||||
/* We have to check the DYING flag inside the lock to prevent
|
||||
a race against nf_ct_get_next_corpse() possibly called from
|
||||
user context, else we insert an already 'dead' hash, blocking
|
||||
further use of that particular connection -JM */
|
||||
/* We have to check the DYING flag after unlink to prevent
|
||||
* a race against nf_ct_get_next_corpse() possibly called from
|
||||
* user context, else we insert an already 'dead' hash, blocking
|
||||
* further use of that particular connection -JM.
|
||||
*/
|
||||
nf_ct_del_from_dying_or_unconfirmed_list(ct);
|
||||
|
||||
if (unlikely(nf_ct_is_dying(ct))) {
|
||||
nf_conntrack_double_unlock(hash, reply_hash);
|
||||
local_bh_enable();
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
if (unlikely(nf_ct_is_dying(ct)))
|
||||
goto out;
|
||||
|
||||
/* See if there's one in the list already, including reverse:
|
||||
NAT could have grabbed it without realizing, since we're
|
||||
@ -636,8 +635,6 @@ __nf_conntrack_confirm(struct sk_buff *skb)
|
||||
zone == nf_ct_zone(nf_ct_tuplehash_to_ctrack(h)))
|
||||
goto out;
|
||||
|
||||
nf_ct_del_from_dying_or_unconfirmed_list(ct);
|
||||
|
||||
/* Timer relative to confirmation time, not original
|
||||
setting time, otherwise we'd get timer wrap in
|
||||
weird delay cases. */
|
||||
@ -673,6 +670,7 @@ __nf_conntrack_confirm(struct sk_buff *skb)
|
||||
return NF_ACCEPT;
|
||||
|
||||
out:
|
||||
nf_ct_add_to_dying_list(ct);
|
||||
nf_conntrack_double_unlock(hash, reply_hash);
|
||||
NF_CT_STAT_INC(net, insert_failed);
|
||||
local_bh_enable();
|
||||
|
@ -713,16 +713,12 @@ static int nft_flush_table(struct nft_ctx *ctx)
|
||||
struct nft_chain *chain, *nc;
|
||||
struct nft_set *set, *ns;
|
||||
|
||||
list_for_each_entry_safe(chain, nc, &ctx->table->chains, list) {
|
||||
list_for_each_entry(chain, &ctx->table->chains, list) {
|
||||
ctx->chain = chain;
|
||||
|
||||
err = nft_delrule_by_chain(ctx);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
err = nft_delchain(ctx);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(set, ns, &ctx->table->sets, list) {
|
||||
@ -735,6 +731,14 @@ static int nft_flush_table(struct nft_ctx *ctx)
|
||||
goto out;
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(chain, nc, &ctx->table->chains, list) {
|
||||
ctx->chain = chain;
|
||||
|
||||
err = nft_delchain(ctx);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = nft_deltable(ctx);
|
||||
out:
|
||||
return err;
|
||||
|
@ -321,7 +321,8 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
nlh = nlmsg_hdr(skb);
|
||||
err = 0;
|
||||
|
||||
if (nlh->nlmsg_len < NLMSG_HDRLEN) {
|
||||
if (nlmsg_len(nlh) < sizeof(struct nfgenmsg) ||
|
||||
skb->len < nlh->nlmsg_len) {
|
||||
err = -EINVAL;
|
||||
goto ack;
|
||||
}
|
||||
@ -469,7 +470,7 @@ static int nfnetlink_bind(struct net *net, int group)
|
||||
int type;
|
||||
|
||||
if (group <= NFNLGRP_NONE || group > NFNLGRP_MAX)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
|
||||
type = nfnl_group2type[group];
|
||||
|
||||
|
@ -65,10 +65,10 @@ static void nft_nat_eval(const struct nft_expr *expr,
|
||||
}
|
||||
|
||||
if (priv->sreg_proto_min) {
|
||||
range.min_proto.all = (__force __be16)
|
||||
data[priv->sreg_proto_min].data[0];
|
||||
range.max_proto.all = (__force __be16)
|
||||
data[priv->sreg_proto_max].data[0];
|
||||
range.min_proto.all =
|
||||
*(__be16 *)&data[priv->sreg_proto_min].data[0];
|
||||
range.max_proto.all =
|
||||
*(__be16 *)&data[priv->sreg_proto_max].data[0];
|
||||
range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user