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.
== Fix ==
Upstream commits:
59e3e4b52663 ("ipv6: use READ_ONCE() for inet->hdrincl as in ipv4")
b9aa52c4cb45 ("ipv6: fix EFAULT on sendto with icmpv6 and hdrincl")
== Regression Potential ==
Low. Only impacts IPv6 raw sockets with IPV6_HDRINCL.
== SRU Justification ==
The following code returns EFAULT (Bad address):
s = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); ipv6_icmp6_ packet, addr); /* returns -1, errno = EFAULT */
setsockopt(s, SOL_IPV6, IPV6_HDRINCL, 1);
sendto(
The IPv4 equivalent code works.
The failure happens because 2 bytes are eaten from the msghdr by proto_opt( ) starting from commit 19e3c66b52ca ("ipv6 proto_opt" "), but at that time it was not a problem because
rawv6_probe_
equivalent of "ipv4: Avoid reading user iov twice after
raw_probe_
IPV6_HDRINCL was not yet introduced.
Only eat these 2 bytes if hdrincl == 0.
== Fix ==
Upstream commits:
59e3e4b52663 ("ipv6: use READ_ONCE() for inet->hdrincl as in ipv4")
b9aa52c4cb45 ("ipv6: fix EFAULT on sendto with icmpv6 and hdrincl")
== Regression Potential ==
Low. Only impacts IPv6 raw sockets with IPV6_HDRINCL.
== Test Case ==
Copy/paste this code in a python3 interpreter:
IPPROTO_ICMPV6 = socket. getprotobyname( 'ipv6-icmp' ) socket( socket. AF_INET6, socket.SOCK_RAW, IPPROTO_ICMPV6) setsockopt( SOL_IPV6, IPV6_HDRINCL, 1) x00\x00\ x00":@? \xfe\x00\ x00\x00\ x00\x00\ x00\x00\ x00\x00\ x00\x00\ x00\x00\ x01?\xfe\ x00\x00\ x00\x00\ x00\x00\ x00\x00\ x00\x00\ x00\x00\ x00\x02\ x80\x00\ xe0\xda9\ xa0V\x8dabcdefg hijklmnopqrstuv wxyz'
SOL_IPV6 = 41
IPV6_HDRINCL = 36
import socket
send_s = socket.
send_s.
# this is an IPv6 + ICMPv6 echo packet
req = b'`\x00\
send_s.sendto(req, ('3ffe::2', 0, 0, 0))
On error, it raises:
OSError: [Errno 14] Bad address
After the fix, no exception is raised.