Skip to content

Commit

Permalink
Merge tag 'ubifs-for-linus-6.13-rc1' of git://git.kernel.org/pub/scm/…
Browse files Browse the repository at this point in the history
…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
  ...
  • Loading branch information
torvalds committed Nov 30, 2024
2 parents e864eff + bcdcb11 commit 04b43ea
Show file tree
Hide file tree
Showing 22 changed files with 96 additions and 98 deletions.
12 changes: 6 additions & 6 deletions drivers/mtd/ubi/attach.c
Original file line number Diff line number Diff line change
Expand Up @@ -1447,7 +1447,7 @@ static int scan_all(struct ubi_device *ubi, struct ubi_attach_info *ai,
return err;
}

static struct ubi_attach_info *alloc_ai(void)
static struct ubi_attach_info *alloc_ai(const char *slab_name)
{
struct ubi_attach_info *ai;

Expand All @@ -1461,7 +1461,7 @@ static struct ubi_attach_info *alloc_ai(void)
INIT_LIST_HEAD(&ai->alien);
INIT_LIST_HEAD(&ai->fastmap);
ai->volumes = RB_ROOT;
ai->aeb_slab_cache = kmem_cache_create("ubi_aeb_slab_cache",
ai->aeb_slab_cache = kmem_cache_create(slab_name,
sizeof(struct ubi_ainf_peb),
0, 0, NULL);
if (!ai->aeb_slab_cache) {
Expand Down Expand Up @@ -1491,7 +1491,7 @@ static int scan_fast(struct ubi_device *ubi, struct ubi_attach_info **ai)

err = -ENOMEM;

scan_ai = alloc_ai();
scan_ai = alloc_ai("ubi_aeb_slab_cache_fastmap");
if (!scan_ai)
goto out;

Expand Down Expand Up @@ -1557,7 +1557,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
int err;
struct ubi_attach_info *ai;

ai = alloc_ai();
ai = alloc_ai("ubi_aeb_slab_cache");
if (!ai)
return -ENOMEM;

Expand All @@ -1575,7 +1575,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
if (err > 0 || mtd_is_eccerr(err)) {
if (err != UBI_NO_FASTMAP) {
destroy_ai(ai);
ai = alloc_ai();
ai = alloc_ai("ubi_aeb_slab_cache");
if (!ai)
return -ENOMEM;

Expand Down Expand Up @@ -1614,7 +1614,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
if (ubi->fm && ubi_dbg_chk_fastmap(ubi)) {
struct ubi_attach_info *scan_ai;

scan_ai = alloc_ai();
scan_ai = alloc_ai("ubi_aeb_slab_cache_dbg_chk_fastmap");
if (!scan_ai) {
err = -ENOMEM;
goto out_wl;
Expand Down
19 changes: 16 additions & 3 deletions drivers/mtd/ubi/fastmap-wl.c
Original file line number Diff line number Diff line change
Expand Up @@ -346,14 +346,27 @@ int ubi_wl_get_peb(struct ubi_device *ubi)
* WL sub-system.
*
* @ubi: UBI device description object
* @need_fill: whether to fill wear-leveling pool when no PEBs are found
*/
static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi)
static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi,
bool need_fill)
{
struct ubi_fm_pool *pool = &ubi->fm_wl_pool;
int pnum;

if (pool->used == pool->size)
if (pool->used == pool->size) {
if (need_fill && !ubi->fm_work_scheduled) {
/*
* We cannot update the fastmap here because this
* function is called in atomic context.
* Let's fail here and refill/update it as soon as
* possible.
*/
ubi->fm_work_scheduled = 1;
schedule_work(&ubi->fm_work);
}
return NULL;
}

pnum = pool->pebs[pool->used];
return ubi->lookuptbl[pnum];
Expand All @@ -375,7 +388,7 @@ static bool need_wear_leveling(struct ubi_device *ubi)
if (!ubi->used.rb_node)
return false;

e = next_peb_for_wl(ubi);
e = next_peb_for_wl(ubi, false);
if (!e) {
if (!ubi->free.rb_node)
return false;
Expand Down
2 changes: 1 addition & 1 deletion drivers/mtd/ubi/nvmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ static int ubi_nvmem_reg_read(void *priv, unsigned int from,
if (err)
return err;

return bytes_left == 0 ? 0 : -EIO;
return 0;
}

static int ubi_nvmem_add(struct ubi_volume_info *vi)
Expand Down
3 changes: 2 additions & 1 deletion drivers/mtd/ubi/ubi.h
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,7 @@ struct ubi_debug_info {
* @peb_buf: a buffer of PEB size used for different purposes
* @buf_mutex: protects @peb_buf
* @ckvol_mutex: serializes static volume checking when opening
* @wl_reboot_notifier: close all wear-leveling work before reboot
*
* @dbg: debugging information for this UBI device
*/
Expand Down Expand Up @@ -651,6 +652,7 @@ struct ubi_device {
void *peb_buf;
struct mutex buf_mutex;
struct mutex ckvol_mutex;
struct notifier_block wl_reboot_notifier;

struct ubi_debug_info dbg;
};
Expand Down Expand Up @@ -831,7 +833,6 @@ void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av);
struct ubi_ainf_peb *ubi_early_get_peb(struct ubi_device *ubi,
struct ubi_attach_info *ai);
int ubi_attach(struct ubi_device *ubi, int force_scan);
void ubi_destroy_ai(struct ubi_attach_info *ai);

/* vtbl.c */
int ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
Expand Down
2 changes: 2 additions & 0 deletions drivers/mtd/ubi/vmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,10 @@ static struct fwnode_handle *find_volume_fwnode(struct ubi_volume *vol)
vol->vol_id != volid)
continue;

fwnode_handle_put(fw_vols);
return fw_vol;
}
fwnode_handle_put(fw_vols);

return NULL;
}
Expand Down
32 changes: 30 additions & 2 deletions drivers/mtd/ubi/wl.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
#include <linux/crc32.h>
#include <linux/freezer.h>
#include <linux/kthread.h>
#include <linux/reboot.h>
#include "ubi.h"
#include "wl.h"

Expand Down Expand Up @@ -127,6 +128,8 @@ static int self_check_in_wl_tree(const struct ubi_device *ubi,
struct ubi_wl_entry *e, struct rb_root *root);
static int self_check_in_pq(const struct ubi_device *ubi,
struct ubi_wl_entry *e);
static int ubi_wl_reboot_notifier(struct notifier_block *n,
unsigned long state, void *cmd);

/**
* wl_tree_add - add a wear-leveling entry to a WL RB-tree.
Expand Down Expand Up @@ -683,7 +686,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
ubi_assert(!ubi->move_to_put);

#ifdef CONFIG_MTD_UBI_FASTMAP
if (!next_peb_for_wl(ubi) ||
if (!next_peb_for_wl(ubi, true) ||
#else
if (!ubi->free.rb_node ||
#endif
Expand Down Expand Up @@ -846,7 +849,14 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
goto out_not_moved;
}
if (err == MOVE_RETRY) {
scrubbing = 1;
/*
* For source PEB:
* 1. The scrubbing is set for scrub type PEB, it will
* be put back into ubi->scrub list.
* 2. Non-scrub type PEB will be put back into ubi->used
* list.
*/
keep = 1;
dst_leb_clean = 1;
goto out_not_moved;
}
Expand Down Expand Up @@ -1943,6 +1953,13 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
if (!ubi->ro_mode && !ubi->fm_disabled)
ubi_ensure_anchor_pebs(ubi);
#endif

if (!ubi->wl_reboot_notifier.notifier_call) {
ubi->wl_reboot_notifier.notifier_call = ubi_wl_reboot_notifier;
ubi->wl_reboot_notifier.priority = 1; /* Higher than MTD */
register_reboot_notifier(&ubi->wl_reboot_notifier);
}

return 0;

out_free:
Expand Down Expand Up @@ -1988,6 +2005,17 @@ void ubi_wl_close(struct ubi_device *ubi)
kfree(ubi->lookuptbl);
}

static int ubi_wl_reboot_notifier(struct notifier_block *n,
unsigned long state, void *cmd)
{
struct ubi_device *ubi;

ubi = container_of(n, struct ubi_device, wl_reboot_notifier);
ubi_wl_close(ubi);

return NOTIFY_DONE;
}

/**
* self_check_ec - make sure that the erase counter of a PEB is correct.
* @ubi: UBI device description object
Expand Down
3 changes: 2 additions & 1 deletion drivers/mtd/ubi/wl.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
static void update_fastmap_work_fn(struct work_struct *wrk);
static struct ubi_wl_entry *find_anchor_wl_entry(struct rb_root *root);
static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi);
static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi);
static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi,
bool need_fill);
static bool need_wear_leveling(struct ubi_device *ubi);
static void ubi_fastmap_close(struct ubi_device *ubi);
static inline void ubi_fastmap_init(struct ubi_device *ubi, int *count)
Expand Down
3 changes: 3 additions & 0 deletions fs/jffs2/compr_rtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -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++];
Expand Down
5 changes: 0 additions & 5 deletions fs/jffs2/compr_rubin.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand Down
7 changes: 3 additions & 4 deletions fs/jffs2/erase.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion fs/jffs2/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ static struct jffs2_eraseblock *jffs2_find_gc_block(struct jffs2_sb_info *c)

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);
Expand Down
17 changes: 9 additions & 8 deletions fs/jffs2/nodemgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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 {
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
}
2 changes: 1 addition & 1 deletion fs/jffs2/readinode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
6 changes: 0 additions & 6 deletions fs/ubifs/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
13 changes: 7 additions & 6 deletions fs/ubifs/journal.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions fs/ubifs/lpt_commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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++)
Expand Down
2 changes: 1 addition & 1 deletion fs/ubifs/orphan.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading

0 comments on commit 04b43ea

Please sign in to comment.