From: Greg Kroah-Hartman Date: Sat, 22 Apr 2023 16:38:39 +0000 (+0200) Subject: 5.15-stable patches X-Git-Tag: v4.14.314~60 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=59669f6ee4b9ce9d224e2a0814eb05d6c722e7af;p=thirdparty%2Fkernel%2Fstable-queue.git 5.15-stable patches added patches: kernel-sys.c-fix-and-improve-control-flow-in-__sys_setresid.patch memstick-fix-memory-leak-if-card-device-is-never-registered.patch nilfs2-initialize-unused-bytes-in-segment-summary-blocks.patch --- diff --git a/queue-5.15/kernel-sys.c-fix-and-improve-control-flow-in-__sys_setresid.patch b/queue-5.15/kernel-sys.c-fix-and-improve-control-flow-in-__sys_setresid.patch new file mode 100644 index 00000000000..f009d227b34 --- /dev/null +++ b/queue-5.15/kernel-sys.c-fix-and-improve-control-flow-in-__sys_setresid.patch @@ -0,0 +1,151 @@ +From 659c0ce1cb9efc7f58d380ca4bb2a51ae9e30553 Mon Sep 17 00:00:00 2001 +From: Ondrej Mosnacek +Date: Fri, 17 Feb 2023 17:21:54 +0100 +Subject: kernel/sys.c: fix and improve control flow in __sys_setres[ug]id() + +From: Ondrej Mosnacek + +commit 659c0ce1cb9efc7f58d380ca4bb2a51ae9e30553 upstream. + +Linux Security Modules (LSMs) that implement the "capable" hook will +usually emit an access denial message to the audit log whenever they +"block" the current task from using the given capability based on their +security policy. + +The occurrence of a denial is used as an indication that the given task +has attempted an operation that requires the given access permission, so +the callers of functions that perform LSM permission checks must take care +to avoid calling them too early (before it is decided if the permission is +actually needed to perform the requested operation). + +The __sys_setres[ug]id() functions violate this convention by first +calling ns_capable_setid() and only then checking if the operation +requires the capability or not. It means that any caller that has the +capability granted by DAC (task's capability set) but not by MAC (LSMs) +will generate a "denied" audit record, even if is doing an operation for +which the capability is not required. + +Fix this by reordering the checks such that ns_capable_setid() is checked +last and -EPERM is returned immediately if it returns false. + +While there, also do two small optimizations: +* move the capability check before prepare_creds() and +* bail out early in case of a no-op. + +Link: https://lkml.kernel.org/r/20230217162154.837549-1-omosnace@redhat.com +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Ondrej Mosnacek +Cc: Eric W. Biederman +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + kernel/sys.c | 69 ++++++++++++++++++++++++++++++++++------------------------- + 1 file changed, 40 insertions(+), 29 deletions(-) + +--- a/kernel/sys.c ++++ b/kernel/sys.c +@@ -656,6 +656,7 @@ long __sys_setresuid(uid_t ruid, uid_t e + struct cred *new; + int retval; + kuid_t kruid, keuid, ksuid; ++ bool ruid_new, euid_new, suid_new; + + kruid = make_kuid(ns, ruid); + keuid = make_kuid(ns, euid); +@@ -670,25 +671,29 @@ long __sys_setresuid(uid_t ruid, uid_t e + if ((suid != (uid_t) -1) && !uid_valid(ksuid)) + return -EINVAL; + ++ old = current_cred(); ++ ++ /* check for no-op */ ++ if ((ruid == (uid_t) -1 || uid_eq(kruid, old->uid)) && ++ (euid == (uid_t) -1 || (uid_eq(keuid, old->euid) && ++ uid_eq(keuid, old->fsuid))) && ++ (suid == (uid_t) -1 || uid_eq(ksuid, old->suid))) ++ return 0; ++ ++ ruid_new = ruid != (uid_t) -1 && !uid_eq(kruid, old->uid) && ++ !uid_eq(kruid, old->euid) && !uid_eq(kruid, old->suid); ++ euid_new = euid != (uid_t) -1 && !uid_eq(keuid, old->uid) && ++ !uid_eq(keuid, old->euid) && !uid_eq(keuid, old->suid); ++ suid_new = suid != (uid_t) -1 && !uid_eq(ksuid, old->uid) && ++ !uid_eq(ksuid, old->euid) && !uid_eq(ksuid, old->suid); ++ if ((ruid_new || euid_new || suid_new) && ++ !ns_capable_setid(old->user_ns, CAP_SETUID)) ++ return -EPERM; ++ + new = prepare_creds(); + if (!new) + return -ENOMEM; + +- old = current_cred(); +- +- retval = -EPERM; +- if (!ns_capable_setid(old->user_ns, CAP_SETUID)) { +- if (ruid != (uid_t) -1 && !uid_eq(kruid, old->uid) && +- !uid_eq(kruid, old->euid) && !uid_eq(kruid, old->suid)) +- goto error; +- if (euid != (uid_t) -1 && !uid_eq(keuid, old->uid) && +- !uid_eq(keuid, old->euid) && !uid_eq(keuid, old->suid)) +- goto error; +- if (suid != (uid_t) -1 && !uid_eq(ksuid, old->uid) && +- !uid_eq(ksuid, old->euid) && !uid_eq(ksuid, old->suid)) +- goto error; +- } +- + if (ruid != (uid_t) -1) { + new->uid = kruid; + if (!uid_eq(kruid, old->uid)) { +@@ -753,6 +758,7 @@ long __sys_setresgid(gid_t rgid, gid_t e + struct cred *new; + int retval; + kgid_t krgid, kegid, ksgid; ++ bool rgid_new, egid_new, sgid_new; + + krgid = make_kgid(ns, rgid); + kegid = make_kgid(ns, egid); +@@ -765,23 +771,28 @@ long __sys_setresgid(gid_t rgid, gid_t e + if ((sgid != (gid_t) -1) && !gid_valid(ksgid)) + return -EINVAL; + ++ old = current_cred(); ++ ++ /* check for no-op */ ++ if ((rgid == (gid_t) -1 || gid_eq(krgid, old->gid)) && ++ (egid == (gid_t) -1 || (gid_eq(kegid, old->egid) && ++ gid_eq(kegid, old->fsgid))) && ++ (sgid == (gid_t) -1 || gid_eq(ksgid, old->sgid))) ++ return 0; ++ ++ rgid_new = rgid != (gid_t) -1 && !gid_eq(krgid, old->gid) && ++ !gid_eq(krgid, old->egid) && !gid_eq(krgid, old->sgid); ++ egid_new = egid != (gid_t) -1 && !gid_eq(kegid, old->gid) && ++ !gid_eq(kegid, old->egid) && !gid_eq(kegid, old->sgid); ++ sgid_new = sgid != (gid_t) -1 && !gid_eq(ksgid, old->gid) && ++ !gid_eq(ksgid, old->egid) && !gid_eq(ksgid, old->sgid); ++ if ((rgid_new || egid_new || sgid_new) && ++ !ns_capable_setid(old->user_ns, CAP_SETGID)) ++ return -EPERM; ++ + new = prepare_creds(); + if (!new) + return -ENOMEM; +- old = current_cred(); +- +- retval = -EPERM; +- if (!ns_capable_setid(old->user_ns, CAP_SETGID)) { +- if (rgid != (gid_t) -1 && !gid_eq(krgid, old->gid) && +- !gid_eq(krgid, old->egid) && !gid_eq(krgid, old->sgid)) +- goto error; +- if (egid != (gid_t) -1 && !gid_eq(kegid, old->gid) && +- !gid_eq(kegid, old->egid) && !gid_eq(kegid, old->sgid)) +- goto error; +- if (sgid != (gid_t) -1 && !gid_eq(ksgid, old->gid) && +- !gid_eq(ksgid, old->egid) && !gid_eq(ksgid, old->sgid)) +- goto error; +- } + + if (rgid != (gid_t) -1) + new->gid = krgid; diff --git a/queue-5.15/memstick-fix-memory-leak-if-card-device-is-never-registered.patch b/queue-5.15/memstick-fix-memory-leak-if-card-device-is-never-registered.patch new file mode 100644 index 00000000000..8de753ddfbc --- /dev/null +++ b/queue-5.15/memstick-fix-memory-leak-if-card-device-is-never-registered.patch @@ -0,0 +1,61 @@ +From 4b6d621c9d859ff89e68cebf6178652592676013 Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman +Date: Sat, 1 Apr 2023 22:03:27 +0200 +Subject: memstick: fix memory leak if card device is never registered + +From: Greg Kroah-Hartman + +commit 4b6d621c9d859ff89e68cebf6178652592676013 upstream. + +When calling dev_set_name() memory is allocated for the name for the +struct device. Once that structure device is registered, or attempted +to be registerd, with the driver core, the driver core will handle +cleaning up that memory when the device is removed from the system. + +Unfortunatly for the memstick code, there is an error path that causes +the struct device to never be registered, and so the memory allocated in +dev_set_name will be leaked. Fix that leak by manually freeing it right +before the memory for the device is freed. + +Cc: Maxim Levitsky +Cc: Alex Dubov +Cc: Ulf Hansson +Cc: "Rafael J. Wysocki" +Cc: Hans de Goede +Cc: Kay Sievers +Cc: linux-mmc@vger.kernel.org +Fixes: 0252c3b4f018 ("memstick: struct device - replace bus_id with dev_name(), dev_set_name()") +Cc: stable +Co-developed-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman +Co-developed-by: Mirsad Goran Todorovac +Signed-off-by: Mirsad Goran Todorovac +Link: https://lore.kernel.org/r/20230401200327.16800-1-gregkh@linuxfoundation.org +Signed-off-by: Ulf Hansson +Signed-off-by: Greg Kroah-Hartman +--- + drivers/memstick/core/memstick.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/memstick/core/memstick.c ++++ b/drivers/memstick/core/memstick.c +@@ -410,6 +410,7 @@ static struct memstick_dev *memstick_all + return card; + err_out: + host->card = old_card; ++ kfree_const(card->dev.kobj.name); + kfree(card); + return NULL; + } +@@ -468,8 +469,10 @@ static void memstick_check(struct work_s + put_device(&card->dev); + host->card = NULL; + } +- } else ++ } else { ++ kfree_const(card->dev.kobj.name); + kfree(card); ++ } + } + + out_power_off: diff --git a/queue-5.15/nilfs2-initialize-unused-bytes-in-segment-summary-blocks.patch b/queue-5.15/nilfs2-initialize-unused-bytes-in-segment-summary-blocks.patch new file mode 100644 index 00000000000..17178700840 --- /dev/null +++ b/queue-5.15/nilfs2-initialize-unused-bytes-in-segment-summary-blocks.patch @@ -0,0 +1,80 @@ +From ef832747a82dfbc22a3702219cc716f449b24e4a Mon Sep 17 00:00:00 2001 +From: Ryusuke Konishi +Date: Tue, 18 Apr 2023 02:35:13 +0900 +Subject: nilfs2: initialize unused bytes in segment summary blocks + +From: Ryusuke Konishi + +commit ef832747a82dfbc22a3702219cc716f449b24e4a upstream. + +Syzbot still reports uninit-value in nilfs_add_checksums_on_logs() for +KMSAN enabled kernels after applying commit 7397031622e0 ("nilfs2: +initialize "struct nilfs_binfo_dat"->bi_pad field"). + +This is because the unused bytes at the end of each block in segment +summaries are not initialized. So this fixes the issue by padding the +unused bytes with null bytes. + +Link: https://lkml.kernel.org/r/20230417173513.12598-1-konishi.ryusuke@gmail.com +Signed-off-by: Ryusuke Konishi +Tested-by: Ryusuke Konishi +Reported-by: syzbot+048585f3f4227bb2b49b@syzkaller.appspotmail.com + Link: https://syzkaller.appspot.com/bug?extid=048585f3f4227bb2b49b +Cc: Alexander Potapenko +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + fs/nilfs2/segment.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +--- a/fs/nilfs2/segment.c ++++ b/fs/nilfs2/segment.c +@@ -430,6 +430,23 @@ static int nilfs_segctor_reset_segment_b + return 0; + } + ++/** ++ * nilfs_segctor_zeropad_segsum - zero pad the rest of the segment summary area ++ * @sci: segment constructor object ++ * ++ * nilfs_segctor_zeropad_segsum() zero-fills unallocated space at the end of ++ * the current segment summary block. ++ */ ++static void nilfs_segctor_zeropad_segsum(struct nilfs_sc_info *sci) ++{ ++ struct nilfs_segsum_pointer *ssp; ++ ++ ssp = sci->sc_blk_cnt > 0 ? &sci->sc_binfo_ptr : &sci->sc_finfo_ptr; ++ if (ssp->offset < ssp->bh->b_size) ++ memset(ssp->bh->b_data + ssp->offset, 0, ++ ssp->bh->b_size - ssp->offset); ++} ++ + static int nilfs_segctor_feed_segment(struct nilfs_sc_info *sci) + { + sci->sc_nblk_this_inc += sci->sc_curseg->sb_sum.nblocks; +@@ -438,6 +455,7 @@ static int nilfs_segctor_feed_segment(st + * The current segment is filled up + * (internal code) + */ ++ nilfs_segctor_zeropad_segsum(sci); + sci->sc_curseg = NILFS_NEXT_SEGBUF(sci->sc_curseg); + return nilfs_segctor_reset_segment_buffer(sci); + } +@@ -542,6 +560,7 @@ static int nilfs_segctor_add_file_block( + goto retry; + } + if (unlikely(required)) { ++ nilfs_segctor_zeropad_segsum(sci); + err = nilfs_segbuf_extend_segsum(segbuf); + if (unlikely(err)) + goto failed; +@@ -1531,6 +1550,7 @@ static int nilfs_segctor_collect(struct + nadd = min_t(int, nadd << 1, SC_MAX_SEGDELTA); + sci->sc_stage = prev_stage; + } ++ nilfs_segctor_zeropad_segsum(sci); + nilfs_segctor_truncate_segments(sci, sci->sc_curseg, nilfs->ns_sufile); + return 0; + diff --git a/queue-5.15/series b/queue-5.15/series index 3d8510d2ed8..d527032f04a 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -35,3 +35,6 @@ xen-netback-use-same-error-messages-for-same-errors.patch platform-x86-gigabyte-wmi-add-support-for-x570s-aoru.patch rtmutex-add-acquire-semantics-for-rtmutex-lock-acquisition-slow-path.patch iio-light-tsl2772-fix-reading-proximity-diodes-from-device-tree.patch +nilfs2-initialize-unused-bytes-in-segment-summary-blocks.patch +memstick-fix-memory-leak-if-card-device-is-never-registered.patch +kernel-sys.c-fix-and-improve-control-flow-in-__sys_setresid.patch