A mini-article about CVE-2017-1000112 — a memory corruption vulnerability I found in the UDP Fragmentation Offload feature of the Linux kernel IP sockets. Contains a brief description of the Local Privilege Escalation exploit I wrote for this bug. Originally posted as an announcement on the OSS-Security mailing list.

Overview

When fuzzing the Linux kernel with syzkaller, I found an exploitable memory corruption in the UDP Fragmentation Offload feature of the Linux kernel IP sockets.

The bug was introduced in commit e89e9cf539a2 (“[IPv4/IPv6]: UFO Scatter-gather approach”) on October 18th 2005, when the UFO feature was added to the kernel. The bug has been fixed in commit 85f1bd9a7b5a (“udp: consistently apply ufo or fragmentation”), which has been merged into 4.14.

If unprivileged user namespaces are available, this bug can be exploited to gain root privileges.

Bug details

« When building a UFO packet with MSG_MORE, __ip_append_data() calls ip_ufo_append_data() to append. However in between two send() calls, the append path can be switched from UFO to non-UFO one, which leads to a memory corruption. In case the UFO packet’s length exceeds MTU, copy = maxfraglen - skb->len becomes negative on the non-UFO path and the branch to allocate new skb is taken. This triggers fragmentation and computation of fraggap = skb_prev->len - maxfraglen. Fraggap can exceed MTU, causing copy = datalen - transhdrlen - fraggap to become negative. Consequently, skb_copy_and_csum_bits() writes out-of-bounds. A similar issue is present in IPv6 code.
CVE-2017-1000112 — MITRE

Exploitation

The bug can be exploited by an unprivileged user when both:

  1. The user can set up an interface with UFO enabled and MTU < 65535, or such interface is already present in the system. The former is possible from inside a user namespace.

  2. The user can disable the NETIF_F_UFO interface feature or set the SO_NO_CHECK socket option. The former requires CAP_NET_ADMIN. The latter is only possible after commit 40ba330227ad (“udp: disallow UFO for sockets with SO_NO_CHECK option”) from January 11th 2016. Both are possible from inside a user namespace.

Thus, this bug can be exploited by an unprivileged user if unprivileged user namespaces are available.

I wrote a proof-of-concept exploit that gets root on a range of Ubuntu kernels. The exploit triggers an out-of-bounds write on a socket buffer and overwrites skb_shared_info.destructor_arg->callback with a pointer to shellcode. This is the same technique that I used for exploiting a double-free in the Linux kernel USB MIDI driver. The exploit bypasses SMEP and KASLR but not SMAP.

💜 Thank you for reading!

Timeline

  • 3 Aug, 2017 — Bug reported to security@kernel.org
  • 4 Aug, 2017 — Notification sent to linux-distros@
  • 10 Aug, 2017 — Patch submitted to netdev@
  • 10 Aug, 2017 — Mainline fix committed
  • 10 Aug, 2017 — Public announcement sent to oss-security@
  • 13 Aug, 2017 — Write-up and exploit published

🐱 About me

I’m a security researcher and a software engineer focusing on the Linux kernel.

I contributed to several security-related Linux kernel subsystems and tools, including KASAN — a fast dynamic bug detector, syzkaller — a production-grade kernel fuzzer, and Arm Memory Tagging Extension — an exploit mitigation. I also wrote a few Linux kernel exploits for the bugs I found.

Occasionally, I’m having fun with hardware hacking, teaching, and other random stuff.

Follow me @andreyknvl on Twitter, @xairy@infosec.exchange on Mastodon, or @xairy on LinkedIn for notifications about new articles, talks, and training sessions.