| From foo@baz Sun 09 Jun 2019 09:24:16 AM CEST |
| From: Olivier Matz <olivier.matz@6wind.com> |
| Date: Thu, 6 Jun 2019 09:15:19 +0200 |
| Subject: ipv6: fix EFAULT on sendto with icmpv6 and hdrincl |
| |
| From: Olivier Matz <olivier.matz@6wind.com> |
| |
| [ Upstream commit b9aa52c4cb457e7416cc0c95f475e72ef4a61336 ] |
| |
| The following code returns EFAULT (Bad address): |
| |
| s = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); |
| setsockopt(s, SOL_IPV6, IPV6_HDRINCL, 1); |
| sendto(ipv6_icmp6_packet, addr); /* returns -1, errno = EFAULT */ |
| |
| The IPv4 equivalent code works. A workaround is to use IPPROTO_RAW |
| instead of IPPROTO_ICMPV6. |
| |
| The failure happens because 2 bytes are eaten from the msghdr by |
| rawv6_probe_proto_opt() starting from commit 19e3c66b52ca ("ipv6 |
| equivalent of "ipv4: Avoid reading user iov twice after |
| raw_probe_proto_opt""), but at that time it was not a problem because |
| IPV6_HDRINCL was not yet introduced. |
| |
| Only eat these 2 bytes if hdrincl == 0. |
| |
| Fixes: 715f504b1189 ("ipv6: add IPV6_HDRINCL option for raw sockets") |
| Signed-off-by: Olivier Matz <olivier.matz@6wind.com> |
| Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/ipv6/raw.c | 13 ++++++++----- |
| 1 file changed, 8 insertions(+), 5 deletions(-) |
| |
| --- a/net/ipv6/raw.c |
| +++ b/net/ipv6/raw.c |
| @@ -895,11 +895,14 @@ static int rawv6_sendmsg(struct sock *sk |
| opt = ipv6_fixup_options(&opt_space, opt); |
| |
| fl6.flowi6_proto = proto; |
| - rfv.msg = msg; |
| - rfv.hlen = 0; |
| - err = rawv6_probe_proto_opt(&rfv, &fl6); |
| - if (err) |
| - goto out; |
| + |
| + if (!hdrincl) { |
| + rfv.msg = msg; |
| + rfv.hlen = 0; |
| + err = rawv6_probe_proto_opt(&rfv, &fl6); |
| + if (err) |
| + goto out; |
| + } |
| |
| if (!ipv6_addr_any(daddr)) |
| fl6.daddr = *daddr; |