diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-12-02 17:06:34 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-12-02 17:06:34 -0800 |
commit | e3a251e366e1a007c7ce7b2809b67f4dece6b17c (patch) | |
tree | c42ff533ba214975c683cafaab16d0bbf75d065a /fs | |
parent | 97eeb4d9d755605385fa329da9afa38729f3413c (diff) | |
parent | 6e78c01fde9023e0701f3af880c1fd9de6e4e8e3 (diff) | |
download | linux-stable-e3a251e366e1a007c7ce7b2809b67f4dece6b17c.tar.gz linux-stable-e3a251e366e1a007c7ce7b2809b67f4dece6b17c.tar.bz2 linux-stable-e3a251e366e1a007c7ce7b2809b67f4dece6b17c.zip |
Merge tag 'upstream-5.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs
Pull UBI/UBIFS/JFFS2 updates from Richard Weinberger:
"This pull request contains mostly fixes for UBI, UBIFS and JFFS2:
UBI:
- Fix a regression around producing a anchor PEB for fastmap.
Due to a change in our locking fastmap was unable to produce fresh
anchors an re-used the existing one a way to often.
UBIFS:
- Fixes for endianness. A few places blindly assumed little endian.
- Fix for a memory leak in the orphan code.
- Fix for a possible crash during a commit.
- Revert a wrong bugfix.
JFFS2:
- Revert a bad bugfix (false positive from a code checking tool)"
* tag 'upstream-5.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs:
Revert "jffs2: Fix possible null-pointer dereferences in jffs2_add_frag_to_fragtree()"
ubi: Fix producing anchor PEBs
ubifs: ubifs_tnc_start_commit: Fix OOB in layout_in_gaps
ubifs: do_kill_orphans: Fix a memory leak bug
Revert "ubifs: Fix memory leak bug in alloc_ubifs_info() error path"
ubifs: Fix type of sup->hash_algo
ubifs: Fixed missed le64_to_cpu() in journal
ubifs: Force prandom result to __le32
ubifs: Remove obsolete TODO from dfs_file_write()
ubi: Fix warning static is not at beginning of declaration
ubi: Print skip_check in ubi_dump_vol_info()
Diffstat (limited to 'fs')
-rw-r--r-- | fs/jffs2/nodelist.c | 2 | ||||
-rw-r--r-- | fs/ubifs/debug.c | 12 | ||||
-rw-r--r-- | fs/ubifs/journal.c | 4 | ||||
-rw-r--r-- | fs/ubifs/orphan.c | 17 | ||||
-rw-r--r-- | fs/ubifs/sb.c | 2 | ||||
-rw-r--r-- | fs/ubifs/super.c | 4 | ||||
-rw-r--r-- | fs/ubifs/tnc_commit.c | 34 |
7 files changed, 42 insertions, 33 deletions
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index 021a4a2190ee..b86c78d178c6 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c @@ -226,7 +226,7 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r lastend = this->ofs + this->size; } else { dbg_fragtree2("lookup gave no frag\n"); - return -EINVAL; + lastend = 0; } /* See if we ran off the end of the fragtree */ diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index e4b52783819d..0f5a480fe264 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -2737,18 +2737,6 @@ static ssize_t dfs_file_write(struct file *file, const char __user *u, struct dentry *dent = file->f_path.dentry; int val; - /* - * TODO: this is racy - the file-system might have already been - * unmounted and we'd oops in this case. The plan is to fix it with - * help of 'iterate_supers_type()' which we should have in v3.0: when - * a debugfs opened, we rember FS's UUID in file->private_data. Then - * whenever we access the FS via a debugfs file, we iterate all UBIFS - * superblocks and fine the one with the same UUID, and take the - * locking right. - * - * The other way to go suggested by Al Viro is to create a separate - * 'ubifs-debug' file-system instead. - */ if (file->f_path.dentry == d->dfs_dump_lprops) { ubifs_dump_lprops(c); return count; diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c index 4fd9683b8245..388fe8f5dc51 100644 --- a/fs/ubifs/journal.c +++ b/fs/ubifs/journal.c @@ -503,7 +503,7 @@ static void mark_inode_clean(struct ubifs_info *c, struct ubifs_inode *ui) static void set_dent_cookie(struct ubifs_info *c, struct ubifs_dent_node *dent) { if (c->double_hash) - dent->cookie = prandom_u32(); + dent->cookie = (__force __le32) prandom_u32(); else dent->cookie = 0; } @@ -899,7 +899,7 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode) fname_name(&nm) = xent->name; fname_len(&nm) = le16_to_cpu(xent->nlen); - xino = ubifs_iget(c->vfs_sb, xent->inum); + xino = ubifs_iget(c->vfs_sb, le64_to_cpu(xent->inum)); if (IS_ERR(xino)) { err = PTR_ERR(xino); ubifs_err(c, "dead directory entry '%s', error %d", diff --git a/fs/ubifs/orphan.c b/fs/ubifs/orphan.c index 3b4b4114f208..54d6db61106f 100644 --- a/fs/ubifs/orphan.c +++ b/fs/ubifs/orphan.c @@ -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; diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c index a551eb3e9b89..2b7c04bf8983 100644 --- a/fs/ubifs/sb.c +++ b/fs/ubifs/sb.c @@ -184,7 +184,7 @@ static int create_default_filesystem(struct ubifs_info *c) if (err) goto out; } else { - sup->hash_algo = 0xffff; + sup->hash_algo = cpu_to_le16(0xffff); } sup->ch.node_type = UBIFS_SB_NODE; diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 7d4547e5202d..5e1e8ec0589e 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -2267,10 +2267,8 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags, } } else { err = ubifs_fill_super(sb, data, flags & SB_SILENT ? 1 : 0); - if (err) { - kfree(c); + if (err) goto out_deact; - } /* We do not support atime */ sb->s_flags |= SB_ACTIVE; if (IS_ENABLED(CONFIG_UBIFS_ATIME_SUPPORT)) diff --git a/fs/ubifs/tnc_commit.c b/fs/ubifs/tnc_commit.c index a384a0f9ff32..234be1c4dc87 100644 --- a/fs/ubifs/tnc_commit.c +++ b/fs/ubifs/tnc_commit.c @@ -212,7 +212,7 @@ static int is_idx_node_in_use(struct ubifs_info *c, union ubifs_key *key, /** * layout_leb_in_gaps - layout index nodes using in-the-gaps method. * @c: UBIFS file-system description object - * @p: return LEB number here + * @p: return LEB number in @c->gap_lebs[p] * * This function lays out new index nodes for dirty znodes using in-the-gaps * method of TNC commit. @@ -221,7 +221,7 @@ static int is_idx_node_in_use(struct ubifs_info *c, union ubifs_key *key, * This function returns the number of index nodes written into the gaps, or a * negative error code on failure. */ -static int layout_leb_in_gaps(struct ubifs_info *c, int *p) +static int layout_leb_in_gaps(struct ubifs_info *c, int p) { struct ubifs_scan_leb *sleb; struct ubifs_scan_node *snod; @@ -236,7 +236,7 @@ static int layout_leb_in_gaps(struct ubifs_info *c, int *p) * filled, however we do not check there at present. */ return lnum; /* Error code */ - *p = lnum; + c->gap_lebs[p] = lnum; dbg_gc("LEB %d", lnum); /* * Scan the index LEB. We use the generic scan for this even though @@ -355,7 +355,7 @@ static int get_leb_cnt(struct ubifs_info *c, int cnt) */ static int layout_in_gaps(struct ubifs_info *c, int cnt) { - int err, leb_needed_cnt, written, *p; + int err, leb_needed_cnt, written, p = 0, old_idx_lebs, *gap_lebs; dbg_gc("%d znodes to write", cnt); @@ -364,9 +364,9 @@ static int layout_in_gaps(struct ubifs_info *c, int cnt) if (!c->gap_lebs) return -ENOMEM; - p = c->gap_lebs; + old_idx_lebs = c->lst.idx_lebs; do { - ubifs_assert(c, p < c->gap_lebs + c->lst.idx_lebs); + ubifs_assert(c, p < c->lst.idx_lebs); written = layout_leb_in_gaps(c, p); if (written < 0) { err = written; @@ -392,9 +392,29 @@ static int layout_in_gaps(struct ubifs_info *c, int cnt) leb_needed_cnt = get_leb_cnt(c, cnt); dbg_gc("%d znodes remaining, need %d LEBs, have %d", cnt, leb_needed_cnt, c->ileb_cnt); + /* + * Dynamically change the size of @c->gap_lebs to prevent + * oob, because @c->lst.idx_lebs could be increased by + * function @get_idx_gc_leb (called by layout_leb_in_gaps-> + * ubifs_find_dirty_idx_leb) during loop. Only enlarge + * @c->gap_lebs when needed. + * + */ + if (leb_needed_cnt > c->ileb_cnt && p >= old_idx_lebs && + old_idx_lebs < c->lst.idx_lebs) { + old_idx_lebs = c->lst.idx_lebs; + gap_lebs = krealloc(c->gap_lebs, sizeof(int) * + (old_idx_lebs + 1), GFP_NOFS); + if (!gap_lebs) { + kfree(c->gap_lebs); + c->gap_lebs = NULL; + return -ENOMEM; + } + c->gap_lebs = gap_lebs; + } } while (leb_needed_cnt > c->ileb_cnt); - *p = -1; + c->gap_lebs[p] = -1; return 0; } |