ipv6: fix neighbour resolution with raw socket

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

ipv6: fix neighbour resolution with raw socket

Nicolas Dichtel
Hi Ubuntu kernel team,

please, can you consider to cherry-pick the following linux upstream fixes:
9b1c1ef13b35 ("ipv6: constify rt6_nexthop()")
2c6b55f45d53 ("ipv6: fix neighbour resolution with raw socket")

They have been included in v5.2. The patch that introduces the bug has not been
identified, but the bug is here since a long time (at least v4.4).

Here is the launchpad entry:
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1834465


Thank you,
Nicolas

--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

Re: ipv6: fix neighbour resolution with raw socket

Kamal Mostafa-2
Hi Nicholas-

These cherry-pick cleanly for our Disco 5.0 kernel and I'll submit
them into our pipeline for Disco.

But the second patch doesn't apply to Bionic 4.15 as ip6_dst_neigh_lookup()
is not present.  If you'd like to submit a backport for Bionic 4.15
(and Xenial 4.4?) we would be happy to consider it.

Thanks!

 -Kamal


On Tue, Aug 13, 2019 at 10:53:02AM +0200, Nicolas Dichtel wrote:

> Hi Ubuntu kernel team,
>
> please, can you consider to cherry-pick the following linux upstream fixes:
> 9b1c1ef13b35 ("ipv6: constify rt6_nexthop()")
> 2c6b55f45d53 ("ipv6: fix neighbour resolution with raw socket")
>
> They have been included in v5.2. The patch that introduces the bug has not been
> identified, but the bug is here since a long time (at least v4.4).
>
> Here is the launchpad entry:
> https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1834465
>
>
> Thank you,
> Nicolas
>
> --
> kernel-team mailing list
> [hidden email]
> https://lists.ubuntu.com/mailman/listinfo/kernel-team

--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[SRU][disco][PATCH 1/2] ipv6: constify rt6_nexthop()

Kamal Mostafa-2
In reply to this post by Nicolas Dichtel
From: Nicolas Dichtel <[hidden email]>

BugLink: https://bugs.launchpad.net/bugs/1834465

There is no functional change in this patch, it only prepares the next one.

rt6_nexthop() will be used by ip6_dst_lookup_neigh(), which uses const
variables.

