From: Greg Kroah-Hartman Date: Fri, 3 Oct 2025 13:21:16 +0000 (+0200) Subject: 6.1-stable patches X-Git-Tag: v6.6.110~9 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1016a8697ea646d8127eb787b49d1b58c3aab660;p=thirdparty%2Fkernel%2Fstable-queue.git 6.1-stable patches added patches: acpi-pptt-remove-acpi_find_cache_levels.patch acpi-pptt-update-acpi_find_last_cache_level-to-acpi_get_cache_info.patch arch_topology-build-cacheinfo-from-primary-cpu.patch cacheinfo-check-cache-unified-property-to-count-cache-leaves.patch cacheinfo-return-error-code-in-init_of_cache_level.patch cacheinfo-use-risc-v-s-init_cache_level-as-generic-of-implementation.patch gcc-plugins-remove-todo_verify_il-for-gcc-16.patch media-b2c2-fix-use-after-free-causing-by-irq_check_work-in-flexcop_pci_remove.patch media-rc-fix-races-with-imon_disconnect.patch media-uvcvideo-mark-invalid-entities-with-id-uvc_invalid_entity_id.patch scsi-target-target_core_configfs-add-length-check-to-avoid-buffer-overflow.patch --- diff --git a/queue-6.1/acpi-pptt-remove-acpi_find_cache_levels.patch b/queue-6.1/acpi-pptt-remove-acpi_find_cache_levels.patch new file mode 100644 index 0000000000..96a5edf8a2 --- /dev/null +++ b/queue-6.1/acpi-pptt-remove-acpi_find_cache_levels.patch @@ -0,0 +1,74 @@ +From fa4d566a605bc4cf32d69f16ef8cf9696635f75a Mon Sep 17 00:00:00 2001 +From: Pierre Gondois +Date: Wed, 4 Jan 2023 19:30:27 +0100 +Subject: ACPI: PPTT: Remove acpi_find_cache_levels() + +From: Pierre Gondois + +commit fa4d566a605bc4cf32d69f16ef8cf9696635f75a upstream. + +acpi_find_cache_levels() is used at a single place and is short +enough to be merged into the calling function. The removal allows +an easier renaming of the calling function in the next patch. + +Also reorder the local variables in the 'reversed Christmas tree' +order. + +Signed-off-by: Pierre Gondois +Reviewed-by: Jeremy Linton +Acked-by: Rafael J. Wysocki +Acked-by: Palmer Dabbelt +Link: https://lore.kernel.org/r/20230104183033.755668-5-pierre.gondois@arm.com +Signed-off-by: Sudeep Holla +Signed-off-by: Wen Yang +Signed-off-by: Greg Kroah-Hartman +--- + drivers/acpi/pptt.c | 21 ++++++--------------- + 1 file changed, 6 insertions(+), 15 deletions(-) + +--- a/drivers/acpi/pptt.c ++++ b/drivers/acpi/pptt.c +@@ -286,19 +286,6 @@ static struct acpi_pptt_processor *acpi_ + return NULL; + } + +-static int acpi_find_cache_levels(struct acpi_table_header *table_hdr, +- u32 acpi_cpu_id) +-{ +- int number_of_levels = 0; +- struct acpi_pptt_processor *cpu; +- +- cpu = acpi_find_processor_node(table_hdr, acpi_cpu_id); +- if (cpu) +- number_of_levels = acpi_count_levels(table_hdr, cpu); +- +- return number_of_levels; +-} +- + static u8 acpi_cache_type(enum cache_type type) + { + switch (type) { +@@ -621,9 +608,10 @@ static int check_acpi_cpu_flag(unsigned + */ + int acpi_find_last_cache_level(unsigned int cpu) + { +- u32 acpi_cpu_id; ++ struct acpi_pptt_processor *cpu_node; + struct acpi_table_header *table; + int number_of_levels = 0; ++ u32 acpi_cpu_id; + + table = acpi_get_pptt(); + if (!table) +@@ -632,7 +620,10 @@ int acpi_find_last_cache_level(unsigned + pr_debug("Cache Setup find last level CPU=%d\n", cpu); + + acpi_cpu_id = get_acpi_id_for_cpu(cpu); +- number_of_levels = acpi_find_cache_levels(table, acpi_cpu_id); ++ cpu_node = acpi_find_processor_node(table, acpi_cpu_id); ++ if (cpu_node) ++ number_of_levels = acpi_count_levels(table, cpu_node); ++ + pr_debug("Cache Setup find last level level=%d\n", number_of_levels); + + return number_of_levels; diff --git a/queue-6.1/acpi-pptt-update-acpi_find_last_cache_level-to-acpi_get_cache_info.patch b/queue-6.1/acpi-pptt-update-acpi_find_last_cache_level-to-acpi_get_cache_info.patch new file mode 100644 index 0000000000..4be19b53b4 --- /dev/null +++ b/queue-6.1/acpi-pptt-update-acpi_find_last_cache_level-to-acpi_get_cache_info.patch @@ -0,0 +1,263 @@ +From bd500361a937c03a3da57178287ce543c8f3681b Mon Sep 17 00:00:00 2001 +From: Pierre Gondois +Date: Wed, 4 Jan 2023 19:30:28 +0100 +Subject: ACPI: PPTT: Update acpi_find_last_cache_level() to acpi_get_cache_info() + +From: Pierre Gondois + +commit bd500361a937c03a3da57178287ce543c8f3681b upstream. + +acpi_find_last_cache_level() allows to find the last level of cache +for a given CPU. The function is only called on arm64 ACPI based +platforms to check for cache information that would be missing in +the CLIDR_EL1 register. +To allow populating (struct cpu_cacheinfo).num_leaves by only parsing +a PPTT, update acpi_find_last_cache_level() to get the 'split_levels', +i.e. the number of cache levels being split in data/instruction +caches. + +It is assumed that there will not be data/instruction caches above a +unified cache. +If a split level consist of one data cache and no instruction cache +(or opposite), then the missing cache will still be populated +by default with minimal cache information, and maximal cpumask +(all non-existing caches have the same fw_token). + +Suggested-by: Jeremy Linton +Signed-off-by: Pierre Gondois +Reviewed-by: Jeremy Linton +Acked-by: Rafael J. Wysocki +Acked-by: Palmer Dabbelt +Link: https://lore.kernel.org/r/20230104183033.755668-6-pierre.gondois@arm.com +Signed-off-by: Sudeep Holla +Signed-off-by: Wen Yang +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/kernel/cacheinfo.c | 11 +++--- + drivers/acpi/pptt.c | 76 +++++++++++++++++++++++++++--------------- + include/linux/cacheinfo.h | 9 +++- + 3 files changed, 63 insertions(+), 33 deletions(-) + +--- a/arch/arm64/kernel/cacheinfo.c ++++ b/arch/arm64/kernel/cacheinfo.c +@@ -46,7 +46,7 @@ static void ci_leaf_init(struct cacheinf + int init_cache_level(unsigned int cpu) + { + unsigned int ctype, level, leaves; +- int fw_level; ++ int fw_level, ret; + struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); + + for (level = 1, leaves = 0; level <= MAX_CACHE_LEVEL; level++) { +@@ -59,10 +59,13 @@ int init_cache_level(unsigned int cpu) + leaves += (ctype == CACHE_TYPE_SEPARATE) ? 2 : 1; + } + +- if (acpi_disabled) ++ if (acpi_disabled) { + fw_level = of_find_last_cache_level(cpu); +- else +- fw_level = acpi_find_last_cache_level(cpu); ++ } else { ++ ret = acpi_get_cache_info(cpu, &fw_level, NULL); ++ if (ret < 0) ++ return ret; ++ } + + if (fw_level < 0) + return fw_level; +--- a/drivers/acpi/pptt.c ++++ b/drivers/acpi/pptt.c +@@ -81,6 +81,7 @@ static inline bool acpi_pptt_match_type( + * acpi_pptt_walk_cache() - Attempt to find the requested acpi_pptt_cache + * @table_hdr: Pointer to the head of the PPTT table + * @local_level: passed res reflects this cache level ++ * @split_levels: Number of split cache levels (data/instruction). + * @res: cache resource in the PPTT we want to walk + * @found: returns a pointer to the requested level if found + * @level: the requested cache level +@@ -100,6 +101,7 @@ static inline bool acpi_pptt_match_type( + */ + static unsigned int acpi_pptt_walk_cache(struct acpi_table_header *table_hdr, + unsigned int local_level, ++ unsigned int *split_levels, + struct acpi_subtable_header *res, + struct acpi_pptt_cache **found, + unsigned int level, int type) +@@ -113,8 +115,17 @@ static unsigned int acpi_pptt_walk_cache + while (cache) { + local_level++; + ++ if (!(cache->flags & ACPI_PPTT_CACHE_TYPE_VALID)) { ++ cache = fetch_pptt_cache(table_hdr, cache->next_level_of_cache); ++ continue; ++ } ++ ++ if (split_levels && ++ (acpi_pptt_match_type(cache->attributes, ACPI_PPTT_CACHE_TYPE_DATA) || ++ acpi_pptt_match_type(cache->attributes, ACPI_PPTT_CACHE_TYPE_INSTR))) ++ *split_levels = local_level; ++ + if (local_level == level && +- cache->flags & ACPI_PPTT_CACHE_TYPE_VALID && + acpi_pptt_match_type(cache->attributes, type)) { + if (*found != NULL && cache != *found) + pr_warn("Found duplicate cache level/type unable to determine uniqueness\n"); +@@ -135,8 +146,8 @@ static unsigned int acpi_pptt_walk_cache + static struct acpi_pptt_cache * + acpi_find_cache_level(struct acpi_table_header *table_hdr, + struct acpi_pptt_processor *cpu_node, +- unsigned int *starting_level, unsigned int level, +- int type) ++ unsigned int *starting_level, unsigned int *split_levels, ++ unsigned int level, int type) + { + struct acpi_subtable_header *res; + unsigned int number_of_levels = *starting_level; +@@ -149,7 +160,8 @@ acpi_find_cache_level(struct acpi_table_ + resource++; + + local_level = acpi_pptt_walk_cache(table_hdr, *starting_level, +- res, &ret, level, type); ++ split_levels, res, &ret, ++ level, type); + /* + * we are looking for the max depth. Since its potentially + * possible for a given node to have resources with differing +@@ -165,29 +177,29 @@ acpi_find_cache_level(struct acpi_table_ + } + + /** +- * acpi_count_levels() - Given a PPTT table, and a CPU node, count the caches ++ * acpi_count_levels() - Given a PPTT table, and a CPU node, count the cache ++ * levels and split cache levels (data/instruction). + * @table_hdr: Pointer to the head of the PPTT table + * @cpu_node: processor node we wish to count caches for ++ * @levels: Number of levels if success. ++ * @split_levels: Number of split cache levels (data/instruction) if ++ * success. Can by NULL. + * + * Given a processor node containing a processing unit, walk into it and count + * how many levels exist solely for it, and then walk up each level until we hit + * the root node (ignore the package level because it may be possible to have +- * caches that exist across packages). Count the number of cache levels that +- * exist at each level on the way up. +- * +- * Return: Total number of levels found. ++ * caches that exist across packages). Count the number of cache levels and ++ * split cache levels (data/instruction) that exist at each level on the way ++ * up. + */ +-static int acpi_count_levels(struct acpi_table_header *table_hdr, +- struct acpi_pptt_processor *cpu_node) ++static void acpi_count_levels(struct acpi_table_header *table_hdr, ++ struct acpi_pptt_processor *cpu_node, ++ unsigned int *levels, unsigned int *split_levels) + { +- int total_levels = 0; +- + do { +- acpi_find_cache_level(table_hdr, cpu_node, &total_levels, 0, 0); ++ acpi_find_cache_level(table_hdr, cpu_node, levels, split_levels, 0, 0); + cpu_node = fetch_pptt_node(table_hdr, cpu_node->parent); + } while (cpu_node); +- +- return total_levels; + } + + /** +@@ -326,7 +338,7 @@ static struct acpi_pptt_cache *acpi_find + + while (cpu_node && !found) { + found = acpi_find_cache_level(table_hdr, cpu_node, +- &total_levels, level, acpi_type); ++ &total_levels, NULL, level, acpi_type); + *node = cpu_node; + cpu_node = fetch_pptt_node(table_hdr, cpu_node->parent); + } +@@ -597,36 +609,48 @@ static int check_acpi_cpu_flag(unsigned + } + + /** +- * acpi_find_last_cache_level() - Determines the number of cache levels for a PE ++ * acpi_get_cache_info() - Determine the number of cache levels and ++ * split cache levels (data/instruction) and for a PE. + * @cpu: Kernel logical CPU number ++ * @levels: Number of levels if success. ++ * @split_levels: Number of levels being split (i.e. data/instruction) ++ * if success. Can by NULL. + * + * Given a logical CPU number, returns the number of levels of cache represented + * in the PPTT. Errors caused by lack of a PPTT table, or otherwise, return 0 + * indicating we didn't find any cache levels. + * +- * Return: Cache levels visible to this core. ++ * Return: -ENOENT if no PPTT table or no PPTT processor struct found. ++ * 0 on success. + */ +-int acpi_find_last_cache_level(unsigned int cpu) ++int acpi_get_cache_info(unsigned int cpu, unsigned int *levels, ++ unsigned int *split_levels) + { + struct acpi_pptt_processor *cpu_node; + struct acpi_table_header *table; +- int number_of_levels = 0; + u32 acpi_cpu_id; + ++ *levels = 0; ++ if (split_levels) ++ *split_levels = 0; ++ + table = acpi_get_pptt(); + if (!table) + return -ENOENT; + +- pr_debug("Cache Setup find last level CPU=%d\n", cpu); ++ pr_debug("Cache Setup: find cache levels for CPU=%d\n", cpu); + + acpi_cpu_id = get_acpi_id_for_cpu(cpu); + cpu_node = acpi_find_processor_node(table, acpi_cpu_id); +- if (cpu_node) +- number_of_levels = acpi_count_levels(table, cpu_node); ++ if (!cpu_node) ++ return -ENOENT; ++ ++ acpi_count_levels(table, cpu_node, levels, split_levels); + +- pr_debug("Cache Setup find last level level=%d\n", number_of_levels); ++ pr_debug("Cache Setup: last_level=%d split_levels=%d\n", ++ *levels, split_levels ? *split_levels : -1); + +- return number_of_levels; ++ return 0; + } + + /** +--- a/include/linux/cacheinfo.h ++++ b/include/linux/cacheinfo.h +@@ -88,19 +88,22 @@ bool last_level_cache_is_shared(unsigned + int detect_cache_attributes(unsigned int cpu); + #ifndef CONFIG_ACPI_PPTT + /* +- * acpi_find_last_cache_level is only called on ACPI enabled ++ * acpi_get_cache_info() is only called on ACPI enabled + * platforms using the PPTT for topology. This means that if + * the platform supports other firmware configuration methods + * we need to stub out the call when ACPI is disabled. + * ACPI enabled platforms not using PPTT won't be making calls + * to this function so we need not worry about them. + */ +-static inline int acpi_find_last_cache_level(unsigned int cpu) ++static inline ++int acpi_get_cache_info(unsigned int cpu, ++ unsigned int *levels, unsigned int *split_levels) + { + return 0; + } + #else +-int acpi_find_last_cache_level(unsigned int cpu); ++int acpi_get_cache_info(unsigned int cpu, ++ unsigned int *levels, unsigned int *split_levels); + #endif + + const struct attribute_group *cache_get_priv_group(struct cacheinfo *this_leaf); diff --git a/queue-6.1/arch_topology-build-cacheinfo-from-primary-cpu.patch b/queue-6.1/arch_topology-build-cacheinfo-from-primary-cpu.patch new file mode 100644 index 0000000000..23f4a53cf5 --- /dev/null +++ b/queue-6.1/arch_topology-build-cacheinfo-from-primary-cpu.patch @@ -0,0 +1,241 @@ +From 5944ce092b97caed5d86d961e963b883b5c44ee2 Mon Sep 17 00:00:00 2001 +From: Pierre Gondois +Date: Wed, 4 Jan 2023 19:30:29 +0100 +Subject: arch_topology: Build cacheinfo from primary CPU + +From: Pierre Gondois + +commit 5944ce092b97caed5d86d961e963b883b5c44ee2 upstream. + +commit 3fcbf1c77d08 ("arch_topology: Fix cache attributes detection +in the CPU hotplug path") +adds a call to detect_cache_attributes() to populate the cacheinfo +before updating the siblings mask. detect_cache_attributes() allocates +memory and can take the PPTT mutex (on ACPI platforms). On PREEMPT_RT +kernels, on secondary CPUs, this triggers a: + 'BUG: sleeping function called from invalid context' [1] +as the code is executed with preemption and interrupts disabled. + +The primary CPU was previously storing the cache information using +the now removed (struct cpu_topology).llc_id: +commit 5b8dc787ce4a ("arch_topology: Drop LLC identifier stash from +the CPU topology") + +allocate_cache_info() tries to build the cacheinfo from the primary +CPU prior secondary CPUs boot, if the DT/ACPI description +contains cache information. +If allocate_cache_info() fails, then fallback to the current state +for the cacheinfo allocation. [1] will be triggered in such case. + +When unplugging a CPU, the cacheinfo memory cannot be freed. If it +was, then the memory would be allocated early by the re-plugged +CPU and would trigger [1]. + +Note that populate_cache_leaves() might be called multiple times +due to populate_leaves being moved up. This is required since +detect_cache_attributes() might be called with per_cpu_cacheinfo(cpu) +being allocated but not populated. + +[1]: + | BUG: sleeping function called from invalid context at kernel/locking/spinlock_rt.c:46 + | in_atomic(): 1, irqs_disabled(): 128, non_block: 0, pid: 0, name: swapper/111 + | preempt_count: 1, expected: 0 + | RCU nest depth: 1, expected: 1 + | 3 locks held by swapper/111/0: + | #0: (&pcp->lock){+.+.}-{3:3}, at: get_page_from_freelist+0x218/0x12c8 + | #1: (rcu_read_lock){....}-{1:3}, at: rt_spin_trylock+0x48/0xf0 + | #2: (&zone->lock){+.+.}-{3:3}, at: rmqueue_bulk+0x64/0xa80 + | irq event stamp: 0 + | hardirqs last enabled at (0): 0x0 + | hardirqs last disabled at (0): copy_process+0x5dc/0x1ab8 + | softirqs last enabled at (0): copy_process+0x5dc/0x1ab8 + | softirqs last disabled at (0): 0x0 + | Preemption disabled at: + | migrate_enable+0x30/0x130 + | CPU: 111 PID: 0 Comm: swapper/111 Tainted: G W 6.0.0-rc4-rt6-[...] + | Call trace: + | __kmalloc+0xbc/0x1e8 + | detect_cache_attributes+0x2d4/0x5f0 + | update_siblings_masks+0x30/0x368 + | store_cpu_topology+0x78/0xb8 + | secondary_start_kernel+0xd0/0x198 + | __secondary_switched+0xb0/0xb4 + +Signed-off-by: Pierre Gondois +Reviewed-by: Sudeep Holla +Acked-by: Palmer Dabbelt +Link: https://lore.kernel.org/r/20230104183033.755668-7-pierre.gondois@arm.com +Signed-off-by: Sudeep Holla +Signed-off-by: Wen Yang +Signed-off-by: Greg Kroah-Hartman +--- + arch/riscv/kernel/cacheinfo.c | 5 -- + drivers/base/arch_topology.c | 12 +++++-- + drivers/base/cacheinfo.c | 71 +++++++++++++++++++++++++++++++----------- + include/linux/cacheinfo.h | 1 + 4 files changed, 65 insertions(+), 24 deletions(-) + +--- a/arch/riscv/kernel/cacheinfo.c ++++ b/arch/riscv/kernel/cacheinfo.c +@@ -113,11 +113,6 @@ static void fill_cacheinfo(struct cachei + } + } + +-int init_cache_level(unsigned int cpu) +-{ +- return init_of_cache_level(cpu); +-} +- + int populate_cache_leaves(unsigned int cpu) + { + struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); +--- a/drivers/base/arch_topology.c ++++ b/drivers/base/arch_topology.c +@@ -736,7 +736,7 @@ void update_siblings_masks(unsigned int + + ret = detect_cache_attributes(cpuid); + if (ret && ret != -ENOENT) +- pr_info("Early cacheinfo failed, ret = %d\n", ret); ++ pr_info("Early cacheinfo allocation failed, ret = %d\n", ret); + + /* update core and thread sibling masks */ + for_each_online_cpu(cpu) { +@@ -825,7 +825,7 @@ __weak int __init parse_acpi_topology(vo + #if defined(CONFIG_ARM64) || defined(CONFIG_RISCV) + void __init init_cpu_topology(void) + { +- int ret; ++ int cpu, ret; + + reset_cpu_topology(); + ret = parse_acpi_topology(); +@@ -840,6 +840,14 @@ void __init init_cpu_topology(void) + reset_cpu_topology(); + return; + } ++ ++ for_each_possible_cpu(cpu) { ++ ret = fetch_cache_info(cpu); ++ if (ret) { ++ pr_err("Early cacheinfo failed, ret = %d\n", ret); ++ break; ++ } ++ } + } + + void store_cpu_topology(unsigned int cpuid) +--- a/drivers/base/cacheinfo.c ++++ b/drivers/base/cacheinfo.c +@@ -412,10 +412,6 @@ static void free_cache_attributes(unsign + return; + + cache_shared_cpu_map_remove(cpu); +- +- kfree(per_cpu_cacheinfo(cpu)); +- per_cpu_cacheinfo(cpu) = NULL; +- cache_leaves(cpu) = 0; + } + + int __weak init_cache_level(unsigned int cpu) +@@ -428,29 +424,71 @@ int __weak populate_cache_leaves(unsigne + return -ENOENT; + } + ++static inline ++int allocate_cache_info(int cpu) ++{ ++ per_cpu_cacheinfo(cpu) = kcalloc(cache_leaves(cpu), ++ sizeof(struct cacheinfo), GFP_ATOMIC); ++ if (!per_cpu_cacheinfo(cpu)) { ++ cache_leaves(cpu) = 0; ++ return -ENOMEM; ++ } ++ ++ return 0; ++} ++ ++int fetch_cache_info(unsigned int cpu) ++{ ++ struct cpu_cacheinfo *this_cpu_ci; ++ unsigned int levels, split_levels; ++ int ret; ++ ++ if (acpi_disabled) { ++ ret = init_of_cache_level(cpu); ++ if (ret < 0) ++ return ret; ++ } else { ++ ret = acpi_get_cache_info(cpu, &levels, &split_levels); ++ if (ret < 0) ++ return ret; ++ ++ this_cpu_ci = get_cpu_cacheinfo(cpu); ++ this_cpu_ci->num_levels = levels; ++ /* ++ * This assumes that: ++ * - there cannot be any split caches (data/instruction) ++ * above a unified cache ++ * - data/instruction caches come by pair ++ */ ++ this_cpu_ci->num_leaves = levels + split_levels; ++ } ++ if (!cache_leaves(cpu)) ++ return -ENOENT; ++ ++ return allocate_cache_info(cpu); ++} ++ + int detect_cache_attributes(unsigned int cpu) + { + int ret; + +- /* Since early detection of the cacheinfo is allowed via this +- * function and this also gets called as CPU hotplug callbacks via +- * cacheinfo_cpu_online, the initialisation can be skipped and only +- * CPU maps can be updated as the CPU online status would be update +- * if called via cacheinfo_cpu_online path. ++ /* Since early initialization/allocation of the cacheinfo is allowed ++ * via fetch_cache_info() and this also gets called as CPU hotplug ++ * callbacks via cacheinfo_cpu_online, the init/alloc can be skipped ++ * as it will happen only once (the cacheinfo memory is never freed). ++ * Just populate the cacheinfo. + */ + if (per_cpu_cacheinfo(cpu)) +- goto update_cpu_map; ++ goto populate_leaves; + + if (init_cache_level(cpu) || !cache_leaves(cpu)) + return -ENOENT; + +- per_cpu_cacheinfo(cpu) = kcalloc(cache_leaves(cpu), +- sizeof(struct cacheinfo), GFP_ATOMIC); +- if (per_cpu_cacheinfo(cpu) == NULL) { +- cache_leaves(cpu) = 0; +- return -ENOMEM; +- } ++ ret = allocate_cache_info(cpu); ++ if (ret) ++ return ret; + ++populate_leaves: + /* + * populate_cache_leaves() may completely setup the cache leaves and + * shared_cpu_map or it may leave it partially setup. +@@ -459,7 +497,6 @@ int detect_cache_attributes(unsigned int + if (ret) + goto free_ci; + +-update_cpu_map: + /* + * For systems using DT for cache hierarchy, fw_token + * and shared_cpu_map will be set up here only if they are +--- a/include/linux/cacheinfo.h ++++ b/include/linux/cacheinfo.h +@@ -85,6 +85,7 @@ int populate_cache_leaves(unsigned int c + int cache_setup_acpi(unsigned int cpu); + bool last_level_cache_is_valid(unsigned int cpu); + bool last_level_cache_is_shared(unsigned int cpu_x, unsigned int cpu_y); ++int fetch_cache_info(unsigned int cpu); + int detect_cache_attributes(unsigned int cpu); + #ifndef CONFIG_ACPI_PPTT + /* diff --git a/queue-6.1/cacheinfo-check-cache-unified-property-to-count-cache-leaves.patch b/queue-6.1/cacheinfo-check-cache-unified-property-to-count-cache-leaves.patch new file mode 100644 index 0000000000..6f7646baf6 --- /dev/null +++ b/queue-6.1/cacheinfo-check-cache-unified-property-to-count-cache-leaves.patch @@ -0,0 +1,94 @@ +From de0df442ee49cb1f6ee58f3fec5dcb5e5eb70aab Mon Sep 17 00:00:00 2001 +From: Pierre Gondois +Date: Wed, 4 Jan 2023 19:30:26 +0100 +Subject: cacheinfo: Check 'cache-unified' property to count cache leaves + +From: Pierre Gondois + +commit de0df442ee49cb1f6ee58f3fec5dcb5e5eb70aab upstream. + +The DeviceTree Specification v0.3 specifies that the cache node +'[d-|i-|]cache-size' property is required. The 'cache-unified' +property is specifies whether the cache level is separate +or unified. + +If the cache-size property is missing, no cache leaves is accounted. +This can lead to a 'BUG: KASAN: slab-out-of-bounds' [1] bug. + +Check 'cache-unified' property and always account for at least +one cache leaf when parsing the device tree. + +[1] https://lore.kernel.org/all/0f19cb3f-d6cf-4032-66d2-dedc9d09a0e3@linaro.org/ + +Reported-by: Krzysztof Kozlowski +Signed-off-by: Pierre Gondois +Tested-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20230104183033.755668-4-pierre.gondois@arm.com +Signed-off-by: Sudeep Holla +Signed-off-by: Wen Yang +Signed-off-by: Greg Kroah-Hartman +--- + drivers/base/cacheinfo.c | 37 ++++++++++++++++++++++++++----------- + 1 file changed, 26 insertions(+), 11 deletions(-) + +--- a/drivers/base/cacheinfo.c ++++ b/drivers/base/cacheinfo.c +@@ -224,12 +224,9 @@ static int cache_setup_of_node(unsigned + return 0; + } + +-int init_of_cache_level(unsigned int cpu) ++static int of_count_cache_leaves(struct device_node *np) + { +- struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); +- struct device_node *np = of_cpu_device_node_get(cpu); +- struct device_node *prev = NULL; +- unsigned int levels = 0, leaves = 0, level; ++ unsigned int leaves = 0; + + if (of_property_read_bool(np, "cache-size")) + ++leaves; +@@ -237,6 +234,28 @@ int init_of_cache_level(unsigned int cpu + ++leaves; + if (of_property_read_bool(np, "d-cache-size")) + ++leaves; ++ ++ if (!leaves) { ++ /* The '[i-|d-|]cache-size' property is required, but ++ * if absent, fallback on the 'cache-unified' property. ++ */ ++ if (of_property_read_bool(np, "cache-unified")) ++ return 1; ++ else ++ return 2; ++ } ++ ++ return leaves; ++} ++ ++int init_of_cache_level(unsigned int cpu) ++{ ++ struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); ++ struct device_node *np = of_cpu_device_node_get(cpu); ++ struct device_node *prev = NULL; ++ unsigned int levels = 0, leaves, level; ++ ++ leaves = of_count_cache_leaves(np); + if (leaves > 0) + levels = 1; + +@@ -250,12 +269,8 @@ int init_of_cache_level(unsigned int cpu + goto err_out; + if (level <= levels) + goto err_out; +- if (of_property_read_bool(np, "cache-size")) +- ++leaves; +- if (of_property_read_bool(np, "i-cache-size")) +- ++leaves; +- if (of_property_read_bool(np, "d-cache-size")) +- ++leaves; ++ ++ leaves += of_count_cache_leaves(np); + levels = level; + } + diff --git a/queue-6.1/cacheinfo-return-error-code-in-init_of_cache_level.patch b/queue-6.1/cacheinfo-return-error-code-in-init_of_cache_level.patch new file mode 100644 index 0000000000..45c7d043be --- /dev/null +++ b/queue-6.1/cacheinfo-return-error-code-in-init_of_cache_level.patch @@ -0,0 +1,54 @@ +From 8844c3df001bc1d8397fddea341308da63855d53 Mon Sep 17 00:00:00 2001 +From: Pierre Gondois +Date: Wed, 4 Jan 2023 19:30:25 +0100 +Subject: cacheinfo: Return error code in init_of_cache_level() + +From: Pierre Gondois + +commit 8844c3df001bc1d8397fddea341308da63855d53 upstream. + +Make init_of_cache_level() return an error code when the cache +information parsing fails to help detecting missing information. + +init_of_cache_level() is only called for riscv. Returning an error +code instead of 0 will prevent detect_cache_attributes() to allocate +memory if an incomplete DT is parsed. + +Signed-off-by: Pierre Gondois +Acked-by: Palmer Dabbelt +Link: https://lore.kernel.org/r/20230104183033.755668-3-pierre.gondois@arm.com +Signed-off-by: Sudeep Holla +Signed-off-by: Wen Yang +Signed-off-by: Greg Kroah-Hartman +--- + drivers/base/cacheinfo.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +--- a/drivers/base/cacheinfo.c ++++ b/drivers/base/cacheinfo.c +@@ -245,11 +245,11 @@ int init_of_cache_level(unsigned int cpu + of_node_put(prev); + prev = np; + if (!of_device_is_compatible(np, "cache")) +- break; ++ goto err_out; + if (of_property_read_u32(np, "cache-level", &level)) +- break; ++ goto err_out; + if (level <= levels) +- break; ++ goto err_out; + if (of_property_read_bool(np, "cache-size")) + ++leaves; + if (of_property_read_bool(np, "i-cache-size")) +@@ -264,6 +264,10 @@ int init_of_cache_level(unsigned int cpu + this_cpu_ci->num_leaves = leaves; + + return 0; ++ ++err_out: ++ of_node_put(np); ++ return -EINVAL; + } + + #else diff --git a/queue-6.1/cacheinfo-use-risc-v-s-init_cache_level-as-generic-of-implementation.patch b/queue-6.1/cacheinfo-use-risc-v-s-init_cache_level-as-generic-of-implementation.patch new file mode 100644 index 0000000000..65e369a42d --- /dev/null +++ b/queue-6.1/cacheinfo-use-risc-v-s-init_cache_level-as-generic-of-implementation.patch @@ -0,0 +1,144 @@ +From c3719bd9eeb2edf84bd263d662e36ca0ba262a23 Mon Sep 17 00:00:00 2001 +From: Pierre Gondois +Date: Wed, 4 Jan 2023 19:30:24 +0100 +Subject: cacheinfo: Use RISC-V's init_cache_level() as generic OF implementation + +From: Pierre Gondois + +commit c3719bd9eeb2edf84bd263d662e36ca0ba262a23 upstream. + +RISC-V's implementation of init_of_cache_level() is following +the Devicetree Specification v0.3 regarding caches, cf.: +- s3.7.3 'Internal (L1) Cache Properties' +- s3.8 'Multi-level and Shared Cache Nodes' + +Allow reusing the implementation by moving it. + +Also make 'levels', 'leaves' and 'level' unsigned int. + +Signed-off-by: Pierre Gondois +Reviewed-by: Conor Dooley +Acked-by: Palmer Dabbelt +Link: https://lore.kernel.org/r/20230104183033.755668-2-pierre.gondois@arm.com +Signed-off-by: Sudeep Holla +Signed-off-by: Wen Yang +Signed-off-by: Greg Kroah-Hartman +--- + arch/riscv/kernel/cacheinfo.c | 39 ------------------------------------- + drivers/base/cacheinfo.c | 44 ++++++++++++++++++++++++++++++++++++++++++ + include/linux/cacheinfo.h | 1 + 3 files changed, 46 insertions(+), 38 deletions(-) + +--- a/arch/riscv/kernel/cacheinfo.c ++++ b/arch/riscv/kernel/cacheinfo.c +@@ -115,44 +115,7 @@ static void fill_cacheinfo(struct cachei + + int init_cache_level(unsigned int cpu) + { +- struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); +- struct device_node *np = of_cpu_device_node_get(cpu); +- struct device_node *prev = NULL; +- int levels = 0, leaves = 0, level; +- +- if (of_property_read_bool(np, "cache-size")) +- ++leaves; +- if (of_property_read_bool(np, "i-cache-size")) +- ++leaves; +- if (of_property_read_bool(np, "d-cache-size")) +- ++leaves; +- if (leaves > 0) +- levels = 1; +- +- prev = np; +- while ((np = of_find_next_cache_node(np))) { +- of_node_put(prev); +- prev = np; +- if (!of_device_is_compatible(np, "cache")) +- break; +- if (of_property_read_u32(np, "cache-level", &level)) +- break; +- if (level <= levels) +- break; +- if (of_property_read_bool(np, "cache-size")) +- ++leaves; +- if (of_property_read_bool(np, "i-cache-size")) +- ++leaves; +- if (of_property_read_bool(np, "d-cache-size")) +- ++leaves; +- levels = level; +- } +- +- of_node_put(np); +- this_cpu_ci->num_levels = levels; +- this_cpu_ci->num_leaves = leaves; +- +- return 0; ++ return init_of_cache_level(cpu); + } + + int populate_cache_leaves(unsigned int cpu) +--- a/drivers/base/cacheinfo.c ++++ b/drivers/base/cacheinfo.c +@@ -223,8 +223,52 @@ static int cache_setup_of_node(unsigned + + return 0; + } ++ ++int init_of_cache_level(unsigned int cpu) ++{ ++ struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); ++ struct device_node *np = of_cpu_device_node_get(cpu); ++ struct device_node *prev = NULL; ++ unsigned int levels = 0, leaves = 0, level; ++ ++ if (of_property_read_bool(np, "cache-size")) ++ ++leaves; ++ if (of_property_read_bool(np, "i-cache-size")) ++ ++leaves; ++ if (of_property_read_bool(np, "d-cache-size")) ++ ++leaves; ++ if (leaves > 0) ++ levels = 1; ++ ++ prev = np; ++ while ((np = of_find_next_cache_node(np))) { ++ of_node_put(prev); ++ prev = np; ++ if (!of_device_is_compatible(np, "cache")) ++ break; ++ if (of_property_read_u32(np, "cache-level", &level)) ++ break; ++ if (level <= levels) ++ break; ++ if (of_property_read_bool(np, "cache-size")) ++ ++leaves; ++ if (of_property_read_bool(np, "i-cache-size")) ++ ++leaves; ++ if (of_property_read_bool(np, "d-cache-size")) ++ ++leaves; ++ levels = level; ++ } ++ ++ of_node_put(np); ++ this_cpu_ci->num_levels = levels; ++ this_cpu_ci->num_leaves = leaves; ++ ++ return 0; ++} ++ + #else + static inline int cache_setup_of_node(unsigned int cpu) { return 0; } ++int init_of_cache_level(unsigned int cpu) { return 0; } + #endif + + int __weak cache_setup_acpi(unsigned int cpu) +--- a/include/linux/cacheinfo.h ++++ b/include/linux/cacheinfo.h +@@ -80,6 +80,7 @@ struct cpu_cacheinfo { + + struct cpu_cacheinfo *get_cpu_cacheinfo(unsigned int cpu); + int init_cache_level(unsigned int cpu); ++int init_of_cache_level(unsigned int cpu); + int populate_cache_leaves(unsigned int cpu); + int cache_setup_acpi(unsigned int cpu); + bool last_level_cache_is_valid(unsigned int cpu); diff --git a/queue-6.1/gcc-plugins-remove-todo_verify_il-for-gcc-16.patch b/queue-6.1/gcc-plugins-remove-todo_verify_il-for-gcc-16.patch new file mode 100644 index 0000000000..7e1e174a56 --- /dev/null +++ b/queue-6.1/gcc-plugins-remove-todo_verify_il-for-gcc-16.patch @@ -0,0 +1,41 @@ +From a40282dd3c484e6c882e93f4680e0a3ef3814453 Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Sat, 20 Sep 2025 16:45:23 -0700 +Subject: gcc-plugins: Remove TODO_verify_il for GCC >= 16 + +From: Kees Cook + +commit a40282dd3c484e6c882e93f4680e0a3ef3814453 upstream. + +GCC now runs TODO_verify_il automatically[1], so it is no longer exposed to +plugins. Only use the flag on GCC < 16. + +Link: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=9739ae9384dd7cd3bb1c7683d6b80b7a9116eaf8 [1] +Suggested-by: Christopher Fore +Link: https://lore.kernel.org/r/20250920234519.work.915-kees@kernel.org +Signed-off-by: Kees Cook +Signed-off-by: Greg Kroah-Hartman +--- + scripts/gcc-plugins/gcc-common.h | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/scripts/gcc-plugins/gcc-common.h ++++ b/scripts/gcc-plugins/gcc-common.h +@@ -196,10 +196,17 @@ inline bool is_a_helper + } + #endif + ++#if BUILDING_GCC_VERSION < 16000 + #define TODO_verify_ssa TODO_verify_il + #define TODO_verify_flow TODO_verify_il + #define TODO_verify_stmts TODO_verify_il + #define TODO_verify_rtl_sharing TODO_verify_il ++#else ++#define TODO_verify_ssa 0 ++#define TODO_verify_flow 0 ++#define TODO_verify_stmts 0 ++#define TODO_verify_rtl_sharing 0 ++#endif + + #define INSN_DELETED_P(insn) (insn)->deleted() + diff --git a/queue-6.1/media-b2c2-fix-use-after-free-causing-by-irq_check_work-in-flexcop_pci_remove.patch b/queue-6.1/media-b2c2-fix-use-after-free-causing-by-irq_check_work-in-flexcop_pci_remove.patch new file mode 100644 index 0000000000..6b9b49d456 --- /dev/null +++ b/queue-6.1/media-b2c2-fix-use-after-free-causing-by-irq_check_work-in-flexcop_pci_remove.patch @@ -0,0 +1,119 @@ +From 01e03fb7db419d39e18d6090d4873c1bff103914 Mon Sep 17 00:00:00 2001 +From: Duoming Zhou +Date: Wed, 17 Sep 2025 17:59:26 +0800 +Subject: media: b2c2: Fix use-after-free causing by irq_check_work in flexcop_pci_remove + +From: Duoming Zhou + +commit 01e03fb7db419d39e18d6090d4873c1bff103914 upstream. + +The original code uses cancel_delayed_work() in flexcop_pci_remove(), which +does not guarantee that the delayed work item irq_check_work has fully +completed if it was already running. This leads to use-after-free scenarios +where flexcop_pci_remove() may free the flexcop_device while irq_check_work +is still active and attempts to dereference the device. + +A typical race condition is illustrated below: + +CPU 0 (remove) | CPU 1 (delayed work callback) +flexcop_pci_remove() | flexcop_pci_irq_check_work() + cancel_delayed_work() | + flexcop_device_kfree(fc_pci->fc_dev) | + | fc = fc_pci->fc_dev; // UAF + +This is confirmed by a KASAN report: + +================================================================== +BUG: KASAN: slab-use-after-free in __run_timer_base.part.0+0x7d7/0x8c0 +Write of size 8 at addr ffff8880093aa8c8 by task bash/135 +... +Call Trace: + + dump_stack_lvl+0x55/0x70 + print_report+0xcf/0x610 + ? __run_timer_base.part.0+0x7d7/0x8c0 + kasan_report+0xb8/0xf0 + ? __run_timer_base.part.0+0x7d7/0x8c0 + __run_timer_base.part.0+0x7d7/0x8c0 + ? __pfx___run_timer_base.part.0+0x10/0x10 + ? __pfx_read_tsc+0x10/0x10 + ? ktime_get+0x60/0x140 + ? lapic_next_event+0x11/0x20 + ? clockevents_program_event+0x1d4/0x2a0 + run_timer_softirq+0xd1/0x190 + handle_softirqs+0x16a/0x550 + irq_exit_rcu+0xaf/0xe0 + sysvec_apic_timer_interrupt+0x70/0x80 + +... + +Allocated by task 1: + kasan_save_stack+0x24/0x50 + kasan_save_track+0x14/0x30 + __kasan_kmalloc+0x7f/0x90 + __kmalloc_noprof+0x1be/0x460 + flexcop_device_kmalloc+0x54/0xe0 + flexcop_pci_probe+0x1f/0x9d0 + local_pci_probe+0xdc/0x190 + pci_device_probe+0x2fe/0x470 + really_probe+0x1ca/0x5c0 + __driver_probe_device+0x248/0x310 + driver_probe_device+0x44/0x120 + __driver_attach+0xd2/0x310 + bus_for_each_dev+0xed/0x170 + bus_add_driver+0x208/0x500 + driver_register+0x132/0x460 + do_one_initcall+0x89/0x300 + kernel_init_freeable+0x40d/0x720 + kernel_init+0x1a/0x150 + ret_from_fork+0x10c/0x1a0 + ret_from_fork_asm+0x1a/0x30 + +Freed by task 135: + kasan_save_stack+0x24/0x50 + kasan_save_track+0x14/0x30 + kasan_save_free_info+0x3a/0x60 + __kasan_slab_free+0x3f/0x50 + kfree+0x137/0x370 + flexcop_device_kfree+0x32/0x50 + pci_device_remove+0xa6/0x1d0 + device_release_driver_internal+0xf8/0x210 + pci_stop_bus_device+0x105/0x150 + pci_stop_and_remove_bus_device_locked+0x15/0x30 + remove_store+0xcc/0xe0 + kernfs_fop_write_iter+0x2c3/0x440 + vfs_write+0x871/0xd70 + ksys_write+0xee/0x1c0 + do_syscall_64+0xac/0x280 + entry_SYSCALL_64_after_hwframe+0x77/0x7f +... + +Replace cancel_delayed_work() with cancel_delayed_work_sync() to ensure +that the delayed work item is properly canceled and any executing delayed +work has finished before the device memory is deallocated. + +This bug was initially identified through static analysis. To reproduce +and test it, I simulated the B2C2 FlexCop PCI device in QEMU and introduced +artificial delays within the flexcop_pci_irq_check_work() function to +increase the likelihood of triggering the bug. + +Fixes: 382c5546d618 ("V4L/DVB (10694): [PATCH] software IRQ watchdog for Flexcop B2C2 DVB PCI cards") +Cc: stable@vger.kernel.org +Signed-off-by: Duoming Zhou +Signed-off-by: Hans Verkuil +Signed-off-by: Greg Kroah-Hartman +--- + drivers/media/pci/b2c2/flexcop-pci.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/media/pci/b2c2/flexcop-pci.c ++++ b/drivers/media/pci/b2c2/flexcop-pci.c +@@ -411,7 +411,7 @@ static void flexcop_pci_remove(struct pc + struct flexcop_pci *fc_pci = pci_get_drvdata(pdev); + + if (irq_chk_intv > 0) +- cancel_delayed_work(&fc_pci->irq_check_work); ++ cancel_delayed_work_sync(&fc_pci->irq_check_work); + + flexcop_pci_dma_exit(fc_pci); + flexcop_device_exit(fc_pci->fc_dev); diff --git a/queue-6.1/media-rc-fix-races-with-imon_disconnect.patch b/queue-6.1/media-rc-fix-races-with-imon_disconnect.patch new file mode 100644 index 0000000000..32b095cdc3 --- /dev/null +++ b/queue-6.1/media-rc-fix-races-with-imon_disconnect.patch @@ -0,0 +1,160 @@ +From fa0f61cc1d828178aa921475a9b786e7fbb65ccb Mon Sep 17 00:00:00 2001 +From: Larshin Sergey +Date: Tue, 29 Jul 2025 13:13:32 +0300 +Subject: media: rc: fix races with imon_disconnect() + +From: Larshin Sergey + +commit fa0f61cc1d828178aa921475a9b786e7fbb65ccb upstream. + +Syzbot reports a KASAN issue as below: +BUG: KASAN: use-after-free in __create_pipe include/linux/usb.h:1945 [inline] +BUG: KASAN: use-after-free in send_packet+0xa2d/0xbc0 drivers/media/rc/imon.c:627 +Read of size 4 at addr ffff8880256fb000 by task syz-executor314/4465 + +CPU: 2 PID: 4465 Comm: syz-executor314 Not tainted 6.0.0-rc1-syzkaller #0 +Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.14.0-2 04/01/2014 +Call Trace: + +__dump_stack lib/dump_stack.c:88 [inline] +dump_stack_lvl+0xcd/0x134 lib/dump_stack.c:106 +print_address_description mm/kasan/report.c:317 [inline] +print_report.cold+0x2ba/0x6e9 mm/kasan/report.c:433 +kasan_report+0xb1/0x1e0 mm/kasan/report.c:495 +__create_pipe include/linux/usb.h:1945 [inline] +send_packet+0xa2d/0xbc0 drivers/media/rc/imon.c:627 +vfd_write+0x2d9/0x550 drivers/media/rc/imon.c:991 +vfs_write+0x2d7/0xdd0 fs/read_write.c:576 +ksys_write+0x127/0x250 fs/read_write.c:631 +do_syscall_x64 arch/x86/entry/common.c:50 [inline] +do_syscall_64+0x35/0xb0 arch/x86/entry/common.c:80 +entry_SYSCALL_64_after_hwframe+0x63/0xcd + +The iMON driver improperly releases the usb_device reference in +imon_disconnect without coordinating with active users of the +device. + +Specifically, the fields usbdev_intf0 and usbdev_intf1 are not +protected by the users counter (ictx->users). During probe, +imon_init_intf0 or imon_init_intf1 increments the usb_device +reference count depending on the interface. However, during +disconnect, usb_put_dev is called unconditionally, regardless of +actual usage. + +As a result, if vfd_write or other operations are still in +progress after disconnect, this can lead to a use-after-free of +the usb_device pointer. + +Thread 1 vfd_write Thread 2 imon_disconnect + ... + if + usb_put_dev(ictx->usbdev_intf0) + else + usb_put_dev(ictx->usbdev_intf1) +... +while + send_packet + if + pipe = usb_sndintpipe( + ictx->usbdev_intf0) UAF + else + pipe = usb_sndctrlpipe( + ictx->usbdev_intf0, 0) UAF + +Guard access to usbdev_intf0 and usbdev_intf1 after disconnect by +checking ictx->disconnected in all writer paths. Add early return +with -ENODEV in send_packet(), vfd_write(), lcd_write() and +display_open() if the device is no longer present. + +Set and read ictx->disconnected under ictx->lock to ensure memory +synchronization. Acquire the lock in imon_disconnect() before setting +the flag to synchronize with any ongoing operations. + +Ensure writers exit early and safely after disconnect before the USB +core proceeds with cleanup. + +Found by Linux Verification Center (linuxtesting.org) with Syzkaller. + +Reported-by: syzbot+f1a69784f6efe748c3bf@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=f1a69784f6efe748c3bf +Fixes: 21677cfc562a ("V4L/DVB: ir-core: add imon driver") +Cc: stable@vger.kernel.org + +Signed-off-by: Larshin Sergey +Signed-off-by: Sean Young +Signed-off-by: Hans Verkuil +Signed-off-by: Greg Kroah-Hartman +--- + drivers/media/rc/imon.c | 27 ++++++++++++++++++++------- + 1 file changed, 20 insertions(+), 7 deletions(-) + +--- a/drivers/media/rc/imon.c ++++ b/drivers/media/rc/imon.c +@@ -536,7 +536,9 @@ static int display_open(struct inode *in + + mutex_lock(&ictx->lock); + +- if (!ictx->display_supported) { ++ if (ictx->disconnected) { ++ retval = -ENODEV; ++ } else if (!ictx->display_supported) { + pr_err("display not supported by device\n"); + retval = -ENODEV; + } else if (ictx->display_isopen) { +@@ -598,6 +600,9 @@ static int send_packet(struct imon_conte + int retval = 0; + struct usb_ctrlrequest *control_req = NULL; + ++ if (ictx->disconnected) ++ return -ENODEV; ++ + /* Check if we need to use control or interrupt urb */ + if (!ictx->tx_control) { + pipe = usb_sndintpipe(ictx->usbdev_intf0, +@@ -949,12 +954,14 @@ static ssize_t vfd_write(struct file *fi + static const unsigned char vfd_packet6[] = { + 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF }; + +- if (ictx->disconnected) +- return -ENODEV; +- + if (mutex_lock_interruptible(&ictx->lock)) + return -ERESTARTSYS; + ++ if (ictx->disconnected) { ++ retval = -ENODEV; ++ goto exit; ++ } ++ + if (!ictx->dev_present_intf0) { + pr_err_ratelimited("no iMON device present\n"); + retval = -ENODEV; +@@ -1029,11 +1036,13 @@ static ssize_t lcd_write(struct file *fi + int retval = 0; + struct imon_context *ictx = file->private_data; + +- if (ictx->disconnected) +- return -ENODEV; +- + mutex_lock(&ictx->lock); + ++ if (ictx->disconnected) { ++ retval = -ENODEV; ++ goto exit; ++ } ++ + if (!ictx->display_supported) { + pr_err_ratelimited("no iMON display present\n"); + retval = -ENODEV; +@@ -2499,7 +2508,11 @@ static void imon_disconnect(struct usb_i + int ifnum; + + ictx = usb_get_intfdata(interface); ++ ++ mutex_lock(&ictx->lock); + ictx->disconnected = true; ++ mutex_unlock(&ictx->lock); ++ + dev = ictx->dev; + ifnum = interface->cur_altsetting->desc.bInterfaceNumber; + diff --git a/queue-6.1/media-uvcvideo-mark-invalid-entities-with-id-uvc_invalid_entity_id.patch b/queue-6.1/media-uvcvideo-mark-invalid-entities-with-id-uvc_invalid_entity_id.patch new file mode 100644 index 0000000000..c92b9c78e6 --- /dev/null +++ b/queue-6.1/media-uvcvideo-mark-invalid-entities-with-id-uvc_invalid_entity_id.patch @@ -0,0 +1,309 @@ +From 0e2ee70291e64a30fe36960c85294726d34a103e Mon Sep 17 00:00:00 2001 +From: Thadeu Lima de Souza Cascardo +Date: Wed, 20 Aug 2025 16:08:16 +0000 +Subject: media: uvcvideo: Mark invalid entities with id UVC_INVALID_ENTITY_ID + +From: Thadeu Lima de Souza Cascardo + +commit 0e2ee70291e64a30fe36960c85294726d34a103e upstream. + +Per UVC 1.1+ specification 3.7.2, units and terminals must have a non-zero +unique ID. + +``` +Each Unit and Terminal within the video function is assigned a unique +identification number, the Unit ID (UID) or Terminal ID (TID), contained in +the bUnitID or bTerminalID field of the descriptor. The value 0x00 is +reserved for undefined ID, +``` + +If we add a new entity with id 0 or a duplicated ID, it will be marked +as UVC_INVALID_ENTITY_ID. + +In a previous attempt commit 3dd075fe8ebb ("media: uvcvideo: Require +entities to have a non-zero unique ID"), we ignored all the invalid units, +this broke a lot of non-compatible cameras. Hopefully we are more lucky +this time. + +This also prevents some syzkaller reproducers from triggering warnings due +to a chain of entities referring to themselves. In one particular case, an +Output Unit is connected to an Input Unit, both with the same ID of 1. But +when looking up for the source ID of the Output Unit, that same entity is +found instead of the input entity, which leads to such warnings. + +In another case, a backward chain was considered finished as the source ID +was 0. Later on, that entity was found, but its pads were not valid. + +Here is a sample stack trace for one of those cases. + +[ 20.650953] usb 1-1: new high-speed USB device number 2 using dummy_hcd +[ 20.830206] usb 1-1: Using ep0 maxpacket: 8 +[ 20.833501] usb 1-1: config 0 descriptor?? +[ 21.038518] usb 1-1: string descriptor 0 read error: -71 +[ 21.038893] usb 1-1: Found UVC 0.00 device (2833:0201) +[ 21.039299] uvcvideo 1-1:0.0: Entity type for entity Output 1 was not initialized! +[ 21.041583] uvcvideo 1-1:0.0: Entity type for entity Input 1 was not initialized! +[ 21.042218] ------------[ cut here ]------------ +[ 21.042536] WARNING: CPU: 0 PID: 9 at drivers/media/mc/mc-entity.c:1147 media_create_pad_link+0x2c4/0x2e0 +[ 21.043195] Modules linked in: +[ 21.043535] CPU: 0 UID: 0 PID: 9 Comm: kworker/0:1 Not tainted 6.11.0-rc7-00030-g3480e43aeccf #444 +[ 21.044101] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.15.0-1 04/01/2014 +[ 21.044639] Workqueue: usb_hub_wq hub_event +[ 21.045100] RIP: 0010:media_create_pad_link+0x2c4/0x2e0 +[ 21.045508] Code: fe e8 20 01 00 00 b8 f4 ff ff ff 48 83 c4 30 5b 41 5c 41 5d 41 5e 41 5f 5d c3 cc cc cc cc 0f 0b eb e9 0f 0b eb 0a 0f 0b eb 06 <0f> 0b eb 02 0f 0b b8 ea ff ff ff eb d4 66 2e 0f 1f 84 00 00 00 00 +[ 21.046801] RSP: 0018:ffffc9000004b318 EFLAGS: 00010246 +[ 21.047227] RAX: ffff888004e5d458 RBX: 0000000000000000 RCX: ffffffff818fccf1 +[ 21.047719] RDX: 000000000000007b RSI: 0000000000000000 RDI: ffff888004313290 +[ 21.048241] RBP: ffff888004313290 R08: 0001ffffffffffff R09: 0000000000000000 +[ 21.048701] R10: 0000000000000013 R11: 0001888004313290 R12: 0000000000000003 +[ 21.049138] R13: ffff888004313080 R14: ffff888004313080 R15: 0000000000000000 +[ 21.049648] FS: 0000000000000000(0000) GS:ffff88803ec00000(0000) knlGS:0000000000000000 +[ 21.050271] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 21.050688] CR2: 0000592cc27635b0 CR3: 000000000431c000 CR4: 0000000000750ef0 +[ 21.051136] PKRU: 55555554 +[ 21.051331] Call Trace: +[ 21.051480] +[ 21.051611] ? __warn+0xc4/0x210 +[ 21.051861] ? media_create_pad_link+0x2c4/0x2e0 +[ 21.052252] ? report_bug+0x11b/0x1a0 +[ 21.052540] ? trace_hardirqs_on+0x31/0x40 +[ 21.052901] ? handle_bug+0x3d/0x70 +[ 21.053197] ? exc_invalid_op+0x1a/0x50 +[ 21.053511] ? asm_exc_invalid_op+0x1a/0x20 +[ 21.053924] ? media_create_pad_link+0x91/0x2e0 +[ 21.054364] ? media_create_pad_link+0x2c4/0x2e0 +[ 21.054834] ? media_create_pad_link+0x91/0x2e0 +[ 21.055131] ? _raw_spin_unlock+0x1e/0x40 +[ 21.055441] ? __v4l2_device_register_subdev+0x202/0x210 +[ 21.055837] uvc_mc_register_entities+0x358/0x400 +[ 21.056144] uvc_register_chains+0x1fd/0x290 +[ 21.056413] uvc_probe+0x380e/0x3dc0 +[ 21.056676] ? __lock_acquire+0x5aa/0x26e0 +[ 21.056946] ? find_held_lock+0x33/0xa0 +[ 21.057196] ? kernfs_activate+0x70/0x80 +[ 21.057533] ? usb_match_dynamic_id+0x1b/0x70 +[ 21.057811] ? find_held_lock+0x33/0xa0 +[ 21.058047] ? usb_match_dynamic_id+0x55/0x70 +[ 21.058330] ? lock_release+0x124/0x260 +[ 21.058657] ? usb_match_one_id_intf+0xa2/0x100 +[ 21.058997] usb_probe_interface+0x1ba/0x330 +[ 21.059399] really_probe+0x1ba/0x4c0 +[ 21.059662] __driver_probe_device+0xb2/0x180 +[ 21.059944] driver_probe_device+0x5a/0x100 +[ 21.060170] __device_attach_driver+0xe9/0x160 +[ 21.060427] ? __pfx___device_attach_driver+0x10/0x10 +[ 21.060872] bus_for_each_drv+0xa9/0x100 +[ 21.061312] __device_attach+0xed/0x190 +[ 21.061812] device_initial_probe+0xe/0x20 +[ 21.062229] bus_probe_device+0x4d/0xd0 +[ 21.062590] device_add+0x308/0x590 +[ 21.062912] usb_set_configuration+0x7b6/0xaf0 +[ 21.063403] usb_generic_driver_probe+0x36/0x80 +[ 21.063714] usb_probe_device+0x7b/0x130 +[ 21.063936] really_probe+0x1ba/0x4c0 +[ 21.064111] __driver_probe_device+0xb2/0x180 +[ 21.064577] driver_probe_device+0x5a/0x100 +[ 21.065019] __device_attach_driver+0xe9/0x160 +[ 21.065403] ? __pfx___device_attach_driver+0x10/0x10 +[ 21.065820] bus_for_each_drv+0xa9/0x100 +[ 21.066094] __device_attach+0xed/0x190 +[ 21.066535] device_initial_probe+0xe/0x20 +[ 21.066992] bus_probe_device+0x4d/0xd0 +[ 21.067250] device_add+0x308/0x590 +[ 21.067501] usb_new_device+0x347/0x610 +[ 21.067817] hub_event+0x156b/0x1e30 +[ 21.068060] ? process_scheduled_works+0x48b/0xaf0 +[ 21.068337] process_scheduled_works+0x5a3/0xaf0 +[ 21.068668] worker_thread+0x3cf/0x560 +[ 21.068932] ? kthread+0x109/0x1b0 +[ 21.069133] kthread+0x197/0x1b0 +[ 21.069343] ? __pfx_worker_thread+0x10/0x10 +[ 21.069598] ? __pfx_kthread+0x10/0x10 +[ 21.069908] ret_from_fork+0x32/0x40 +[ 21.070169] ? __pfx_kthread+0x10/0x10 +[ 21.070424] ret_from_fork_asm+0x1a/0x30 +[ 21.070737] + +Reported-by: syzbot+0584f746fde3d52b4675@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=0584f746fde3d52b4675 +Reported-by: syzbot+dd320d114deb3f5bb79b@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=dd320d114deb3f5bb79b +Reported-by: Youngjun Lee +Fixes: a3fbc2e6bb05 ("media: mc-entity.c: use WARN_ON, validate link pads") +Cc: stable@vger.kernel.org +Signed-off-by: Thadeu Lima de Souza Cascardo +Co-developed-by: Ricardo Ribalda +Signed-off-by: Ricardo Ribalda +Reviewed-by: Laurent Pinchart +Reviewed-by: Hans de Goede +Signed-off-by: Hans de Goede +Signed-off-by: Laurent Pinchart +Signed-off-by: Hans Verkuil +Signed-off-by: Greg Kroah-Hartman +--- + drivers/media/usb/uvc/uvc_driver.c | 73 +++++++++++++++++++++++-------------- + drivers/media/usb/uvc/uvcvideo.h | 2 + + 2 files changed, 48 insertions(+), 27 deletions(-) + +--- a/drivers/media/usb/uvc/uvc_driver.c ++++ b/drivers/media/usb/uvc/uvc_driver.c +@@ -134,6 +134,9 @@ struct uvc_entity *uvc_entity_by_id(stru + { + struct uvc_entity *entity; + ++ if (id == UVC_INVALID_ENTITY_ID) ++ return NULL; ++ + list_for_each_entry(entity, &dev->entities, list) { + if (entity->id == id) + return entity; +@@ -757,14 +760,27 @@ static const u8 uvc_media_transport_inpu + UVC_GUID_UVC_MEDIA_TRANSPORT_INPUT; + static const u8 uvc_processing_guid[16] = UVC_GUID_UVC_PROCESSING; + +-static struct uvc_entity *uvc_alloc_entity(u16 type, u16 id, +- unsigned int num_pads, unsigned int extra_size) ++static struct uvc_entity *uvc_alloc_new_entity(struct uvc_device *dev, u16 type, ++ u16 id, unsigned int num_pads, ++ unsigned int extra_size) + { + struct uvc_entity *entity; + unsigned int num_inputs; + unsigned int size; + unsigned int i; + ++ /* Per UVC 1.1+ spec 3.7.2, the ID should be non-zero. */ ++ if (id == 0) { ++ dev_err(&dev->intf->dev, "Found Unit with invalid ID 0\n"); ++ id = UVC_INVALID_ENTITY_ID; ++ } ++ ++ /* Per UVC 1.1+ spec 3.7.2, the ID is unique. */ ++ if (uvc_entity_by_id(dev, id)) { ++ dev_err(&dev->intf->dev, "Found multiple Units with ID %u\n", id); ++ id = UVC_INVALID_ENTITY_ID; ++ } ++ + extra_size = roundup(extra_size, sizeof(*entity->pads)); + if (num_pads) + num_inputs = type & UVC_TERM_OUTPUT ? num_pads : num_pads - 1; +@@ -774,7 +790,7 @@ static struct uvc_entity *uvc_alloc_enti + + num_inputs; + entity = kzalloc(size, GFP_KERNEL); + if (entity == NULL) +- return NULL; ++ return ERR_PTR(-ENOMEM); + + entity->id = id; + entity->type = type; +@@ -865,10 +881,10 @@ static int uvc_parse_vendor_control(stru + break; + } + +- unit = uvc_alloc_entity(UVC_VC_EXTENSION_UNIT, buffer[3], +- p + 1, 2*n); +- if (unit == NULL) +- return -ENOMEM; ++ unit = uvc_alloc_new_entity(dev, UVC_VC_EXTENSION_UNIT, ++ buffer[3], p + 1, 2 * n); ++ if (IS_ERR(unit)) ++ return PTR_ERR(unit); + + memcpy(unit->guid, &buffer[4], 16); + unit->extension.bNumControls = buffer[20]; +@@ -978,10 +994,10 @@ static int uvc_parse_standard_control(st + return -EINVAL; + } + +- term = uvc_alloc_entity(type | UVC_TERM_INPUT, buffer[3], +- 1, n + p); +- if (term == NULL) +- return -ENOMEM; ++ term = uvc_alloc_new_entity(dev, type | UVC_TERM_INPUT, ++ buffer[3], 1, n + p); ++ if (IS_ERR(term)) ++ return PTR_ERR(term); + + if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA) { + term->camera.bControlSize = n; +@@ -1038,10 +1054,10 @@ static int uvc_parse_standard_control(st + return 0; + } + +- term = uvc_alloc_entity(type | UVC_TERM_OUTPUT, buffer[3], +- 1, 0); +- if (term == NULL) +- return -ENOMEM; ++ term = uvc_alloc_new_entity(dev, type | UVC_TERM_OUTPUT, ++ buffer[3], 1, 0); ++ if (IS_ERR(term)) ++ return PTR_ERR(term); + + memcpy(term->baSourceID, &buffer[7], 1); + +@@ -1062,9 +1078,10 @@ static int uvc_parse_standard_control(st + return -EINVAL; + } + +- unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, 0); +- if (unit == NULL) +- return -ENOMEM; ++ unit = uvc_alloc_new_entity(dev, buffer[2], buffer[3], ++ p + 1, 0); ++ if (IS_ERR(unit)) ++ return PTR_ERR(unit); + + memcpy(unit->baSourceID, &buffer[5], p); + +@@ -1086,9 +1103,9 @@ static int uvc_parse_standard_control(st + return -EINVAL; + } + +- unit = uvc_alloc_entity(buffer[2], buffer[3], 2, n); +- if (unit == NULL) +- return -ENOMEM; ++ unit = uvc_alloc_new_entity(dev, buffer[2], buffer[3], 2, n); ++ if (IS_ERR(unit)) ++ return PTR_ERR(unit); + + memcpy(unit->baSourceID, &buffer[4], 1); + unit->processing.wMaxMultiplier = +@@ -1117,9 +1134,10 @@ static int uvc_parse_standard_control(st + return -EINVAL; + } + +- unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, n); +- if (unit == NULL) +- return -ENOMEM; ++ unit = uvc_alloc_new_entity(dev, buffer[2], buffer[3], ++ p + 1, n); ++ if (IS_ERR(unit)) ++ return PTR_ERR(unit); + + memcpy(unit->guid, &buffer[4], 16); + unit->extension.bNumControls = buffer[20]; +@@ -1260,9 +1278,10 @@ static int uvc_gpio_parse(struct uvc_dev + return dev_err_probe(&dev->intf->dev, irq, + "No IRQ for privacy GPIO\n"); + +- unit = uvc_alloc_entity(UVC_EXT_GPIO_UNIT, UVC_EXT_GPIO_UNIT_ID, 0, 1); +- if (!unit) +- return -ENOMEM; ++ unit = uvc_alloc_new_entity(dev, UVC_EXT_GPIO_UNIT, ++ UVC_EXT_GPIO_UNIT_ID, 0, 1); ++ if (IS_ERR(unit)) ++ return PTR_ERR(unit); + + unit->gpio.gpio_privacy = gpio_privacy; + unit->gpio.irq = irq; +--- a/drivers/media/usb/uvc/uvcvideo.h ++++ b/drivers/media/usb/uvc/uvcvideo.h +@@ -41,6 +41,8 @@ + #define UVC_EXT_GPIO_UNIT 0x7ffe + #define UVC_EXT_GPIO_UNIT_ID 0x100 + ++#define UVC_INVALID_ENTITY_ID 0xffff ++ + /* ------------------------------------------------------------------------ + * Driver specific constants. + */ diff --git a/queue-6.1/scsi-target-target_core_configfs-add-length-check-to-avoid-buffer-overflow.patch b/queue-6.1/scsi-target-target_core_configfs-add-length-check-to-avoid-buffer-overflow.patch new file mode 100644 index 0000000000..d9b2f77838 --- /dev/null +++ b/queue-6.1/scsi-target-target_core_configfs-add-length-check-to-avoid-buffer-overflow.patch @@ -0,0 +1,47 @@ +From 27e06650a5eafe832a90fd2604f0c5e920857fae Mon Sep 17 00:00:00 2001 +From: Wang Haoran +Date: Sat, 20 Sep 2025 15:44:41 +0800 +Subject: scsi: target: target_core_configfs: Add length check to avoid buffer overflow + +From: Wang Haoran + +commit 27e06650a5eafe832a90fd2604f0c5e920857fae upstream. + +A buffer overflow arises from the usage of snprintf to write into the +buffer "buf" in target_lu_gp_members_show function located in +/drivers/target/target_core_configfs.c. This buffer is allocated with +size LU_GROUP_NAME_BUF (256 bytes). + +snprintf(...) formats multiple strings into buf with the HBA name +(hba->hba_group.cg_item), a slash character, a devicename (dev-> +dev_group.cg_item) and a newline character, the total formatted string +length may exceed the buffer size of 256 bytes. + +Since snprintf() returns the total number of bytes that would have been +written (the length of %s/%sn ), this value may exceed the buffer length +(256 bytes) passed to memcpy(), this will ultimately cause function +memcpy reporting a buffer overflow error. + +An additional check of the return value of snprintf() can avoid this +buffer overflow. + +Reported-by: Wang Haoran +Reported-by: ziiiro +Signed-off-by: Wang Haoran +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/target/target_core_configfs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/target/target_core_configfs.c ++++ b/drivers/target/target_core_configfs.c +@@ -2691,7 +2691,7 @@ static ssize_t target_lu_gp_members_show + config_item_name(&dev->dev_group.cg_item)); + cur_len++; /* Extra byte for NULL terminator */ + +- if ((cur_len + len) > PAGE_SIZE) { ++ if ((cur_len + len) > PAGE_SIZE || cur_len > LU_GROUP_NAME_BUF) { + pr_warn("Ran out of lu_gp_show_attr" + "_members buffer\n"); + break; diff --git a/queue-6.1/series b/queue-6.1/series index a6fa8aa5ad..c9318b37e4 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -1,2 +1,13 @@ stable-crypto-sha256-fix-crash-at-kexec.patch selftests-mptcp-connect-fix-build-regression-caused-by-backport.patch +cacheinfo-use-risc-v-s-init_cache_level-as-generic-of-implementation.patch +cacheinfo-return-error-code-in-init_of_cache_level.patch +cacheinfo-check-cache-unified-property-to-count-cache-leaves.patch +acpi-pptt-remove-acpi_find_cache_levels.patch +acpi-pptt-update-acpi_find_last_cache_level-to-acpi_get_cache_info.patch +arch_topology-build-cacheinfo-from-primary-cpu.patch +gcc-plugins-remove-todo_verify_il-for-gcc-16.patch +scsi-target-target_core_configfs-add-length-check-to-avoid-buffer-overflow.patch +media-b2c2-fix-use-after-free-causing-by-irq_check_work-in-flexcop_pci_remove.patch +media-rc-fix-races-with-imon_disconnect.patch +media-uvcvideo-mark-invalid-entities-with-id-uvc_invalid_entity_id.patch