linux-user: convert sockaddr_ll from host to target
diff mbox

Message ID 1466979502-7589-1-git-send-email-laurent@vivier.eu
State New
Headers show

Commit Message

Laurent Vivier June 26, 2016, 10:18 p.m. UTC
As we convert sockaddr for AF_PACKET family for sendto() (target to
host) we need also to convert this for getsockname() (host to target).

arping uses getsockname() to get the the interface address and uses
this address with sendto().

Tested with:

    /sbin/arping -D -q -c2 -I eno1 192.168.122.88

...
getsockname(3, {sa_family=AF_PACKET, proto=0x806, if2,
pkttype=PACKET_HOST, addr(6)={1, 10c37b6b9a76}, [18]) = 0
...
sendto(3, "..." 28, 0,
       {sa_family=AF_PACKET, proto=0x806, if2, pkttype=PACKET_HOST,
       addr(6)={1, ffffffffffff}, 20) = 28
...

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 linux-user/syscall.c | 5 +++++
 1 file changed, 5 insertions(+)

Comments

Peter Maydell June 27, 2016, 1:09 p.m. UTC | #1
On 26 June 2016 at 23:18, Laurent Vivier <laurent@vivier.eu> wrote:
> As we convert sockaddr for AF_PACKET family for sendto() (target to
> host) we need also to convert this for getsockname() (host to target).
>
> arping uses getsockname() to get the the interface address and uses
> this address with sendto().
>
> Tested with:
>
>     /sbin/arping -D -q -c2 -I eno1 192.168.122.88
>
> ...
> getsockname(3, {sa_family=AF_PACKET, proto=0x806, if2,
> pkttype=PACKET_HOST, addr(6)={1, 10c37b6b9a76}, [18]) = 0
> ...
> sendto(3, "..." 28, 0,
>        {sa_family=AF_PACKET, proto=0x806, if2, pkttype=PACKET_HOST,
>        addr(6)={1, ffffffffffff}, 20) = 28
> ...
>
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  linux-user/syscall.c | 5 +++++
>  1 file changed, 5 insertions(+)
>
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 731926d..599b946 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -100,6 +100,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
>  #include <linux/route.h>
>  #include <linux/filter.h>
>  #include <linux/blkpg.h>
> +#include <netpacket/packet.h>

Do we need the new include? We already use struct sockaddr_ll
without it.

>  #include <linux/netlink.h>
>  #ifdef CONFIG_RTNETLINK
>  #include <linux/rtnetlink.h>
> @@ -1379,6 +1380,10 @@ static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
>          struct sockaddr_nl *target_nl = (struct sockaddr_nl *)target_saddr;
>          target_nl->nl_pid = tswap32(target_nl->nl_pid);
>          target_nl->nl_groups = tswap32(target_nl->nl_groups);
> +    } else if (addr->sa_family == AF_PACKET) {
> +        struct sockaddr_ll *target_ll = (struct sockaddr_ll *)target_saddr;
> +        target_ll->sll_ifindex = tswap32(target_ll->sll_ifindex);
> +        target_ll->sll_hatype = tswap16(target_ll->sll_hatype);
>      }
>      unlock_user(target_saddr, target_addr, len);

Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM
Laurent Vivier June 27, 2016, 1:12 p.m. UTC | #2
Le 27/06/2016 à 15:09, Peter Maydell a écrit :
> On 26 June 2016 at 23:18, Laurent Vivier <laurent@vivier.eu> wrote:
>> As we convert sockaddr for AF_PACKET family for sendto() (target to
>> host) we need also to convert this for getsockname() (host to target).
>>
>> arping uses getsockname() to get the the interface address and uses
>> this address with sendto().
>>
>> Tested with:
>>
>>     /sbin/arping -D -q -c2 -I eno1 192.168.122.88
>>
>> ...
>> getsockname(3, {sa_family=AF_PACKET, proto=0x806, if2,
>> pkttype=PACKET_HOST, addr(6)={1, 10c37b6b9a76}, [18]) = 0
>> ...
>> sendto(3, "..." 28, 0,
>>        {sa_family=AF_PACKET, proto=0x806, if2, pkttype=PACKET_HOST,
>>        addr(6)={1, ffffffffffff}, 20) = 28
>> ...
>>
>> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
>> ---
>>  linux-user/syscall.c | 5 +++++
>>  1 file changed, 5 insertions(+)
>>
>> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
>> index 731926d..599b946 100644
>> --- a/linux-user/syscall.c
>> +++ b/linux-user/syscall.c
>> @@ -100,6 +100,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
>>  #include <linux/route.h>
>>  #include <linux/filter.h>
>>  #include <linux/blkpg.h>
>> +#include <netpacket/packet.h>
> 
> Do we need the new include? We already use struct sockaddr_ll
> without it.

we already use target_sockaddr_ll, not sockaddr_ll.

> 
>>  #include <linux/netlink.h>
>>  #ifdef CONFIG_RTNETLINK
>>  #include <linux/rtnetlink.h>
>> @@ -1379,6 +1380,10 @@ static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
>>          struct sockaddr_nl *target_nl = (struct sockaddr_nl *)target_saddr;
>>          target_nl->nl_pid = tswap32(target_nl->nl_pid);
>>          target_nl->nl_groups = tswap32(target_nl->nl_groups);
>> +    } else if (addr->sa_family == AF_PACKET) {
>> +        struct sockaddr_ll *target_ll = (struct sockaddr_ll *)target_saddr;
>> +        target_ll->sll_ifindex = tswap32(target_ll->sll_ifindex);
>> +        target_ll->sll_hatype = tswap16(target_ll->sll_hatype);
>>      }
>>      unlock_user(target_saddr, target_addr, len);
> 
> Otherwise
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

Thanks,
Laurent
Peter Maydell June 27, 2016, 1:20 p.m. UTC | #3
On 27 June 2016 at 14:12, Laurent Vivier <laurent@vivier.eu> wrote:
>
>
> Le 27/06/2016 à 15:09, Peter Maydell a écrit :
>> Do we need the new include? We already use struct sockaddr_ll
>> without it.
>
> we already use target_sockaddr_ll, not sockaddr_ll.

Oh yes; I got confused with sockaddr_nl I think.

thanks
-- PMM
Laurent Vivier June 29, 2016, 12:23 p.m. UTC | #4
Le 27/06/2016 à 00:18, Laurent Vivier a écrit :
> As we convert sockaddr for AF_PACKET family for sendto() (target to
> host) we need also to convert this for getsockname() (host to target).
> 
> arping uses getsockname() to get the the interface address and uses
> this address with sendto().
> 
> Tested with:
> 
>     /sbin/arping -D -q -c2 -I eno1 192.168.122.88
> 
> ...
> getsockname(3, {sa_family=AF_PACKET, proto=0x806, if2,
> pkttype=PACKET_HOST, addr(6)={1, 10c37b6b9a76}, [18]) = 0
> ...
> sendto(3, "..." 28, 0,
>        {sa_family=AF_PACKET, proto=0x806, if2, pkttype=PACKET_HOST,
>        addr(6)={1, ffffffffffff}, 20) = 28
> ...
> 
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  linux-user/syscall.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 731926d..599b946 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -100,6 +100,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
>  #include <linux/route.h>
>  #include <linux/filter.h>
>  #include <linux/blkpg.h>
> +#include <netpacket/packet.h>
>  #include <linux/netlink.h>
>  #ifdef CONFIG_RTNETLINK
>  #include <linux/rtnetlink.h>
> @@ -1379,6 +1380,10 @@ static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
>          struct sockaddr_nl *target_nl = (struct sockaddr_nl *)target_saddr;
>          target_nl->nl_pid = tswap32(target_nl->nl_pid);
>          target_nl->nl_groups = tswap32(target_nl->nl_groups);
> +    } else if (addr->sa_family == AF_PACKET) {
> +        struct sockaddr_ll *target_ll = (struct sockaddr_ll *)target_saddr;
> +        target_ll->sll_ifindex = tswap32(target_ll->sll_ifindex);
> +        target_ll->sll_hatype = tswap16(target_ll->sll_hatype);
>      }
>      unlock_user(target_saddr, target_addr, len);
>  
> 

It would be good to have this patch in 2.7 as this bug breaks dhclient:
dhclient uses arping to check the IP address is not already in use and
then hangs. I've seen that, at least, in a fedora21 + qemu-ppc64 container.

Thanks,
Laurent

Patch
diff mbox

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 731926d..599b946 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -100,6 +100,7 @@  int __clone2(int (*fn)(void *), void *child_stack_base,
 #include <linux/route.h>
 #include <linux/filter.h>
 #include <linux/blkpg.h>
+#include <netpacket/packet.h>
 #include <linux/netlink.h>
 #ifdef CONFIG_RTNETLINK
 #include <linux/rtnetlink.h>
@@ -1379,6 +1380,10 @@  static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
         struct sockaddr_nl *target_nl = (struct sockaddr_nl *)target_saddr;
         target_nl->nl_pid = tswap32(target_nl->nl_pid);
         target_nl->nl_groups = tswap32(target_nl->nl_groups);
+    } else if (addr->sa_family == AF_PACKET) {
+        struct sockaddr_ll *target_ll = (struct sockaddr_ll *)target_saddr;
+        target_ll->sll_ifindex = tswap32(target_ll->sll_ifindex);
+        target_ll->sll_hatype = tswap16(target_ll->sll_hatype);
     }
     unlock_user(target_saddr, target_addr, len);