]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.14.125/ipv6-fix-efault-on-sendto-with-icmpv6-and-hdrincl.patch
Linux 4.19.50
[thirdparty/kernel/stable-queue.git] / releases / 4.14.125 / ipv6-fix-efault-on-sendto-with-icmpv6-and-hdrincl.patch
1 From foo@baz Sun 09 Jun 2019 09:44:19 AM CEST
2 From: Olivier Matz <olivier.matz@6wind.com>
3 Date: Thu, 6 Jun 2019 09:15:19 +0200
4 Subject: ipv6: fix EFAULT on sendto with icmpv6 and hdrincl
5
6 From: Olivier Matz <olivier.matz@6wind.com>
7
8 [ Upstream commit b9aa52c4cb457e7416cc0c95f475e72ef4a61336 ]
9
10 The following code returns EFAULT (Bad address):
11
12 s = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
13 setsockopt(s, SOL_IPV6, IPV6_HDRINCL, 1);
14 sendto(ipv6_icmp6_packet, addr); /* returns -1, errno = EFAULT */
15
16 The IPv4 equivalent code works. A workaround is to use IPPROTO_RAW
17 instead of IPPROTO_ICMPV6.
18
19 The failure happens because 2 bytes are eaten from the msghdr by
20 rawv6_probe_proto_opt() starting from commit 19e3c66b52ca ("ipv6
21 equivalent of "ipv4: Avoid reading user iov twice after
22 raw_probe_proto_opt""), but at that time it was not a problem because
23 IPV6_HDRINCL was not yet introduced.
24
25 Only eat these 2 bytes if hdrincl == 0.
26
27 Fixes: 715f504b1189 ("ipv6: add IPV6_HDRINCL option for raw sockets")
28 Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
29 Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
30 Signed-off-by: David S. Miller <davem@davemloft.net>
31 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
32 ---
33 net/ipv6/raw.c | 13 ++++++++-----
34 1 file changed, 8 insertions(+), 5 deletions(-)
35
36 --- a/net/ipv6/raw.c
37 +++ b/net/ipv6/raw.c
38 @@ -889,11 +889,14 @@ static int rawv6_sendmsg(struct sock *sk
39 opt = ipv6_fixup_options(&opt_space, opt);
40
41 fl6.flowi6_proto = proto;
42 - rfv.msg = msg;
43 - rfv.hlen = 0;
44 - err = rawv6_probe_proto_opt(&rfv, &fl6);
45 - if (err)
46 - goto out;
47 +
48 + if (!hdrincl) {
49 + rfv.msg = msg;
50 + rfv.hlen = 0;
51 + err = rawv6_probe_proto_opt(&rfv, &fl6);
52 + if (err)
53 + goto out;
54 + }
55
56 if (!ipv6_addr_any(daddr))
57 fl6.daddr = *daddr;