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

Reply via email to