netprio_cgroup: Fix unlimited memory leak of v2 cgroups
authorZefan Li <lizefan@huawei.com>
Sat, 9 May 2020 03:32:10 +0000 (11:32 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 20 May 2020 06:22:04 +0000 (08:22 +0200)
commite2d928d5ee43f372618a9f98b0c73674717f2a2c
tree9666ea6623037a3843b3c8bac7d5650e919e51a7
parentc8dd69b74d2f34e552d6c5ebcfa84356b9293dba
netprio_cgroup: Fix unlimited memory leak of v2 cgroups

[ Upstream commit 090e28b229af92dc5b40786ca673999d59e73056 ]

If systemd is configured to use hybrid mode which enables the use of
both cgroup v1 and v2, systemd will create new cgroup on both the default
root (v2) and netprio_cgroup hierarchy (v1) for a new session and attach
task to the two cgroups. If the task does some network thing then the v2
cgroup can never be freed after the session exited.

One of our machines ran into OOM due to this memory leak.

In the scenario described above when sk_alloc() is called
cgroup_sk_alloc() thought it's in v2 mode, so it stores
the cgroup pointer in sk->sk_cgrp_data and increments
the cgroup refcnt, but then sock_update_netprioidx()
thought it's in v1 mode, so it stores netprioidx value
in sk->sk_cgrp_data, so the cgroup refcnt will never be freed.

Currently we do the mode switch when someone writes to the ifpriomap
cgroup control file. The easiest fix is to also do the switch when
a task is attached to a new cgroup.

Fixes: bd1060a1d671 ("sock, cgroup: add sock->sk_cgroup")
Reported-by: Yang Yingliang <yangyingliang@huawei.com>
Tested-by: Yang Yingliang <yangyingliang@huawei.com>
Signed-off-by: Zefan Li <lizefan@huawei.com>
Acked-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
net/core/netprio_cgroup.c