Commit 163c3e3d authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-linus-5.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs

Pull JFFS2, UBI and UBIFS updates from Richard Weinberger:
 "JFFS2:
   - Fix for a corner case while mounting
   - Fix for an use-after-free issue

  UBI:
   - Fix for a memory load while attaching
   - Don't produce an anchor PEB with fastmap being disabled

  UBIFS:
   - Fix for orphan inode logic
   - Spelling fixes
   - New mount option to specify filesystem version"

* tag 'for-linus-5.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs:
  jffs2: fix UAF problem
  jffs2: fix jffs2 mounting failure
  ubifs: Fix wrong orphan node deletion in ubifs_jnl_update|rename
  ubi: fastmap: Free fastmap next anchor peb during detach
  ubi: fastmap: Don't produce the initial next anchor PEB when fastmap is disabled
  ubifs: misc.h: delete a duplicated word
  ubifs: add option to specify version for new file systems
parents 4bcf69e5 798b7347
...@@ -381,6 +381,11 @@ static void ubi_fastmap_close(struct ubi_device *ubi) ...@@ -381,6 +381,11 @@ static void ubi_fastmap_close(struct ubi_device *ubi)
ubi->fm_anchor = NULL; ubi->fm_anchor = NULL;
} }
if (ubi->fm_next_anchor) {
return_unused_peb(ubi, ubi->fm_next_anchor);
ubi->fm_next_anchor = NULL;
}
if (ubi->fm) { if (ubi->fm) {
for (i = 0; i < ubi->fm->used_blocks; i++) for (i = 0; i < ubi->fm->used_blocks; i++)
kfree(ubi->fm->e[i]); kfree(ubi->fm->e[i]);
......
...@@ -1086,7 +1086,8 @@ static int __erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk) ...@@ -1086,7 +1086,8 @@ static int __erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk)
if (!err) { if (!err) {
spin_lock(&ubi->wl_lock); spin_lock(&ubi->wl_lock);
if (!ubi->fm_next_anchor && e->pnum < UBI_FM_MAX_START) { if (!ubi->fm_disabled && !ubi->fm_next_anchor &&
e->pnum < UBI_FM_MAX_START) {
/* Abort anchor production, if needed it will be /* Abort anchor production, if needed it will be
* enabled again in the wear leveling started below. * enabled again in the wear leveling started below.
*/ */
......
...@@ -590,10 +590,14 @@ static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry) ...@@ -590,10 +590,14 @@ static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry)
int ret; int ret;
uint32_t now = JFFS2_NOW(); uint32_t now = JFFS2_NOW();
mutex_lock(&f->sem);
for (fd = f->dents ; fd; fd = fd->next) { for (fd = f->dents ; fd; fd = fd->next) {
if (fd->ino) if (fd->ino) {
mutex_unlock(&f->sem);
return -ENOTEMPTY; return -ENOTEMPTY;
} }
}
mutex_unlock(&f->sem);
ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name, ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name,
dentry->d_name.len, f, now); dentry->d_name.len, f, now);
......
...@@ -261,7 +261,8 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) ...@@ -261,7 +261,8 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
} }
#endif #endif
if (c->nr_erasing_blocks) { if (c->nr_erasing_blocks) {
if ( !c->used_size && ((c->nr_free_blocks+empty_blocks+bad_blocks)!= c->nr_blocks || bad_blocks == c->nr_blocks) ) { if (!c->used_size && !c->unchecked_size &&
((c->nr_free_blocks+empty_blocks+bad_blocks) != c->nr_blocks || bad_blocks == c->nr_blocks)) {
pr_notice("Cowardly refusing to erase blocks on filesystem with no valid JFFS2 nodes\n"); pr_notice("Cowardly refusing to erase blocks on filesystem with no valid JFFS2 nodes\n");
pr_notice("empty_blocks %d, bad_blocks %d, c->nr_blocks %d\n", pr_notice("empty_blocks %d, bad_blocks %d, c->nr_blocks %d\n",
empty_blocks, bad_blocks, c->nr_blocks); empty_blocks, bad_blocks, c->nr_blocks);
......
...@@ -539,7 +539,7 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, ...@@ -539,7 +539,7 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir,
const struct fscrypt_name *nm, const struct inode *inode, const struct fscrypt_name *nm, const struct inode *inode,
int deletion, int xent) int deletion, int xent)
{ {
int err, dlen, ilen, len, lnum, ino_offs, dent_offs; int err, dlen, ilen, len, lnum, ino_offs, dent_offs, orphan_added = 0;
int aligned_dlen, aligned_ilen, sync = IS_DIRSYNC(dir); int aligned_dlen, aligned_ilen, sync = IS_DIRSYNC(dir);
int last_reference = !!(deletion && inode->i_nlink == 0); int last_reference = !!(deletion && inode->i_nlink == 0);
struct ubifs_inode *ui = ubifs_inode(inode); struct ubifs_inode *ui = ubifs_inode(inode);
...@@ -630,6 +630,7 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, ...@@ -630,6 +630,7 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir,
goto out_finish; goto out_finish;
} }
ui->del_cmtno = c->cmt_no; ui->del_cmtno = c->cmt_no;
orphan_added = 1;
} }
err = write_head(c, BASEHD, dent, len, &lnum, &dent_offs, sync); err = write_head(c, BASEHD, dent, len, &lnum, &dent_offs, sync);
...@@ -702,7 +703,7 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, ...@@ -702,7 +703,7 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir,
kfree(dent); kfree(dent);
out_ro: out_ro:
ubifs_ro_mode(c, err); ubifs_ro_mode(c, err);
if (last_reference) if (orphan_added)
ubifs_delete_orphan(c, inode->i_ino); ubifs_delete_orphan(c, inode->i_ino);
finish_reservation(c); finish_reservation(c);
return err; return err;
...@@ -1218,7 +1219,7 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir, ...@@ -1218,7 +1219,7 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
void *p; void *p;
union ubifs_key key; union ubifs_key key;
struct ubifs_dent_node *dent, *dent2; struct ubifs_dent_node *dent, *dent2;
int err, dlen1, dlen2, ilen, lnum, offs, len; int err, dlen1, dlen2, ilen, lnum, offs, len, orphan_added = 0;
int aligned_dlen1, aligned_dlen2, plen = UBIFS_INO_NODE_SZ; int aligned_dlen1, aligned_dlen2, plen = UBIFS_INO_NODE_SZ;
int last_reference = !!(new_inode && new_inode->i_nlink == 0); int last_reference = !!(new_inode && new_inode->i_nlink == 0);
int move = (old_dir != new_dir); int move = (old_dir != new_dir);
...@@ -1334,6 +1335,7 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir, ...@@ -1334,6 +1335,7 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
goto out_finish; goto out_finish;
} }
new_ui->del_cmtno = c->cmt_no; new_ui->del_cmtno = c->cmt_no;
orphan_added = 1;
} }
err = write_head(c, BASEHD, dent, len, &lnum, &offs, sync); err = write_head(c, BASEHD, dent, len, &lnum, &offs, sync);
...@@ -1415,7 +1417,7 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir, ...@@ -1415,7 +1417,7 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
release_head(c, BASEHD); release_head(c, BASEHD);
out_ro: out_ro:
ubifs_ro_mode(c, err); ubifs_ro_mode(c, err);
if (last_reference) if (orphan_added)
ubifs_delete_orphan(c, new_inode->i_ino); ubifs_delete_orphan(c, new_inode->i_ino);
out_finish: out_finish:
finish_reservation(c); finish_reservation(c);
......
...@@ -121,7 +121,7 @@ static inline const char *ubifs_compr_name(struct ubifs_info *c, int compr_type) ...@@ -121,7 +121,7 @@ static inline const char *ubifs_compr_name(struct ubifs_info *c, int compr_type)
* ubifs_wbuf_sync - synchronize write-buffer. * ubifs_wbuf_sync - synchronize write-buffer.
* @wbuf: write-buffer to synchronize * @wbuf: write-buffer to synchronize
* *
* This is the same as as 'ubifs_wbuf_sync_nolock()' but it does not assume * This is the same as 'ubifs_wbuf_sync_nolock()' but it does not assume
* that the write-buffer is already locked. * that the write-buffer is already locked.
*/ */
static inline int ubifs_wbuf_sync(struct ubifs_wbuf *wbuf) static inline int ubifs_wbuf_sync(struct ubifs_wbuf *wbuf)
......
...@@ -174,6 +174,7 @@ static int create_default_filesystem(struct ubifs_info *c) ...@@ -174,6 +174,7 @@ static int create_default_filesystem(struct ubifs_info *c)
tmp64 = (long long)max_buds * c->leb_size; tmp64 = (long long)max_buds * c->leb_size;
if (big_lpt) if (big_lpt)
sup_flags |= UBIFS_FLG_BIGLPT; sup_flags |= UBIFS_FLG_BIGLPT;
if (ubifs_default_version > 4)
sup_flags |= UBIFS_FLG_DOUBLE_HASH; sup_flags |= UBIFS_FLG_DOUBLE_HASH;
if (ubifs_authenticated(c)) { if (ubifs_authenticated(c)) {
...@@ -200,7 +201,7 @@ static int create_default_filesystem(struct ubifs_info *c) ...@@ -200,7 +201,7 @@ static int create_default_filesystem(struct ubifs_info *c)
sup->jhead_cnt = cpu_to_le32(DEFAULT_JHEADS_CNT); sup->jhead_cnt = cpu_to_le32(DEFAULT_JHEADS_CNT);
sup->fanout = cpu_to_le32(DEFAULT_FANOUT); sup->fanout = cpu_to_le32(DEFAULT_FANOUT);
sup->lsave_cnt = cpu_to_le32(c->lsave_cnt); sup->lsave_cnt = cpu_to_le32(c->lsave_cnt);
sup->fmt_version = cpu_to_le32(UBIFS_FORMAT_VERSION); sup->fmt_version = cpu_to_le32(ubifs_default_version);
sup->time_gran = cpu_to_le32(DEFAULT_TIME_GRAN); sup->time_gran = cpu_to_le32(DEFAULT_TIME_GRAN);
if (c->mount_opts.override_compr) if (c->mount_opts.override_compr)
sup->default_compr = cpu_to_le16(c->mount_opts.compr_type); sup->default_compr = cpu_to_le16(c->mount_opts.compr_type);
......
...@@ -26,6 +26,24 @@ ...@@ -26,6 +26,24 @@
#include <linux/writeback.h> #include <linux/writeback.h>
#include "ubifs.h" #include "ubifs.h"
static int ubifs_default_version_set(const char *val, const struct kernel_param *kp)
{
int n = 0, ret;
ret = kstrtoint(val, 10, &n);
if (ret != 0 || n < 4 || n > UBIFS_FORMAT_VERSION)
return -EINVAL;
return param_set_int(val, kp);
}
static const struct kernel_param_ops ubifs_default_version_ops = {
.set = ubifs_default_version_set,
.get = param_get_int,
};
int ubifs_default_version = UBIFS_FORMAT_VERSION;
module_param_cb(default_version, &ubifs_default_version_ops, &ubifs_default_version, 0600);
/* /*
* Maximum amount of memory we may 'kmalloc()' without worrying that we are * Maximum amount of memory we may 'kmalloc()' without worrying that we are
* allocating too much. * allocating too much.
......
...@@ -1504,6 +1504,7 @@ extern const struct file_operations ubifs_dir_operations; ...@@ -1504,6 +1504,7 @@ extern const struct file_operations ubifs_dir_operations;
extern const struct inode_operations ubifs_dir_inode_operations; extern const struct inode_operations ubifs_dir_inode_operations;
extern const struct inode_operations ubifs_symlink_inode_operations; extern const struct inode_operations ubifs_symlink_inode_operations;
extern struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT]; extern struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT];
extern int ubifs_default_version;
/* auth.c */ /* auth.c */
static inline int ubifs_authenticated(const struct ubifs_info *c) static inline int ubifs_authenticated(const struct ubifs_info *c)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment