提交 20b83643 编写于 作者: D 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) Missing check for full sock in ip_route_me_harder(), from
   Florian Westphal.

2) Incorrect sip helper structure initilization that breaks it when
   several ports are used, from Christophe Leroy.

3) Fix incorrect assumption when looking up for matching with adjacent
   intervals in the nft_set_rbtree.

4) Fix broken netlink event error reporting in nf_tables that results
   in misleading ESRCH errors propagated to userspace listeners.
====================
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
...@@ -988,7 +988,7 @@ struct nft_object *nf_tables_obj_lookup(const struct nft_table *table, ...@@ -988,7 +988,7 @@ struct nft_object *nf_tables_obj_lookup(const struct nft_table *table,
const struct nlattr *nla, u32 objtype, const struct nlattr *nla, u32 objtype,
u8 genmask); u8 genmask);
int nft_obj_notify(struct net *net, struct nft_table *table, void nft_obj_notify(struct net *net, struct nft_table *table,
struct nft_object *obj, u32 portid, u32 seq, struct nft_object *obj, u32 portid, u32 seq,
int event, int family, int report, gfp_t gfp); int event, int family, int report, gfp_t gfp);
......
...@@ -23,7 +23,8 @@ int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned int addr_t ...@@ -23,7 +23,8 @@ int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned int addr_t
struct rtable *rt; struct rtable *rt;
struct flowi4 fl4 = {}; struct flowi4 fl4 = {};
__be32 saddr = iph->saddr; __be32 saddr = iph->saddr;
__u8 flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : 0; const struct sock *sk = skb_to_full_sk(skb);
__u8 flags = sk ? inet_sk_flowi_flags(sk) : 0;
struct net_device *dev = skb_dst(skb)->dev; struct net_device *dev = skb_dst(skb)->dev;
unsigned int hh_len; unsigned int hh_len;
...@@ -40,7 +41,7 @@ int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned int addr_t ...@@ -40,7 +41,7 @@ int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned int addr_t
fl4.daddr = iph->daddr; fl4.daddr = iph->daddr;
fl4.saddr = saddr; fl4.saddr = saddr;
fl4.flowi4_tos = RT_TOS(iph->tos); fl4.flowi4_tos = RT_TOS(iph->tos);
fl4.flowi4_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0; fl4.flowi4_oif = sk ? sk->sk_bound_dev_if : 0;
if (!fl4.flowi4_oif) if (!fl4.flowi4_oif)
fl4.flowi4_oif = l3mdev_master_ifindex(dev); fl4.flowi4_oif = l3mdev_master_ifindex(dev);
fl4.flowi4_mark = skb->mark; fl4.flowi4_mark = skb->mark;
...@@ -61,7 +62,7 @@ int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned int addr_t ...@@ -61,7 +62,7 @@ int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned int addr_t
xfrm_decode_session(skb, flowi4_to_flowi(&fl4), AF_INET) == 0) { xfrm_decode_session(skb, flowi4_to_flowi(&fl4), AF_INET) == 0) {
struct dst_entry *dst = skb_dst(skb); struct dst_entry *dst = skb_dst(skb);
skb_dst_set(skb, NULL); skb_dst_set(skb, NULL);
dst = xfrm_lookup(net, dst, flowi4_to_flowi(&fl4), skb->sk, 0); dst = xfrm_lookup(net, dst, flowi4_to_flowi(&fl4), sk, 0);
if (IS_ERR(dst)) if (IS_ERR(dst))
return PTR_ERR(dst); return PTR_ERR(dst);
skb_dst_set(skb, dst); skb_dst_set(skb, dst);
......
...@@ -1628,8 +1628,6 @@ static int __init nf_conntrack_sip_init(void) ...@@ -1628,8 +1628,6 @@ static int __init nf_conntrack_sip_init(void)
ports[ports_c++] = SIP_PORT; ports[ports_c++] = SIP_PORT;
for (i = 0; i < ports_c; i++) { for (i = 0; i < ports_c; i++) {
memset(&sip[i], 0, sizeof(sip[i]));
nf_ct_helper_init(&sip[4 * i], AF_INET, IPPROTO_UDP, "sip", nf_ct_helper_init(&sip[4 * i], AF_INET, IPPROTO_UDP, "sip",
SIP_PORT, ports[i], i, sip_exp_policy, SIP_PORT, ports[i], i, sip_exp_policy,
SIP_EXPECT_MAX, SIP_EXPECT_MAX,
......
...@@ -461,16 +461,15 @@ static int nf_tables_fill_table_info(struct sk_buff *skb, struct net *net, ...@@ -461,16 +461,15 @@ static int nf_tables_fill_table_info(struct sk_buff *skb, struct net *net,
return -1; return -1;
} }
static int nf_tables_table_notify(const struct nft_ctx *ctx, int event) static void nf_tables_table_notify(const struct nft_ctx *ctx, int event)
{ {
struct sk_buff *skb; struct sk_buff *skb;
int err; int err;
if (!ctx->report && if (!ctx->report &&
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES)) !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
return 0; return;
err = -ENOBUFS;
skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
if (skb == NULL) if (skb == NULL)
goto err; goto err;
...@@ -482,14 +481,11 @@ static int nf_tables_table_notify(const struct nft_ctx *ctx, int event) ...@@ -482,14 +481,11 @@ static int nf_tables_table_notify(const struct nft_ctx *ctx, int event)
goto err; goto err;
} }
err = nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES, nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES,
ctx->report, GFP_KERNEL); ctx->report, GFP_KERNEL);
return;
err: err:
if (err < 0) { nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS);
nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES,
err);
}
return err;
} }
static int nf_tables_dump_tables(struct sk_buff *skb, static int nf_tables_dump_tables(struct sk_buff *skb,
...@@ -1050,16 +1046,15 @@ static int nf_tables_fill_chain_info(struct sk_buff *skb, struct net *net, ...@@ -1050,16 +1046,15 @@ static int nf_tables_fill_chain_info(struct sk_buff *skb, struct net *net,
return -1; return -1;
} }
static int nf_tables_chain_notify(const struct nft_ctx *ctx, int event) static void nf_tables_chain_notify(const struct nft_ctx *ctx, int event)
{ {
struct sk_buff *skb; struct sk_buff *skb;
int err; int err;
if (!ctx->report && if (!ctx->report &&
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES)) !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
return 0; return;
err = -ENOBUFS;
skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
if (skb == NULL) if (skb == NULL)
goto err; goto err;
...@@ -1072,14 +1067,11 @@ static int nf_tables_chain_notify(const struct nft_ctx *ctx, int event) ...@@ -1072,14 +1067,11 @@ static int nf_tables_chain_notify(const struct nft_ctx *ctx, int event)
goto err; goto err;
} }
err = nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES, nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES,
ctx->report, GFP_KERNEL); ctx->report, GFP_KERNEL);
return;
err: err:
if (err < 0) { nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS);
nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES,
err);
}
return err;
} }
static int nf_tables_dump_chains(struct sk_buff *skb, static int nf_tables_dump_chains(struct sk_buff *skb,
...@@ -1934,18 +1926,16 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, struct net *net, ...@@ -1934,18 +1926,16 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, struct net *net,
return -1; return -1;
} }
static int nf_tables_rule_notify(const struct nft_ctx *ctx, static void nf_tables_rule_notify(const struct nft_ctx *ctx,
const struct nft_rule *rule, const struct nft_rule *rule, int event)
int event)
{ {
struct sk_buff *skb; struct sk_buff *skb;
int err; int err;
if (!ctx->report && if (!ctx->report &&
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES)) !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
return 0; return;
err = -ENOBUFS;
skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
if (skb == NULL) if (skb == NULL)
goto err; goto err;
...@@ -1958,14 +1948,11 @@ static int nf_tables_rule_notify(const struct nft_ctx *ctx, ...@@ -1958,14 +1948,11 @@ static int nf_tables_rule_notify(const struct nft_ctx *ctx,
goto err; goto err;
} }
err = nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES, nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES,
ctx->report, GFP_KERNEL); ctx->report, GFP_KERNEL);
return;
err: err:
if (err < 0) { nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS);
nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES,
err);
}
return err;
} }
struct nft_rule_dump_ctx { struct nft_rule_dump_ctx {
...@@ -2696,9 +2683,9 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx, ...@@ -2696,9 +2683,9 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
return -1; return -1;
} }
static int nf_tables_set_notify(const struct nft_ctx *ctx, static void nf_tables_set_notify(const struct nft_ctx *ctx,
const struct nft_set *set, const struct nft_set *set, int event,
int event, gfp_t gfp_flags) gfp_t gfp_flags)
{ {
struct sk_buff *skb; struct sk_buff *skb;
u32 portid = ctx->portid; u32 portid = ctx->portid;
...@@ -2706,9 +2693,8 @@ static int nf_tables_set_notify(const struct nft_ctx *ctx, ...@@ -2706,9 +2693,8 @@ static int nf_tables_set_notify(const struct nft_ctx *ctx,
if (!ctx->report && if (!ctx->report &&
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES)) !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
return 0; return;
err = -ENOBUFS;
skb = nlmsg_new(NLMSG_GOODSIZE, gfp_flags); skb = nlmsg_new(NLMSG_GOODSIZE, gfp_flags);
if (skb == NULL) if (skb == NULL)
goto err; goto err;
...@@ -2719,12 +2705,11 @@ static int nf_tables_set_notify(const struct nft_ctx *ctx, ...@@ -2719,12 +2705,11 @@ static int nf_tables_set_notify(const struct nft_ctx *ctx,
goto err; goto err;
} }
err = nfnetlink_send(skb, ctx->net, portid, NFNLGRP_NFTABLES, nfnetlink_send(skb, ctx->net, portid, NFNLGRP_NFTABLES, ctx->report,
ctx->report, gfp_flags); gfp_flags);
return;
err: err:
if (err < 0) nfnetlink_set_err(ctx->net, portid, NFNLGRP_NFTABLES, -ENOBUFS);
nfnetlink_set_err(ctx->net, portid, NFNLGRP_NFTABLES, err);
return err;
} }
static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb) static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb)
...@@ -3504,7 +3489,7 @@ static int nf_tables_fill_setelem_info(struct sk_buff *skb, ...@@ -3504,7 +3489,7 @@ static int nf_tables_fill_setelem_info(struct sk_buff *skb,
return -1; return -1;
} }
static int nf_tables_setelem_notify(const struct nft_ctx *ctx, static void nf_tables_setelem_notify(const struct nft_ctx *ctx,
const struct nft_set *set, const struct nft_set *set,
const struct nft_set_elem *elem, const struct nft_set_elem *elem,
int event, u16 flags) int event, u16 flags)
...@@ -3515,9 +3500,8 @@ static int nf_tables_setelem_notify(const struct nft_ctx *ctx, ...@@ -3515,9 +3500,8 @@ static int nf_tables_setelem_notify(const struct nft_ctx *ctx,
int err; int err;
if (!ctx->report && !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES)) if (!ctx->report && !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
return 0; return;
err = -ENOBUFS;
skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
if (skb == NULL) if (skb == NULL)
goto err; goto err;
...@@ -3529,12 +3513,11 @@ static int nf_tables_setelem_notify(const struct nft_ctx *ctx, ...@@ -3529,12 +3513,11 @@ static int nf_tables_setelem_notify(const struct nft_ctx *ctx,
goto err; goto err;
} }
err = nfnetlink_send(skb, net, portid, NFNLGRP_NFTABLES, ctx->report, nfnetlink_send(skb, net, portid, NFNLGRP_NFTABLES, ctx->report,
GFP_KERNEL); GFP_KERNEL);
return;
err: err:
if (err < 0) nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, -ENOBUFS);
nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, err);
return err;
} }
static struct nft_trans *nft_trans_elem_alloc(struct nft_ctx *ctx, static struct nft_trans *nft_trans_elem_alloc(struct nft_ctx *ctx,
...@@ -4476,7 +4459,7 @@ static int nf_tables_delobj(struct net *net, struct sock *nlsk, ...@@ -4476,7 +4459,7 @@ static int nf_tables_delobj(struct net *net, struct sock *nlsk,
return nft_delobj(&ctx, obj); return nft_delobj(&ctx, obj);
} }
int nft_obj_notify(struct net *net, struct nft_table *table, void nft_obj_notify(struct net *net, struct nft_table *table,
struct nft_object *obj, u32 portid, u32 seq, int event, struct nft_object *obj, u32 portid, u32 seq, int event,
int family, int report, gfp_t gfp) int family, int report, gfp_t gfp)
{ {
...@@ -4485,9 +4468,8 @@ int nft_obj_notify(struct net *net, struct nft_table *table, ...@@ -4485,9 +4468,8 @@ int nft_obj_notify(struct net *net, struct nft_table *table,
if (!report && if (!report &&
!nfnetlink_has_listeners(net, NFNLGRP_NFTABLES)) !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
return 0; return;
err = -ENOBUFS;
skb = nlmsg_new(NLMSG_GOODSIZE, gfp); skb = nlmsg_new(NLMSG_GOODSIZE, gfp);
if (skb == NULL) if (skb == NULL)
goto err; goto err;
...@@ -4499,21 +4481,18 @@ int nft_obj_notify(struct net *net, struct nft_table *table, ...@@ -4499,21 +4481,18 @@ int nft_obj_notify(struct net *net, struct nft_table *table,
goto err; goto err;
} }
err = nfnetlink_send(skb, net, portid, NFNLGRP_NFTABLES, report, gfp); nfnetlink_send(skb, net, portid, NFNLGRP_NFTABLES, report, gfp);
return;
err: err:
if (err < 0) { nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, -ENOBUFS);
nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, err);
}
return err;
} }
EXPORT_SYMBOL_GPL(nft_obj_notify); EXPORT_SYMBOL_GPL(nft_obj_notify);
static int nf_tables_obj_notify(const struct nft_ctx *ctx, static void nf_tables_obj_notify(const struct nft_ctx *ctx,
struct nft_object *obj, int event) struct nft_object *obj, int event)
{ {
return nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid, nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid, ctx->seq, event,
ctx->seq, event, ctx->afi->family, ctx->report, ctx->afi->family, ctx->report, GFP_KERNEL);
GFP_KERNEL);
} }
static int nf_tables_fill_gen_info(struct sk_buff *skb, struct net *net, static int nf_tables_fill_gen_info(struct sk_buff *skb, struct net *net,
...@@ -4543,7 +4522,8 @@ static int nf_tables_fill_gen_info(struct sk_buff *skb, struct net *net, ...@@ -4543,7 +4522,8 @@ static int nf_tables_fill_gen_info(struct sk_buff *skb, struct net *net,
return -EMSGSIZE; return -EMSGSIZE;
} }
static int nf_tables_gen_notify(struct net *net, struct sk_buff *skb, int event) static void nf_tables_gen_notify(struct net *net, struct sk_buff *skb,
int event)
{ {
struct nlmsghdr *nlh = nlmsg_hdr(skb); struct nlmsghdr *nlh = nlmsg_hdr(skb);
struct sk_buff *skb2; struct sk_buff *skb2;
...@@ -4551,9 +4531,8 @@ static int nf_tables_gen_notify(struct net *net, struct sk_buff *skb, int event) ...@@ -4551,9 +4531,8 @@ static int nf_tables_gen_notify(struct net *net, struct sk_buff *skb, int event)
if (nlmsg_report(nlh) && if (nlmsg_report(nlh) &&
!nfnetlink_has_listeners(net, NFNLGRP_NFTABLES)) !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
return 0; return;
err = -ENOBUFS;
skb2 = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); skb2 = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
if (skb2 == NULL) if (skb2 == NULL)
goto err; goto err;
...@@ -4565,14 +4544,12 @@ static int nf_tables_gen_notify(struct net *net, struct sk_buff *skb, int event) ...@@ -4565,14 +4544,12 @@ static int nf_tables_gen_notify(struct net *net, struct sk_buff *skb, int event)
goto err; goto err;
} }
err = nfnetlink_send(skb2, net, NETLINK_CB(skb).portid, nfnetlink_send(skb2, net, NETLINK_CB(skb).portid, NFNLGRP_NFTABLES,
NFNLGRP_NFTABLES, nlmsg_report(nlh), GFP_KERNEL); nlmsg_report(nlh), GFP_KERNEL);
return;
err: err:
if (err < 0) {
nfnetlink_set_err(net, NETLINK_CB(skb).portid, NFNLGRP_NFTABLES, nfnetlink_set_err(net, NETLINK_CB(skb).portid, NFNLGRP_NFTABLES,
err); -ENOBUFS);
}
return err;
} }
static int nf_tables_getgen(struct net *net, struct sock *nlsk, static int nf_tables_getgen(struct net *net, struct sock *nlsk,
......
...@@ -60,11 +60,10 @@ static bool nft_rbtree_lookup(const struct net *net, const struct nft_set *set, ...@@ -60,11 +60,10 @@ static bool nft_rbtree_lookup(const struct net *net, const struct nft_set *set,
d = memcmp(this, key, set->klen); d = memcmp(this, key, set->klen);
if (d < 0) { if (d < 0) {
parent = parent->rb_left; parent = parent->rb_left;
/* In case of adjacent ranges, we always see the high if (interval &&
* part of the range in first place, before the low one. nft_rbtree_equal(set, this, interval) &&
* So don't update interval if the keys are equal. nft_rbtree_interval_end(this) &&
*/ !nft_rbtree_interval_end(interval))
if (interval && nft_rbtree_equal(set, this, interval))
continue; continue;
interval = rbe; interval = rbe;
} else if (d > 0) } else if (d > 0)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册