Commit e0831ef7 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:

1) Remove a direct dependency with IPv6 introduced by the
   sip_external_media feature, from Alin Nastac.

2) Fix bogus ENOENT when removing interval elements from set.

3) Set transport_header from br_netfilter to mimic the stack
   behaviour, this partially fixes a checksum validation bug
   from the SCTP connection tracking, from Xin Long.

4) Fix undefined reference to symbol in xt_TEE, due to missing
   Kconfig dependencies, from Arnd Bergmann.

5) Check for NULL in skb_header_pointer() calls in ip6t_shr,
   from Kangjie Lu.

6) Fix bogus EBUSY when removing an existing conntrack helper from
   a transaction.

7) Fix module autoload of the redirect extension.

8) Remove duplicated transition in flowtable diagram in the existing
   documentation.

9) Missing .release_ops call from error path in newrule() which
   results module refcount leak, from Taehee Yoo.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ceabee6c b25a31bf
...@@ -44,10 +44,10 @@ including the Netfilter hooks and the flowtable fastpath bypass. ...@@ -44,10 +44,10 @@ including the Netfilter hooks and the flowtable fastpath bypass.
/ \ / \ |Routing | / \ / \ / \ |Routing | / \
--> ingress ---> prerouting ---> |decision| | postrouting |--> neigh_xmit --> ingress ---> prerouting ---> |decision| | postrouting |--> neigh_xmit
\_________/ \__________/ ---------- \____________/ ^ \_________/ \__________/ ---------- \____________/ ^
| ^ | | ^ | | ^ | ^ |
flowtable | | ____\/___ | | flowtable | ____\/___ | |
| | | / \ | | | | / \ | |
__\/___ | --------->| forward |------------ | __\/___ | | forward |------------ |
|-----| | \_________/ | |-----| | \_________/ |
|-----| | 'flow offload' rule | |-----| | 'flow offload' rule |
|-----| | adds entry to | |-----| | adds entry to |
......
...@@ -502,6 +502,7 @@ static unsigned int br_nf_pre_routing(void *priv, ...@@ -502,6 +502,7 @@ static unsigned int br_nf_pre_routing(void *priv,
nf_bridge->ipv4_daddr = ip_hdr(skb)->daddr; nf_bridge->ipv4_daddr = ip_hdr(skb)->daddr;
skb->protocol = htons(ETH_P_IP); skb->protocol = htons(ETH_P_IP);
skb->transport_header = skb->network_header + ip_hdr(skb)->ihl * 4;
NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, state->net, state->sk, skb, NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, state->net, state->sk, skb,
skb->dev, NULL, skb->dev, NULL,
......
...@@ -235,6 +235,8 @@ unsigned int br_nf_pre_routing_ipv6(void *priv, ...@@ -235,6 +235,8 @@ unsigned int br_nf_pre_routing_ipv6(void *priv,
nf_bridge->ipv6_daddr = ipv6_hdr(skb)->daddr; nf_bridge->ipv6_daddr = ipv6_hdr(skb)->daddr;
skb->protocol = htons(ETH_P_IPV6); skb->protocol = htons(ETH_P_IPV6);
skb->transport_header = skb->network_header + sizeof(struct ipv6hdr);
NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, state->net, state->sk, skb, NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, state->net, state->sk, skb,
skb->dev, NULL, skb->dev, NULL,
br_nf_pre_routing_finish_ipv6); br_nf_pre_routing_finish_ipv6);
......
...@@ -210,6 +210,8 @@ static bool srh1_mt6(const struct sk_buff *skb, struct xt_action_param *par) ...@@ -210,6 +210,8 @@ static bool srh1_mt6(const struct sk_buff *skb, struct xt_action_param *par)
psidoff = srhoff + sizeof(struct ipv6_sr_hdr) + psidoff = srhoff + sizeof(struct ipv6_sr_hdr) +
((srh->segments_left + 1) * sizeof(struct in6_addr)); ((srh->segments_left + 1) * sizeof(struct in6_addr));
psid = skb_header_pointer(skb, psidoff, sizeof(_psid), &_psid); psid = skb_header_pointer(skb, psidoff, sizeof(_psid), &_psid);
if (!psid)
return false;
if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_PSID, if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_PSID,
ipv6_masked_addr_cmp(psid, &srhinfo->psid_msk, ipv6_masked_addr_cmp(psid, &srhinfo->psid_msk,
&srhinfo->psid_addr))) &srhinfo->psid_addr)))
...@@ -223,6 +225,8 @@ static bool srh1_mt6(const struct sk_buff *skb, struct xt_action_param *par) ...@@ -223,6 +225,8 @@ static bool srh1_mt6(const struct sk_buff *skb, struct xt_action_param *par)
nsidoff = srhoff + sizeof(struct ipv6_sr_hdr) + nsidoff = srhoff + sizeof(struct ipv6_sr_hdr) +
((srh->segments_left - 1) * sizeof(struct in6_addr)); ((srh->segments_left - 1) * sizeof(struct in6_addr));
nsid = skb_header_pointer(skb, nsidoff, sizeof(_nsid), &_nsid); nsid = skb_header_pointer(skb, nsidoff, sizeof(_nsid), &_nsid);
if (!nsid)
return false;
if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_NSID, if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_NSID,
ipv6_masked_addr_cmp(nsid, &srhinfo->nsid_msk, ipv6_masked_addr_cmp(nsid, &srhinfo->nsid_msk,
&srhinfo->nsid_addr))) &srhinfo->nsid_addr)))
...@@ -233,6 +237,8 @@ static bool srh1_mt6(const struct sk_buff *skb, struct xt_action_param *par) ...@@ -233,6 +237,8 @@ static bool srh1_mt6(const struct sk_buff *skb, struct xt_action_param *par)
if (srhinfo->mt_flags & IP6T_SRH_LSID) { if (srhinfo->mt_flags & IP6T_SRH_LSID) {
lsidoff = srhoff + sizeof(struct ipv6_sr_hdr); lsidoff = srhoff + sizeof(struct ipv6_sr_hdr);
lsid = skb_header_pointer(skb, lsidoff, sizeof(_lsid), &_lsid); lsid = skb_header_pointer(skb, lsidoff, sizeof(_lsid), &_lsid);
if (!lsid)
return false;
if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LSID, if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LSID,
ipv6_masked_addr_cmp(lsid, &srhinfo->lsid_msk, ipv6_masked_addr_cmp(lsid, &srhinfo->lsid_msk,
&srhinfo->lsid_addr))) &srhinfo->lsid_addr)))
......
...@@ -1007,6 +1007,7 @@ config NETFILTER_XT_TARGET_TEE ...@@ -1007,6 +1007,7 @@ config NETFILTER_XT_TARGET_TEE
depends on NETFILTER_ADVANCED depends on NETFILTER_ADVANCED
depends on IPV6 || IPV6=n depends on IPV6 || IPV6=n
depends on !NF_CONNTRACK || NF_CONNTRACK depends on !NF_CONNTRACK || NF_CONNTRACK
depends on IP6_NF_IPTABLES || !IP6_NF_IPTABLES
select NF_DUP_IPV4 select NF_DUP_IPV4
select NF_DUP_IPV6 if IP6_NF_IPTABLES select NF_DUP_IPV6 if IP6_NF_IPTABLES
---help--- ---help---
......
...@@ -20,9 +20,9 @@ ...@@ -20,9 +20,9 @@
#include <linux/udp.h> #include <linux/udp.h>
#include <linux/tcp.h> #include <linux/tcp.h>
#include <linux/netfilter.h> #include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_ipv6.h>
#include <net/route.h>
#include <net/ip6_route.h>
#include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_core.h> #include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_conntrack_expect.h> #include <net/netfilter/nf_conntrack_expect.h>
...@@ -871,38 +871,33 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int protoff, ...@@ -871,38 +871,33 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int protoff,
} else if (sip_external_media) { } else if (sip_external_media) {
struct net_device *dev = skb_dst(skb)->dev; struct net_device *dev = skb_dst(skb)->dev;
struct net *net = dev_net(dev); struct net *net = dev_net(dev);
struct rtable *rt; struct flowi fl;
struct flowi4 fl4 = {};
#if IS_ENABLED(CONFIG_IPV6)
struct flowi6 fl6 = {};
#endif
struct dst_entry *dst = NULL; struct dst_entry *dst = NULL;
memset(&fl, 0, sizeof(fl));
switch (nf_ct_l3num(ct)) { switch (nf_ct_l3num(ct)) {
case NFPROTO_IPV4: case NFPROTO_IPV4:
fl4.daddr = daddr->ip; fl.u.ip4.daddr = daddr->ip;
rt = ip_route_output_key(net, &fl4); nf_ip_route(net, &dst, &fl, false);
if (!IS_ERR(rt))
dst = &rt->dst;
break; break;
#if IS_ENABLED(CONFIG_IPV6)
case NFPROTO_IPV6: case NFPROTO_IPV6:
fl6.daddr = daddr->in6; fl.u.ip6.daddr = daddr->in6;
dst = ip6_route_output(net, NULL, &fl6); nf_ip6_route(net, &dst, &fl, false);
if (dst->error) {
dst_release(dst);
dst = NULL;
}
break; break;
#endif
} }
/* Don't predict any conntracks when media endpoint is reachable /* Don't predict any conntracks when media endpoint is reachable
* through the same interface as the signalling peer. * through the same interface as the signalling peer.
*/ */
if (dst && dst->dev == dev) if (dst) {
return NF_ACCEPT; bool external_media = (dst->dev == dev);
dst_release(dst);
if (external_media)
return NF_ACCEPT;
}
} }
/* We need to check whether the registration exists before attempting /* We need to check whether the registration exists before attempting
......
...@@ -2806,8 +2806,11 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk, ...@@ -2806,8 +2806,11 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
nf_tables_rule_release(&ctx, rule); nf_tables_rule_release(&ctx, rule);
err1: err1:
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
if (info[i].ops != NULL) if (info[i].ops) {
module_put(info[i].ops->type->owner); module_put(info[i].ops->type->owner);
if (info[i].ops->type->release_ops)
info[i].ops->type->release_ops(info[i].ops);
}
} }
kvfree(info); kvfree(info);
return err; return err;
......
...@@ -65,21 +65,34 @@ static int nft_objref_dump(struct sk_buff *skb, const struct nft_expr *expr) ...@@ -65,21 +65,34 @@ static int nft_objref_dump(struct sk_buff *skb, const struct nft_expr *expr)
return -1; return -1;
} }
static void nft_objref_destroy(const struct nft_ctx *ctx, static void nft_objref_deactivate(const struct nft_ctx *ctx,
const struct nft_expr *expr) const struct nft_expr *expr,
enum nft_trans_phase phase)
{ {
struct nft_object *obj = nft_objref_priv(expr); struct nft_object *obj = nft_objref_priv(expr);
if (phase == NFT_TRANS_COMMIT)
return;
obj->use--; obj->use--;
} }
static void nft_objref_activate(const struct nft_ctx *ctx,
const struct nft_expr *expr)
{
struct nft_object *obj = nft_objref_priv(expr);
obj->use++;
}
static struct nft_expr_type nft_objref_type; static struct nft_expr_type nft_objref_type;
static const struct nft_expr_ops nft_objref_ops = { static const struct nft_expr_ops nft_objref_ops = {
.type = &nft_objref_type, .type = &nft_objref_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_object *)), .size = NFT_EXPR_SIZE(sizeof(struct nft_object *)),
.eval = nft_objref_eval, .eval = nft_objref_eval,
.init = nft_objref_init, .init = nft_objref_init,
.destroy = nft_objref_destroy, .activate = nft_objref_activate,
.deactivate = nft_objref_deactivate,
.dump = nft_objref_dump, .dump = nft_objref_dump,
}; };
......
...@@ -233,5 +233,5 @@ module_exit(nft_redir_module_exit); ...@@ -233,5 +233,5 @@ module_exit(nft_redir_module_exit);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>"); MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>");
MODULE_ALIAS_NFT_AF_EXPR(AF_INET4, "redir"); MODULE_ALIAS_NFT_AF_EXPR(AF_INET, "redir");
MODULE_ALIAS_NFT_AF_EXPR(AF_INET6, "redir"); MODULE_ALIAS_NFT_AF_EXPR(AF_INET6, "redir");
...@@ -308,10 +308,6 @@ static void *nft_rbtree_deactivate(const struct net *net, ...@@ -308,10 +308,6 @@ static void *nft_rbtree_deactivate(const struct net *net,
else if (d > 0) else if (d > 0)
parent = parent->rb_right; parent = parent->rb_right;
else { else {
if (!nft_set_elem_active(&rbe->ext, genmask)) {
parent = parent->rb_left;
continue;
}
if (nft_rbtree_interval_end(rbe) && if (nft_rbtree_interval_end(rbe) &&
!nft_rbtree_interval_end(this)) { !nft_rbtree_interval_end(this)) {
parent = parent->rb_left; parent = parent->rb_left;
...@@ -320,6 +316,9 @@ static void *nft_rbtree_deactivate(const struct net *net, ...@@ -320,6 +316,9 @@ static void *nft_rbtree_deactivate(const struct net *net,
nft_rbtree_interval_end(this)) { nft_rbtree_interval_end(this)) {
parent = parent->rb_right; parent = parent->rb_right;
continue; continue;
} else if (!nft_set_elem_active(&rbe->ext, genmask)) {
parent = parent->rb_left;
continue;
} }
nft_rbtree_flush(net, set, rbe); nft_rbtree_flush(net, set, rbe);
return rbe; return rbe;
......
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