[RHEL8,COMMIT] ve/binfmt_misc: destroy all nodes on ve stop

Submitted by Konstantin Khorenko on June 8, 2020, 4:07 p.m.

Details

Message ID 202006081607.058G7TFD030553@finist-co8.sw.ru
State New
Series "ve/binfmt_misc: destroy all nodes on ve stop"
Headers show

Commit Message

Konstantin Khorenko June 8, 2020, 4:07 p.m.
The commit is pushed to "branch-rh8-4.18.0-80.1.2.vz8.3.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh8-4.18.0-80.1.2.vz8.3.11
------>
commit c11a2463a01f78a90bb42d0e3b20506474af3ac5
Author: Valeriy Vdovin <valeriy.vdovin@virtuozzo.com>
Date:   Mon Jun 8 19:07:29 2020 +0300

    ve/binfmt_misc: destroy all nodes on ve stop
    
    Patchset description:
    
    zap sb->s_ns + fix memleak in binfmt_misc
    
    Vladimir Davydov (6):
      binfmt_misc: do not use sb->s_fs_info
      Revert "VE/VFS: use sb->s_ns member to store namespace for mount_ns()
        calls"
      Revert "ve/sunrpc: use correct pointer to net_namespace in auth_gss.c"
      Revert "nfsd/sunrpc/mqueue: use sb->s_ns instead of data in
        fill_super"
      binfmt_misc: do not use s_ns
      binfmt_misc: destroy all nodes on ve stop
    
    https://jira.sw.ru/browse/PSBM-39154
    
    Reviewed-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
    
    ======================
    This patch description:
    
    Each registered binfmt_misc node pins binfmt_misc mount point, which in
    turn pins the owner ve. This means that if we don't clean up binfmt_misc
    nodes on ve stop, the mount point as well as the ve struct will leak.
    
    Signed-off-by: Vladimir Davydov <vdavydov@parallels.com>
    
    (cherry-picked from commit a018c0f03fa1d072e0970d31b5c5f57be5c2cdb5)
    
    Signed-off-by: Valeriy Vdovin <valeriy.vdovin@virtuozzo.com>
---
 fs/binfmt_misc.c | 28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

Patch hide | download patch | download mbox

diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index 0288a0ee04ac..e325c83e24cb 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -905,16 +905,42 @@  static struct file_system_type bm_fs_type = {
 };
 MODULE_ALIAS_FS("binfmt_misc");
 
+static void ve_binfmt_fini(void *data)
+{
+	struct ve_struct *ve = data;
+	struct binfmt_misc *bm_data = ve->binfmt_misc;
+
+	if (!bm_data)
+		return;
+
+	/*
+	 * XXX: Note we don't take any locks here. This is safe as long as
+	 * nobody uses binfmt_misc outside the owner ve.
+	 */
+	while (!list_empty(&bm_data->entries))
+		kill_node(bm_data, list_first_entry(
+			&bm_data->entries, Node, list));
+}
+
+static struct ve_hook ve_binfmt_hook = {
+	.fini		= ve_binfmt_fini,
+	.priority	= HOOK_PRIO_DEFAULT,
+	.owner		= THIS_MODULE,
+};
+
 static int __init init_misc_binfmt(void)
 {
 	int err = register_filesystem(&bm_fs_type);
-	if (!err)
+	if (!err) {
 		insert_binfmt(&misc_format);
+		ve_hook_register(VE_SS_CHAIN, &ve_binfmt_hook);
+	}
 	return err;
 }
 
 static void __exit exit_misc_binfmt(void)
 {
+	ve_hook_unregister(&ve_binfmt_hook);
 	unregister_binfmt(&misc_format);
 	unregister_filesystem(&bm_fs_type);
 }