Skip to content

Commit

Permalink
Merge tag 'for-linus-5.7-rc1' of git://git.kernel.org/pub/scm/linux/k…
Browse files Browse the repository at this point in the history
…ernel/git/rw/ubifs

Pull UBI and UBIFS updates from Richard Weinberger:

 - Fix for memory leaks around UBIFS orphan handling

 - Fix for memory leaks around UBI fastmap

 - Remove zero-length array from ubi-media.h

 - Fix for TNC lookup in UBIFS orphan code

* tag 'for-linus-5.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs:
  ubi: ubi-media.h: Replace zero-length array with flexible-array member
  ubifs: Fix out-of-bounds memory access caused by abnormal value of node_len
  ubi: fastmap: Only produce the initial anchor PEB when fastmap is used
  ubi: fastmap: Free unused fastmap anchor peb during detach
  ubifs: ubifs_add_orphan: Fix a memory leak bug
  ubifs: ubifs_jnl_write_inode: Fix a memory leak bug
  ubifs: Fix ubifs_tnc_lookup() usage in do_kill_orphans()
  • Loading branch information
torvalds committed Apr 7, 2020
2 parents 762a9f2 + 3676f32 commit 763dede
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 10 deletions.
15 changes: 13 additions & 2 deletions drivers/mtd/ubi/fastmap-wl.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ static struct ubi_wl_entry *find_anchor_wl_entry(struct rb_root *root)
return victim;
}

static inline void return_unused_peb(struct ubi_device *ubi,
struct ubi_wl_entry *e)
{
wl_tree_add(e, &ubi->free);
ubi->free_count++;
}

/**
* return_unused_pool_pebs - returns unused PEB to the free tree.
* @ubi: UBI device description object
Expand All @@ -52,8 +59,7 @@ static void return_unused_pool_pebs(struct ubi_device *ubi,

for (i = pool->used; i < pool->size; i++) {
e = ubi->lookuptbl[pool->pebs[i]];
wl_tree_add(e, &ubi->free);
ubi->free_count++;
return_unused_peb(ubi, e);
}
}

Expand Down Expand Up @@ -361,6 +367,11 @@ static void ubi_fastmap_close(struct ubi_device *ubi)
return_unused_pool_pebs(ubi, &ubi->fm_pool);
return_unused_pool_pebs(ubi, &ubi->fm_wl_pool);

if (ubi->fm_anchor) {
return_unused_peb(ubi, ubi->fm_anchor);
ubi->fm_anchor = NULL;
}

if (ubi->fm) {
for (i = 0; i < ubi->fm->used_blocks; i++)
kfree(ubi->fm->e[i]);
Expand Down
2 changes: 1 addition & 1 deletion drivers/mtd/ubi/ubi-media.h
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,6 @@ struct ubi_fm_volhdr {
struct ubi_fm_eba {
__be32 magic;
__be32 reserved_pebs;
__be32 pnum[0];
__be32 pnum[];
} __packed;
#endif /* !__UBI_MEDIA_H__ */
3 changes: 2 additions & 1 deletion drivers/mtd/ubi/wl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1875,7 +1875,8 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
goto out_free;

#ifdef CONFIG_MTD_UBI_FASTMAP
ubi_ensure_anchor_pebs(ubi);
if (!ubi->ro_mode && !ubi->fm_disabled)
ubi_ensure_anchor_pebs(ubi);
#endif
return 0;

Expand Down
16 changes: 14 additions & 2 deletions fs/ubifs/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ int ubifs_is_mapped(const struct ubifs_info *c, int lnum)
int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum,
int offs, int quiet, int must_chk_crc)
{
int err = -EINVAL, type, node_len;
int err = -EINVAL, type, node_len, dump_node = 1;
uint32_t crc, node_crc, magic;
const struct ubifs_ch *ch = buf;

Expand Down Expand Up @@ -278,10 +278,22 @@ int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum,
out_len:
if (!quiet)
ubifs_err(c, "bad node length %d", node_len);
if (type == UBIFS_DATA_NODE && node_len > UBIFS_DATA_NODE_SZ)
dump_node = 0;
out:
if (!quiet) {
ubifs_err(c, "bad node at LEB %d:%d", lnum, offs);
ubifs_dump_node(c, buf);
if (dump_node) {
ubifs_dump_node(c, buf);
} else {
int safe_len = min3(node_len, c->leb_size - offs,
(int)UBIFS_MAX_DATA_NODE_SZ);
pr_err("\tprevent out-of-bounds memory access\n");
pr_err("\ttruncated data node length %d\n", safe_len);
pr_err("\tcorrupted data node:\n");
print_hex_dump(KERN_ERR, "\t", DUMP_PREFIX_OFFSET, 32, 1,
buf, safe_len, 0);
}
dump_stack();
}
return err;
Expand Down
1 change: 1 addition & 0 deletions fs/ubifs/journal.c
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,7 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode)
ubifs_err(c, "dead directory entry '%s', error %d",
xent->name, err);
ubifs_ro_mode(c, err);
kfree(xent);
goto out_release;
}
ubifs_assert(c, ubifs_inode(xino)->xattr);
Expand Down
13 changes: 9 additions & 4 deletions fs/ubifs/orphan.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ int ubifs_add_orphan(struct ubifs_info *c, ino_t inum)
int err = 0;
ino_t xattr_inum;
union ubifs_key key;
struct ubifs_dent_node *xent;
struct ubifs_dent_node *xent, *pxent = NULL;
struct fscrypt_name nm = {0};
struct ubifs_orphan *xattr_orphan;
struct ubifs_orphan *orphan;
Expand All @@ -181,11 +181,16 @@ int ubifs_add_orphan(struct ubifs_info *c, ino_t inum)
xattr_inum = le64_to_cpu(xent->inum);

xattr_orphan = orphan_add(c, xattr_inum, orphan);
if (IS_ERR(xattr_orphan))
if (IS_ERR(xattr_orphan)) {
kfree(xent);
return PTR_ERR(xattr_orphan);
}

kfree(pxent);
pxent = xent;
key_read(c, &xent->key, &key);
}
kfree(pxent);

return 0;
}
Expand Down Expand Up @@ -688,14 +693,14 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb,

ino_key_init(c, &key1, inum);
err = ubifs_tnc_lookup(c, &key1, ino);
if (err)
if (err && err != -ENOENT)
goto out_free;

/*
* Check whether an inode can really get deleted.
* linkat() with O_TMPFILE allows rebirth of an inode.
*/
if (ino->nlink == 0) {
if (err == 0 && ino->nlink == 0) {
dbg_rcvry("deleting orphaned inode %lu",
(unsigned long)inum);

Expand Down

0 comments on commit 763dede

Please sign in to comment.