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.
/ \ / \ |Routing | / \
--> ingress ---> prerouting ---> |decision| | postrouting |--> neigh_xmit
\_________/ \__________/ ---------- \____________/ ^
| ^ | | ^ |
flowtable | | ____\/___ | |
| | | / \ | |
__\/___ | --------->| forward |------------ |
| ^ | ^ |
flowtable | ____\/___ | |
| | / \ | |
__\/___ | | forward |------------ |
|-----| | \_________/ |
|-----| | 'flow offload' rule |
|-----| | adds entry to |
......
......@@ -502,6 +502,7 @@ static unsigned int br_nf_pre_routing(void *priv,
nf_bridge->ipv4_daddr = ip_hdr(skb)->daddr;
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,
skb->dev, NULL,
......
......@@ -235,6 +235,8 @@ unsigned int br_nf_pre_routing_ipv6(void *priv,
nf_bridge->ipv6_daddr = ipv6_hdr(skb)->daddr;
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,
skb->dev, NULL,
br_nf_pre_routing_finish_ipv6);
......
......@@ -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) +
((srh->segments_left + 1) * sizeof(struct in6_addr));
psid = skb_header_pointer(skb, psidoff, sizeof(_psid), &_psid);
if (!psid)
return false;
if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_PSID,
ipv6_masked_addr_cmp(psid, &srhinfo->psid_msk,
&srhinfo->psid_addr)))
......@@ -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) +
((srh->segments_left - 1) * sizeof(struct in6_addr));
nsid = skb_header_pointer(skb, nsidoff, sizeof(_nsid), &_nsid);
if (!nsid)
return false;
if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_NSID,
ipv6_masked_addr_cmp(nsid, &srhinfo->nsid_msk,
&srhinfo->nsid_addr)))
......@@ -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) {
lsidoff = srhoff + sizeof(struct ipv6_sr_hdr);
lsid = skb_header_pointer(skb, lsidoff, sizeof(_lsid), &_lsid);
if (!lsid)
return false;
if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LSID,
ipv6_masked_addr_cmp(lsid, &srhinfo->lsid_msk,
&srhinfo->lsid_addr)))
......
......@@ -1007,6 +1007,7 @@ config NETFILTER_XT_TARGET_TEE
depends on NETFILTER_ADVANCED
depends on IPV6 || IPV6=n
depends on !NF_CONNTRACK || NF_CONNTRACK
depends on IP6_NF_IPTABLES || !IP6_NF_IPTABLES
select NF_DUP_IPV4
select NF_DUP_IPV6 if IP6_NF_IPTABLES
---help---
......
......@@ -20,9 +20,9 @@
#include <linux/udp.h>
#include <linux/tcp.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_core.h>
#include <net/netfilter/nf_conntrack_expect.h>
......@@ -871,39 +871,34 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int protoff,
} else if (sip_external_media) {
struct net_device *dev = skb_dst(skb)->dev;
struct net *net = dev_net(dev);
struct rtable *rt;
struct flowi4 fl4 = {};
#if IS_ENABLED(CONFIG_IPV6)
struct flowi6 fl6 = {};
#endif
struct flowi fl;
struct dst_entry *dst = NULL;
memset(&fl, 0, sizeof(fl));
switch (nf_ct_l3num(ct)) {
case NFPROTO_IPV4:
fl4.daddr = daddr->ip;
rt = ip_route_output_key(net, &fl4);
if (!IS_ERR(rt))
dst = &rt->dst;
fl.u.ip4.daddr = daddr->ip;
nf_ip_route(net, &dst, &fl, false);
break;
#if IS_ENABLED(CONFIG_IPV6)
case NFPROTO_IPV6:
fl6.daddr = daddr->in6;
dst = ip6_route_output(net, NULL, &fl6);
if (dst->error) {
dst_release(dst);
dst = NULL;
}
fl.u.ip6.daddr = daddr->in6;
nf_ip6_route(net, &dst, &fl, false);
break;
#endif
}
/* Don't predict any conntracks when media endpoint is reachable
* through the same interface as the signalling peer.
*/
if (dst && dst->dev == dev)
if (dst) {
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
* to register it since we can see the same media description multiple
......
......@@ -2806,8 +2806,11 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
nf_tables_rule_release(&ctx, rule);
err1:
for (i = 0; i < n; i++) {
if (info[i].ops != NULL)
if (info[i].ops) {
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);
return err;
......
......@@ -65,21 +65,34 @@ static int nft_objref_dump(struct sk_buff *skb, const struct nft_expr *expr)
return -1;
}
static void nft_objref_destroy(const struct nft_ctx *ctx,
const struct nft_expr *expr)
static void nft_objref_deactivate(const struct nft_ctx *ctx,
const struct nft_expr *expr,
enum nft_trans_phase phase)
{
struct nft_object *obj = nft_objref_priv(expr);
if (phase == NFT_TRANS_COMMIT)
return;
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 const struct nft_expr_ops nft_objref_ops = {
.type = &nft_objref_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_object *)),
.eval = nft_objref_eval,
.init = nft_objref_init,
.destroy = nft_objref_destroy,
.activate = nft_objref_activate,
.deactivate = nft_objref_deactivate,
.dump = nft_objref_dump,
};
......
......@@ -233,5 +233,5 @@ module_exit(nft_redir_module_exit);
MODULE_LICENSE("GPL");
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");
......@@ -308,10 +308,6 @@ static void *nft_rbtree_deactivate(const struct net *net,
else if (d > 0)
parent = parent->rb_right;
else {
if (!nft_set_elem_active(&rbe->ext, genmask)) {
parent = parent->rb_left;
continue;
}
if (nft_rbtree_interval_end(rbe) &&
!nft_rbtree_interval_end(this)) {
parent = parent->rb_left;
......@@ -320,6 +316,9 @@ static void *nft_rbtree_deactivate(const struct net *net,
nft_rbtree_interval_end(this)) {
parent = parent->rb_right;
continue;
} else if (!nft_set_elem_active(&rbe->ext, genmask)) {
parent = parent->rb_left;
continue;
}
nft_rbtree_flush(net, set, 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