diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2024-11-30 10:32:47 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2024-11-30 10:32:47 -0800 |
commit | 04b43ea325d21c4c98e831383a1b7d540721898a (patch) | |
tree | c0aa301a8d46c22788d7f74ff5e2c6c092a39951 /fs | |
parent | e864effa1fe240473e023fc8e8d243045a7763e0 (diff) | |
parent | bcdcb115eaed5e988cf37cc9a1dd5f5dd200e927 (diff) |
Merge tag 'ubifs-for-linus-6.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs
Pull JFFS2, UBI and UBIFS updates from Richard Weinberger:
"JFFS2:
- Bug fix for rtime compression
- Various cleanups
UBI:
- Cleanups for fastmap and wear leveling
UBIFS:
- Add support for FS_IOC_GETFSSYSFSPATH
- Remove dead ioctl code
- Fix UAF in ubifs_tnc_end_commit()"
* tag 'ubifs-for-linus-6.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs: (25 commits)
ubifs: Fix uninitialized use of err in ubifs_jnl_write_inode()
jffs2: Prevent rtime decompress memory corruption
jffs2: remove redundant check on outpos > pos
fs: jffs2: Fix inconsistent indentation in jffs2_mark_node_obsolete
jffs2: Correct some typos in comments
jffs2: fix use of uninitialized variable
jffs2: Use str_yes_no() helper function
mtd: ubi: remove redundant check on bytes_left at end of function
mtd: ubi: fix unreleased fwnode_handle in find_volume_fwnode()
ubifs: authentication: Fix use-after-free in ubifs_tnc_end_commit
ubi: fastmap: Fix duplicate slab cache names while attaching
ubifs: xattr: remove unused anonymous enum
ubifs: Reduce kfree() calls in ubifs_purge_xattrs()
ubifs: Call iput(xino) only once in ubifs_purge_xattrs()
ubi: wl: Close down wear-leveling before nand is suspended
mtd: ubi: Rmove unused declaration in header file
ubifs: Correct the total block count by deducting journal reservation
ubifs: Convert to use ERR_CAST()
ubifs: add support for FS_IOC_GETFSSYSFSPATH
ubifs: remove unused ioctl flags GETFLAGS/SETFLAGS
...
Diffstat (limited to 'fs')
-rw-r--r-- | fs/jffs2/compr_rtime.c | 3 | ||||
-rw-r--r-- | fs/jffs2/compr_rubin.c | 5 | ||||
-rw-r--r-- | fs/jffs2/erase.c | 7 | ||||
-rw-r--r-- | fs/jffs2/gc.c | 2 | ||||
-rw-r--r-- | fs/jffs2/nodemgmt.c | 17 | ||||
-rw-r--r-- | fs/jffs2/readinode.c | 2 | ||||
-rw-r--r-- | fs/ubifs/ioctl.c | 6 | ||||
-rw-r--r-- | fs/ubifs/journal.c | 13 | ||||
-rw-r--r-- | fs/ubifs/lpt_commit.c | 4 | ||||
-rw-r--r-- | fs/ubifs/orphan.c | 2 | ||||
-rw-r--r-- | fs/ubifs/super.c | 8 | ||||
-rw-r--r-- | fs/ubifs/tnc.c | 2 | ||||
-rw-r--r-- | fs/ubifs/tnc_commit.c | 2 | ||||
-rw-r--r-- | fs/ubifs/ubifs.h | 3 | ||||
-rw-r--r-- | fs/ubifs/xattr.c | 45 |
15 files changed, 37 insertions, 84 deletions
diff --git a/fs/jffs2/compr_rtime.c b/fs/jffs2/compr_rtime.c index 79e771ab624f..2b9ef713b844 100644 --- a/fs/jffs2/compr_rtime.c +++ b/fs/jffs2/compr_rtime.c @@ -95,6 +95,9 @@ static int jffs2_rtime_decompress(unsigned char *data_in, positions[value]=outpos; if (repeat) { + if ((outpos + repeat) >= destlen) { + return 1; + } if (backoffs + repeat >= outpos) { while(repeat) { cpage_out[outpos++] = cpage_out[backoffs++]; diff --git a/fs/jffs2/compr_rubin.c b/fs/jffs2/compr_rubin.c index 556de100ebd5..9854253d0108 100644 --- a/fs/jffs2/compr_rubin.c +++ b/fs/jffs2/compr_rubin.c @@ -276,11 +276,6 @@ static int rubin_do_compress(int bit_divider, int *bits, unsigned char *data_in, end_rubin(&rs); - if (outpos > pos) { - /* We failed */ - return -1; - } - /* Tell the caller how much we managed to compress, * and how much space it took */ diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index acd32f05b519..ef3a1e1b6cb0 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c @@ -338,10 +338,9 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl } while(--retlen); mtd_unpoint(c->mtd, jeb->offset, c->sector_size); if (retlen) { - pr_warn("Newly-erased block contained word 0x%lx at offset 0x%08tx\n", - *wordebuf, - jeb->offset + - c->sector_size-retlen * sizeof(*wordebuf)); + *bad_offset = jeb->offset + c->sector_size - retlen * sizeof(*wordebuf); + pr_warn("Newly-erased block contained word 0x%lx at offset 0x%08x\n", + *wordebuf, *bad_offset); return -EIO; } return 0; diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index 822949d0eb00..1b833bbffcf5 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c @@ -82,7 +82,7 @@ again: nextlist = &c->erasable_list; } else if (!list_empty(&c->erasable_pending_wbuf_list)) { - /* There are blocks are wating for the wbuf sync */ + /* There are blocks are waiting for the wbuf sync */ jffs2_dbg(1, "Synching wbuf in order to reuse erasable_pending_wbuf_list blocks\n"); spin_unlock(&c->erase_completion_lock); jffs2_flush_wbuf_pad(c); diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index bbab2bdc71b6..3fb9f9807b66 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c @@ -15,6 +15,7 @@ #include <linux/mtd/mtd.h> #include <linux/compiler.h> #include <linux/sched/signal.h> +#include <linux/string_choices.h> #include "nodelist.h" #include "debug.h" @@ -317,9 +318,9 @@ static int jffs2_find_nextblock(struct jffs2_sb_info *c) And there's no space left. At all. */ pr_crit("Argh. No free space left for GC. nr_erasing_blocks is %d. nr_free_blocks is %d. (erasableempty: %s, erasingempty: %s, erasependingempty: %s)\n", c->nr_erasing_blocks, c->nr_free_blocks, - list_empty(&c->erasable_list) ? "yes" : "no", - list_empty(&c->erasing_list) ? "yes" : "no", - list_empty(&c->erase_pending_list) ? "yes" : "no"); + str_yes_no(list_empty(&c->erasable_list)), + str_yes_no(list_empty(&c->erasing_list)), + str_yes_no(list_empty(&c->erase_pending_list))); return -ENOSPC; } @@ -630,8 +631,8 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref ref->flash_offset, jeb->used_size); BUG(); }) - jffs2_dbg(1, "Obsoleting previously unchecked node at 0x%08x of len %x\n", - ref_offset(ref), freed_len); + jffs2_dbg(1, "Obsoleting previously unchecked node at 0x%08x of len %x\n", + ref_offset(ref), freed_len); jeb->unchecked_size -= freed_len; c->unchecked_size -= freed_len; } else { @@ -641,8 +642,8 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref ref->flash_offset, jeb->used_size); BUG(); }) - jffs2_dbg(1, "Obsoleting node at 0x%08x of len %#x: ", - ref_offset(ref), freed_len); + jffs2_dbg(1, "Obsoleting node at 0x%08x of len %#x: ", + ref_offset(ref), freed_len); jeb->used_size -= freed_len; c->used_size -= freed_len; } @@ -883,7 +884,7 @@ int jffs2_thread_should_wake(struct jffs2_sb_info *c) jffs2_dbg(1, "%s(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x, vdirty_blocks %d: %s\n", __func__, c->nr_free_blocks, c->nr_erasing_blocks, - c->dirty_size, nr_very_dirty, ret ? "yes" : "no"); + c->dirty_size, nr_very_dirty, str_yes_no(ret)); return ret; } diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 03b4f99614be..f987f78a894e 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -72,7 +72,7 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info if (err != -EOPNOTSUPP) JFFS2_WARNING("MTD point failed: error code %d.\n", err); } else - pointed = 1; /* succefully pointed to device */ + pointed = 1; /* successfully pointed to device */ #endif if (!pointed) { diff --git a/fs/ubifs/ioctl.c b/fs/ubifs/ioctl.c index d79cabe193c3..2c99349cf537 100644 --- a/fs/ubifs/ioctl.c +++ b/fs/ubifs/ioctl.c @@ -213,12 +213,6 @@ long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) long ubifs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { switch (cmd) { - case FS_IOC32_GETFLAGS: - cmd = FS_IOC_GETFLAGS; - break; - case FS_IOC32_SETFLAGS: - cmd = FS_IOC_SETFLAGS; - break; case FS_IOC_SET_ENCRYPTION_POLICY: case FS_IOC_GET_ENCRYPTION_POLICY: case FS_IOC_GET_ENCRYPTION_POLICY_EX: diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c index 4a35f9e8f668..36ba79fbd2ff 100644 --- a/fs/ubifs/journal.c +++ b/fs/ubifs/journal.c @@ -981,6 +981,13 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode) dbg_jnl("ino %lu, nlink %u", inode->i_ino, inode->i_nlink); + if (kill_xattrs && ui->xattr_cnt > ubifs_xattr_max_cnt(c)) { + ubifs_err(c, "Cannot delete inode, it has too much xattrs!"); + err = -EPERM; + ubifs_ro_mode(c, err); + return err; + } + /* * If the inode is being deleted, do not write the attached data. No * need to synchronize the write-buffer either. @@ -1012,12 +1019,6 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode) struct inode *xino; struct ubifs_dent_node *xent, *pxent = NULL; - if (ui->xattr_cnt > ubifs_xattr_max_cnt(c)) { - err = -EPERM; - ubifs_err(c, "Cannot delete inode, it has too much xattrs!"); - goto out_release; - } - lowest_xent_key(c, &key, inode->i_ino); while (1) { xent = ubifs_tnc_next_ent(c, &key, &nm); diff --git a/fs/ubifs/lpt_commit.c b/fs/ubifs/lpt_commit.c index 07351fdce722..aa8837e6247c 100644 --- a/fs/ubifs/lpt_commit.c +++ b/fs/ubifs/lpt_commit.c @@ -577,7 +577,7 @@ static struct ubifs_pnode *next_pnode_to_dirty(struct ubifs_info *c, /* Go right */ nnode = ubifs_get_nnode(c, nnode, iip); if (IS_ERR(nnode)) - return (void *)nnode; + return ERR_CAST(nnode); /* Go down to level 1 */ while (nnode->level > 1) { @@ -594,7 +594,7 @@ static struct ubifs_pnode *next_pnode_to_dirty(struct ubifs_info *c, } nnode = ubifs_get_nnode(c, nnode, iip); if (IS_ERR(nnode)) - return (void *)nnode; + return ERR_CAST(nnode); } for (iip = 0; iip < UBIFS_LPT_FANOUT; iip++) diff --git a/fs/ubifs/orphan.c b/fs/ubifs/orphan.c index fb957d963ba6..5555dd740889 100644 --- a/fs/ubifs/orphan.c +++ b/fs/ubifs/orphan.c @@ -76,7 +76,7 @@ int ubifs_add_orphan(struct ubifs_info *c, ino_t inum) else if (inum > o->inum) p = &(*p)->rb_right; else { - ubifs_err(c, "orphaned twice"); + ubifs_err(c, "ino %lu orphaned twice", (unsigned long)inum); spin_unlock(&c->orphan_lock); kfree(orphan); return -EINVAL; diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 3fb308b6e167..f3e3b2068608 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -773,10 +773,10 @@ static void init_constants_master(struct ubifs_info *c) * necessary to report something for the 'statfs()' call. * * Subtract the LEB reserved for GC, the LEB which is reserved for - * deletions, minimum LEBs for the index, and assume only one journal - * head is available. + * deletions, minimum LEBs for the index, the LEBs which are reserved + * for each journal head. */ - tmp64 = c->main_lebs - 1 - 1 - MIN_INDEX_LEBS - c->jhead_cnt + 1; + tmp64 = c->main_lebs - 1 - 1 - MIN_INDEX_LEBS - c->jhead_cnt; tmp64 *= (long long)c->leb_size - c->leb_overhead; tmp64 = ubifs_reported_space(c, tmp64); c->block_cnt = tmp64 >> UBIFS_BLOCK_SHIFT; @@ -2206,6 +2206,8 @@ static int ubifs_fill_super(struct super_block *sb, struct fs_context *fc) } super_set_uuid(sb, c->uuid, sizeof(c->uuid)); + super_set_sysfs_name_generic(sb, UBIFS_DFS_DIR_NAME, + c->vi.ubi_num, c->vi.vol_id); mutex_unlock(&c->umount_mutex); return 0; diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c index 45cacdcd4746..33946b518148 100644 --- a/fs/ubifs/tnc.c +++ b/fs/ubifs/tnc.c @@ -2930,8 +2930,6 @@ int ubifs_tnc_remove_ino(struct ubifs_info *c, ino_t inum) dbg_tnc("xent '%s', ino %lu", xent->name, (unsigned long)xattr_inum); - ubifs_evict_xattr_inode(c, xattr_inum); - fname_name(&nm) = xent->name; fname_len(&nm) = le16_to_cpu(xent->nlen); err = ubifs_tnc_remove_nm(c, &key1, &nm); diff --git a/fs/ubifs/tnc_commit.c b/fs/ubifs/tnc_commit.c index a55e04822d16..7c43e0ccf6d4 100644 --- a/fs/ubifs/tnc_commit.c +++ b/fs/ubifs/tnc_commit.c @@ -657,6 +657,8 @@ static int get_znodes_to_commit(struct ubifs_info *c) znode->alt = 0; cnext = find_next_dirty(znode); if (!cnext) { + ubifs_assert(c, !znode->parent); + znode->cparent = NULL; znode->cnext = c->cnext; break; } diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index d69a5a42d693..3375bbe0508c 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -2040,13 +2040,10 @@ ssize_t ubifs_xattr_get(struct inode *host, const char *name, void *buf, #ifdef CONFIG_UBIFS_FS_XATTR extern const struct xattr_handler * const ubifs_xattr_handlers[]; ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size); -void ubifs_evict_xattr_inode(struct ubifs_info *c, ino_t xattr_inum); int ubifs_purge_xattrs(struct inode *host); #else #define ubifs_listxattr NULL #define ubifs_xattr_handlers NULL -static inline void ubifs_evict_xattr_inode(struct ubifs_info *c, - ino_t xattr_inum) { } static inline int ubifs_purge_xattrs(struct inode *host) { return 0; diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c index f734588b224a..c21a0c2b3e90 100644 --- a/fs/ubifs/xattr.c +++ b/fs/ubifs/xattr.c @@ -48,19 +48,6 @@ #include <linux/slab.h> #include <linux/xattr.h> -/* - * Extended attribute type constants. - * - * USER_XATTR: user extended attribute ("user.*") - * TRUSTED_XATTR: trusted extended attribute ("trusted.*) - * SECURITY_XATTR: security extended attribute ("security.*") - */ -enum { - USER_XATTR, - TRUSTED_XATTR, - SECURITY_XATTR, -}; - static const struct inode_operations empty_iops; static const struct file_operations empty_fops; @@ -532,8 +519,6 @@ int ubifs_purge_xattrs(struct inode *host) ubifs_err(c, "dead directory entry '%s', error %d", xent->name, err); ubifs_ro_mode(c, err); - kfree(pxent); - kfree(xent); goto out_err; } @@ -541,16 +526,12 @@ int ubifs_purge_xattrs(struct inode *host) clear_nlink(xino); err = remove_xattr(c, host, xino, &nm); + iput(xino); if (err) { - kfree(pxent); - kfree(xent); - iput(xino); ubifs_err(c, "cannot remove xattr, error %d", err); goto out_err; } - iput(xino); - kfree(pxent); pxent = xent; key_read(c, &xent->key, &key); @@ -566,32 +547,12 @@ int ubifs_purge_xattrs(struct inode *host) return 0; out_err: + kfree(pxent); + kfree(xent); up_write(&ubifs_inode(host)->xattr_sem); return err; } -/** - * ubifs_evict_xattr_inode - Evict an xattr inode. - * @c: UBIFS file-system description object - * @xattr_inum: xattr inode number - * - * When an inode that hosts xattrs is being removed we have to make sure - * that cached inodes of the xattrs also get removed from the inode cache - * otherwise we'd waste memory. This function looks up an inode from the - * inode cache and clears the link counter such that iput() will evict - * the inode. - */ -void ubifs_evict_xattr_inode(struct ubifs_info *c, ino_t xattr_inum) -{ - struct inode *inode; - - inode = ilookup(c->vfs_sb, xattr_inum); - if (inode) { - clear_nlink(inode); - iput(inode); - } -} - static int ubifs_xattr_remove(struct inode *host, const char *name) { struct inode *inode; |