slirp: fix ICMP handling on macOS hosts
PATCH 1/1 slirp: fix ICMP handling on macOS hosts
From: Andrew Oates <[email protected]>
On Linux, SOCK_DGRAM+IPPROTO_ICMP sockets give only the ICMP packet when read from. On macOS, however, the socket acts like a SOCK_RAW socket and includes the IP header as well.
This change strips the extra IP header from the received packet on macOS before sending it to the guest.
--- slirp/ip_icmp.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
slirp/ip_icmp.c +9 -1
@@ -420,7 +420,15 @@ void icmp_receive(struct socket *so) icp = mtod(m, struct icmp *); id = icp->icmp_id; - len =qemu_recv (so->s, icp, m->m_len,0 ); + len =qemu_recv (so->s, icp,M_ROOM (m),0 ); +#ifdef CONFIG_DARWIN +if (len >0 ) { +/* Skip the IP header that OS X (unlike Linux) includes. */ + struct ip *inner_ip = mtod(m, struct ip *); +int inner_hlen = inner_ip->ip_hl <<2 ; +memmove (icp, (unsigned char *)icp + inner_hlen, len - inner_hlen); + } +#endif icp->icmp_id = id; m->m_data -= hlen;
Signature · 1 line
2.17.0
Hello,
[email protected], le mer. 25 juil. 2018 21:08:12 -0400, a ecrit:
Quoted 20 lines
From: Andrew Oates <[email protected]>
On Linux, SOCK_DGRAM+IPPROTO_ICMP sockets give only the ICMP packet when read from. On macOS, however, the socket acts like a
SOCK_RAWsocket and includes the IP header as well.This change strips the extra IP header from the received packet on macOS before sending it to the guest.
Signed-off-by Andrew Oates <[email protected]>--- slirp/ip_icmp.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)slirp/ip_icmp.c +0
-0@@ -420,7 +420,15 @@ void icmp_receive(struct socket *so) icp = mtod(m, struct icmp *);
slirp/ip_icmp.c void icmp_receive(struct socket *so) · line 429
Quoted 10 lines
slirp/ip_icmp.c +7
-1id = icp->icmp_id; - len =qemu_recv (so->s, icp, m->m_len,0 ); + len =qemu_recv (so->s, icp,M_ROOM (m),0 ); +#ifdef CONFIG_DARWIN +if (len >0 ) { +/* Skip the IP header that OS X (unlike Linux) includes. */ + struct ip *inner_ip = mtod(m, struct ip *); +int inner_hlen = inner_ip->ip_hl <<2 ; +memmove (icp, (unsigned char *)icp + inner_hlen, len - inner_hlen);
Please also check that the provided inner_hlen is not bigger than len. (otherwise it'd be a security issue). Also, substract inner_len from len for coherency. In case inner_len is bigger than len, you'd set len to -1 and set errno to EINVAL, handled below.
Thanks,
Samuel
Quoted 35 lines · On Sat, Jul 28, 2018, 13:53 Samuel Thibault <[email protected]> wrote:
Hello,
[email protected], le mer. 25 juil. 2018 21:08:12 -0400, a ecrit:
Quoted 20 lines
From: Andrew Oates <[email protected]>
On Linux, SOCK_DGRAM+IPPROTO_ICMP sockets give only the ICMP packet when read from. On macOS, however, the socket acts like a
SOCK_RAWsocket and includes the IP header as well.This change strips the extra IP header from the received packet on macOS before sending it to the guest.
Signed-off-by Andrew Oates <[email protected]>--- slirp/ip_icmp.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)slirp/ip_icmp.c +0
-0@@ -420,7 +420,15 @@ void icmp_receive(struct socket *so) icp = mtod(m, struct icmp *);slirp/ip_icmp.c void icmp_receive(struct socket *so) · line 429
Quoted 10 lines
slirp/ip_icmp.c +7
-1id = icp->icmp_id; - len =qemu_recv (so->s, icp, m->m_len,0 ); + len =qemu_recv (so->s, icp,M_ROOM (m),0 ); +#ifdef CONFIG_DARWIN +if (len >0 ) { +/* Skip the IP header that OS X (unlike Linux) includes. */ + struct ip *inner_ip = mtod(m, struct ip *); +int inner_hlen = inner_ip->ip_hl <<2 ; + memmove(icp, (unsigned char *)icp + inner_hlen, len -
inner_hlen);
Quoted 5 lines
Please also check that the provided
inner_hlenis not bigger than len. (otherwise it'd be a security issue). Also, substractinner_lenfrom len for coherency. In caseinner_lenis bigger than len, you'd set len to -1 and set errno to EINVAL, handled below.
Good catch, thanks! I think that could only happen if there was a bug in the host kernel, since it generates the inner IP header. I'll send a revised version.
Quoted 3 lines
Thanks,
Samuel