[PATCH net,v2] vrf: check forwarding on the original netdevice when generating ICMP dest unreachable

Subsystems: networking [general], networking [ipv4/ipv6], the rest

STALE3113d

4 messages, 2 authors, 2018-02-28 · open the first message on its own page

[PATCH net,v2] vrf: check forwarding on the original netdevice when generating ICMP dest unreachable

From: Stephen Suryaputra <hidden>
Date: 2018-02-28 14:47:08

When ip_error() is called the device is the l3mdev master instead of the
original device. So the forwarding check should be on the original one.

Changes from v1:
- Only need to reset the device on which __in_dev_get_rcu() is done (per
  David Ahern).

Signed-off-by: Stephen Suryaputra <redacted>
---
 net/ipv4/route.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index a4f44d8..89c020f 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -930,19 +930,26 @@ void ip_rt_send_redirect(struct sk_buff *skb)
 
 static int ip_error(struct sk_buff *skb)
 {
-	struct in_device *in_dev = __in_dev_get_rcu(skb->dev);
 	struct rtable *rt = skb_rtable(skb);
+	struct net_device *dev = skb->dev;
+	struct in_device *in_dev;
 	struct inet_peer *peer;
 	unsigned long now;
 	struct net *net;
 	bool send;
 	int code;
 
+	net = dev_net(rt->dst.dev);
+
+	if (netif_is_l3_master(skb->dev))
+		dev = __dev_get_by_index(net, IPCB(skb)->iif);
+
+	in_dev = __in_dev_get_rcu(dev);
+
 	/* IP on this device is disabled. */
 	if (!in_dev)
 		goto out;
 
-	net = dev_net(rt->dst.dev);
 	if (!IN_DEV_FORWARD(in_dev)) {
 		switch (rt->dst.error) {
 		case EHOSTUNREACH:
-- 
2.7.4

Re: [PATCH net,v2] vrf: check forwarding on the original netdevice when generating ICMP dest unreachable

From: David Ahern <hidden>
Date: 2018-02-28 15:49:27

On 2/28/18 7:46 AM, Stephen Suryaputra wrote:
quoted hunk
When ip_error() is called the device is the l3mdev master instead of the
original device. So the forwarding check should be on the original one.

Changes from v1:
- Only need to reset the device on which __in_dev_get_rcu() is done (per
  David Ahern).

Signed-off-by: Stephen Suryaputra <redacted>
---
 net/ipv4/route.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index a4f44d8..89c020f 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -930,19 +930,26 @@ void ip_rt_send_redirect(struct sk_buff *skb)
 
 static int ip_error(struct sk_buff *skb)
 {
-	struct in_device *in_dev = __in_dev_get_rcu(skb->dev);
 	struct rtable *rt = skb_rtable(skb);
+	struct net_device *dev = skb->dev;
+	struct in_device *in_dev;
 	struct inet_peer *peer;
 	unsigned long now;
 	struct net *net;
 	bool send;
 	int code;
 
+	net = dev_net(rt->dst.dev);
+
+	if (netif_is_l3_master(skb->dev))
+		dev = __dev_get_by_index(net, IPCB(skb)->iif);
Do need to handle the device disappearing.
if (!dev)
	goto out;
+
+	in_dev = __in_dev_get_rcu(dev);
+
 	/* IP on this device is disabled. */
 	if (!in_dev)
 		goto out;
 
-	net = dev_net(rt->dst.dev);
 	if (!IN_DEV_FORWARD(in_dev)) {
 		switch (rt->dst.error) {
 		case EHOSTUNREACH:

Re: [PATCH net,v2] vrf: check forwarding on the original netdevice when generating ICMP dest unreachable

From: Stephen Suryaputra <hidden>
Date: 2018-02-28 16:55:16

The concern only applies when the skb->dev is an l3mdev master, right?
After I sent v2, I'm worried that rt shouldn't be derefrenced if
in_dev is NULL. Even though I think it should be ok, it's better to
keep the original execution order. So, how about this before I put
another patch? The net for the iif is derived from skb->dev.
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index a4f44d8..9a29225 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -930,14 +930,23 @@ void ip_rt_send_redirect(struct sk_buff *skb)

 static int ip_error(struct sk_buff *skb)
 {
-       struct in_device *in_dev = __in_dev_get_rcu(skb->dev);
        struct rtable *rt = skb_rtable(skb);
+       struct net_device *dev = skb->dev;
+       struct in_device *in_dev;
        struct inet_peer *peer;
        unsigned long now;
        struct net *net;
        bool send;
        int code;

+       if (netif_is_l3_master(skb->dev)) {
+               dev = __dev_get_by_index(dev_net(skb->dev), IPCB(skb)->iif);
+               if (!dev)
+                       goto out;
+       }
+
+       in_dev = __in_dev_get_rcu(dev);
+
        /* IP on this device is disabled. */
        if (!in_dev)
                goto out;

On Wed, Feb 28, 2018 at 10:49 AM, David Ahern [off-list ref] wrote:
On 2/28/18 7:46 AM, Stephen Suryaputra wrote:
quoted
When ip_error() is called the device is the l3mdev master instead of the
original device. So the forwarding check should be on the original one.

Changes from v1:
- Only need to reset the device on which __in_dev_get_rcu() is done (per
  David Ahern).

Signed-off-by: Stephen Suryaputra <redacted>
---
 net/ipv4/route.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index a4f44d8..89c020f 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -930,19 +930,26 @@ void ip_rt_send_redirect(struct sk_buff *skb)

 static int ip_error(struct sk_buff *skb)
 {
-     struct in_device *in_dev = __in_dev_get_rcu(skb->dev);
      struct rtable *rt = skb_rtable(skb);
+     struct net_device *dev = skb->dev;
+     struct in_device *in_dev;
      struct inet_peer *peer;
      unsigned long now;
      struct net *net;
      bool send;
      int code;

+     net = dev_net(rt->dst.dev);
+
+     if (netif_is_l3_master(skb->dev))
+             dev = __dev_get_by_index(net, IPCB(skb)->iif);
Do need to handle the device disappearing.
if (!dev)
        goto out;
quoted
+
+     in_dev = __in_dev_get_rcu(dev);
+
      /* IP on this device is disabled. */
      if (!in_dev)
              goto out;

-     net = dev_net(rt->dst.dev);
      if (!IN_DEV_FORWARD(in_dev)) {
              switch (rt->dst.error) {
              case EHOSTUNREACH:

Re: [PATCH net,v2] vrf: check forwarding on the original netdevice when generating ICMP dest unreachable

From: David Ahern <hidden>
Date: 2018-02-28 17:39:51

On 2/28/18 9:55 AM, Stephen Suryaputra wrote:
quoted hunk
The concern only applies when the skb->dev is an l3mdev master, right?
After I sent v2, I'm worried that rt shouldn't be derefrenced if
in_dev is NULL. Even though I think it should be ok, it's better to
keep the original execution order. So, how about this before I put
another patch? The net for the iif is derived from skb->dev.
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index a4f44d8..9a29225 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -930,14 +930,23 @@ void ip_rt_send_redirect(struct sk_buff *skb)

 static int ip_error(struct sk_buff *skb)
 {
-       struct in_device *in_dev = __in_dev_get_rcu(skb->dev);
        struct rtable *rt = skb_rtable(skb);
+       struct net_device *dev = skb->dev;
+       struct in_device *in_dev;
        struct inet_peer *peer;
        unsigned long now;
        struct net *net;
        bool send;
        int code;

+       if (netif_is_l3_master(skb->dev)) {
+               dev = __dev_get_by_index(dev_net(skb->dev), IPCB(skb)->iif);
+               if (!dev)
+                       goto out;
+       }
+
+       in_dev = __in_dev_get_rcu(dev);
+
        /* IP on this device is disabled. */
        if (!in_dev)
                goto out;
Using dev_net from skb is fine, preferable really since the real ingress
device and the VRF device have to be in the same network namespace.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help