Merge 3502b1a297
("netfilter: fib: check correct rtable in vrf setups") into android12-5.10-lts
Steps on the way to 5.10.227 Change-Id: I8c942c5c9bd222d1b7b04fdf45f17f1ca0bc5d1c Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
commit
81d8cb7a3e
@ -470,14 +470,13 @@ static netdev_tx_t vrf_process_v6_outbound(struct sk_buff *skb,
|
||||
|
||||
memset(&fl6, 0, sizeof(fl6));
|
||||
/* needed to match OIF rule */
|
||||
fl6.flowi6_oif = dev->ifindex;
|
||||
fl6.flowi6_l3mdev = dev->ifindex;
|
||||
fl6.flowi6_iif = LOOPBACK_IFINDEX;
|
||||
fl6.daddr = iph->daddr;
|
||||
fl6.saddr = iph->saddr;
|
||||
fl6.flowlabel = ip6_flowinfo(iph);
|
||||
fl6.flowi6_mark = skb->mark;
|
||||
fl6.flowi6_proto = iph->nexthdr;
|
||||
fl6.flowi6_flags = FLOWI_FLAG_SKIP_NH_OIF;
|
||||
|
||||
dst = ip6_dst_lookup_flow(net, NULL, &fl6, NULL);
|
||||
if (IS_ERR(dst) || dst == dst_null)
|
||||
@ -550,10 +549,10 @@ static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb,
|
||||
|
||||
memset(&fl4, 0, sizeof(fl4));
|
||||
/* needed to match OIF rule */
|
||||
fl4.flowi4_oif = vrf_dev->ifindex;
|
||||
fl4.flowi4_l3mdev = vrf_dev->ifindex;
|
||||
fl4.flowi4_iif = LOOPBACK_IFINDEX;
|
||||
fl4.flowi4_tos = RT_TOS(ip4h->tos);
|
||||
fl4.flowi4_flags = FLOWI_FLAG_ANYSRC | FLOWI_FLAG_SKIP_NH_OIF;
|
||||
fl4.flowi4_flags = FLOWI_FLAG_ANYSRC;
|
||||
fl4.flowi4_proto = ip4h->protocol;
|
||||
fl4.daddr = ip4h->daddr;
|
||||
fl4.saddr = ip4h->saddr;
|
||||
|
@ -29,6 +29,7 @@ struct flowi_tunnel {
|
||||
struct flowi_common {
|
||||
int flowic_oif;
|
||||
int flowic_iif;
|
||||
int flowic_l3mdev;
|
||||
__u32 flowic_mark;
|
||||
__u8 flowic_tos;
|
||||
__u8 flowic_scope;
|
||||
@ -36,7 +37,6 @@ struct flowi_common {
|
||||
__u8 flowic_flags;
|
||||
#define FLOWI_FLAG_ANYSRC 0x01
|
||||
#define FLOWI_FLAG_KNOWN_NH 0x02
|
||||
#define FLOWI_FLAG_SKIP_NH_OIF 0x04
|
||||
__u32 flowic_secid;
|
||||
kuid_t flowic_uid;
|
||||
struct flowi_tunnel flowic_tun_key;
|
||||
@ -71,6 +71,7 @@ struct flowi4 {
|
||||
struct flowi_common __fl_common;
|
||||
#define flowi4_oif __fl_common.flowic_oif
|
||||
#define flowi4_iif __fl_common.flowic_iif
|
||||
#define flowi4_l3mdev __fl_common.flowic_l3mdev
|
||||
#define flowi4_mark __fl_common.flowic_mark
|
||||
#define flowi4_tos __fl_common.flowic_tos
|
||||
#define flowi4_scope __fl_common.flowic_scope
|
||||
@ -104,6 +105,7 @@ static inline void flowi4_init_output(struct flowi4 *fl4, int oif,
|
||||
{
|
||||
fl4->flowi4_oif = oif;
|
||||
fl4->flowi4_iif = LOOPBACK_IFINDEX;
|
||||
fl4->flowi4_l3mdev = 0;
|
||||
fl4->flowi4_mark = mark;
|
||||
fl4->flowi4_tos = tos;
|
||||
fl4->flowi4_scope = scope;
|
||||
@ -134,6 +136,7 @@ struct flowi6 {
|
||||
struct flowi_common __fl_common;
|
||||
#define flowi6_oif __fl_common.flowic_oif
|
||||
#define flowi6_iif __fl_common.flowic_iif
|
||||
#define flowi6_l3mdev __fl_common.flowic_l3mdev
|
||||
#define flowi6_mark __fl_common.flowic_mark
|
||||
#define flowi6_scope __fl_common.flowic_scope
|
||||
#define flowi6_proto __fl_common.flowic_proto
|
||||
@ -180,6 +183,7 @@ struct flowi {
|
||||
} u;
|
||||
#define flowi_oif u.__fl_common.flowic_oif
|
||||
#define flowi_iif u.__fl_common.flowic_iif
|
||||
#define flowi_l3mdev u.__fl_common.flowic_l3mdev
|
||||
#define flowi_mark u.__fl_common.flowic_mark
|
||||
#define flowi_tos u.__fl_common.flowic_tos
|
||||
#define flowi_scope u.__fl_common.flowic_scope
|
||||
|
@ -290,7 +290,7 @@ __be32 fib_compute_spec_dst(struct sk_buff *skb)
|
||||
bool vmark = in_dev && IN_DEV_SRC_VMARK(in_dev);
|
||||
struct flowi4 fl4 = {
|
||||
.flowi4_iif = LOOPBACK_IFINDEX,
|
||||
.flowi4_oif = l3mdev_master_ifindex_rcu(dev),
|
||||
.flowi4_l3mdev = l3mdev_master_ifindex_rcu(dev),
|
||||
.daddr = ip_hdr(skb)->saddr,
|
||||
.flowi4_tos = ip_hdr(skb)->tos & IPTOS_RT_MASK,
|
||||
.flowi4_scope = scope,
|
||||
@ -352,9 +352,8 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
|
||||
bool dev_match;
|
||||
|
||||
fl4.flowi4_oif = 0;
|
||||
fl4.flowi4_iif = l3mdev_master_ifindex_rcu(dev);
|
||||
if (!fl4.flowi4_iif)
|
||||
fl4.flowi4_iif = oif ? : LOOPBACK_IFINDEX;
|
||||
fl4.flowi4_l3mdev = l3mdev_master_ifindex_rcu(dev);
|
||||
fl4.flowi4_iif = oif ? : LOOPBACK_IFINDEX;
|
||||
fl4.daddr = src;
|
||||
fl4.saddr = dst;
|
||||
fl4.flowi4_tos = tos;
|
||||
|
@ -2267,7 +2267,7 @@ void fib_select_multipath(struct fib_result *res, int hash)
|
||||
void fib_select_path(struct net *net, struct fib_result *res,
|
||||
struct flowi4 *fl4, const struct sk_buff *skb)
|
||||
{
|
||||
if (fl4->flowi4_oif && !(fl4->flowi4_flags & FLOWI_FLAG_SKIP_NH_OIF))
|
||||
if (fl4->flowi4_oif)
|
||||
goto check_saddr;
|
||||
|
||||
#ifdef CONFIG_IP_ROUTE_MULTIPATH
|
||||
|
@ -1384,11 +1384,8 @@ bool fib_lookup_good_nhc(const struct fib_nh_common *nhc, int fib_flags,
|
||||
!(fib_flags & FIB_LOOKUP_IGNORE_LINKSTATE))
|
||||
return false;
|
||||
|
||||
if (!(flp->flowi4_flags & FLOWI_FLAG_SKIP_NH_OIF)) {
|
||||
if (flp->flowi4_oif &&
|
||||
flp->flowi4_oif != nhc->nhc_oif)
|
||||
return false;
|
||||
}
|
||||
if (flp->flowi4_oif && flp->flowi4_oif != nhc->nhc_oif)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -78,7 +78,8 @@ static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
|
||||
flow.flowi4_mark = info->flags & XT_RPFILTER_VALID_MARK ? skb->mark : 0;
|
||||
flow.flowi4_tos = iph->tos & IPTOS_RT_MASK;
|
||||
flow.flowi4_scope = RT_SCOPE_UNIVERSE;
|
||||
flow.flowi4_oif = l3mdev_master_ifindex_rcu(xt_in(par));
|
||||
flow.flowi4_l3mdev = l3mdev_master_ifindex_rcu(xt_in(par));
|
||||
flow.flowi4_uid = sock_net_uid(xt_net(par), NULL);
|
||||
|
||||
return rpfilter_lookup_reverse(xt_net(par), &flow, xt_in(par), info->flags) ^ invert;
|
||||
}
|
||||
|
@ -65,6 +65,8 @@ void nft_fib4_eval(const struct nft_expr *expr, struct nft_regs *regs,
|
||||
struct flowi4 fl4 = {
|
||||
.flowi4_scope = RT_SCOPE_UNIVERSE,
|
||||
.flowi4_iif = LOOPBACK_IFINDEX,
|
||||
.flowi4_uid = sock_net_uid(nft_net(pkt), NULL),
|
||||
.flowi4_l3mdev = l3mdev_master_ifindex_rcu(nft_in(pkt)),
|
||||
};
|
||||
const struct net_device *oif;
|
||||
const struct net_device *found;
|
||||
@ -83,9 +85,6 @@ void nft_fib4_eval(const struct nft_expr *expr, struct nft_regs *regs,
|
||||
else
|
||||
oif = NULL;
|
||||
|
||||
if (priv->flags & NFTA_FIB_F_IIF)
|
||||
fl4.flowi4_oif = l3mdev_master_ifindex_rcu(oif);
|
||||
|
||||
if (nft_hook(pkt) == NF_INET_PRE_ROUTING &&
|
||||
nft_fib_is_loopback(pkt->skb, nft_in(pkt))) {
|
||||
nft_fib_store_result(dest, priv, nft_in(pkt));
|
||||
|
@ -2191,6 +2191,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
|
||||
/*
|
||||
* Now we are ready to route packet.
|
||||
*/
|
||||
fl4.flowi4_l3mdev = 0;
|
||||
fl4.flowi4_oif = 0;
|
||||
fl4.flowi4_iif = dev->ifindex;
|
||||
fl4.flowi4_mark = skb->mark;
|
||||
@ -2663,8 +2664,7 @@ struct rtable *ip_route_output_key_hash_rcu(struct net *net, struct flowi4 *fl4,
|
||||
res->fi = NULL;
|
||||
res->table = NULL;
|
||||
if (fl4->flowi4_oif &&
|
||||
(ipv4_is_multicast(fl4->daddr) ||
|
||||
!netif_index_is_l3_master(net, fl4->flowi4_oif))) {
|
||||
(ipv4_is_multicast(fl4->daddr) || !fl4->flowi4_l3mdev)) {
|
||||
/* Apparently, routing tables are wrong. Assume,
|
||||
that the destination is on link.
|
||||
|
||||
|
@ -28,13 +28,11 @@ static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4,
|
||||
memset(fl4, 0, sizeof(*fl4));
|
||||
fl4->daddr = daddr->a4;
|
||||
fl4->flowi4_tos = tos;
|
||||
fl4->flowi4_oif = l3mdev_master_ifindex_by_index(net, oif);
|
||||
fl4->flowi4_l3mdev = l3mdev_master_ifindex_by_index(net, oif);
|
||||
fl4->flowi4_mark = mark;
|
||||
if (saddr)
|
||||
fl4->saddr = saddr->a4;
|
||||
|
||||
fl4->flowi4_flags = FLOWI_FLAG_SKIP_NH_OIF;
|
||||
|
||||
rt = __ip_route_output_key(net, fl4);
|
||||
if (!IS_ERR(rt))
|
||||
return &rt->dst;
|
||||
|
@ -1067,8 +1067,7 @@ static struct dst_entry *ip6_sk_dst_check(struct sock *sk,
|
||||
#ifdef CONFIG_IPV6_SUBTREES
|
||||
ip6_rt_check(&rt->rt6i_src, &fl6->saddr, np->saddr_cache) ||
|
||||
#endif
|
||||
(!(fl6->flowi6_flags & FLOWI_FLAG_SKIP_NH_OIF) &&
|
||||
(fl6->flowi6_oif && fl6->flowi6_oif != dst->dev->ifindex))) {
|
||||
(fl6->flowi6_oif && fl6->flowi6_oif != dst->dev->ifindex)) {
|
||||
dst_release(dst);
|
||||
dst = NULL;
|
||||
}
|
||||
|
@ -37,8 +37,10 @@ static bool rpfilter_lookup_reverse6(struct net *net, const struct sk_buff *skb,
|
||||
bool ret = false;
|
||||
struct flowi6 fl6 = {
|
||||
.flowi6_iif = LOOPBACK_IFINDEX,
|
||||
.flowi6_l3mdev = l3mdev_master_ifindex_rcu(dev),
|
||||
.flowlabel = (* (__be32 *) iph) & IPV6_FLOWINFO_MASK,
|
||||
.flowi6_proto = iph->nexthdr,
|
||||
.flowi6_uid = sock_net_uid(net, NULL),
|
||||
.daddr = iph->saddr,
|
||||
};
|
||||
int lookup_flags;
|
||||
@ -55,9 +57,7 @@ static bool rpfilter_lookup_reverse6(struct net *net, const struct sk_buff *skb,
|
||||
if (rpfilter_addr_linklocal(&iph->saddr)) {
|
||||
lookup_flags |= RT6_LOOKUP_F_IFACE;
|
||||
fl6.flowi6_oif = dev->ifindex;
|
||||
/* Set flowi6_oif for vrf devices to lookup route in l3mdev domain. */
|
||||
} else if (netif_is_l3_master(dev) || netif_is_l3_slave(dev) ||
|
||||
(flags & XT_RPFILTER_LOOSE) == 0)
|
||||
} else if ((flags & XT_RPFILTER_LOOSE) == 0)
|
||||
fl6.flowi6_oif = dev->ifindex;
|
||||
|
||||
rt = (void *)ip6_route_lookup(net, &fl6, skb, lookup_flags);
|
||||
@ -72,9 +72,7 @@ static bool rpfilter_lookup_reverse6(struct net *net, const struct sk_buff *skb,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (rt->rt6i_idev->dev == dev ||
|
||||
l3mdev_master_ifindex_rcu(rt->rt6i_idev->dev) == dev->ifindex ||
|
||||
(flags & XT_RPFILTER_LOOSE))
|
||||
if (rt->rt6i_idev->dev == dev || (flags & XT_RPFILTER_LOOSE))
|
||||
ret = true;
|
||||
out:
|
||||
ip6_rt_put(rt);
|
||||
|
@ -37,9 +37,6 @@ static int nft_fib6_flowi_init(struct flowi6 *fl6, const struct nft_fib *priv,
|
||||
if (ipv6_addr_type(&fl6->daddr) & IPV6_ADDR_LINKLOCAL) {
|
||||
lookup_flags |= RT6_LOOKUP_F_IFACE;
|
||||
fl6->flowi6_oif = get_ifindex(dev ? dev : pkt->skb->dev);
|
||||
} else if ((priv->flags & NFTA_FIB_F_IIF) &&
|
||||
(netif_is_l3_master(dev) || netif_is_l3_slave(dev))) {
|
||||
fl6->flowi6_oif = dev->ifindex;
|
||||
}
|
||||
|
||||
if (ipv6_addr_type(&fl6->saddr) & IPV6_ADDR_UNICAST)
|
||||
@ -63,6 +60,7 @@ static u32 __nft_fib6_eval_type(const struct nft_fib *priv,
|
||||
struct flowi6 fl6 = {
|
||||
.flowi6_iif = LOOPBACK_IFINDEX,
|
||||
.flowi6_proto = pkt->tprot,
|
||||
.flowi6_uid = sock_net_uid(nft_net(pkt), NULL),
|
||||
};
|
||||
u32 ret = 0;
|
||||
|
||||
@ -71,6 +69,8 @@ static u32 __nft_fib6_eval_type(const struct nft_fib *priv,
|
||||
else if (priv->flags & NFTA_FIB_F_OIF)
|
||||
dev = nft_out(pkt);
|
||||
|
||||
fl6.flowi6_l3mdev = l3mdev_master_ifindex_rcu(dev);
|
||||
|
||||
nft_fib6_flowi_init(&fl6, priv, pkt, dev, iph);
|
||||
|
||||
if (dev && nf_ipv6_chk_addr(nft_net(pkt), &fl6.daddr, dev, true))
|
||||
@ -160,6 +160,8 @@ void nft_fib6_eval(const struct nft_expr *expr, struct nft_regs *regs,
|
||||
struct flowi6 fl6 = {
|
||||
.flowi6_iif = LOOPBACK_IFINDEX,
|
||||
.flowi6_proto = pkt->tprot,
|
||||
.flowi6_uid = sock_net_uid(nft_net(pkt), NULL),
|
||||
.flowi6_l3mdev = l3mdev_master_ifindex_rcu(nft_in(pkt)),
|
||||
};
|
||||
struct rt6_info *rt;
|
||||
int lookup_flags;
|
||||
|
@ -1207,9 +1207,6 @@ INDIRECT_CALLABLE_SCOPE struct rt6_info *ip6_pol_route_lookup(struct net *net,
|
||||
struct fib6_node *fn;
|
||||
struct rt6_info *rt;
|
||||
|
||||
if (fl6->flowi6_flags & FLOWI_FLAG_SKIP_NH_OIF)
|
||||
flags &= ~RT6_LOOKUP_F_IFACE;
|
||||
|
||||
rcu_read_lock();
|
||||
fn = fib6_node_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
|
||||
restart:
|
||||
@ -2183,9 +2180,6 @@ int fib6_table_lookup(struct net *net, struct fib6_table *table, int oif,
|
||||
fn = fib6_node_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
|
||||
saved_fn = fn;
|
||||
|
||||
if (fl6->flowi6_flags & FLOWI_FLAG_SKIP_NH_OIF)
|
||||
oif = 0;
|
||||
|
||||
redo_rt6_select:
|
||||
rt6_select(net, fn, oif, res, strict);
|
||||
if (res->f6i == net->ipv6.fib6_null_entry) {
|
||||
@ -2932,12 +2926,6 @@ INDIRECT_CALLABLE_SCOPE struct rt6_info *__ip6_route_redirect(struct net *net,
|
||||
struct fib6_info *rt;
|
||||
struct fib6_node *fn;
|
||||
|
||||
/* l3mdev_update_flow overrides oif if the device is enslaved; in
|
||||
* this case we must match on the real ingress device, so reset it
|
||||
*/
|
||||
if (fl6->flowi6_flags & FLOWI_FLAG_SKIP_NH_OIF)
|
||||
fl6->flowi6_oif = skb->dev->ifindex;
|
||||
|
||||
/* Get the "current" route for this destination and
|
||||
* check if the redirect has come from appropriate router.
|
||||
*
|
||||
|
@ -33,8 +33,7 @@ static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos, int oif,
|
||||
int err;
|
||||
|
||||
memset(&fl6, 0, sizeof(fl6));
|
||||
fl6.flowi6_oif = l3mdev_master_ifindex_by_index(net, oif);
|
||||
fl6.flowi6_flags = FLOWI_FLAG_SKIP_NH_OIF;
|
||||
fl6.flowi6_l3mdev = l3mdev_master_ifindex_by_index(net, oif);
|
||||
fl6.flowi6_mark = mark;
|
||||
memcpy(&fl6.daddr, daddr, sizeof(fl6.daddr));
|
||||
if (saddr)
|
||||
|
@ -249,25 +249,19 @@ int l3mdev_fib_rule_match(struct net *net, struct flowi *fl,
|
||||
struct net_device *dev;
|
||||
int rc = 0;
|
||||
|
||||
/* update flow ensures flowi_l3mdev is set when relevant */
|
||||
if (!fl->flowi_l3mdev)
|
||||
return 0;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
dev = dev_get_by_index_rcu(net, fl->flowi_oif);
|
||||
dev = dev_get_by_index_rcu(net, fl->flowi_l3mdev);
|
||||
if (dev && netif_is_l3_master(dev) &&
|
||||
dev->l3mdev_ops->l3mdev_fib_table) {
|
||||
arg->table = dev->l3mdev_ops->l3mdev_fib_table(dev);
|
||||
rc = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev = dev_get_by_index_rcu(net, fl->flowi_iif);
|
||||
if (dev && netif_is_l3_master(dev) &&
|
||||
dev->l3mdev_ops->l3mdev_fib_table) {
|
||||
arg->table = dev->l3mdev_ops->l3mdev_fib_table(dev);
|
||||
rc = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
|
||||
return rc;
|
||||
@ -276,31 +270,28 @@ int l3mdev_fib_rule_match(struct net *net, struct flowi *fl,
|
||||
void l3mdev_update_flow(struct net *net, struct flowi *fl)
|
||||
{
|
||||
struct net_device *dev;
|
||||
int ifindex;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
if (fl->flowi_oif) {
|
||||
dev = dev_get_by_index_rcu(net, fl->flowi_oif);
|
||||
if (dev) {
|
||||
ifindex = l3mdev_master_ifindex_rcu(dev);
|
||||
if (ifindex) {
|
||||
fl->flowi_oif = ifindex;
|
||||
fl->flowi_flags |= FLOWI_FLAG_SKIP_NH_OIF;
|
||||
goto out;
|
||||
}
|
||||
if (!fl->flowi_l3mdev)
|
||||
fl->flowi_l3mdev = l3mdev_master_ifindex_rcu(dev);
|
||||
|
||||
/* oif set to L3mdev directs lookup to its table;
|
||||
* reset to avoid oif match in fib_lookup
|
||||
*/
|
||||
if (netif_is_l3_master(dev))
|
||||
fl->flowi_oif = 0;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (fl->flowi_iif) {
|
||||
if (fl->flowi_iif > LOOPBACK_IFINDEX && !fl->flowi_l3mdev) {
|
||||
dev = dev_get_by_index_rcu(net, fl->flowi_iif);
|
||||
if (dev) {
|
||||
ifindex = l3mdev_master_ifindex_rcu(dev);
|
||||
if (ifindex) {
|
||||
fl->flowi_iif = ifindex;
|
||||
fl->flowi_flags |= FLOWI_FLAG_SKIP_NH_OIF;
|
||||
}
|
||||
}
|
||||
if (dev)
|
||||
fl->flowi_l3mdev = l3mdev_master_ifindex_rcu(dev);
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -741,7 +741,7 @@ ipv4_ping_vrf()
|
||||
log_start
|
||||
show_hint "Fails since address on vrf device is out of device scope"
|
||||
run_cmd ping -c1 -w1 -I ${NSA_DEV} ${a}
|
||||
log_test_addr ${a} $? 1 "ping local, device bind"
|
||||
log_test_addr ${a} $? 2 "ping local, device bind"
|
||||
done
|
||||
|
||||
#
|
||||
|
Loading…
Reference in New Issue
Block a user