Skip to content

Commit

Permalink
Merge tag 'upstream-5.6-rc1' of git://git.kernel.org/pub/scm/linux/ke…
Browse files Browse the repository at this point in the history
…rnel/git/rw/ubifs

Pull UBI/UBIFS updates from Miquel Raynal:
 "This pull request contains mostly fixes for UBI and UBIFS:

  UBI:
   - Fixes for memory leaks in error paths
   - Fix for an logic error in a fastmap selfcheck

  UBIFS:
   - Fix for FS_IOC_SETFLAGS related to fscrypt flag
   - Support for FS_ENCRYPT_FL
   - Fix for a dead lock in bulk-read mode"

Sent on behalf of Richard Weinberger who is traveling.

* tag 'upstream-5.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs:
  ubi: Fix an error pointer dereference in error handling code
  ubifs: Fix memory leak from c->sup_node
  ubifs: Fix ino_t format warnings in orphan_delete()
  ubifs: Fix deadlock in concurrent bulk-read and writepage
  ubifs: Fix wrong memory allocation
  ubi: Free the normal volumes in error paths of ubi_attach_mtd_dev()
  ubi: Check the presence of volume before call ubi_fastmap_destroy_checkmap()
  ubifs: Add support for FS_ENCRYPT_FL
  ubifs: Fix FS_IOC_SETFLAGS unexpectedly clearing encrypt flag
  ubi: wl: Remove set but not used variable 'prev_e'
  ubi: fastmap: Fix inverted logic in seen selfcheck
  • Loading branch information
Linus Torvalds committed Jan 30, 2020
2 parents 6e135ba + 5d3805a commit e84bcd6
Show file tree
Hide file tree
Showing 11 changed files with 63 additions and 31 deletions.
2 changes: 1 addition & 1 deletion drivers/mtd/ubi/attach.c
Original file line number Diff line number Diff line change
Expand Up @@ -1640,7 +1640,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
out_wl:
ubi_wl_close(ubi);
out_vtbl:
ubi_free_internal_volumes(ubi);
ubi_free_all_volumes(ubi);
vfree(ubi->vtbl);
out_ai:
destroy_ai(ai);
Expand Down
31 changes: 26 additions & 5 deletions drivers/mtd/ubi/build.c
Original file line number Diff line number Diff line change
Expand Up @@ -503,21 +503,42 @@ static void uif_close(struct ubi_device *ubi)
}

