ubifs: do_kill_orphans: Fix a memory leak bug
authorZhihao Cheng <chengzhihao1@huawei.com>
Tue, 29 Oct 2019 12:58:23 +0000 (20:58 +0800)
committerRichard Weinberger <richard@nod.at>
Sun, 17 Nov 2019 21:22:54 +0000 (22:22 +0100)
If there are more than one valid snod on the sleb->nodes list,
do_kill_orphans will malloc ino more than once without releasing
previous ino's memory. Finally, it will trigger memory leak.

Fixes: ee1438ce5dc4 ("ubifs: Check link count of inodes when...")
Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
Signed-off-by: zhangyi (F) <yi.zhang@huawei.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
fs/ubifs/orphan.c

index 3b4b411..54d6db6 100644 (file)
@@ -631,12 +631,17 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
        ino_t inum;
        int i, n, err, first = 1;
 
+       ino = kmalloc(UBIFS_MAX_INO_NODE_SZ, GFP_NOFS);
+       if (!ino)
+               return -ENOMEM;
+
        list_for_each_entry(snod, &sleb->nodes, list) {
                if (snod->type != UBIFS_ORPH_NODE) {
                        ubifs_err(c, "invalid node type %d in orphan area at %d:%d",
                                  snod->type, sleb->lnum, snod->offs);
                        ubifs_dump_node(c, snod->node);
-                       return -EINVAL;
+                       err = -EINVAL;
+                       goto out_free;
                }
 
                orph = snod->node;
@@ -663,20 +668,18 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
                                ubifs_err(c, "out of order commit number %llu in orphan node at %d:%d",
                                          cmt_no, sleb->lnum, snod->offs);
                                ubifs_dump_node(c, snod->node);
-                               return -EINVAL;
+                               err = -EINVAL;
+                               goto out_free;
                        }
                        dbg_rcvry("out of date LEB %d", sleb->lnum);
                        *outofdate = 1;
-                       return 0;
+                       err = 0;
+                       goto out_free;
                }
 
                if (first)
                        first = 0;
 
-               ino = kmalloc(UBIFS_MAX_INO_NODE_SZ, GFP_NOFS);
-               if (!ino)
-                       return -ENOMEM;
-
                n = (le32_to_cpu(orph->ch.len) - UBIFS_ORPH_NODE_SZ) >> 3;
                for (i = 0; i < n; i++) {
                        union ubifs_key key1, key2;