From: Greg Kroah-Hartman Date: Sun, 14 Aug 2022 14:48:27 +0000 (+0200) Subject: 5.18-stable patches X-Git-Tag: v5.15.61~104 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e06123b063f9e8af6ece43bfcba6394987f8fcc3;p=thirdparty%2Fkernel%2Fstable-queue.git 5.18-stable patches added patches: __follow_mount_rcu-verify-that-mount_lock-remains-unchanged.patch drivers-base-fix-userspace-break-from-using-bin_attributes-for-cpumap-and-cpulist.patch spmi-trace-fix-stack-out-of-bound-access-in-spmi-tracing-functions.patch --- diff --git a/queue-5.18/__follow_mount_rcu-verify-that-mount_lock-remains-unchanged.patch b/queue-5.18/__follow_mount_rcu-verify-that-mount_lock-remains-unchanged.patch new file mode 100644 index 00000000000..8b441c8326f --- /dev/null +++ b/queue-5.18/__follow_mount_rcu-verify-that-mount_lock-remains-unchanged.patch @@ -0,0 +1,46 @@ +From 20aac6c60981f5bfacd66661d090d907bf1482f0 Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Mon, 4 Jul 2022 17:26:29 -0400 +Subject: __follow_mount_rcu(): verify that mount_lock remains unchanged + +From: Al Viro + +commit 20aac6c60981f5bfacd66661d090d907bf1482f0 upstream. + +Validate mount_lock seqcount as soon as we cross into mount in RCU +mode. Sure, ->mnt_root is pinned and will remain so until we +do rcu_read_unlock() anyway, and we will eventually fail to unlazy if +the mount_lock had been touched, but we might run into a hard error +(e.g. -ENOENT) before trying to unlazy. And it's possible to end +up with RCU pathwalk racing with rename() and umount() in a way +that would fail with -ENOENT while non-RCU pathwalk would've +succeeded with any timings. + +Once upon a time we hadn't needed that, but analysis had been subtle, +brittle and went out of window as soon as RENAME_EXCHANGE had been +added. + +It's narrow, hard to hit and won't get you anything other than +stray -ENOENT that could be arranged in much easier way with the +same priveleges, but it's a bug all the same. + +Cc: stable@kernel.org +X-sky-is-falling: unlikely +Fixes: da1ce0670c14 "vfs: add cross-rename" +Signed-off-by: Al Viro +Signed-off-by: Greg Kroah-Hartman +--- + fs/namei.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/namei.c ++++ b/fs/namei.c +@@ -1511,6 +1511,8 @@ static bool __follow_mount_rcu(struct na + * becoming unpinned. + */ + flags = dentry->d_flags; ++ if (read_seqretry(&mount_lock, nd->m_seq)) ++ return false; + continue; + } + if (read_seqretry(&mount_lock, nd->m_seq)) diff --git a/queue-5.18/drivers-base-fix-userspace-break-from-using-bin_attributes-for-cpumap-and-cpulist.patch b/queue-5.18/drivers-base-fix-userspace-break-from-using-bin_attributes-for-cpumap-and-cpulist.patch new file mode 100644 index 00000000000..610677bc88f --- /dev/null +++ b/queue-5.18/drivers-base-fix-userspace-break-from-using-bin_attributes-for-cpumap-and-cpulist.patch @@ -0,0 +1,177 @@ +From 7ee951acd31a88f941fd6535fbdee3a1567f1d63 Mon Sep 17 00:00:00 2001 +From: Phil Auld +Date: Fri, 15 Jul 2022 09:49:24 -0400 +Subject: drivers/base: fix userspace break from using bin_attributes for cpumap and cpulist + +From: Phil Auld + +commit 7ee951acd31a88f941fd6535fbdee3a1567f1d63 upstream. + +Using bin_attributes with a 0 size causes fstat and friends to return that +0 size. This breaks userspace code that retrieves the size before reading +the file. Rather than reverting 75bd50fa841 ("drivers/base/node.c: use +bin_attribute to break the size limitation of cpumap ABI") let's put in a +size value at compile time. + +For cpulist the maximum size is on the order of + NR_CPUS * (ceil(log10(NR_CPUS)) + 1)/2 + +which for 8192 is 20480 (8192 * 5)/2. In order to get near that you'd need +a system with every other CPU on one node. For example: (0,2,4,8, ... ). +To simplify the math and support larger NR_CPUS in the future we are using +(NR_CPUS * 7)/2. We also set it to a min of PAGE_SIZE to retain the older +behavior for smaller NR_CPUS. + +The cpumap file the size works out to be NR_CPUS/4 + NR_CPUS/32 - 1 +(or NR_CPUS * 9/32 - 1) including the ","s. + +Add a set of macros for these values to cpumask.h so they can be used in +multiple places. Apply these to the handful of such files in +drivers/base/topology.c as well as node.c. + +As an example, on an 80 cpu 4-node system (NR_CPUS == 8192): + +before: + +-r--r--r--. 1 root root 0 Jul 12 14:08 system/node/node0/cpulist +-r--r--r--. 1 root root 0 Jul 11 17:25 system/node/node0/cpumap + +after: + +-r--r--r--. 1 root root 28672 Jul 13 11:32 system/node/node0/cpulist +-r--r--r--. 1 root root 4096 Jul 13 11:31 system/node/node0/cpumap + +CONFIG_NR_CPUS = 16384 +-r--r--r--. 1 root root 57344 Jul 13 14:03 system/node/node0/cpulist +-r--r--r--. 1 root root 4607 Jul 13 14:02 system/node/node0/cpumap + +The actual number of cpus doesn't matter for the reported size since they +are based on NR_CPUS. + +Fixes: 75bd50fa841d ("drivers/base/node.c: use bin_attribute to break the size limitation of cpumap ABI") +Fixes: bb9ec13d156e ("topology: use bin_attribute to break the size limitation of cpumap ABI") +Cc: Greg Kroah-Hartman +Cc: "Rafael J. Wysocki" +Cc: Yury Norov +Cc: stable@vger.kernel.org +Acked-by: Yury Norov (for include/linux/cpumask.h) +Signed-off-by: Phil Auld +Link: https://lore.kernel.org/r/20220715134924.3466194-1-pauld@redhat.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/base/node.c | 4 ++-- + drivers/base/topology.c | 32 ++++++++++++++++---------------- + include/linux/cpumask.h | 18 ++++++++++++++++++ + 3 files changed, 36 insertions(+), 18 deletions(-) + +--- a/drivers/base/node.c ++++ b/drivers/base/node.c +@@ -45,7 +45,7 @@ static inline ssize_t cpumap_read(struct + return n; + } + +-static BIN_ATTR_RO(cpumap, 0); ++static BIN_ATTR_RO(cpumap, CPUMAP_FILE_MAX_BYTES); + + static inline ssize_t cpulist_read(struct file *file, struct kobject *kobj, + struct bin_attribute *attr, char *buf, +@@ -66,7 +66,7 @@ static inline ssize_t cpulist_read(struc + return n; + } + +-static BIN_ATTR_RO(cpulist, 0); ++static BIN_ATTR_RO(cpulist, CPULIST_FILE_MAX_BYTES); + + /** + * struct node_access_nodes - Access class device to hold user visible +--- a/drivers/base/topology.c ++++ b/drivers/base/topology.c +@@ -62,47 +62,47 @@ define_id_show_func(ppin, "0x%llx"); + static DEVICE_ATTR_ADMIN_RO(ppin); + + define_siblings_read_func(thread_siblings, sibling_cpumask); +-static BIN_ATTR_RO(thread_siblings, 0); +-static BIN_ATTR_RO(thread_siblings_list, 0); ++static BIN_ATTR_RO(thread_siblings, CPUMAP_FILE_MAX_BYTES); ++static BIN_ATTR_RO(thread_siblings_list, CPULIST_FILE_MAX_BYTES); + + define_siblings_read_func(core_cpus, sibling_cpumask); +-static BIN_ATTR_RO(core_cpus, 0); +-static BIN_ATTR_RO(core_cpus_list, 0); ++static BIN_ATTR_RO(core_cpus, CPUMAP_FILE_MAX_BYTES); ++static BIN_ATTR_RO(core_cpus_list, CPULIST_FILE_MAX_BYTES); + + define_siblings_read_func(core_siblings, core_cpumask); +-static BIN_ATTR_RO(core_siblings, 0); +-static BIN_ATTR_RO(core_siblings_list, 0); ++static BIN_ATTR_RO(core_siblings, CPUMAP_FILE_MAX_BYTES); ++static BIN_ATTR_RO(core_siblings_list, CPULIST_FILE_MAX_BYTES); + + #ifdef TOPOLOGY_CLUSTER_SYSFS + define_siblings_read_func(cluster_cpus, cluster_cpumask); +-static BIN_ATTR_RO(cluster_cpus, 0); +-static BIN_ATTR_RO(cluster_cpus_list, 0); ++static BIN_ATTR_RO(cluster_cpus, CPUMAP_FILE_MAX_BYTES); ++static BIN_ATTR_RO(cluster_cpus_list, CPULIST_FILE_MAX_BYTES); + #endif + + #ifdef TOPOLOGY_DIE_SYSFS + define_siblings_read_func(die_cpus, die_cpumask); +-static BIN_ATTR_RO(die_cpus, 0); +-static BIN_ATTR_RO(die_cpus_list, 0); ++static BIN_ATTR_RO(die_cpus, CPUMAP_FILE_MAX_BYTES); ++static BIN_ATTR_RO(die_cpus_list, CPULIST_FILE_MAX_BYTES); + #endif + + define_siblings_read_func(package_cpus, core_cpumask); +-static BIN_ATTR_RO(package_cpus, 0); +-static BIN_ATTR_RO(package_cpus_list, 0); ++static BIN_ATTR_RO(package_cpus, CPUMAP_FILE_MAX_BYTES); ++static BIN_ATTR_RO(package_cpus_list, CPULIST_FILE_MAX_BYTES); + + #ifdef TOPOLOGY_BOOK_SYSFS + define_id_show_func(book_id, "%d"); + static DEVICE_ATTR_RO(book_id); + define_siblings_read_func(book_siblings, book_cpumask); +-static BIN_ATTR_RO(book_siblings, 0); +-static BIN_ATTR_RO(book_siblings_list, 0); ++static BIN_ATTR_RO(book_siblings, CPUMAP_FILE_MAX_BYTES); ++static BIN_ATTR_RO(book_siblings_list, CPULIST_FILE_MAX_BYTES); + #endif + + #ifdef TOPOLOGY_DRAWER_SYSFS + define_id_show_func(drawer_id, "%d"); + static DEVICE_ATTR_RO(drawer_id); + define_siblings_read_func(drawer_siblings, drawer_cpumask); +-static BIN_ATTR_RO(drawer_siblings, 0); +-static BIN_ATTR_RO(drawer_siblings_list, 0); ++static BIN_ATTR_RO(drawer_siblings, CPUMAP_FILE_MAX_BYTES); ++static BIN_ATTR_RO(drawer_siblings_list, CPULIST_FILE_MAX_BYTES); + #endif + + static struct bin_attribute *bin_attrs[] = { +--- a/include/linux/cpumask.h ++++ b/include/linux/cpumask.h +@@ -1071,4 +1071,22 @@ cpumap_print_list_to_buf(char *buf, cons + [0] = 1UL \ + } } + ++/* ++ * Provide a valid theoretical max size for cpumap and cpulist sysfs files ++ * to avoid breaking userspace which may allocate a buffer based on the size ++ * reported by e.g. fstat. ++ * ++ * for cpumap NR_CPUS * 9/32 - 1 should be an exact length. ++ * ++ * For cpulist 7 is (ceil(log10(NR_CPUS)) + 1) allowing for NR_CPUS to be up ++ * to 2 orders of magnitude larger than 8192. And then we divide by 2 to ++ * cover a worst-case of every other cpu being on one of two nodes for a ++ * very large NR_CPUS. ++ * ++ * Use PAGE_SIZE as a minimum for smaller configurations. ++ */ ++#define CPUMAP_FILE_MAX_BYTES ((((NR_CPUS * 9)/32 - 1) > PAGE_SIZE) \ ++ ? (NR_CPUS * 9)/32 - 1 : PAGE_SIZE) ++#define CPULIST_FILE_MAX_BYTES (((NR_CPUS * 7)/2 > PAGE_SIZE) ? (NR_CPUS * 7)/2 : PAGE_SIZE) ++ + #endif /* __LINUX_CPUMASK_H */ diff --git a/queue-5.18/series b/queue-5.18/series index 99815861d8d..3056a654dd6 100644 --- a/queue-5.18/series +++ b/queue-5.18/series @@ -985,3 +985,6 @@ x86-olpc-fix-logical-not-is-only-applied-to-the-left-hand-side.patch smb3-fix-lease-break-timeout-when-multiple-deferred-close-handles-for-the-same-file.patch posix-cpu-timers-cleanup-cpu-timers-before-freeing-them-during-exec.patch input-gscps2-check-return-value-of-ioremap-in-gscps2_probe.patch +__follow_mount_rcu-verify-that-mount_lock-remains-unchanged.patch +spmi-trace-fix-stack-out-of-bound-access-in-spmi-tracing-functions.patch +drivers-base-fix-userspace-break-from-using-bin_attributes-for-cpumap-and-cpulist.patch diff --git a/queue-5.18/spmi-trace-fix-stack-out-of-bound-access-in-spmi-tracing-functions.patch b/queue-5.18/spmi-trace-fix-stack-out-of-bound-access-in-spmi-tracing-functions.patch new file mode 100644 index 00000000000..26b692678a6 --- /dev/null +++ b/queue-5.18/spmi-trace-fix-stack-out-of-bound-access-in-spmi-tracing-functions.patch @@ -0,0 +1,110 @@ +From 2af28b241eea816e6f7668d1954f15894b45d7e3 Mon Sep 17 00:00:00 2001 +From: David Collins +Date: Mon, 27 Jun 2022 16:55:12 -0700 +Subject: spmi: trace: fix stack-out-of-bound access in SPMI tracing functions + +From: David Collins + +commit 2af28b241eea816e6f7668d1954f15894b45d7e3 upstream. + +trace_spmi_write_begin() and trace_spmi_read_end() both call +memcpy() with a length of "len + 1". This leads to one extra +byte being read beyond the end of the specified buffer. Fix +this out-of-bound memory access by using a length of "len" +instead. + +Here is a KASAN log showing the issue: + +BUG: KASAN: stack-out-of-bounds in trace_event_raw_event_spmi_read_end+0x1d0/0x234 +Read of size 2 at addr ffffffc0265b7540 by task thermal@2.0-ser/1314 +... +Call trace: + dump_backtrace+0x0/0x3e8 + show_stack+0x2c/0x3c + dump_stack_lvl+0xdc/0x11c + print_address_description+0x74/0x384 + kasan_report+0x188/0x268 + kasan_check_range+0x270/0x2b0 + memcpy+0x90/0xe8 + trace_event_raw_event_spmi_read_end+0x1d0/0x234 + spmi_read_cmd+0x294/0x3ac + spmi_ext_register_readl+0x84/0x9c + regmap_spmi_ext_read+0x144/0x1b0 [regmap_spmi] + _regmap_raw_read+0x40c/0x754 + regmap_raw_read+0x3a0/0x514 + regmap_bulk_read+0x418/0x494 + adc5_gen3_poll_wait_hs+0xe8/0x1e0 [qcom_spmi_adc5_gen3] + ... + __arm64_sys_read+0x4c/0x60 + invoke_syscall+0x80/0x218 + el0_svc_common+0xec/0x1c8 + ... + +addr ffffffc0265b7540 is located in stack of task thermal@2.0-ser/1314 at offset 32 in frame: + adc5_gen3_poll_wait_hs+0x0/0x1e0 [qcom_spmi_adc5_gen3] + +this frame has 1 object: + [32, 33) 'status' + +Memory state around the buggy address: + ffffffc0265b7400: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 + ffffffc0265b7480: 04 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00 +>ffffffc0265b7500: 00 00 00 00 f1 f1 f1 f1 01 f3 f3 f3 00 00 00 00 + ^ + ffffffc0265b7580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ffffffc0265b7600: f1 f1 f1 f1 01 f2 07 f2 f2 f2 01 f3 00 00 00 00 +================================================================== + +Fixes: a9fce374815d ("spmi: add command tracepoints for SPMI") +Cc: stable@vger.kernel.org +Reviewed-by: Stephen Boyd +Acked-by: Steven Rostedt (Google) +Signed-off-by: David Collins +Link: https://lore.kernel.org/r/20220627235512.2272783-1-quic_collinsd@quicinc.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman +--- + include/trace/events/spmi.h | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/include/trace/events/spmi.h ++++ b/include/trace/events/spmi.h +@@ -21,15 +21,15 @@ TRACE_EVENT(spmi_write_begin, + __field ( u8, sid ) + __field ( u16, addr ) + __field ( u8, len ) +- __dynamic_array ( u8, buf, len + 1 ) ++ __dynamic_array ( u8, buf, len ) + ), + + TP_fast_assign( + __entry->opcode = opcode; + __entry->sid = sid; + __entry->addr = addr; +- __entry->len = len + 1; +- memcpy(__get_dynamic_array(buf), buf, len + 1); ++ __entry->len = len; ++ memcpy(__get_dynamic_array(buf), buf, len); + ), + + TP_printk("opc=%d sid=%02d addr=0x%04x len=%d buf=0x[%*phD]", +@@ -92,7 +92,7 @@ TRACE_EVENT(spmi_read_end, + __field ( u16, addr ) + __field ( int, ret ) + __field ( u8, len ) +- __dynamic_array ( u8, buf, len + 1 ) ++ __dynamic_array ( u8, buf, len ) + ), + + TP_fast_assign( +@@ -100,8 +100,8 @@ TRACE_EVENT(spmi_read_end, + __entry->sid = sid; + __entry->addr = addr; + __entry->ret = ret; +- __entry->len = len + 1; +- memcpy(__get_dynamic_array(buf), buf, len + 1); ++ __entry->len = len; ++ memcpy(__get_dynamic_array(buf), buf, len); + ), + + TP_printk("opc=%d sid=%02d addr=0x%04x ret=%d len=%02d buf=0x[%*phD]",