/**
* ubi_free_internal_volumes - free internal volumes.
* ubi_free_volumes_from - free volumes from specific index.
* @ubi: UBI device description object
* @from: the start index used for volume free.
*/
void ubi_free_internal_volumes(struct ubi_device *ubi)
static void ubi_free_volumes_from(struct ubi_device *ubi, int from)
{
int i;

for (i = ubi->vtbl_slots;
i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) {
for (i = from; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) {
if (!ubi->volumes[i])
continue;
ubi_eba_replace_table(ubi->volumes[i], NULL);
ubi_fastmap_destroy_checkmap(ubi->volumes[i]);
kfree(ubi->volumes[i]);
ubi->volumes[i] = NULL;
}
}

/**
* ubi_free_all_volumes - free all volumes.
* @ubi: UBI device description object
*/
void ubi_free_all_volumes(struct ubi_device *ubi)
{
ubi_free_volumes_from(ubi, 0);
}

/**
* ubi_free_internal_volumes - free internal volumes.
* @ubi: UBI device description object
*/
void ubi_free_internal_volumes(struct ubi_device *ubi)
{
ubi_free_volumes_from(ubi, ubi->vtbl_slots);
}

static int get_bad_peb_limit(const struct ubi_device *ubi, int max_beb_per1024)
{
int limit, device_pebs;
Expand Down Expand Up @@ -1013,7 +1034,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
out_detach:
ubi_devices[ubi_num] = NULL;
ubi_wl_close(ubi);
ubi_free_internal_volumes(ubi);
ubi_free_all_volumes(ubi);
vfree(ubi->vtbl);
out_free:
vfree(ubi->peb_buf);
Expand Down
23 changes: 13 additions & 10 deletions drivers/mtd/ubi/fastmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ static int self_check_seen(struct ubi_device *ubi, unsigned long *seen)
return 0;

for (pnum = 0; pnum < ubi->peb_count; pnum++) {
if (test_bit(pnum, seen) && ubi->lookuptbl[pnum]) {
if (!test_bit(pnum, seen) && ubi->lookuptbl[pnum]) {
ubi_err(ubi, "self-check failed for PEB %d, fastmap didn't see it", pnum);
ret = -EINVAL;
}
Expand Down Expand Up @@ -1137,7 +1137,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
struct rb_node *tmp_rb;
int ret, i, j, free_peb_count, used_peb_count, vol_count;
int scrub_peb_count, erase_peb_count;
unsigned long *seen_pebs = NULL;
unsigned long *seen_pebs;

fm_raw = ubi->fm_buf;
memset(ubi->fm_buf, 0, ubi->fm_size);
Expand All @@ -1151,7 +1151,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
dvbuf = new_fm_vbuf(ubi, UBI_FM_DATA_VOLUME_ID);
if (!dvbuf) {
ret = -ENOMEM;
goto out_kfree;
goto out_free_avbuf;
}

avhdr = ubi_get_vid_hdr(avbuf);
Expand All @@ -1160,7 +1160,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
seen_pebs = init_seen(ubi);
if (IS_ERR(seen_pebs)) {
ret = PTR_ERR(seen_pebs);
goto out_kfree;
goto out_free_dvbuf;
}

spin_lock(&ubi->volumes_lock);
Expand Down Expand Up @@ -1328,7 +1328,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
ret = ubi_io_write_vid_hdr(ubi, new_fm->e[0]->pnum, avbuf);
if (ret) {
ubi_err(ubi, "unable to write vid_hdr to fastmap SB!");
goto out_kfree;
goto out_free_seen;
}

for (i = 0; i < new_fm->used_blocks; i++) {
Expand All @@ -1350,7 +1350,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
if (ret) {
ubi_err(ubi, "unable to write vid_hdr to PEB %i!",
new_fm->e[i]->pnum);
goto out_kfree;
goto out_free_seen;
}
}

Expand All @@ -1360,7 +1360,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
if (ret) {
ubi_err(ubi, "unable to write fastmap to PEB %i!",
new_fm->e[i]->pnum);
goto out_kfree;
goto out_free_seen;
}
}

Expand All @@ -1370,10 +1370,13 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
ret = self_check_seen(ubi, seen_pebs);
dbg_bld("fastmap written!");

out_kfree:
ubi_free_vid_buf(avbuf);
ubi_free_vid_buf(dvbuf);
out_free_seen:
free_seen(seen_pebs);
out_free_dvbuf:
ubi_free_vid_buf(dvbuf);
out_free_avbuf:
ubi_free_vid_buf(avbuf);

out:
return ret;
}
Expand Down
1 change: 1 addition & 0 deletions drivers/mtd/ubi/ubi.h
Original file line number Diff line number Diff line change
Expand Up @@ -950,6 +950,7 @@ int ubi_volume_notify(struct ubi_device *ubi, struct ubi_volume *vol,
int ubi_notify_all(struct ubi_device *ubi, int ntype,
struct notifier_block *nb);
int ubi_enumerate_volumes(struct notifier_block *nb);
void ubi_free_all_volumes(struct ubi_device *ubi);
void ubi_free_internal_volumes(struct ubi_device *ubi);

/* kapi.c */
Expand Down
8 changes: 2 additions & 6 deletions drivers/mtd/ubi/vtbl.c
Original file line number Diff line number Diff line change
Expand Up @@ -782,7 +782,7 @@ static int check_attaching_info(const struct ubi_device *ubi,
*/
int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_attach_info *ai)
{
int i, err;
int err;
struct ubi_ainf_volume *av;

empty_vtbl_record.crc = cpu_to_be32(0xf116c36b);
Expand Down Expand Up @@ -851,11 +851,7 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_attach_info *ai)

out_free:
vfree(ubi->vtbl);
for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) {
ubi_fastmap_destroy_checkmap(ubi->volumes[i]);
kfree(ubi->volumes[i]);
ubi->volumes[i] = NULL;
}
ubi_free_all_volumes(ubi);
return err;
}

Expand Down
3 changes: 1 addition & 2 deletions drivers/mtd/ubi/wl.c
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ static struct ubi_wl_entry *find_wl_entry(struct ubi_device *ubi,
struct rb_root *root, int diff)
{
struct rb_node *p;
struct ubi_wl_entry *e, *prev_e = NULL;
struct ubi_wl_entry *e;
int max;

e = rb_entry(rb_first(root), struct ubi_wl_entry, u.rb);
Expand All @@ -334,7 +334,6 @@ static struct ubi_wl_entry *find_wl_entry(struct ubi_device *ubi,
p = p->rb_left;
else {
p = p->rb_right;
prev_e = e;
e = e1;
}
}
Expand Down
4 changes: 3 additions & 1 deletion fs/ubifs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -786,7 +786,9 @@ static int ubifs_do_bulk_read(struct ubifs_info *c, struct bu_info *bu,

if (page_offset > end_index)
break;
page = find_or_create_page(mapping, page_offset, ra_gfp_mask);
page = pagecache_get_page(mapping, page_offset,
FGP_LOCK|FGP_ACCESSED|FGP_CREAT|FGP_NOWAIT,
ra_gfp_mask);
if (!page)
break;
if (!PageUptodate(page))
Expand Down
14 changes: 11 additions & 3 deletions fs/ubifs/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@
#include "ubifs.h"

/* Need to be kept consistent with checked flags in ioctl2ubifs() */
#define UBIFS_SUPPORTED_IOCTL_FLAGS \
#define UBIFS_SETTABLE_IOCTL_FLAGS \
(FS_COMPR_FL | FS_SYNC_FL | FS_APPEND_FL | \
FS_IMMUTABLE_FL | FS_DIRSYNC_FL)

/* Need to be kept consistent with checked flags in ubifs2ioctl() */
#define UBIFS_GETTABLE_IOCTL_FLAGS \
(UBIFS_SETTABLE_IOCTL_FLAGS | FS_ENCRYPT_FL)

/**
* ubifs_set_inode_flags - set VFS inode flags.
* @inode: VFS inode to set flags for
Expand Down Expand Up @@ -91,6 +95,8 @@ static int ubifs2ioctl(int ubifs_flags)
ioctl_flags |= FS_IMMUTABLE_FL;
if (ubifs_flags & UBIFS_DIRSYNC_FL)
ioctl_flags |= FS_DIRSYNC_FL;
if (ubifs_flags & UBIFS_CRYPT_FL)
ioctl_flags |= FS_ENCRYPT_FL;

return ioctl_flags;
}
Expand All @@ -113,7 +119,8 @@ static int setflags(struct inode *inode, int flags)
if (err)
goto out_unlock;

ui->flags = ioctl2ubifs(flags);
ui->flags &= ~ioctl2ubifs(UBIFS_SETTABLE_IOCTL_FLAGS);
ui->flags |= ioctl2ubifs(flags);
ubifs_set_inode_flags(inode);
inode->i_ctime = current_time(inode);
release = ui->dirty;
Expand Down Expand Up @@ -155,8 +162,9 @@ long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if (get_user(flags, (int __user *) arg))
return -EFAULT;

if (flags & ~UBIFS_SUPPORTED_IOCTL_FLAGS)
if (flags & ~UBIFS_GETTABLE_IOCTL_FLAGS)
return -EOPNOTSUPP;
flags &= UBIFS_SETTABLE_IOCTL_FLAGS;

if (!S_ISDIR(inode->i_mode))
flags &= ~FS_DIRSYNC_FL;
Expand Down
4 changes: 2 additions & 2 deletions fs/ubifs/orphan.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,15 +129,15 @@ static void __orphan_drop(struct ubifs_info *c, struct ubifs_orphan *o)
static void orphan_delete(struct ubifs_info *c, struct ubifs_orphan *orph)
{
if (orph->del) {
dbg_gen("deleted twice ino %lu", orph->inum);
dbg_gen("deleted twice ino %lu", (unsigned long)orph->inum);
return;
}

if (orph->cmt) {
orph->del = 1;
orph->dnext = c->orph_dnext;
c->orph_dnext = orph;
dbg_gen("delete later ino %lu", orph->inum);
dbg_gen("delete later ino %lu", (unsigned long)orph->inum);
return;
}

Expand Down
2 changes: 1 addition & 1 deletion fs/ubifs/sb.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ static int create_default_filesystem(struct ubifs_info *c)
sup = kzalloc(ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size), GFP_KERNEL);
mst = kzalloc(c->mst_node_alsz, GFP_KERNEL);
idx_node_size = ubifs_idx_node_sz(c, 1);
idx = kzalloc(ALIGN(tmp, c->min_io_size), GFP_KERNEL);
idx = kzalloc(ALIGN(idx_node_size, c->min_io_size), GFP_KERNEL);
ino = kzalloc(ALIGN(UBIFS_INO_NODE_SZ, c->min_io_size), GFP_KERNEL);
cs = kzalloc(ALIGN(UBIFS_CS_NODE_SZ, c->min_io_size), GFP_KERNEL);

Expand Down
2 changes: 2 additions & 0 deletions fs/ubifs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -1599,6 +1599,7 @@ static int mount_ubifs(struct ubifs_info *c)
vfree(c->ileb_buf);
vfree(c->sbuf);
kfree(c->bottom_up_buf);
kfree(c->sup_node);
ubifs_debugging_exit(c);
return err;
}
Expand Down Expand Up @@ -1641,6 +1642,7 @@ static void ubifs_umount(struct ubifs_info *c)
vfree(c->ileb_buf);
vfree(c->sbuf);
kfree(c->bottom_up_buf);
kfree(c->sup_node);
ubifs_debugging_exit(c);
}

Expand Down

0 comments on commit e84bcd6

Please sign in to comment.