From: Greg Kroah-Hartman Date: Sat, 6 May 2023 07:00:11 +0000 (+0900) Subject: 5.10-stable patches X-Git-Tag: v5.15.111~110 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=33f05e9e0c2a0b6e26d0999b6c08110827e11da4;p=thirdparty%2Fkernel%2Fstable-queue.git 5.10-stable patches added patches: revert-ubifs-dirty_cow_znode-fix-memleak-in-error-handling-path.patch sound-oss-dmasound-fix-build-when-drivers-are-mixed-y-m.patch ubi-fix-return-value-overwrite-issue-in-try_write_vid_and_data.patch ubifs-fix-memleak-when-insert_old_idx-failed.patch ubifs-free-memory-for-tmpfile-name.patch --- diff --git a/queue-5.10/revert-ubifs-dirty_cow_znode-fix-memleak-in-error-handling-path.patch b/queue-5.10/revert-ubifs-dirty_cow_znode-fix-memleak-in-error-handling-path.patch new file mode 100644 index 00000000000..c83244d4ac9 --- /dev/null +++ b/queue-5.10/revert-ubifs-dirty_cow_znode-fix-memleak-in-error-handling-path.patch @@ -0,0 +1,47 @@ +From 7d01cb27f6aebc54efbe28d8961a973b8f795b13 Mon Sep 17 00:00:00 2001 +From: Zhihao Cheng +Date: Wed, 1 Mar 2023 20:29:18 +0800 +Subject: Revert "ubifs: dirty_cow_znode: Fix memleak in error handling path" + +From: Zhihao Cheng + +commit 7d01cb27f6aebc54efbe28d8961a973b8f795b13 upstream. + +This reverts commit 122deabfe1428 (ubifs: dirty_cow_znode: Fix memleak +in error handling path). +After commit 122deabfe1428 applied, if insert_old_idx() failed, old +index neither exists in TNC nor in old-index tree. Which means that +old index node could be overwritten in layout_leb_in_gaps(), then +ubifs image will be corrupted in power-cut. + +Fixes: 122deabfe1428 (ubifs: dirty_cow_znode: Fix memleak ... path) +Cc: stable@vger.kernel.org +Signed-off-by: Zhihao Cheng +Signed-off-by: Richard Weinberger +Signed-off-by: Greg Kroah-Hartman +--- + fs/ubifs/tnc.c | 9 +-------- + 1 file changed, 1 insertion(+), 8 deletions(-) + +--- a/fs/ubifs/tnc.c ++++ b/fs/ubifs/tnc.c +@@ -267,18 +267,11 @@ static struct ubifs_znode *dirty_cow_zno + if (zbr->len) { + err = insert_old_idx(c, zbr->lnum, zbr->offs); + if (unlikely(err)) +- /* +- * Obsolete znodes will be freed by tnc_destroy_cnext() +- * or free_obsolete_znodes(), copied up znodes should +- * be added back to tnc and freed by +- * ubifs_destroy_tnc_subtree(). +- */ +- goto out; ++ return ERR_PTR(err); + err = add_idx_dirt(c, zbr->lnum, zbr->len); + } else + err = 0; + +-out: + zbr->znode = zn; + zbr->lnum = 0; + zbr->offs = 0; diff --git a/queue-5.10/series b/queue-5.10/series index 99cb9aca077..db422b85374 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -44,3 +44,8 @@ relayfs-fix-out-of-bounds-access-in-relay_file_read.patch writeback-cgroup-fix-null-ptr-deref-write-in-bdi_spl.patch i2c-omap-fix-standard-mode-false-ack-readings.patch iommu-amd-fix-guest-virtual-apic-table-root-pointer-configuration-in-irte.patch +revert-ubifs-dirty_cow_znode-fix-memleak-in-error-handling-path.patch +ubifs-fix-memleak-when-insert_old_idx-failed.patch +ubi-fix-return-value-overwrite-issue-in-try_write_vid_and_data.patch +ubifs-free-memory-for-tmpfile-name.patch +sound-oss-dmasound-fix-build-when-drivers-are-mixed-y-m.patch diff --git a/queue-5.10/sound-oss-dmasound-fix-build-when-drivers-are-mixed-y-m.patch b/queue-5.10/sound-oss-dmasound-fix-build-when-drivers-are-mixed-y-m.patch new file mode 100644 index 00000000000..adbf6ef15a4 --- /dev/null +++ b/queue-5.10/sound-oss-dmasound-fix-build-when-drivers-are-mixed-y-m.patch @@ -0,0 +1,166 @@ +From 9dd7c46346ca4390f84a7ea9933005eb1b175c15 Mon Sep 17 00:00:00 2001 +From: Randy Dunlap +Date: Tue, 5 Apr 2022 16:41:18 -0700 +Subject: sound/oss/dmasound: fix build when drivers are mixed =y/=m + +From: Randy Dunlap + +commit 9dd7c46346ca4390f84a7ea9933005eb1b175c15 upstream. + +When CONFIG_DMASOUND_ATARI=m and CONFIG_DMASOUND_Q40=y (or vice versa), +dmasound_core.o can be built without dmasound_deinit() being defined, +causing a build error: + +ERROR: modpost: "dmasound_deinit" [sound/oss/dmasound/dmasound_atari.ko] undefined! + +Modify dmasound_core.c and dmasound.h so that dmasound_deinit() is +always available. + +The mixed modes (=y/=m) also mean that several variables and structs +have to be declared in all cases. + +Suggested-by: Arnd Bergmann +Suggested-by: Geert Uytterhoeven +Signed-off-by: Randy Dunlap +Reported-by: kernel test robot +Link: lore.kernel.org/r/202204032138.EFT9qGEd-lkp@intel.com +Cc: Geert Uytterhoeven +Cc: Jaroslav Kysela +Cc: Takashi Iwai +Cc: alsa-devel@alsa-project.org +Link: https://lore.kernel.org/r/20220405234118.24830-1-rdunlap@infradead.org +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + sound/oss/dmasound/dmasound.h | 6 ------ + sound/oss/dmasound/dmasound_core.c | 24 +----------------------- + 2 files changed, 1 insertion(+), 29 deletions(-) + +--- a/sound/oss/dmasound/dmasound.h ++++ b/sound/oss/dmasound/dmasound.h +@@ -88,11 +88,7 @@ static inline int ioctl_return(int __use + */ + + extern int dmasound_init(void); +-#ifdef MODULE + extern void dmasound_deinit(void); +-#else +-#define dmasound_deinit() do { } while (0) +-#endif + + /* description of the set-up applies to either hard or soft settings */ + +@@ -114,9 +110,7 @@ typedef struct { + void *(*dma_alloc)(unsigned int, gfp_t); + void (*dma_free)(void *, unsigned int); + int (*irqinit)(void); +-#ifdef MODULE + void (*irqcleanup)(void); +-#endif + void (*init)(void); + void (*silence)(void); + int (*setFormat)(int); +--- a/sound/oss/dmasound/dmasound_core.c ++++ b/sound/oss/dmasound/dmasound_core.c +@@ -206,12 +206,10 @@ module_param(writeBufSize, int, 0); + + MODULE_LICENSE("GPL"); + +-#ifdef MODULE + static int sq_unit = -1; + static int mixer_unit = -1; + static int state_unit = -1; + static int irq_installed; +-#endif /* MODULE */ + + /* control over who can modify resources shared between play/record */ + static fmode_t shared_resource_owner; +@@ -391,9 +389,6 @@ static const struct file_operations mixe + + static void mixer_init(void) + { +-#ifndef MODULE +- int mixer_unit; +-#endif + mixer_unit = register_sound_mixer(&mixer_fops, -1); + if (mixer_unit < 0) + return; +@@ -1176,9 +1171,6 @@ static const struct file_operations sq_f + static int sq_init(void) + { + const struct file_operations *fops = &sq_fops; +-#ifndef MODULE +- int sq_unit; +-#endif + + sq_unit = register_sound_dsp(fops, -1); + if (sq_unit < 0) { +@@ -1380,9 +1372,6 @@ static const struct file_operations stat + + static int state_init(void) + { +-#ifndef MODULE +- int state_unit; +-#endif + state_unit = register_sound_special(&state_fops, SND_DEV_STATUS); + if (state_unit < 0) + return state_unit ; +@@ -1400,10 +1389,9 @@ static int state_init(void) + int dmasound_init(void) + { + int res ; +-#ifdef MODULE ++ + if (irq_installed) + return -EBUSY; +-#endif + + /* Set up sound queue, /dev/audio and /dev/dsp. */ + +@@ -1422,9 +1410,7 @@ int dmasound_init(void) + printk(KERN_ERR "DMA sound driver: Interrupt initialization failed\n"); + return -ENODEV; + } +-#ifdef MODULE + irq_installed = 1; +-#endif + + printk(KERN_INFO "%s DMA sound driver rev %03d installed\n", + dmasound.mach.name, (DMASOUND_CORE_REVISION<<4) + +@@ -1438,8 +1424,6 @@ int dmasound_init(void) + return 0; + } + +-#ifdef MODULE +- + void dmasound_deinit(void) + { + if (irq_installed) { +@@ -1458,8 +1442,6 @@ void dmasound_deinit(void) + unregister_sound_dsp(sq_unit); + } + +-#else /* !MODULE */ +- + static int dmasound_setup(char *str) + { + int ints[6], size; +@@ -1503,8 +1485,6 @@ static int dmasound_setup(char *str) + + __setup("dmasound=", dmasound_setup); + +-#endif /* !MODULE */ +- + /* + * Conversion tables + */ +@@ -1591,9 +1571,7 @@ char dmasound_alaw2dma8[] = { + + EXPORT_SYMBOL(dmasound); + EXPORT_SYMBOL(dmasound_init); +-#ifdef MODULE + EXPORT_SYMBOL(dmasound_deinit); +-#endif + EXPORT_SYMBOL(dmasound_write_sq); + EXPORT_SYMBOL(dmasound_catchRadius); + #ifdef HAS_8BIT_TABLES diff --git a/queue-5.10/ubi-fix-return-value-overwrite-issue-in-try_write_vid_and_data.patch b/queue-5.10/ubi-fix-return-value-overwrite-issue-in-try_write_vid_and_data.patch new file mode 100644 index 00000000000..9f4b41a5301 --- /dev/null +++ b/queue-5.10/ubi-fix-return-value-overwrite-issue-in-try_write_vid_and_data.patch @@ -0,0 +1,63 @@ +From 31a149d5c13c4cbcf97de3435817263a2d8c9d6e Mon Sep 17 00:00:00 2001 +From: Wang YanQing +Date: Tue, 28 Mar 2023 23:35:34 +0800 +Subject: ubi: Fix return value overwrite issue in try_write_vid_and_data() + +From: Wang YanQing + +commit 31a149d5c13c4cbcf97de3435817263a2d8c9d6e upstream. + +The commit 2d78aee426d8 ("UBI: simplify LEB write and atomic LEB change code") +adds helper function, try_write_vid_and_data(), to simplify the code, but this +helper function has bug, it will return 0 (success) when ubi_io_write_vid_hdr() +or the ubi_io_write_data() return error number (-EIO, etc), because the return +value of ubi_wl_put_peb() will overwrite the original return value. + +This issue will cause unexpected data loss issue, because the caller of this +function and UBIFS willn't know the data is lost. + +Fixes: 2d78aee426d8 ("UBI: simplify LEB write and atomic LEB change code") +Cc: stable@vger.kernel.org +Signed-off-by: Wang YanQing +Reviewed-by: Zhihao Cheng +Signed-off-by: Richard Weinberger +Signed-off-by: Greg Kroah-Hartman +--- + drivers/mtd/ubi/eba.c | 19 ++++++++++++++----- + 1 file changed, 14 insertions(+), 5 deletions(-) + +--- a/drivers/mtd/ubi/eba.c ++++ b/drivers/mtd/ubi/eba.c +@@ -947,7 +947,7 @@ static int try_write_vid_and_data(struct + int offset, int len) + { + struct ubi_device *ubi = vol->ubi; +- int pnum, opnum, err, vol_id = vol->vol_id; ++ int pnum, opnum, err, err2, vol_id = vol->vol_id; + + pnum = ubi_wl_get_peb(ubi); + if (pnum < 0) { +@@ -982,10 +982,19 @@ static int try_write_vid_and_data(struct + out_put: + up_read(&ubi->fm_eba_sem); + +- if (err && pnum >= 0) +- err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1); +- else if (!err && opnum >= 0) +- err = ubi_wl_put_peb(ubi, vol_id, lnum, opnum, 0); ++ if (err && pnum >= 0) { ++ err2 = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1); ++ if (err2) { ++ ubi_warn(ubi, "failed to return physical eraseblock %d, error %d", ++ pnum, err2); ++ } ++ } else if (!err && opnum >= 0) { ++ err2 = ubi_wl_put_peb(ubi, vol_id, lnum, opnum, 0); ++ if (err2) { ++ ubi_warn(ubi, "failed to return physical eraseblock %d, error %d", ++ opnum, err2); ++ } ++ } + + return err; + } diff --git a/queue-5.10/ubifs-fix-memleak-when-insert_old_idx-failed.patch b/queue-5.10/ubifs-fix-memleak-when-insert_old_idx-failed.patch new file mode 100644 index 00000000000..e0e29c3f3e8 --- /dev/null +++ b/queue-5.10/ubifs-fix-memleak-when-insert_old_idx-failed.patch @@ -0,0 +1,222 @@ +From b5fda08ef213352ac2df7447611eb4d383cce929 Mon Sep 17 00:00:00 2001 +From: Zhihao Cheng +Date: Wed, 1 Mar 2023 20:29:19 +0800 +Subject: ubifs: Fix memleak when insert_old_idx() failed + +From: Zhihao Cheng + +commit b5fda08ef213352ac2df7447611eb4d383cce929 upstream. + +Following process will cause a memleak for copied up znode: + +dirty_cow_znode + zn = copy_znode(c, znode); + err = insert_old_idx(c, zbr->lnum, zbr->offs); + if (unlikely(err)) + return ERR_PTR(err); // No one refers to zn. + +Fetch a reproducer in [Link]. + +Function copy_znode() is split into 2 parts: resource allocation +and znode replacement, insert_old_idx() is split in similar way, +so resource cleanup could be done in error handling path without +corrupting metadata(mem & disk). +It's okay that old index inserting is put behind of add_idx_dirt(), +old index is used in layout_leb_in_gaps(), so the two processes do +not depend on each other. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=216705 +Fixes: 1e51764a3c2a ("UBIFS: add new flash file system") +Cc: stable@vger.kernel.org +Signed-off-by: Zhihao Cheng +Signed-off-by: Richard Weinberger +Signed-off-by: Greg Kroah-Hartman +--- + fs/ubifs/tnc.c | 137 ++++++++++++++++++++++++++++++++++++--------------------- + 1 file changed, 87 insertions(+), 50 deletions(-) + +--- a/fs/ubifs/tnc.c ++++ b/fs/ubifs/tnc.c +@@ -44,6 +44,33 @@ enum { + NOT_ON_MEDIA = 3, + }; + ++static void do_insert_old_idx(struct ubifs_info *c, ++ struct ubifs_old_idx *old_idx) ++{ ++ struct ubifs_old_idx *o; ++ struct rb_node **p, *parent = NULL; ++ ++ p = &c->old_idx.rb_node; ++ while (*p) { ++ parent = *p; ++ o = rb_entry(parent, struct ubifs_old_idx, rb); ++ if (old_idx->lnum < o->lnum) ++ p = &(*p)->rb_left; ++ else if (old_idx->lnum > o->lnum) ++ p = &(*p)->rb_right; ++ else if (old_idx->offs < o->offs) ++ p = &(*p)->rb_left; ++ else if (old_idx->offs > o->offs) ++ p = &(*p)->rb_right; ++ else { ++ ubifs_err(c, "old idx added twice!"); ++ kfree(old_idx); ++ } ++ } ++ rb_link_node(&old_idx->rb, parent, p); ++ rb_insert_color(&old_idx->rb, &c->old_idx); ++} ++ + /** + * insert_old_idx - record an index node obsoleted since the last commit start. + * @c: UBIFS file-system description object +@@ -69,35 +96,15 @@ enum { + */ + static int insert_old_idx(struct ubifs_info *c, int lnum, int offs) + { +- struct ubifs_old_idx *old_idx, *o; +- struct rb_node **p, *parent = NULL; ++ struct ubifs_old_idx *old_idx; + + old_idx = kmalloc(sizeof(struct ubifs_old_idx), GFP_NOFS); + if (unlikely(!old_idx)) + return -ENOMEM; + old_idx->lnum = lnum; + old_idx->offs = offs; ++ do_insert_old_idx(c, old_idx); + +- p = &c->old_idx.rb_node; +- while (*p) { +- parent = *p; +- o = rb_entry(parent, struct ubifs_old_idx, rb); +- if (lnum < o->lnum) +- p = &(*p)->rb_left; +- else if (lnum > o->lnum) +- p = &(*p)->rb_right; +- else if (offs < o->offs) +- p = &(*p)->rb_left; +- else if (offs > o->offs) +- p = &(*p)->rb_right; +- else { +- ubifs_err(c, "old idx added twice!"); +- kfree(old_idx); +- return 0; +- } +- } +- rb_link_node(&old_idx->rb, parent, p); +- rb_insert_color(&old_idx->rb, &c->old_idx); + return 0; + } + +@@ -199,23 +206,6 @@ static struct ubifs_znode *copy_znode(st + __set_bit(DIRTY_ZNODE, &zn->flags); + __clear_bit(COW_ZNODE, &zn->flags); + +- ubifs_assert(c, !ubifs_zn_obsolete(znode)); +- __set_bit(OBSOLETE_ZNODE, &znode->flags); +- +- if (znode->level != 0) { +- int i; +- const int n = zn->child_cnt; +- +- /* The children now have new parent */ +- for (i = 0; i < n; i++) { +- struct ubifs_zbranch *zbr = &zn->zbranch[i]; +- +- if (zbr->znode) +- zbr->znode->parent = zn; +- } +- } +- +- atomic_long_inc(&c->dirty_zn_cnt); + return zn; + } + +@@ -234,6 +224,42 @@ static int add_idx_dirt(struct ubifs_inf + } + + /** ++ * replace_znode - replace old znode with new znode. ++ * @c: UBIFS file-system description object ++ * @new_zn: new znode ++ * @old_zn: old znode ++ * @zbr: the branch of parent znode ++ * ++ * Replace old znode with new znode in TNC. ++ */ ++static void replace_znode(struct ubifs_info *c, struct ubifs_znode *new_zn, ++ struct ubifs_znode *old_zn, struct ubifs_zbranch *zbr) ++{ ++ ubifs_assert(c, !ubifs_zn_obsolete(old_zn)); ++ __set_bit(OBSOLETE_ZNODE, &old_zn->flags); ++ ++ if (old_zn->level != 0) { ++ int i; ++ const int n = new_zn->child_cnt; ++ ++ /* The children now have new parent */ ++ for (i = 0; i < n; i++) { ++ struct ubifs_zbranch *child = &new_zn->zbranch[i]; ++ ++ if (child->znode) ++ child->znode->parent = new_zn; ++ } ++ } ++ ++ zbr->znode = new_zn; ++ zbr->lnum = 0; ++ zbr->offs = 0; ++ zbr->len = 0; ++ ++ atomic_long_inc(&c->dirty_zn_cnt); ++} ++ ++/** + * dirty_cow_znode - ensure a znode is not being committed. + * @c: UBIFS file-system description object + * @zbr: branch of znode to check +@@ -265,21 +291,32 @@ static struct ubifs_znode *dirty_cow_zno + return zn; + + if (zbr->len) { +- err = insert_old_idx(c, zbr->lnum, zbr->offs); +- if (unlikely(err)) +- return ERR_PTR(err); ++ struct ubifs_old_idx *old_idx; ++ ++ old_idx = kmalloc(sizeof(struct ubifs_old_idx), GFP_NOFS); ++ if (unlikely(!old_idx)) { ++ err = -ENOMEM; ++ goto out; ++ } ++ old_idx->lnum = zbr->lnum; ++ old_idx->offs = zbr->offs; ++ + err = add_idx_dirt(c, zbr->lnum, zbr->len); +- } else +- err = 0; ++ if (err) { ++ kfree(old_idx); ++ goto out; ++ } + +- zbr->znode = zn; +- zbr->lnum = 0; +- zbr->offs = 0; +- zbr->len = 0; ++ do_insert_old_idx(c, old_idx); ++ } ++ ++ replace_znode(c, zn, znode, zbr); + +- if (unlikely(err)) +- return ERR_PTR(err); + return zn; ++ ++out: ++ kfree(zn); ++ return ERR_PTR(err); + } + + /** diff --git a/queue-5.10/ubifs-free-memory-for-tmpfile-name.patch b/queue-5.10/ubifs-free-memory-for-tmpfile-name.patch new file mode 100644 index 00000000000..99e93e19ed8 --- /dev/null +++ b/queue-5.10/ubifs-free-memory-for-tmpfile-name.patch @@ -0,0 +1,52 @@ +From 1fb815b38bb31d6af9bd0540b8652a0d6fe6cfd3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?M=C3=A5rten=20Lindahl?= +Date: Thu, 30 Mar 2023 11:32:14 +0200 +Subject: ubifs: Free memory for tmpfile name +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: MÃ¥rten Lindahl + +commit 1fb815b38bb31d6af9bd0540b8652a0d6fe6cfd3 upstream. + +When opening a ubifs tmpfile on an encrypted directory, function +fscrypt_setup_filename allocates memory for the name that is to be +stored in the directory entry, but after the name has been copied to the +directory entry inode, the memory is not freed. + +When running kmemleak on it we see that it is registered as a leak. The +report below is triggered by a simple program 'tmpfile' just opening a +tmpfile: + + unreferenced object 0xffff88810178f380 (size 32): + comm "tmpfile", pid 509, jiffies 4294934744 (age 1524.742s) + backtrace: + __kmem_cache_alloc_node + __kmalloc + fscrypt_setup_filename + ubifs_tmpfile + vfs_tmpfile + path_openat + +Free this memory after it has been copied to the inode. + +Signed-off-by: MÃ¥rten Lindahl +Reviewed-by: Zhihao Cheng +Cc: stable@vger.kernel.org +Signed-off-by: Richard Weinberger +Signed-off-by: Greg Kroah-Hartman +--- + fs/ubifs/dir.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/ubifs/dir.c ++++ b/fs/ubifs/dir.c +@@ -425,6 +425,7 @@ static int do_tmpfile(struct inode *dir, + mutex_unlock(&dir_ui->ui_mutex); + + ubifs_release_budget(c, &req); ++ fscrypt_free_filename(&nm); + + return 0; +