Subject: CVE-2021-47238: net: ipv4: fix memory leak in ip_mc_add1_src

From: Greg Kroah-Hartman <[email-masked]>

Description
===========

In the Linux kernel, the following vulnerability has been resolved:

net: ipv4: fix memory leak in ip_mc_add1_src

BUG: memory leak
unreferenced object 0xffff888101bc4c00 (size 32):
  comm "syz-executor527", pid 360, jiffies 4294807421 (age 19.329s)
  hex dump (first 32 bytes):
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
    01 00 00 00 00 00 00 00 ac 14 14 bb 00 00 02 00 ................
  backtrace:
    [<00000000f17c5244>] kmalloc include/linux/slab.h:558 [inline]
    [<00000000f17c5244>] kzalloc include/linux/slab.h:688 [inline]
    [<00000000f17c5244>] ip_mc_add1_src net/ipv4/igmp.c:1971 [inline]
    [<00000000f17c5244>] ip_mc_add_src+0x95f/0xdb0 net/ipv4/igmp.c:2095
    [<000000001cb99709>] ip_mc_source+0x84c/0xea0 net/ipv4/igmp.c:2416
    [<0000000052cf19ed>] do_ip_setsockopt net/ipv4/ip_sockglue.c:1294 [inline]
    [<0000000052cf19ed>] ip_setsockopt+0x114b/0x30c0 net/ipv4/ip_sockglue.c:1423
    [<00000000477edfbc>] raw_setsockopt+0x13d/0x170 net/ipv4/raw.c:857
    [<00000000e75ca9bb>] __sys_setsockopt+0x158/0x270 net/socket.c:2117
    [<00000000bdb993a8>] __do_sys_setsockopt net/socket.c:2128 [inline]
    [<00000000bdb993a8>] __se_sys_setsockopt net/socket.c:2125 [inline]
    [<00000000bdb993a8>] __x64_sys_setsockopt+0xba/0x150 net/socket.c:2125
    [<000000006a1ffdbd>] do_syscall_64+0x40/0x80 arch/x86/entry/common.c:47
    [<00000000b11467c4>] entry_SYSCALL_64_after_hwframe+0x44/0xae

In commit 24803f38a5c0 ("igmp: do not remove igmp souce list info when set
link down"), the ip_mc_clear_src() in ip_mc_destroy_dev() was removed,
because it was also called in igmpv3_clear_delrec().

Rough callgraph:

inetdev_destroy
-> ip_mc_destroy_dev
     -> igmpv3_clear_delrec
        -> ip_mc_clear_src
-> RCU_INIT_POINTER(dev->ip_ptr, NULL)

However, ip_mc_clear_src() called in igmpv3_clear_delrec() doesn't
release in_dev->mc_list->sources. And RCU_INIT_POINTER() assigns the
NULL to dev->ip_ptr. As a result, in_dev cannot be obtained through
inetdev_by_index() and then in_dev->mc_list->sources cannot be released
by ip_mc_del1_src() in the sock_close. Rough call sequence goes like:

sock_close
-> __sock_release
   -> inet_release
      -> ip_mc_drop_socket
         -> inetdev_by_index
         -> ip_mc_leave_src
            -> ip_mc_del_src
               -> ip_mc_del1_src

So we still need to call ip_mc_clear_src() in ip_mc_destroy_dev() to free
in_dev->mc_list->sources.

The Linux kernel CVE team has assigned CVE-2021-47238 to this issue.

Affected and fixed versions
===========================

	Issue introduced in 4.9 with commit 24803f38a5c0 and fixed in 4.9.274 with commit 0dc13e75507f
	Issue introduced in 4.9 with commit 24803f38a5c0 and fixed in 4.14.238 with commit 6cff57eea334
	Issue introduced in 4.9 with commit 24803f38a5c0 and fixed in 4.19.196 with commit 1e28018b5c83
	Issue introduced in 4.9 with commit 24803f38a5c0 and fixed in 5.4.128 with commit 3dd2aeac2e96
	Issue introduced in 4.9 with commit 24803f38a5c0 and fixed in 5.10.46 with commit ac31cc837caf
	Issue introduced in 4.9 with commit 24803f38a5c0 and fixed in 5.12.13 with commit 77de6ee73f54
	Issue introduced in 4.9 with commit 24803f38a5c0 and fixed in 5.13 with commit d8e2973029b8
	Issue introduced in 3.2.87 with commit bd1b664a1940
	Issue introduced in 3.16.42 with commit b38c6e0bd5b5

Please see https://www.kernel.org for a full list of currently supported
kernel versions by the kernel community.

Unaffected versions might change over time as fixes are backported to
older supported kernel versions.  The official CVE entry at
	https://cve.org/CVERecord/?id=CVE-2021-47238
will be updated if fixes are backported, please check that for the most
up to date information about this issue.

Affected files
==============

The file(s) affected by this issue are:
	net/ipv4/igmp.c

Mitigation
==========

The Linux kernel CVE team recommends that you update to the latest
stable kernel version for this, and many other bugfixes.  Individual
changes are never tested alone, but rather are part of a larger kernel
release.  Cherry-picking individual commits is not recommended or
supported by the Linux kernel community at all.  If however, updating to
the latest release is impossible, the individual changes to resolve this
issue can be found at these commits:
	https://git.kernel.org/stable/c/0dc13e75507faa17ac9f7562b4ef7bf8fcd78422
	https://git.kernel.org/stable/c/6cff57eea3347f79f1867cc53e1093b6614138d8
	https://git.kernel.org/stable/c/1e28018b5c83d5073f74a6fb72eabe8370b2f501
	https://git.kernel.org/stable/c/3dd2aeac2e9624cff9fa634710837e4f2e352758
	https://git.kernel.org/stable/c/ac31cc837cafb57a271babad8ccffbf733caa076
	https://git.kernel.org/stable/c/77de6ee73f54a9a89c0afa0bf4c53b239aa9953a
	https://git.kernel.org/stable/c/d8e2973029b8b2ce477b564824431f3385c77083