aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2017-03-03 23:40:06 -0500
committerDavid S. Miller <davem@davemloft.net>2017-03-03 23:40:06 -0500
commit20b83643abbc714342f3c52c5c273eeca649d3f9 (patch)
tree26db2246f1f73129a932903a564a5246028e00a5
parent45115553f32ddbedb1633a6b73751a75a4a4f43a (diff)
parent25e94a997b324b5f167f56d56d7106d38b78c9de (diff)
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: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/netfilter/nf_tables.h6
-rw-r--r--net/ipv4/netfilter.c7
-rw-r--r--net/netfilter/nf_conntrack_sip.c2
-rw-r--r--net/netfilter/nf_tables_api.c133
-rw-r--r--net/netfilter/nft_set_rbtree.c9
5 files changed, 66 insertions, 91 deletions
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index ac84686aaafb..2aa8a9d80fbe 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -988,9 +988,9 @@ struct nft_object *nf_tables_obj_lookup(const struct nft_table *table,
988 const struct nlattr *nla, u32 objtype, 988 const struct nlattr *nla, u32 objtype,
989 u8 genmask); 989 u8 genmask);
990 990
991int nft_obj_notify(struct net *net, struct nft_table *table, 991void nft_obj_notify(struct net *net, struct nft_table *table,
992 struct nft_object *obj, u32 portid, u32 seq, 992 struct nft_object *obj, u32 portid, u32 seq,
993 int event, int family, int report, gfp_t gfp); 993 int event, int family, int report, gfp_t gfp);
994 994
995/** 995/**
996 * struct nft_object_type - stateful object type 996 * struct nft_object_type - stateful object type
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index b3cc1335adbc..c0cc6aa8cfaa 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -23,7 +23,8 @@ int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned int addr_t
23 struct rtable *rt; 23 struct rtable *rt;
24 struct flowi4 fl4 = {}; 24 struct flowi4 fl4 = {};
25 __be32 saddr = iph->saddr; 25 __be32 saddr = iph->saddr;
26 __u8 flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : 0; 26 const struct sock *sk = skb_to_full_sk(skb);
27 __u8 flags = sk ? inet_sk_flowi_flags(sk) : 0;
27 struct net_device *dev = skb_dst(skb)->dev; 28 struct net_device *dev = skb_dst(skb)->dev;
28 unsigned int hh_len; 29 unsigned int hh_len;
29 30
@@ -40,7 +41,7 @@ int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned int addr_t
40 fl4.daddr = iph->daddr; 41 fl4.daddr = iph->daddr;
41 fl4.saddr = saddr; 42 fl4.saddr = saddr;
42 fl4.flowi4_tos = RT_TOS(iph->tos); 43 fl4.flowi4_tos = RT_TOS(iph->tos);
43 fl4.flowi4_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0; 44 fl4.flowi4_oif = sk ? sk->sk_bound_dev_if : 0;
44 if (!fl4.flowi4_oif) 45 if (!fl4.flowi4_oif)
45 fl4.flowi4_oif = l3mdev_master_ifindex(dev); 46 fl4.flowi4_oif = l3mdev_master_ifindex(dev);
46 fl4.flowi4_mark = skb->mark; 47 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 xfrm_decode_session(skb, flowi4_to_flowi(&fl4), AF_INET) == 0) { 62 xfrm_decode_session(skb, flowi4_to_flowi(&fl4), AF_INET) == 0) {
62 struct dst_entry *dst = skb_dst(skb); 63 struct dst_entry *dst = skb_dst(skb);
63 skb_dst_set(skb, NULL); 64 skb_dst_set(skb, NULL);
64 dst = xfrm_lookup(net, dst, flowi4_to_flowi(&fl4), skb->sk, 0); 65 dst = xfrm_lookup(net, dst, flowi4_to_flowi(&fl4), sk, 0);
65 if (IS_ERR(dst)) 66 if (IS_ERR(dst))
66 return PTR_ERR(dst); 67 return PTR_ERR(dst);
67 skb_dst_set(skb, dst); 68 skb_dst_set(skb, dst);
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index 24174c520239..0d17894798b5 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -1628,8 +1628,6 @@ static int __init nf_conntrack_sip_init(void)
1628 ports[ports_c++] = SIP_PORT; 1628 ports[ports_c++] = SIP_PORT;
1629 1629
1630 for (i = 0; i < ports_c; i++) { 1630 for (i = 0; i < ports_c; i++) {
1631 memset(&sip[i], 0, sizeof(sip[i]));
1632
1633 nf_ct_helper_init(&sip[4 * i], AF_INET, IPPROTO_UDP, "sip", 1631 nf_ct_helper_init(&sip[4 * i], AF_INET, IPPROTO_UDP, "sip",
1634 SIP_PORT, ports[i], i, sip_exp_policy, 1632 SIP_PORT, ports[i], i, sip_exp_policy,
1635 SIP_EXPECT_MAX, 1633 SIP_EXPECT_MAX,
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index ff7304ae58ac..5e0ccfd5bb37 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -461,16 +461,15 @@ nla_put_failure:
461 return -1; 461 return -1;
462} 462}
463 463
464static int nf_tables_table_notify(const struct nft_ctx *ctx, int event) 464static void nf_tables_table_notify(const struct nft_ctx *ctx, int event)
465{ 465{
466 struct sk_buff *skb; 466 struct sk_buff *skb;
467 int err; 467 int err;
468 468
469 if (!ctx->report && 469 if (!ctx->report &&
470 !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES)) 470 !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
471 return 0; 471 return;
472 472
473 err = -ENOBUFS;
474 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 473 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
475 if (skb == NULL) 474 if (skb == NULL)
476 goto err; 475 goto err;
@@ -482,14 +481,11 @@ static int nf_tables_table_notify(const struct nft_ctx *ctx, int event)
482 goto err; 481 goto err;
483 } 482 }
484 483
485 err = nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES, 484 nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES,
486 ctx->report, GFP_KERNEL); 485 ctx->report, GFP_KERNEL);
486 return;
487err: 487err:
488 if (err < 0) { 488 nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS);
489 nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES,
490 err);
491 }
492 return err;
493} 489}
494 490
495static int nf_tables_dump_tables(struct sk_buff *skb, 491static int nf_tables_dump_tables(struct sk_buff *skb,
@@ -1050,16 +1046,15 @@ nla_put_failure:
1050 return -1; 1046 return -1;
1051} 1047}
1052 1048
1053static int nf_tables_chain_notify(const struct nft_ctx *ctx, int event) 1049static void nf_tables_chain_notify(const struct nft_ctx *ctx, int event)
1054{ 1050{
1055 struct sk_buff *skb; 1051 struct sk_buff *skb;
1056 int err; 1052 int err;
1057 1053
1058 if (!ctx->report && 1054 if (!ctx->report &&
1059 !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES)) 1055 !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
1060 return 0; 1056 return;
1061 1057
1062 err = -ENOBUFS;
1063 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 1058 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1064 if (skb == NULL) 1059 if (skb == NULL)
1065 goto err; 1060 goto err;
@@ -1072,14 +1067,11 @@ static int nf_tables_chain_notify(const struct nft_ctx *ctx, int event)
1072 goto err; 1067 goto err;
1073 } 1068 }
1074 1069
1075 err = nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES, 1070 nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES,
1076 ctx->report, GFP_KERNEL); 1071 ctx->report, GFP_KERNEL);
1072 return;
1077err: 1073err:
1078 if (err < 0) { 1074 nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS);
1079 nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES,
1080 err);
1081 }
1082 return err;
1083} 1075}
1084 1076
1085static int nf_tables_dump_chains(struct sk_buff *skb, 1077static int nf_tables_dump_chains(struct sk_buff *skb,
@@ -1934,18 +1926,16 @@ nla_put_failure:
1934 return -1; 1926 return -1;
1935} 1927}
1936 1928
1937static int nf_tables_rule_notify(const struct nft_ctx *ctx, 1929static void nf_tables_rule_notify(const struct nft_ctx *ctx,
1938 const struct nft_rule *rule, 1930 const struct nft_rule *rule, int event)
1939 int event)
1940{ 1931{
1941 struct sk_buff *skb; 1932 struct sk_buff *skb;
1942 int err; 1933 int err;
1943 1934
1944 if (!ctx->report && 1935 if (!ctx->report &&
1945 !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES)) 1936 !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
1946 return 0; 1937 return;
1947 1938
1948 err = -ENOBUFS;
1949 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 1939 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1950 if (skb == NULL) 1940 if (skb == NULL)
1951 goto err; 1941 goto err;
@@ -1958,14 +1948,11 @@ static int nf_tables_rule_notify(const struct nft_ctx *ctx,
1958 goto err; 1948 goto err;
1959 } 1949 }
1960 1950
1961 err = nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES, 1951 nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES,
1962 ctx->report, GFP_KERNEL); 1952 ctx->report, GFP_KERNEL);
1953 return;
1963err: 1954err:
1964 if (err < 0) { 1955 nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS);
1965 nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES,
1966 err);
1967 }
1968 return err;
1969} 1956}
1970 1957
1971struct nft_rule_dump_ctx { 1958struct nft_rule_dump_ctx {
@@ -2696,9 +2683,9 @@ nla_put_failure:
2696 return -1; 2683 return -1;
2697} 2684}
2698 2685
2699static int nf_tables_set_notify(const struct nft_ctx *ctx, 2686static void nf_tables_set_notify(const struct nft_ctx *ctx,
2700 const struct nft_set *set, 2687 const struct nft_set *set, int event,
2701 int event, gfp_t gfp_flags) 2688 gfp_t gfp_flags)
2702{ 2689{
2703 struct sk_buff *skb; 2690 struct sk_buff *skb;
2704 u32 portid = ctx->portid; 2691 u32 portid = ctx->portid;
@@ -2706,9 +2693,8 @@ static int nf_tables_set_notify(const struct nft_ctx *ctx,
2706 2693
2707 if (!ctx->report && 2694 if (!ctx->report &&
2708 !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES)) 2695 !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
2709 return 0; 2696 return;
2710 2697
2711 err = -ENOBUFS;
2712 skb = nlmsg_new(NLMSG_GOODSIZE, gfp_flags); 2698 skb = nlmsg_new(NLMSG_GOODSIZE, gfp_flags);
2713 if (skb == NULL) 2699 if (skb == NULL)
2714 goto err; 2700 goto err;
@@ -2719,12 +2705,11 @@ static int nf_tables_set_notify(const struct nft_ctx *ctx,
2719 goto err; 2705 goto err;
2720 } 2706 }
2721 2707
2722 err = nfnetlink_send(skb, ctx->net, portid, NFNLGRP_NFTABLES, 2708 nfnetlink_send(skb, ctx->net, portid, NFNLGRP_NFTABLES, ctx->report,
2723 ctx->report, gfp_flags); 2709 gfp_flags);
2710 return;
2724err: 2711err:
2725 if (err < 0) 2712 nfnetlink_set_err(ctx->net, portid, NFNLGRP_NFTABLES, -ENOBUFS);
2726 nfnetlink_set_err(ctx->net, portid, NFNLGRP_NFTABLES, err);
2727 return err;
2728} 2713}
2729 2714
2730static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb) 2715static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb)
@@ -3504,10 +3489,10 @@ nla_put_failure:
3504 return -1; 3489 return -1;
3505} 3490}
3506 3491
3507static int nf_tables_setelem_notify(const struct nft_ctx *ctx, 3492static void nf_tables_setelem_notify(const struct nft_ctx *ctx,
3508 const struct nft_set *set, 3493 const struct nft_set *set,
3509 const struct nft_set_elem *elem, 3494 const struct nft_set_elem *elem,
3510 int event, u16 flags) 3495 int event, u16 flags)
3511{ 3496{
3512 struct net *net = ctx->net; 3497 struct net *net = ctx->net;
3513 u32 portid = ctx->portid; 3498 u32 portid = ctx->portid;
@@ -3515,9 +3500,8 @@ static int nf_tables_setelem_notify(const struct nft_ctx *ctx,
3515 int err; 3500 int err;
3516 3501
3517 if (!ctx->report && !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES)) 3502 if (!ctx->report && !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
3518 return 0; 3503 return;
3519 3504
3520 err = -ENOBUFS;
3521 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 3505 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
3522 if (skb == NULL) 3506 if (skb == NULL)
3523 goto err; 3507 goto err;
@@ -3529,12 +3513,11 @@ static int nf_tables_setelem_notify(const struct nft_ctx *ctx,
3529 goto err; 3513 goto err;
3530 } 3514 }
3531 3515
3532 err = nfnetlink_send(skb, net, portid, NFNLGRP_NFTABLES, ctx->report, 3516 nfnetlink_send(skb, net, portid, NFNLGRP_NFTABLES, ctx->report,
3533 GFP_KERNEL); 3517 GFP_KERNEL);
3518 return;
3534err: 3519err:
3535 if (err < 0) 3520 nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, -ENOBUFS);
3536 nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, err);
3537 return err;
3538} 3521}
3539 3522
3540static struct nft_trans *nft_trans_elem_alloc(struct nft_ctx *ctx, 3523static struct nft_trans *nft_trans_elem_alloc(struct nft_ctx *ctx,
@@ -4476,18 +4459,17 @@ static int nf_tables_delobj(struct net *net, struct sock *nlsk,
4476 return nft_delobj(&ctx, obj); 4459 return nft_delobj(&ctx, obj);
4477} 4460}
4478 4461
4479int nft_obj_notify(struct net *net, struct nft_table *table, 4462void nft_obj_notify(struct net *net, struct nft_table *table,
4480 struct nft_object *obj, u32 portid, u32 seq, int event, 4463 struct nft_object *obj, u32 portid, u32 seq, int event,
4481 int family, int report, gfp_t gfp) 4464 int family, int report, gfp_t gfp)
4482{ 4465{
4483 struct sk_buff *skb; 4466 struct sk_buff *skb;
4484 int err; 4467 int err;
4485 4468
4486 if (!report && 4469 if (!report &&
4487 !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES)) 4470 !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
4488 return 0; 4471 return;
4489 4472
4490 err = -ENOBUFS;
4491 skb = nlmsg_new(NLMSG_GOODSIZE, gfp); 4473 skb = nlmsg_new(NLMSG_GOODSIZE, gfp);
4492 if (skb == NULL) 4474 if (skb == NULL)
4493 goto err; 4475 goto err;
@@ -4499,21 +4481,18 @@ int nft_obj_notify(struct net *net, struct nft_table *table,
4499 goto err; 4481 goto err;
4500 } 4482 }
4501 4483
4502 err = nfnetlink_send(skb, net, portid, NFNLGRP_NFTABLES, report, gfp); 4484 nfnetlink_send(skb, net, portid, NFNLGRP_NFTABLES, report, gfp);
4485 return;
4503err: 4486err:
4504 if (err < 0) { 4487 nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, -ENOBUFS);
4505 nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, err);
4506 }
4507 return err;
4508} 4488}
4509EXPORT_SYMBOL_GPL(nft_obj_notify); 4489EXPORT_SYMBOL_GPL(nft_obj_notify);
4510 4490
4511static int nf_tables_obj_notify(const struct nft_ctx *ctx, 4491static void nf_tables_obj_notify(const struct nft_ctx *ctx,
4512 struct nft_object *obj, int event) 4492 struct nft_object *obj, int event)
4513{ 4493{
4514 return nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid, 4494 nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid, ctx->seq, event,
4515 ctx->seq, event, ctx->afi->family, ctx->report, 4495 ctx->afi->family, ctx->report, GFP_KERNEL);
4516 GFP_KERNEL);
4517} 4496}
4518 4497
4519static int nf_tables_fill_gen_info(struct sk_buff *skb, struct net *net, 4498static int nf_tables_fill_gen_info(struct sk_buff *skb, struct net *net,
@@ -4543,7 +4522,8 @@ nla_put_failure:
4543 return -EMSGSIZE; 4522 return -EMSGSIZE;
4544} 4523}
4545 4524
4546static int nf_tables_gen_notify(struct net *net, struct sk_buff *skb, int event) 4525static void nf_tables_gen_notify(struct net *net, struct sk_buff *skb,
4526 int event)
4547{ 4527{
4548 struct nlmsghdr *nlh = nlmsg_hdr(skb); 4528 struct nlmsghdr *nlh = nlmsg_hdr(skb);
4549 struct sk_buff *skb2; 4529 struct sk_buff *skb2;
@@ -4551,9 +4531,8 @@ static int nf_tables_gen_notify(struct net *net, struct sk_buff *skb, int event)
4551 4531
4552 if (nlmsg_report(nlh) && 4532 if (nlmsg_report(nlh) &&
4553 !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES)) 4533 !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
4554 return 0; 4534 return;
4555 4535
4556 err = -ENOBUFS;
4557 skb2 = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 4536 skb2 = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
4558 if (skb2 == NULL) 4537 if (skb2 == NULL)
4559 goto err; 4538 goto err;
@@ -4565,14 +4544,12 @@ static int nf_tables_gen_notify(struct net *net, struct sk_buff *skb, int event)
4565 goto err; 4544 goto err;
4566 } 4545 }
4567 4546
4568 err = nfnetlink_send(skb2, net, NETLINK_CB(skb).portid, 4547 nfnetlink_send(skb2, net, NETLINK_CB(skb).portid, NFNLGRP_NFTABLES,
4569 NFNLGRP_NFTABLES, nlmsg_report(nlh), GFP_KERNEL); 4548 nlmsg_report(nlh), GFP_KERNEL);
4549 return;
4570err: 4550err:
4571 if (err < 0) { 4551 nfnetlink_set_err(net, NETLINK_CB(skb).portid, NFNLGRP_NFTABLES,
4572 nfnetlink_set_err(net, NETLINK_CB(skb).portid, NFNLGRP_NFTABLES, 4552 -ENOBUFS);
4573 err);
4574 }
4575 return err;
4576} 4553}
4577 4554
4578static int nf_tables_getgen(struct net *net, struct sock *nlsk, 4555static int nf_tables_getgen(struct net *net, struct sock *nlsk,
diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
index 71e8fb886a73..78dfbf9588b3 100644
--- a/net/netfilter/nft_set_rbtree.c
+++ b/net/netfilter/nft_set_rbtree.c
@@ -60,11 +60,10 @@ static bool nft_rbtree_lookup(const struct net *net, const struct nft_set *set,
60 d = memcmp(this, key, set->klen); 60 d = memcmp(this, key, set->klen);
61 if (d < 0) { 61 if (d < 0) {
62 parent = parent->rb_left; 62 parent = parent->rb_left;
63 /* In case of adjacent ranges, we always see the high 63 if (interval &&
64 * part of the range in first place, before the low one. 64 nft_rbtree_equal(set, this, interval) &&
65 * So don't update interval if the keys are equal. 65 nft_rbtree_interval_end(this) &&
66 */ 66 !nft_rbtree_interval_end(interval))
67 if (interval && nft_rbtree_equal(set, this, interval))
68 continue; 67 continue;
69 interval = rbe; 68 interval = rbe;
70 } else if (d > 0) 69 } else if (d > 0)