In the Linux kernel, the following vulnerability has been resolved: net: sched: fix memory leak in tcindexsetparms Syzkaller reports a memory leak as follows: ==================================== BUG: memory leak unreferenced object 0xffff88810c287f00 (size 256): comm "syz-executor105", pid 3600, jiffies 4294943292 (age 12.990s) hex dump (first 32 bytes): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [<ffffffff814cf9f0>] kmalloctrace+0x20/0x90 mm/slabcommon.c:1046 [<ffffffff839c9e07>] kmalloc include/linux/slab.h:576 [inline] [<ffffffff839c9e07>] kmallocarray include/linux/slab.h:627 [inline] [<ffffffff839c9e07>] kcalloc include/linux/slab.h:659 [inline] [<ffffffff839c9e07>] tcfextsinit include/net/pktcls.h:250 [inline] [<ffffffff839c9e07>] tcindexsetparms+0xa7/0xbe0 net/sched/clstcindex.c:342 [<ffffffff839caa1f>] tcindexchange+0xdf/0x120 net/sched/clstcindex.c:553 [<ffffffff8394db62>] tcnewtfilter+0x4f2/0x1100 net/sched/clsapi.c:2147 [<ffffffff8389e91c>] rtnetlinkrcvmsg+0x4dc/0x5d0 net/core/rtnetlink.c:6082 [<ffffffff839eba67>] netlinkrcvskb+0x87/0x1d0 net/netlink/afnetlink.c:2540 [<ffffffff839eab87>] netlinkunicastkernel net/netlink/afnetlink.c:1319 [inline] [<ffffffff839eab87>] netlinkunicast+0x397/0x4c0 net/netlink/afnetlink.c:1345 [<ffffffff839eb046>] netlinksendmsg+0x396/0x710 net/netlink/afnetlink.c:1921 [<ffffffff8383e796>] socksendmsgnosec net/socket.c:714 [inline] [<ffffffff8383e796>] socksendmsg+0x56/0x80 net/socket.c:734 [<ffffffff8383eb08>] syssendmsg+0x178/0x410 net/socket.c:2482 [<ffffffff83843678>] syssendmsg+0xa8/0x110 net/socket.c:2536 [<ffffffff838439c5>] _syssendmmsg+0x105/0x330 net/socket.c:2622 [<ffffffff83843c14>] _dosyssendmmsg net/socket.c:2651 [inline] [<ffffffff83843c14>] _sesyssendmmsg net/socket.c:2648 [inline] [<ffffffff83843c14>] _x64syssendmmsg+0x24/0x30 net/socket.c:2648 [<ffffffff84605fd5>] dosyscallx64 arch/x86/entry/common.c:50 [inline] [<ffffffff84605fd5>] dosyscall64+0x35/0xb0 arch/x86/entry/common.c:80 [<ffffffff84800087>] entrySYSCALL64afterhwframe+0x63/0xcd ==================================== Kernel uses tcindexchange() to change an existing filter properties. Yet the problem is that, during the process of changing, if old_r
is retrieved from p->perfect
, then kernel uses tcindexallocperfecthash() to newly allocate filter results, uses tcindexfilterresultinit() to clear the old filter result, without destroying its tcfexts structure, which triggers the above memory leak. To be more specific, there are only two source for the old_r
, according to the tcindexlookup(). old_r
is retrieved from p->perfect
, or old_r
is retrieved from p->h
. * If old_r
is retrieved from p->perfect
, kernel uses tcindexallocperfecthash() to newly allocate the filter results. Then r
is assigned with cp->perfect + handle
, which is newly allocated. So condition old_r && old_r != r
is true in this situation, and kernel uses tcindexfilterresultinit() to clear the old filter result, without destroying its tcfexts structure * If old_r
is retrieved from p->h
, then p->perfect
is NULL according to the tcindexlookup(). Considering that cp->h
is directly copied from p->h
and p->perfect
is NULL, r
is assigned with tcindex_lookup(cp, handle)
, whose value should be the same as old_r
, so condition old_r && old_r != r
is false in this situation, kernel ignores using tcindexfilterresultinit() to clear the old filter result. So only when old_r
is retrieved from p->perfect
does kernel use tcindexfilterresultinit() to clear the old filter result, which triggers the above memory leak. Considering that there already exists a tcfilterwq workqueue to destroy the old tcindex_d ---truncated---