Public bug reported: == SRU Justification ==
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. 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. == Test Case == Copy/paste this code in a python3 interpreter: IPPROTO_ICMPV6 = socket.getprotobyname('ipv6-icmp') SOL_IPV6 = 41 IPV6_HDRINCL = 36 import socket send_s = socket.socket(socket.AF_INET6, socket.SOCK_RAW, IPPROTO_ICMPV6) send_s.setsockopt(SOL_IPV6, IPV6_HDRINCL, 1) # this is an IPv6 + ICMPv6 echo packet req = b'`\x00\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\x8dabcdefghijklmnopqrstuvwxyz' 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. ** Affects: linux (Ubuntu) Importance: Undecided Status: Incomplete -- You received this bug notification because you are a member of Kernel Packages, which is subscribed to linux in Ubuntu. https://bugs.launchpad.net/bugs/1832828 Title: ipv6: fix EFAULT on sendto with icmpv6 and hdrincl Status in linux package in Ubuntu: Incomplete Bug description: == SRU Justification == 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. 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. == Test Case == Copy/paste this code in a python3 interpreter: IPPROTO_ICMPV6 = socket.getprotobyname('ipv6-icmp') SOL_IPV6 = 41 IPV6_HDRINCL = 36 import socket send_s = socket.socket(socket.AF_INET6, socket.SOCK_RAW, IPPROTO_ICMPV6) send_s.setsockopt(SOL_IPV6, IPV6_HDRINCL, 1) # this is an IPv6 + ICMPv6 echo packet req = b'`\x00\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\x8dabcdefghijklmnopqrstuvwxyz' 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. To manage notifications about this bug go to: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1832828/+subscriptions -- Mailing list: https://launchpad.net/~kernel-packages Post to : kernel-packages@lists.launchpad.net Unsubscribe : https://launchpad.net/~kernel-packages More help : https://help.launchpad.net/ListHelp