Signed-off-by: Nicolas Dichtel <[hidden email]>
Reported-by: kbuild test robot <[hidden email]>
Acked-by: Nick Desaulniers <[hidden email]>
Signed-off-by: David S. Miller <[hidden email]>
(cherry picked from commit 9b1c1ef13b35fa35051b635ca9fbda39fe6bbc70)
Signed-off-by: Kamal Mostafa <[hidden email]>
---
 drivers/net/vrf.c                | 2 +-
 include/net/ip6_route.h          | 4 ++--
 net/bluetooth/6lowpan.c          | 4 ++--
 net/ipv6/ip6_output.c            | 2 +-
 net/netfilter/nf_flow_table_ip.c | 2 +-
 5 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index b4ac87aa09fd..a2428976c20c 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -366,8 +366,8 @@ static int vrf_finish_output6(struct net *net, struct sock *sk,
 {
  struct dst_entry *dst = skb_dst(skb);
  struct net_device *dev = dst->dev;
+ const struct in6_addr *nexthop;
  struct neighbour *neigh;
- struct in6_addr *nexthop;
  int ret;
 
  nf_reset(skb);
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 7ab119936e69..eecc24cdeb0c 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -261,8 +261,8 @@ static inline bool ip6_sk_ignore_df(const struct sock *sk)
        inet6_sk(sk)->pmtudisc == IPV6_PMTUDISC_OMIT;
 }
 
-static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt,
-   struct in6_addr *daddr)
+static inline const struct in6_addr *rt6_nexthop(const struct rt6_info *rt,
+ const struct in6_addr *daddr)
 {
  if (rt->rt6i_flags & RTF_GATEWAY)
  return &rt->rt6i_gateway;
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index 553dc719afde..798b49640426 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -167,10 +167,10 @@ static inline struct lowpan_peer *peer_lookup_dst(struct lowpan_btle_dev *dev,
   struct in6_addr *daddr,
   struct sk_buff *skb)
 {
- struct lowpan_peer *peer;
- struct in6_addr *nexthop;
  struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
  int count = atomic_read(&dev->peer_count);
+ const struct in6_addr *nexthop;
+ struct lowpan_peer *peer;
 
  BT_DBG("peers %d addr %pI6c rt %p", count, daddr, rt);
 
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 07224c34338b..0efba986e8f4 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -63,8 +63,8 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *
 {
  struct dst_entry *dst = skb_dst(skb);
  struct net_device *dev = dst->dev;
+ const struct in6_addr *nexthop;
  struct neighbour *neigh;
- struct in6_addr *nexthop;
  int ret;
 
  if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)) {
diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
index e7c3daddeffc..1169227934e7 100644
--- a/net/netfilter/nf_flow_table_ip.c
+++ b/net/netfilter/nf_flow_table_ip.c
@@ -441,9 +441,9 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
  struct nf_flowtable *flow_table = priv;
  struct flow_offload_tuple tuple = {};
  enum flow_offload_tuple_dir dir;
+ const struct in6_addr *nexthop;
  struct flow_offload *flow;
  struct net_device *outdev;
- struct in6_addr *nexthop;
  struct ipv6hdr *ip6h;
  struct rt6_info *rt;
 
--
2.17.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[SRU][disco][PATCH 2/2] ipv6: fix neighbour resolution with raw socket

Kamal Mostafa-2
From: Nicolas Dichtel <[hidden email]>

BugLink: https://bugs.launchpad.net/bugs/1834465

The scenario is the following: the user uses a raw socket to send an ipv6
packet, destinated to a not-connected network, and specify a connected nh.
Here is the corresponding python script to reproduce this scenario:

 import socket
 IPPROTO_RAW = 255
 send_s = socket.socket(socket.AF_INET6, socket.SOCK_RAW, IPPROTO_RAW)
 # scapy
 # p = IPv6(src='fd00:100::1', dst='fd00:200::fa')/ICMPv6EchoRequest()
 # str(p)
 req = b'`\x00\x00\x00\x00\x08:@\xfd\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xfd\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfa\x80\x00\x81\xc0\x00\x00\x00\x00'
 send_s.sendto(req, ('fd00:175::2', 0, 0, 0))

fd00:175::/64 is a connected route and fd00:200::fa is not a connected
host.

With this scenario, the kernel starts by sending a NS to resolve
fd00:175::2. When it receives the NA, it flushes its queue and try to send
the initial packet. But instead of sending it, it sends another NS to
resolve fd00:200::fa, which obvioulsy fails, thus the packet is dropped. If
the user sends again the packet, it now uses the right nh (fd00:175::2).

The problem is that ip6_dst_lookup_neigh() uses the rt6i_gateway, which is
:: because the associated route is a connected route, thus it uses the dst
addr of the packet. Let's use rt6_nexthop() to choose the right nh.

Signed-off-by: Nicolas Dichtel <[hidden email]>
Signed-off-by: David S. Miller <[hidden email]>
(cherry picked from commit 2c6b55f45d53420d8310d41310e0e2cd41fe073f)
Signed-off-by: Kamal Mostafa <[hidden email]>
---
 net/ipv6/route.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 0be7158d1816..d00c58ae21fa 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -221,7 +221,8 @@ static struct neighbour *ip6_dst_neigh_lookup(const struct dst_entry *dst,
 {
  const struct rt6_info *rt = container_of(dst, struct rt6_info, dst);
 
- return ip6_neigh_lookup(&rt->rt6i_gateway, dst->dev, skb, daddr);
+ return ip6_neigh_lookup(rt6_nexthop(rt, &in6addr_any),
+ dst->dev, skb, daddr);
 }
 
 static void ip6_confirm_neigh(const struct dst_entry *dst, const void *daddr)
--
2.17.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

ACK/Cmnt: [SRU][disco][PATCH 1/2] ipv6: constify rt6_nexthop()

Stefan Bader-2
In reply to this post by Kamal Mostafa-2
On 26.08.19 19:33, Kamal Mostafa wrote:

> From: Nicolas Dichtel <[hidden email]>
>
> BugLink: https://bugs.launchpad.net/bugs/1834465
>
> There is no functional change in this patch, it only prepares the next one.
>
> rt6_nexthop() will be used by ip6_dst_lookup_neigh(), which uses const
> variables.
>
> Signed-off-by: Nicolas Dichtel <[hidden email]>
> Reported-by: kbuild test robot <[hidden email]>
> Acked-by: Nick Desaulniers <[hidden email]>
> Signed-off-by: David S. Miller <[hidden email]>
> (cherry picked from commit 9b1c1ef13b35fa35051b635ca9fbda39fe6bbc70)
> Signed-off-by: Kamal Mostafa <[hidden email]>
Acked-by: Stefan Bader <[hidden email]>
> ---

In the bug report Nicolas states this would be affecting Xenial, too. Though it
might be much harder. While working on other things I found that there is a
certain difference between ipv6 fixes which went into newer stable and 4.4.y.

Picking into Disco/5.0 looks to be safe enough.

>  drivers/net/vrf.c                | 2 +-
>  include/net/ip6_route.h          | 4 ++--
>  net/bluetooth/6lowpan.c          | 4 ++--
>  net/ipv6/ip6_output.c            | 2 +-
>  net/netfilter/nf_flow_table_ip.c | 2 +-
>  5 files changed, 7 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
> index b4ac87aa09fd..a2428976c20c 100644
> --- a/drivers/net/vrf.c
> +++ b/drivers/net/vrf.c
> @@ -366,8 +366,8 @@ static int vrf_finish_output6(struct net *net, struct sock *sk,
>  {
>   struct dst_entry *dst = skb_dst(skb);
>   struct net_device *dev = dst->dev;
> + const struct in6_addr *nexthop;
>   struct neighbour *neigh;
> - struct in6_addr *nexthop;
>   int ret;
>  
>   nf_reset(skb);
> diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
> index 7ab119936e69..eecc24cdeb0c 100644
> --- a/include/net/ip6_route.h
> +++ b/include/net/ip6_route.h
> @@ -261,8 +261,8 @@ static inline bool ip6_sk_ignore_df(const struct sock *sk)
>         inet6_sk(sk)->pmtudisc == IPV6_PMTUDISC_OMIT;
>  }
>  
> -static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt,
> -   struct in6_addr *daddr)
> +static inline const struct in6_addr *rt6_nexthop(const struct rt6_info *rt,
> + const struct in6_addr *daddr)
>  {
>   if (rt->rt6i_flags & RTF_GATEWAY)
>   return &rt->rt6i_gateway;
> diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
> index 553dc719afde..798b49640426 100644
> --- a/net/bluetooth/6lowpan.c
> +++ b/net/bluetooth/6lowpan.c
> @@ -167,10 +167,10 @@ static inline struct lowpan_peer *peer_lookup_dst(struct lowpan_btle_dev *dev,
>    struct in6_addr *daddr,
>    struct sk_buff *skb)
>  {
> - struct lowpan_peer *peer;
> - struct in6_addr *nexthop;
>   struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
>   int count = atomic_read(&dev->peer_count);
> + const struct in6_addr *nexthop;
> + struct lowpan_peer *peer;
>  
>   BT_DBG("peers %d addr %pI6c rt %p", count, daddr, rt);
>  
> diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
> index 07224c34338b..0efba986e8f4 100644
> --- a/net/ipv6/ip6_output.c
> +++ b/net/ipv6/ip6_output.c
> @@ -63,8 +63,8 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *
>  {
>   struct dst_entry *dst = skb_dst(skb);
>   struct net_device *dev = dst->dev;
> + const struct in6_addr *nexthop;
>   struct neighbour *neigh;
> - struct in6_addr *nexthop;
>   int ret;
>  
>   if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)) {
> diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
> index e7c3daddeffc..1169227934e7 100644
> --- a/net/netfilter/nf_flow_table_ip.c
> +++ b/net/netfilter/nf_flow_table_ip.c
> @@ -441,9 +441,9 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
>   struct nf_flowtable *flow_table = priv;
>   struct flow_offload_tuple tuple = {};
>   enum flow_offload_tuple_dir dir;
> + const struct in6_addr *nexthop;
>   struct flow_offload *flow;
>   struct net_device *outdev;
> - struct in6_addr *nexthop;
>   struct ipv6hdr *ip6h;
>   struct rt6_info *rt;
>  
>


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

ACK: [SRU][disco][PATCH 1/2] ipv6: constify rt6_nexthop()

Kleber Souza
In reply to this post by Kamal Mostafa-2
On 8/26/19 7:33 PM, Kamal Mostafa wrote:

> From: Nicolas Dichtel <[hidden email]>
>
> BugLink: https://bugs.launchpad.net/bugs/1834465
>
> There is no functional change in this patch, it only prepares the next one.
>
> rt6_nexthop() will be used by ip6_dst_lookup_neigh(), which uses const
> variables.
>
> Signed-off-by: Nicolas Dichtel <[hidden email]>
> Reported-by: kbuild test robot <[hidden email]>
> Acked-by: Nick Desaulniers <[hidden email]>
> Signed-off-by: David S. Miller <[hidden email]>
> (cherry picked from commit 9b1c1ef13b35fa35051b635ca9fbda39fe6bbc70)
> Signed-off-by: Kamal Mostafa <[hidden email]>
> ---
>  drivers/net/vrf.c                | 2 +-
>  include/net/ip6_route.h          | 4 ++--
>  net/bluetooth/6lowpan.c          | 4 ++--
>  net/ipv6/ip6_output.c            | 2 +-
>  net/netfilter/nf_flow_table_ip.c | 2 +-
>  5 files changed, 7 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
> index b4ac87aa09fd..a2428976c20c 100644
> --- a/drivers/net/vrf.c
> +++ b/drivers/net/vrf.c
> @@ -366,8 +366,8 @@ static int vrf_finish_output6(struct net *net, struct sock *sk,
>  {
>   struct dst_entry *dst = skb_dst(skb);
>   struct net_device *dev = dst->dev;
> + const struct in6_addr *nexthop;
>   struct neighbour *neigh;
> - struct in6_addr *nexthop;
>   int ret;
>  
>   nf_reset(skb);
> diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
> index 7ab119936e69..eecc24cdeb0c 100644
> --- a/include/net/ip6_route.h
> +++ b/include/net/ip6_route.h
> @@ -261,8 +261,8 @@ static inline bool ip6_sk_ignore_df(const struct sock *sk)
>         inet6_sk(sk)->pmtudisc == IPV6_PMTUDISC_OMIT;
>  }
>  
> -static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt,
> -   struct in6_addr *daddr)
> +static inline const struct in6_addr *rt6_nexthop(const struct rt6_info *rt,
> + const struct in6_addr *daddr)
>  {
>   if (rt->rt6i_flags & RTF_GATEWAY)
>   return &rt->rt6i_gateway;
> diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
> index 553dc719afde..798b49640426 100644
> --- a/net/bluetooth/6lowpan.c
> +++ b/net/bluetooth/6lowpan.c
> @@ -167,10 +167,10 @@ static inline struct lowpan_peer *peer_lookup_dst(struct lowpan_btle_dev *dev,
>    struct in6_addr *daddr,
>    struct sk_buff *skb)
>  {
> - struct lowpan_peer *peer;
> - struct in6_addr *nexthop;
>   struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
>   int count = atomic_read(&dev->peer_count);
> + const struct in6_addr *nexthop;
> + struct lowpan_peer *peer;
>  
>   BT_DBG("peers %d addr %pI6c rt %p", count, daddr, rt);
>  
> diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
> index 07224c34338b..0efba986e8f4 100644
> --- a/net/ipv6/ip6_output.c
> +++ b/net/ipv6/ip6_output.c
> @@ -63,8 +63,8 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *
>  {
>   struct dst_entry *dst = skb_dst(skb);
>   struct net_device *dev = dst->dev;
> + const struct in6_addr *nexthop;
>   struct neighbour *neigh;
> - struct in6_addr *nexthop;
>   int ret;
>  
>   if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)) {
> diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
> index e7c3daddeffc..1169227934e7 100644
> --- a/net/netfilter/nf_flow_table_ip.c
> +++ b/net/netfilter/nf_flow_table_ip.c
> @@ -441,9 +441,9 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
>   struct nf_flowtable *flow_table = priv;
>   struct flow_offload_tuple tuple = {};
>   enum flow_offload_tuple_dir dir;
> + const struct in6_addr *nexthop;
>   struct flow_offload *flow;
>   struct net_device *outdev;
> - struct in6_addr *nexthop;
>   struct ipv6hdr *ip6h;
>   struct rt6_info *rt;
>  
>

For both patches:

Acked-by: Kleber Sacilotto de Souza <[hidden email]>

--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

APPLIED: [SRU][disco][PATCH 1/2] ipv6: constify rt6_nexthop()

Kleber Souza
In reply to this post by Kamal Mostafa-2
On 8/26/19 7:33 PM, Kamal Mostafa wrote:

> From: Nicolas Dichtel <[hidden email]>
>
> BugLink: https://bugs.launchpad.net/bugs/1834465
>
> There is no functional change in this patch, it only prepares the next one.
>
> rt6_nexthop() will be used by ip6_dst_lookup_neigh(), which uses const
> variables.
>
> Signed-off-by: Nicolas Dichtel <[hidden email]>
> Reported-by: kbuild test robot <[hidden email]>
> Acked-by: Nick Desaulniers <[hidden email]>
> Signed-off-by: David S. Miller <[hidden email]>
> (cherry picked from commit 9b1c1ef13b35fa35051b635ca9fbda39fe6bbc70)
> Signed-off-by: Kamal Mostafa <[hidden email]>
> ---
>  drivers/net/vrf.c                | 2 +-
>  include/net/ip6_route.h          | 4 ++--
>  net/bluetooth/6lowpan.c          | 4 ++--
>  net/ipv6/ip6_output.c            | 2 +-
>  net/netfilter/nf_flow_table_ip.c | 2 +-
>  5 files changed, 7 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
> index b4ac87aa09fd..a2428976c20c 100644
> --- a/drivers/net/vrf.c
> +++ b/drivers/net/vrf.c
> @@ -366,8 +366,8 @@ static int vrf_finish_output6(struct net *net, struct sock *sk,
>  {
>   struct dst_entry *dst = skb_dst(skb);
>   struct net_device *dev = dst->dev;
> + const struct in6_addr *nexthop;
>   struct neighbour *neigh;
> - struct in6_addr *nexthop;
>   int ret;
>  
>   nf_reset(skb);
> diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
> index 7ab119936e69..eecc24cdeb0c 100644
> --- a/include/net/ip6_route.h
> +++ b/include/net/ip6_route.h
> @@ -261,8 +261,8 @@ static inline bool ip6_sk_ignore_df(const struct sock *sk)
>         inet6_sk(sk)->pmtudisc == IPV6_PMTUDISC_OMIT;
>  }
>  
> -static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt,
> -   struct in6_addr *daddr)
> +static inline const struct in6_addr *rt6_nexthop(const struct rt6_info *rt,
> + const struct in6_addr *daddr)
>  {
>   if (rt->rt6i_flags & RTF_GATEWAY)
>   return &rt->rt6i_gateway;
> diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
> index 553dc719afde..798b49640426 100644
> --- a/net/bluetooth/6lowpan.c
> +++ b/net/bluetooth/6lowpan.c
> @@ -167,10 +167,10 @@ static inline struct lowpan_peer *peer_lookup_dst(struct lowpan_btle_dev *dev,
>    struct in6_addr *daddr,
>    struct sk_buff *skb)
>  {
> - struct lowpan_peer *peer;
> - struct in6_addr *nexthop;
>   struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
>   int count = atomic_read(&dev->peer_count);
> + const struct in6_addr *nexthop;
> + struct lowpan_peer *peer;
>  
>   BT_DBG("peers %d addr %pI6c rt %p", count, daddr, rt);
>  
> diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
> index 07224c34338b..0efba986e8f4 100644
> --- a/net/ipv6/ip6_output.c
> +++ b/net/ipv6/ip6_output.c
> @@ -63,8 +63,8 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *
>  {
>   struct dst_entry *dst = skb_dst(skb);
>   struct net_device *dev = dst->dev;
> + const struct in6_addr *nexthop;
>   struct neighbour *neigh;
> - struct in6_addr *nexthop;
>   int ret;
>  
>   if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)) {
> diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
> index e7c3daddeffc..1169227934e7 100644
> --- a/net/netfilter/nf_flow_table_ip.c
> +++ b/net/netfilter/nf_flow_table_ip.c
> @@ -441,9 +441,9 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
>   struct nf_flowtable *flow_table = priv;
>   struct flow_offload_tuple tuple = {};
>   enum flow_offload_tuple_dir dir;
> + const struct in6_addr *nexthop;
>   struct flow_offload *flow;
>   struct net_device *outdev;
> - struct in6_addr *nexthop;
>   struct ipv6hdr *ip6h;
>   struct rt6_info *rt;
>  
>

Applied both patches to disco/master-next branch.

Thanks,
Kleber


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[SRU bionic PATCH 1/2] ipv6: constify rt6_nexthop()

Nicolas Dichtel
In reply to this post by Kamal Mostafa-2
BugLink: https://bugs.launchpad.net/bugs/1834465

There is no functional change in this patch, it only prepares the next one.

rt6_nexthop() will be used by ip6_dst_lookup_neigh(), which uses const
variables.

Signed-off-by: Nicolas Dichtel <[hidden email]>
Reported-by: kbuild test robot <[hidden email]>
Acked-by: Nick Desaulniers <[hidden email]>
Signed-off-by: David S. Miller <[hidden email]>
(cherry picked from commit 9b1c1ef13b35fa35051b635ca9fbda39fe6bbc70)
Signed-off-by: Nicolas Dichtel <[hidden email]>
---
 drivers/net/vrf.c       | 2 +-
 include/net/ip6_route.h | 4 ++--
 net/bluetooth/6lowpan.c | 4 ++--
 net/ipv6/ip6_output.c   | 2 +-
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index ac40924fe437..f24f135dd537 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -351,8 +351,8 @@ static int vrf_finish_output6(struct net *net, struct sock *sk,
 {
  struct dst_entry *dst = skb_dst(skb);
  struct net_device *dev = dst->dev;
+ const struct in6_addr *nexthop;
  struct neighbour *neigh;
- struct in6_addr *nexthop;
  int ret;
 
  nf_reset(skb);
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 5c9732fdbecf..ba85be3f4f71 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -242,8 +242,8 @@ static inline bool ip6_sk_ignore_df(const struct sock *sk)
        inet6_sk(sk)->pmtudisc == IPV6_PMTUDISC_OMIT;
 }
 
-static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt,
-   struct in6_addr *daddr)
+static inline const struct in6_addr *rt6_nexthop(const struct rt6_info *rt,
+ const struct in6_addr *daddr)
 {
  if (rt->rt6i_flags & RTF_GATEWAY)
  return &rt->rt6i_gateway;
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index 4e2576fc0c59..a28e3fdb3e5b 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -167,10 +167,10 @@ static inline struct lowpan_peer *peer_lookup_dst(struct lowpan_btle_dev *dev,
   struct in6_addr *daddr,
   struct sk_buff *skb)
 {
- struct lowpan_peer *peer;
- struct in6_addr *nexthop;
  struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
  int count = atomic_read(&dev->peer_count);
+ const struct in6_addr *nexthop;
+ struct lowpan_peer *peer;
 
  BT_DBG("peers %d addr %pI6c rt %p", count, daddr, rt);
 
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 7ca8264cbdf9..11789f2bab90 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -63,8 +63,8 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *
 {
  struct dst_entry *dst = skb_dst(skb);
  struct net_device *dev = dst->dev;
+ const struct in6_addr *nexthop;
  struct neighbour *neigh;
- struct in6_addr *nexthop;
  int ret;
 
  if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)) {
--
2.21.0


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[SRU bionic PATCH 2/2] ipv6: fix neighbour resolution with raw socket

Nicolas Dichtel
BugLink: https://bugs.launchpad.net/bugs/1834465

The scenario is the following: the user uses a raw socket to send an ipv6
packet, destinated to a not-connected network, and specify a connected nh.
Here is the corresponding python script to reproduce this scenario:

 import socket
 IPPROTO_RAW = 255
 send_s = socket.socket(socket.AF_INET6, socket.SOCK_RAW, IPPROTO_RAW)
 # scapy
 # p = IPv6(src='fd00:100::1', dst='fd00:200::fa')/ICMPv6EchoRequest()
 # str(p)
 req = b'`\x00\x00\x00\x00\x08:@\xfd\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xfd\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfa\x80\x00\x81\xc0\x00\x00\x00\x00'
 send_s.sendto(req, ('fd00:175::2', 0, 0, 0))

fd00:175::/64 is a connected route and fd00:200::fa is not a connected
host.

With this scenario, the kernel starts by sending a NS to resolve
fd00:175::2. When it receives the NA, it flushes its queue and try to send
the initial packet. But instead of sending it, it sends another NS to
resolve fd00:200::fa, which obvioulsy fails, thus the packet is dropped. If
the user sends again the packet, it now uses the right nh (fd00:175::2).

The problem is that ip6_dst_lookup_neigh() uses the rt6i_gateway, which is
:: because the associated route is a connected route, thus it uses the dst
addr of the packet. Let's use rt6_nexthop() to choose the right nh.

Signed-off-by: Nicolas Dichtel <[hidden email]>
Signed-off-by: David S. Miller <[hidden email]>
(cherry picked from commit 2c6b55f45d53420d8310d41310e0e2cd41fe073f)

The upstream patch was slightly modified because ip6_dst_lookup_neigh()
does not exist in v4.15. It has been introduced in v4.18 by the upstream
commit f8a1b43b709d ("net/ipv6: Create a neigh_lookup for FIB entries"). In
fact, ip6_dst_lookup_neigh() just calls ip6_neigh_lookup().

Signed-off-by: Nicolas Dichtel <[hidden email]>
---
 net/ipv6/route.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 28d39567c26a..df5cadc6423d 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -201,12 +201,10 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old)
  return dst_cow_metrics_generic(dst, old);
 }
 
-static inline const void *choose_neigh_daddr(struct rt6_info *rt,
+static inline const void *choose_neigh_daddr(const struct in6_addr *p,
      struct sk_buff *skb,
      const void *daddr)
 {
- struct in6_addr *p = &rt->rt6i_gateway;
-
  if (!ipv6_addr_any(p))
  return (const void *) p;
  else if (skb)
@@ -221,7 +219,7 @@ static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst,
  struct rt6_info *rt = (struct rt6_info *) dst;
  struct neighbour *n;
 
- daddr = choose_neigh_daddr(rt, skb, daddr);
+ daddr = choose_neigh_daddr(rt6_nexthop(rt, &in6addr_any), skb, daddr);
  n = __ipv6_neigh_lookup(dst->dev, daddr);
  if (n)
  return n;
@@ -233,7 +231,7 @@ static void ip6_confirm_neigh(const struct dst_entry *dst, const void *daddr)
  struct net_device *dev = dst->dev;
  struct rt6_info *rt = (struct rt6_info *)dst;
 
- daddr = choose_neigh_daddr(rt, NULL, daddr);
+ daddr = choose_neigh_daddr(&rt->rt6i_gateway, NULL, daddr);
  if (!daddr)
  return;
  if (dev->flags & (IFF_NOARP | IFF_LOOPBACK))
--
2.21.0


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team