From: Greg Kroah-Hartman Date: Mon, 6 Mar 2023 18:54:40 +0000 (+0100) Subject: 6.2-stable patches X-Git-Tag: v6.2.3~57 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=db047b730c30db5c5a41234be7fa085d0bfcb450;p=thirdparty%2Fkernel%2Fstable-queue.git 6.2-stable patches added patches: crypto-qat-fix-out-of-bounds-read.patch irqdomain-drop-bogus-fwspec-mapping-error-handling.patch irqdomain-fix-association-race.patch irqdomain-fix-disassociation-race.patch irqdomain-fix-domain-registration-race.patch irqdomain-fix-mapping-creation-race.patch irqdomain-look-for-existing-mapping-only-once.patch irqdomain-refactor-__irq_domain_alloc_irqs.patch --- diff --git a/queue-6.2/crypto-qat-fix-out-of-bounds-read.patch b/queue-6.2/crypto-qat-fix-out-of-bounds-read.patch new file mode 100644 index 00000000000..cf12785798e --- /dev/null +++ b/queue-6.2/crypto-qat-fix-out-of-bounds-read.patch @@ -0,0 +1,61 @@ +From f6044cc3030e139f60c281386f28bda6e3049d66 Mon Sep 17 00:00:00 2001 +From: Giovanni Cabiddu +Date: Wed, 1 Feb 2023 15:59:44 +0000 +Subject: crypto: qat - fix out-of-bounds read + +From: Giovanni Cabiddu + +commit f6044cc3030e139f60c281386f28bda6e3049d66 upstream. + +When preparing an AER-CTR request, the driver copies the key provided by +the user into a data structure that is accessible by the firmware. +If the target device is QAT GEN4, the key size is rounded up by 16 since +a rounded up size is expected by the device. +If the key size is rounded up before the copy, the size used for copying +the key might be bigger than the size of the region containing the key, +causing an out-of-bounds read. + +Fix by doing the copy first and then update the keylen. + +This is to fix the following warning reported by KASAN: + + [ 138.150574] BUG: KASAN: global-out-of-bounds in qat_alg_skcipher_init_com.isra.0+0x197/0x250 [intel_qat] + [ 138.150641] Read of size 32 at addr ffffffff88c402c0 by task cryptomgr_test/2340 + + [ 138.150651] CPU: 15 PID: 2340 Comm: cryptomgr_test Not tainted 6.2.0-rc1+ #45 + [ 138.150659] Hardware name: Intel Corporation ArcherCity/ArcherCity, BIOS EGSDCRB1.86B.0087.D13.2208261706 08/26/2022 + [ 138.150663] Call Trace: + [ 138.150668] + [ 138.150922] kasan_check_range+0x13a/0x1c0 + [ 138.150931] memcpy+0x1f/0x60 + [ 138.150940] qat_alg_skcipher_init_com.isra.0+0x197/0x250 [intel_qat] + [ 138.151006] qat_alg_skcipher_init_sessions+0xc1/0x240 [intel_qat] + [ 138.151073] crypto_skcipher_setkey+0x82/0x160 + [ 138.151085] ? prepare_keybuf+0xa2/0xd0 + [ 138.151095] test_skcipher_vec_cfg+0x2b8/0x800 + +Fixes: 67916c951689 ("crypto: qat - add AES-CTR support for QAT GEN4 devices") +Cc: +Reported-by: Vladis Dronov +Signed-off-by: Giovanni Cabiddu +Reviewed-by: Fiona Trahe +Reviewed-by: Vladis Dronov +Tested-by: Vladis Dronov +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/crypto/qat/qat_common/qat_algs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/crypto/qat/qat_common/qat_algs.c ++++ b/drivers/crypto/qat/qat_common/qat_algs.c +@@ -435,8 +435,8 @@ static void qat_alg_skcipher_init_com(st + } else if (aes_v2_capable && mode == ICP_QAT_HW_CIPHER_CTR_MODE) { + ICP_QAT_FW_LA_SLICE_TYPE_SET(header->serv_specif_flags, + ICP_QAT_FW_LA_USE_UCS_SLICE_TYPE); +- keylen = round_up(keylen, 16); + memcpy(cd->ucs_aes.key, key, keylen); ++ keylen = round_up(keylen, 16); + } else { + memcpy(cd->aes.key, key, keylen); + } diff --git a/queue-6.2/irqdomain-drop-bogus-fwspec-mapping-error-handling.patch b/queue-6.2/irqdomain-drop-bogus-fwspec-mapping-error-handling.patch new file mode 100644 index 00000000000..a563247a129 --- /dev/null +++ b/queue-6.2/irqdomain-drop-bogus-fwspec-mapping-error-handling.patch @@ -0,0 +1,46 @@ +From e3b7ab025e931accdc2c12acf9b75c6197f1c062 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 13 Feb 2023 11:42:45 +0100 +Subject: irqdomain: Drop bogus fwspec-mapping error handling + +From: Johan Hovold + +commit e3b7ab025e931accdc2c12acf9b75c6197f1c062 upstream. + +In case a newly allocated IRQ ever ends up not having any associated +struct irq_data it would not even be possible to dispose the mapping. + +Replace the bogus disposal with a WARN_ON(). + +This will also be used to fix a shared-interrupt mapping race, hence the +CC-stable tag. + +Fixes: 1e2a7d78499e ("irqdomain: Don't set type when mapping an IRQ") +Cc: stable@vger.kernel.org # 4.8 +Tested-by: Hsin-Yi Wang +Tested-by: Mark-PK Tsai +Signed-off-by: Johan Hovold +Signed-off-by: Marc Zyngier +Link: https://lore.kernel.org/r/20230213104302.17307-4-johan+linaro@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + kernel/irq/irqdomain.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -853,13 +853,8 @@ unsigned int irq_create_fwspec_mapping(s + } + + irq_data = irq_get_irq_data(virq); +- if (!irq_data) { +- if (irq_domain_is_hierarchy(domain)) +- irq_domain_free_irqs(virq, 1); +- else +- irq_dispose_mapping(virq); ++ if (WARN_ON(!irq_data)) + return 0; +- } + + /* Store trigger type */ + irqd_set_trigger_type(irq_data, type); diff --git a/queue-6.2/irqdomain-fix-association-race.patch b/queue-6.2/irqdomain-fix-association-race.patch new file mode 100644 index 00000000000..85209743389 --- /dev/null +++ b/queue-6.2/irqdomain-fix-association-race.patch @@ -0,0 +1,83 @@ +From b06730a571a9ff1ba5bd6b20bf9e50e5a12f1ec6 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 13 Feb 2023 11:42:43 +0100 +Subject: irqdomain: Fix association race + +From: Johan Hovold + +commit b06730a571a9ff1ba5bd6b20bf9e50e5a12f1ec6 upstream. + +The sanity check for an already mapped virq is done outside of the +irq_domain_mutex-protected section which means that an (unlikely) racing +association may not be detected. + +Fix this by factoring out the association implementation, which will +also be used in a follow-on change to fix a shared-interrupt mapping +race. + +Fixes: ddaf144c61da ("irqdomain: Refactor irq_domain_associate_many()") +Cc: stable@vger.kernel.org # 3.11 +Tested-by: Hsin-Yi Wang +Tested-by: Mark-PK Tsai +Signed-off-by: Johan Hovold +Signed-off-by: Marc Zyngier +Link: https://lore.kernel.org/r/20230213104302.17307-2-johan+linaro@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + kernel/irq/irqdomain.c | 19 ++++++++++++++----- + 1 file changed, 14 insertions(+), 5 deletions(-) + +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -559,8 +559,8 @@ static void irq_domain_disassociate(stru + irq_domain_clear_mapping(domain, hwirq); + } + +-int irq_domain_associate(struct irq_domain *domain, unsigned int virq, +- irq_hw_number_t hwirq) ++static int irq_domain_associate_locked(struct irq_domain *domain, unsigned int virq, ++ irq_hw_number_t hwirq) + { + struct irq_data *irq_data = irq_get_irq_data(virq); + int ret; +@@ -573,7 +573,6 @@ int irq_domain_associate(struct irq_doma + if (WARN(irq_data->domain, "error: virq%i is already associated", virq)) + return -EINVAL; + +- mutex_lock(&irq_domain_mutex); + irq_data->hwirq = hwirq; + irq_data->domain = domain; + if (domain->ops->map) { +@@ -590,7 +589,6 @@ int irq_domain_associate(struct irq_doma + } + irq_data->domain = NULL; + irq_data->hwirq = 0; +- mutex_unlock(&irq_domain_mutex); + return ret; + } + +@@ -601,12 +599,23 @@ int irq_domain_associate(struct irq_doma + + domain->mapcount++; + irq_domain_set_mapping(domain, hwirq, irq_data); +- mutex_unlock(&irq_domain_mutex); + + irq_clear_status_flags(virq, IRQ_NOREQUEST); + + return 0; + } ++ ++int irq_domain_associate(struct irq_domain *domain, unsigned int virq, ++ irq_hw_number_t hwirq) ++{ ++ int ret; ++ ++ mutex_lock(&irq_domain_mutex); ++ ret = irq_domain_associate_locked(domain, virq, hwirq); ++ mutex_unlock(&irq_domain_mutex); ++ ++ return ret; ++} + EXPORT_SYMBOL_GPL(irq_domain_associate); + + void irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base, diff --git a/queue-6.2/irqdomain-fix-disassociation-race.patch b/queue-6.2/irqdomain-fix-disassociation-race.patch new file mode 100644 index 00000000000..b0eaf84d659 --- /dev/null +++ b/queue-6.2/irqdomain-fix-disassociation-race.patch @@ -0,0 +1,51 @@ +From 3f883c38f5628f46b30bccf090faec054088e262 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 13 Feb 2023 11:42:44 +0100 +Subject: irqdomain: Fix disassociation race + +From: Johan Hovold + +commit 3f883c38f5628f46b30bccf090faec054088e262 upstream. + +The global irq_domain_mutex is held when mapping interrupts from +non-hierarchical domains but currently not when disposing them. + +This specifically means that updates of the domain mapcount is racy +(currently only used for statistics in debugfs). + +Make sure to hold the global irq_domain_mutex also when disposing +mappings from non-hierarchical domains. + +Fixes: 9dc6be3d4193 ("genirq/irqdomain: Add map counter") +Cc: stable@vger.kernel.org # 4.13 +Tested-by: Hsin-Yi Wang +Tested-by: Mark-PK Tsai +Signed-off-by: Johan Hovold +Signed-off-by: Marc Zyngier +Link: https://lore.kernel.org/r/20230213104302.17307-3-johan+linaro@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + kernel/irq/irqdomain.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -538,6 +538,9 @@ static void irq_domain_disassociate(stru + return; + + hwirq = irq_data->hwirq; ++ ++ mutex_lock(&irq_domain_mutex); ++ + irq_set_status_flags(irq, IRQ_NOREQUEST); + + /* remove chip and handler */ +@@ -557,6 +560,8 @@ static void irq_domain_disassociate(stru + + /* Clear reverse map for this hwirq */ + irq_domain_clear_mapping(domain, hwirq); ++ ++ mutex_unlock(&irq_domain_mutex); + } + + static int irq_domain_associate_locked(struct irq_domain *domain, unsigned int virq, diff --git a/queue-6.2/irqdomain-fix-domain-registration-race.patch b/queue-6.2/irqdomain-fix-domain-registration-race.patch new file mode 100644 index 00000000000..9ce7f941d14 --- /dev/null +++ b/queue-6.2/irqdomain-fix-domain-registration-race.patch @@ -0,0 +1,129 @@ +From 8932c32c3053accd50702b36e944ac2016cd103c Mon Sep 17 00:00:00 2001 +From: Marc Zyngier +Date: Mon, 13 Feb 2023 11:42:49 +0100 +Subject: irqdomain: Fix domain registration race + +From: Marc Zyngier + +commit 8932c32c3053accd50702b36e944ac2016cd103c upstream. + +Hierarchical domains created using irq_domain_create_hierarchy() are +currently added to the domain list before having been fully initialised. + +This specifically means that a racing allocation request might fail to +allocate irq data for the inner domains of a hierarchy in case the +parent domain pointer has not yet been set up. + +Note that this is not really any issue for irqchip drivers that are +registered early (e.g. via IRQCHIP_DECLARE() or IRQCHIP_ACPI_DECLARE()) +but could potentially cause trouble with drivers that are registered +later (e.g. modular drivers using IRQCHIP_PLATFORM_DRIVER_BEGIN(), +gpiochip drivers, etc.). + +Fixes: afb7da83b9f4 ("irqdomain: Introduce helper function irq_domain_add_hierarchy()") +Cc: stable@vger.kernel.org # 3.19 +Signed-off-by: Marc Zyngier +[ johan: add commit message ] +Signed-off-by: Johan Hovold +Signed-off-by: Marc Zyngier +Link: https://lore.kernel.org/r/20230213104302.17307-8-johan+linaro@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + kernel/irq/irqdomain.c | 62 +++++++++++++++++++++++++++++++++---------------- + 1 file changed, 43 insertions(+), 19 deletions(-) + +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -126,23 +126,12 @@ void irq_domain_free_fwnode(struct fwnod + } + EXPORT_SYMBOL_GPL(irq_domain_free_fwnode); + +-/** +- * __irq_domain_add() - Allocate a new irq_domain data structure +- * @fwnode: firmware node for the interrupt controller +- * @size: Size of linear map; 0 for radix mapping only +- * @hwirq_max: Maximum number of interrupts supported by controller +- * @direct_max: Maximum value of direct maps; Use ~0 for no limit; 0 for no +- * direct mapping +- * @ops: domain callbacks +- * @host_data: Controller private data pointer +- * +- * Allocates and initializes an irq_domain structure. +- * Returns pointer to IRQ domain, or NULL on failure. +- */ +-struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, unsigned int size, +- irq_hw_number_t hwirq_max, int direct_max, +- const struct irq_domain_ops *ops, +- void *host_data) ++static struct irq_domain *__irq_domain_create(struct fwnode_handle *fwnode, ++ unsigned int size, ++ irq_hw_number_t hwirq_max, ++ int direct_max, ++ const struct irq_domain_ops *ops, ++ void *host_data) + { + struct irqchip_fwid *fwid; + struct irq_domain *domain; +@@ -230,12 +219,44 @@ struct irq_domain *__irq_domain_add(stru + + irq_domain_check_hierarchy(domain); + ++ return domain; ++} ++ ++static void __irq_domain_publish(struct irq_domain *domain) ++{ + mutex_lock(&irq_domain_mutex); + debugfs_add_domain_dir(domain); + list_add(&domain->link, &irq_domain_list); + mutex_unlock(&irq_domain_mutex); + + pr_debug("Added domain %s\n", domain->name); ++} ++ ++/** ++ * __irq_domain_add() - Allocate a new irq_domain data structure ++ * @fwnode: firmware node for the interrupt controller ++ * @size: Size of linear map; 0 for radix mapping only ++ * @hwirq_max: Maximum number of interrupts supported by controller ++ * @direct_max: Maximum value of direct maps; Use ~0 for no limit; 0 for no ++ * direct mapping ++ * @ops: domain callbacks ++ * @host_data: Controller private data pointer ++ * ++ * Allocates and initializes an irq_domain structure. ++ * Returns pointer to IRQ domain, or NULL on failure. ++ */ ++struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, unsigned int size, ++ irq_hw_number_t hwirq_max, int direct_max, ++ const struct irq_domain_ops *ops, ++ void *host_data) ++{ ++ struct irq_domain *domain; ++ ++ domain = __irq_domain_create(fwnode, size, hwirq_max, direct_max, ++ ops, host_data); ++ if (domain) ++ __irq_domain_publish(domain); ++ + return domain; + } + EXPORT_SYMBOL_GPL(__irq_domain_add); +@@ -1138,12 +1159,15 @@ struct irq_domain *irq_domain_create_hie + struct irq_domain *domain; + + if (size) +- domain = irq_domain_create_linear(fwnode, size, ops, host_data); ++ domain = __irq_domain_create(fwnode, size, size, 0, ops, host_data); + else +- domain = irq_domain_create_tree(fwnode, ops, host_data); ++ domain = __irq_domain_create(fwnode, 0, ~0, 0, ops, host_data); ++ + if (domain) { + domain->parent = parent; + domain->flags |= flags; ++ ++ __irq_domain_publish(domain); + } + + return domain; diff --git a/queue-6.2/irqdomain-fix-mapping-creation-race.patch b/queue-6.2/irqdomain-fix-mapping-creation-race.patch new file mode 100644 index 00000000000..de47ab2e7a1 --- /dev/null +++ b/queue-6.2/irqdomain-fix-mapping-creation-race.patch @@ -0,0 +1,179 @@ +From 601363cc08da25747feb87c55573dd54de91d66a Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 13 Feb 2023 11:42:48 +0100 +Subject: irqdomain: Fix mapping-creation race + +From: Johan Hovold + +commit 601363cc08da25747feb87c55573dd54de91d66a upstream. + +Parallel probing of devices that share interrupts (e.g. when a driver +uses asynchronous probing) can currently result in two mappings for the +same hardware interrupt to be created due to missing serialisation. + +Make sure to hold the irq_domain_mutex when creating mappings so that +looking for an existing mapping before creating a new one is done +atomically. + +Fixes: 765230b5f084 ("driver-core: add asynchronous probing support for drivers") +Fixes: b62b2cf5759b ("irqdomain: Fix handling of type settings for existing mappings") +Link: https://lore.kernel.org/r/YuJXMHoT4ijUxnRb@hovoldconsulting.com +Cc: stable@vger.kernel.org # 4.8 +Cc: Dmitry Torokhov +Cc: Jon Hunter +Tested-by: Hsin-Yi Wang +Tested-by: Mark-PK Tsai +Signed-off-by: Johan Hovold +Signed-off-by: Marc Zyngier +Link: https://lore.kernel.org/r/20230213104302.17307-7-johan+linaro@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + kernel/irq/irqdomain.c | 64 +++++++++++++++++++++++++++++++++++-------------- + 1 file changed, 46 insertions(+), 18 deletions(-) + +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -25,6 +25,9 @@ static DEFINE_MUTEX(irq_domain_mutex); + + static struct irq_domain *irq_default_domain; + ++static int irq_domain_alloc_irqs_locked(struct irq_domain *domain, int irq_base, ++ unsigned int nr_irqs, int node, void *arg, ++ bool realloc, const struct irq_affinity_desc *affinity); + static void irq_domain_check_hierarchy(struct irq_domain *domain); + + struct irqchip_fwid { +@@ -682,9 +685,9 @@ unsigned int irq_create_direct_mapping(s + EXPORT_SYMBOL_GPL(irq_create_direct_mapping); + #endif + +-static unsigned int __irq_create_mapping_affinity(struct irq_domain *domain, +- irq_hw_number_t hwirq, +- const struct irq_affinity_desc *affinity) ++static unsigned int irq_create_mapping_affinity_locked(struct irq_domain *domain, ++ irq_hw_number_t hwirq, ++ const struct irq_affinity_desc *affinity) + { + struct device_node *of_node = irq_domain_get_of_node(domain); + int virq; +@@ -699,7 +702,7 @@ static unsigned int __irq_create_mapping + return 0; + } + +- if (irq_domain_associate(domain, virq, hwirq)) { ++ if (irq_domain_associate_locked(domain, virq, hwirq)) { + irq_free_desc(virq); + return 0; + } +@@ -735,14 +738,20 @@ unsigned int irq_create_mapping_affinity + return 0; + } + ++ mutex_lock(&irq_domain_mutex); ++ + /* Check if mapping already exists */ + virq = irq_find_mapping(domain, hwirq); + if (virq) { + pr_debug("existing mapping on virq %d\n", virq); +- return virq; ++ goto out; + } + +- return __irq_create_mapping_affinity(domain, hwirq, affinity); ++ virq = irq_create_mapping_affinity_locked(domain, hwirq, affinity); ++out: ++ mutex_unlock(&irq_domain_mutex); ++ ++ return virq; + } + EXPORT_SYMBOL_GPL(irq_create_mapping_affinity); + +@@ -809,6 +818,8 @@ unsigned int irq_create_fwspec_mapping(s + if (WARN_ON(type & ~IRQ_TYPE_SENSE_MASK)) + type &= IRQ_TYPE_SENSE_MASK; + ++ mutex_lock(&irq_domain_mutex); ++ + /* + * If we've already configured this interrupt, + * don't do it again, or hell will break loose. +@@ -821,7 +832,7 @@ unsigned int irq_create_fwspec_mapping(s + * interrupt number. + */ + if (type == IRQ_TYPE_NONE || type == irq_get_trigger_type(virq)) +- return virq; ++ goto out; + + /* + * If the trigger type has not been set yet, then set +@@ -829,35 +840,45 @@ unsigned int irq_create_fwspec_mapping(s + */ + if (irq_get_trigger_type(virq) == IRQ_TYPE_NONE) { + irq_data = irq_get_irq_data(virq); +- if (!irq_data) +- return 0; ++ if (!irq_data) { ++ virq = 0; ++ goto out; ++ } + + irqd_set_trigger_type(irq_data, type); +- return virq; ++ goto out; + } + + pr_warn("type mismatch, failed to map hwirq-%lu for %s!\n", + hwirq, of_node_full_name(to_of_node(fwspec->fwnode))); +- return 0; ++ virq = 0; ++ goto out; + } + + if (irq_domain_is_hierarchy(domain)) { +- virq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, fwspec); +- if (virq <= 0) +- return 0; ++ virq = irq_domain_alloc_irqs_locked(domain, -1, 1, NUMA_NO_NODE, ++ fwspec, false, NULL); ++ if (virq <= 0) { ++ virq = 0; ++ goto out; ++ } + } else { + /* Create mapping */ +- virq = __irq_create_mapping_affinity(domain, hwirq, NULL); ++ virq = irq_create_mapping_affinity_locked(domain, hwirq, NULL); + if (!virq) +- return virq; ++ goto out; + } + + irq_data = irq_get_irq_data(virq); +- if (WARN_ON(!irq_data)) +- return 0; ++ if (WARN_ON(!irq_data)) { ++ virq = 0; ++ goto out; ++ } + + /* Store trigger type */ + irqd_set_trigger_type(irq_data, type); ++out: ++ mutex_unlock(&irq_domain_mutex); + + return virq; + } +@@ -1888,6 +1909,13 @@ void irq_domain_set_info(struct irq_doma + irq_set_handler_data(virq, handler_data); + } + ++static int irq_domain_alloc_irqs_locked(struct irq_domain *domain, int irq_base, ++ unsigned int nr_irqs, int node, void *arg, ++ bool realloc, const struct irq_affinity_desc *affinity) ++{ ++ return -EINVAL; ++} ++ + static void irq_domain_check_hierarchy(struct irq_domain *domain) + { + } diff --git a/queue-6.2/irqdomain-look-for-existing-mapping-only-once.patch b/queue-6.2/irqdomain-look-for-existing-mapping-only-once.patch new file mode 100644 index 00000000000..74cf8bacaa1 --- /dev/null +++ b/queue-6.2/irqdomain-look-for-existing-mapping-only-once.patch @@ -0,0 +1,128 @@ +From 6e6f75c9c98d2d246d90411ff2b6f0cd271f4cba Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 13 Feb 2023 11:42:46 +0100 +Subject: irqdomain: Look for existing mapping only once + +From: Johan Hovold + +commit 6e6f75c9c98d2d246d90411ff2b6f0cd271f4cba upstream. + +Avoid looking for an existing mapping twice when creating a new mapping +using irq_create_fwspec_mapping() by factoring out the actual allocation +which is shared with irq_create_mapping_affinity(). + +The new helper function will also be used to fix a shared-interrupt +mapping race, hence the Fixes tag. + +Fixes: b62b2cf5759b ("irqdomain: Fix handling of type settings for existing mappings") +Cc: stable@vger.kernel.org # 4.8 +Tested-by: Hsin-Yi Wang +Tested-by: Mark-PK Tsai +Signed-off-by: Johan Hovold +Signed-off-by: Marc Zyngier +Link: https://lore.kernel.org/r/20230213104302.17307-5-johan+linaro@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + kernel/irq/irqdomain.c | 60 ++++++++++++++++++++++++++----------------------- + 1 file changed, 33 insertions(+), 27 deletions(-) + +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -682,6 +682,34 @@ unsigned int irq_create_direct_mapping(s + EXPORT_SYMBOL_GPL(irq_create_direct_mapping); + #endif + ++static unsigned int __irq_create_mapping_affinity(struct irq_domain *domain, ++ irq_hw_number_t hwirq, ++ const struct irq_affinity_desc *affinity) ++{ ++ struct device_node *of_node = irq_domain_get_of_node(domain); ++ int virq; ++ ++ pr_debug("irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq); ++ ++ /* Allocate a virtual interrupt number */ ++ virq = irq_domain_alloc_descs(-1, 1, hwirq, of_node_to_nid(of_node), ++ affinity); ++ if (virq <= 0) { ++ pr_debug("-> virq allocation failed\n"); ++ return 0; ++ } ++ ++ if (irq_domain_associate(domain, virq, hwirq)) { ++ irq_free_desc(virq); ++ return 0; ++ } ++ ++ pr_debug("irq %lu on domain %s mapped to virtual irq %u\n", ++ hwirq, of_node_full_name(of_node), virq); ++ ++ return virq; ++} ++ + /** + * irq_create_mapping_affinity() - Map a hardware interrupt into linux irq space + * @domain: domain owning this hardware interrupt or NULL for default domain +@@ -694,14 +722,11 @@ EXPORT_SYMBOL_GPL(irq_create_direct_mapp + * on the number returned from that call. + */ + unsigned int irq_create_mapping_affinity(struct irq_domain *domain, +- irq_hw_number_t hwirq, +- const struct irq_affinity_desc *affinity) ++ irq_hw_number_t hwirq, ++ const struct irq_affinity_desc *affinity) + { +- struct device_node *of_node; + int virq; + +- pr_debug("irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq); +- + /* Look for default domain if necessary */ + if (domain == NULL) + domain = irq_default_domain; +@@ -709,34 +734,15 @@ unsigned int irq_create_mapping_affinity + WARN(1, "%s(, %lx) called with NULL domain\n", __func__, hwirq); + return 0; + } +- pr_debug("-> using domain @%p\n", domain); +- +- of_node = irq_domain_get_of_node(domain); + + /* Check if mapping already exists */ + virq = irq_find_mapping(domain, hwirq); + if (virq) { +- pr_debug("-> existing mapping on virq %d\n", virq); ++ pr_debug("existing mapping on virq %d\n", virq); + return virq; + } + +- /* Allocate a virtual interrupt number */ +- virq = irq_domain_alloc_descs(-1, 1, hwirq, of_node_to_nid(of_node), +- affinity); +- if (virq <= 0) { +- pr_debug("-> virq allocation failed\n"); +- return 0; +- } +- +- if (irq_domain_associate(domain, virq, hwirq)) { +- irq_free_desc(virq); +- return 0; +- } +- +- pr_debug("irq %lu on domain %s mapped to virtual irq %u\n", +- hwirq, of_node_full_name(of_node), virq); +- +- return virq; ++ return __irq_create_mapping_affinity(domain, hwirq, affinity); + } + EXPORT_SYMBOL_GPL(irq_create_mapping_affinity); + +@@ -841,7 +847,7 @@ unsigned int irq_create_fwspec_mapping(s + return 0; + } else { + /* Create mapping */ +- virq = irq_create_mapping(domain, hwirq); ++ virq = __irq_create_mapping_affinity(domain, hwirq, NULL); + if (!virq) + return virq; + } diff --git a/queue-6.2/irqdomain-refactor-__irq_domain_alloc_irqs.patch b/queue-6.2/irqdomain-refactor-__irq_domain_alloc_irqs.patch new file mode 100644 index 00000000000..dfea335cd94 --- /dev/null +++ b/queue-6.2/irqdomain-refactor-__irq_domain_alloc_irqs.patch @@ -0,0 +1,150 @@ +From d55f7f4c58c07beb5050a834bf57ae2ede599c7e Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 13 Feb 2023 11:42:47 +0100 +Subject: irqdomain: Refactor __irq_domain_alloc_irqs() + +From: Johan Hovold + +commit d55f7f4c58c07beb5050a834bf57ae2ede599c7e upstream. + +Refactor __irq_domain_alloc_irqs() so that it can be called internally +while holding the irq_domain_mutex. + +This will be used to fix a shared-interrupt mapping race, hence the +Fixes tag. + +Fixes: b62b2cf5759b ("irqdomain: Fix handling of type settings for existing mappings") +Cc: stable@vger.kernel.org # 4.8 +Tested-by: Hsin-Yi Wang +Tested-by: Mark-PK Tsai +Signed-off-by: Johan Hovold +Signed-off-by: Marc Zyngier +Link: https://lore.kernel.org/r/20230213104302.17307-6-johan+linaro@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + kernel/irq/irqdomain.c | 88 ++++++++++++++++++++++++++----------------------- + 1 file changed, 48 insertions(+), 40 deletions(-) + +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -1441,40 +1441,12 @@ int irq_domain_alloc_irqs_hierarchy(stru + return domain->ops->alloc(domain, irq_base, nr_irqs, arg); + } + +-/** +- * __irq_domain_alloc_irqs - Allocate IRQs from domain +- * @domain: domain to allocate from +- * @irq_base: allocate specified IRQ number if irq_base >= 0 +- * @nr_irqs: number of IRQs to allocate +- * @node: NUMA node id for memory allocation +- * @arg: domain specific argument +- * @realloc: IRQ descriptors have already been allocated if true +- * @affinity: Optional irq affinity mask for multiqueue devices +- * +- * Allocate IRQ numbers and initialized all data structures to support +- * hierarchy IRQ domains. +- * Parameter @realloc is mainly to support legacy IRQs. +- * Returns error code or allocated IRQ number +- * +- * The whole process to setup an IRQ has been split into two steps. +- * The first step, __irq_domain_alloc_irqs(), is to allocate IRQ +- * descriptor and required hardware resources. The second step, +- * irq_domain_activate_irq(), is to program the hardware with preallocated +- * resources. In this way, it's easier to rollback when failing to +- * allocate resources. +- */ +-int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base, +- unsigned int nr_irqs, int node, void *arg, +- bool realloc, const struct irq_affinity_desc *affinity) ++static int irq_domain_alloc_irqs_locked(struct irq_domain *domain, int irq_base, ++ unsigned int nr_irqs, int node, void *arg, ++ bool realloc, const struct irq_affinity_desc *affinity) + { + int i, ret, virq; + +- if (domain == NULL) { +- domain = irq_default_domain; +- if (WARN(!domain, "domain is NULL; cannot allocate IRQ\n")) +- return -EINVAL; +- } +- + if (realloc && irq_base >= 0) { + virq = irq_base; + } else { +@@ -1493,24 +1465,18 @@ int __irq_domain_alloc_irqs(struct irq_d + goto out_free_desc; + } + +- mutex_lock(&irq_domain_mutex); + ret = irq_domain_alloc_irqs_hierarchy(domain, virq, nr_irqs, arg); +- if (ret < 0) { +- mutex_unlock(&irq_domain_mutex); ++ if (ret < 0) + goto out_free_irq_data; +- } + + for (i = 0; i < nr_irqs; i++) { + ret = irq_domain_trim_hierarchy(virq + i); +- if (ret) { +- mutex_unlock(&irq_domain_mutex); ++ if (ret) + goto out_free_irq_data; +- } + } +- ++ + for (i = 0; i < nr_irqs; i++) + irq_domain_insert_irq(virq + i); +- mutex_unlock(&irq_domain_mutex); + + return virq; + +@@ -1520,6 +1486,48 @@ out_free_desc: + irq_free_descs(virq, nr_irqs); + return ret; + } ++ ++/** ++ * __irq_domain_alloc_irqs - Allocate IRQs from domain ++ * @domain: domain to allocate from ++ * @irq_base: allocate specified IRQ number if irq_base >= 0 ++ * @nr_irqs: number of IRQs to allocate ++ * @node: NUMA node id for memory allocation ++ * @arg: domain specific argument ++ * @realloc: IRQ descriptors have already been allocated if true ++ * @affinity: Optional irq affinity mask for multiqueue devices ++ * ++ * Allocate IRQ numbers and initialized all data structures to support ++ * hierarchy IRQ domains. ++ * Parameter @realloc is mainly to support legacy IRQs. ++ * Returns error code or allocated IRQ number ++ * ++ * The whole process to setup an IRQ has been split into two steps. ++ * The first step, __irq_domain_alloc_irqs(), is to allocate IRQ ++ * descriptor and required hardware resources. The second step, ++ * irq_domain_activate_irq(), is to program the hardware with preallocated ++ * resources. In this way, it's easier to rollback when failing to ++ * allocate resources. ++ */ ++int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base, ++ unsigned int nr_irqs, int node, void *arg, ++ bool realloc, const struct irq_affinity_desc *affinity) ++{ ++ int ret; ++ ++ if (domain == NULL) { ++ domain = irq_default_domain; ++ if (WARN(!domain, "domain is NULL; cannot allocate IRQ\n")) ++ return -EINVAL; ++ } ++ ++ mutex_lock(&irq_domain_mutex); ++ ret = irq_domain_alloc_irqs_locked(domain, irq_base, nr_irqs, node, arg, ++ realloc, affinity); ++ mutex_unlock(&irq_domain_mutex); ++ ++ return ret; ++} + EXPORT_SYMBOL_GPL(__irq_domain_alloc_irqs); + + /* The irq_data was moved, fix the revmap to refer to the new location */ diff --git a/queue-6.2/series b/queue-6.2/series index 8ccdea9e10e..629c7f212c5 100644 --- a/queue-6.2/series +++ b/queue-6.2/series @@ -878,3 +878,11 @@ selftests-drivers-fix-incorrect-kernel-headers-search-path.patch selftests-dmabuf-heaps-fix-incorrect-kernel-headers-search-path.patch selftests-vm-fix-incorrect-kernel-headers-search-path.patch selftests-seccomp-fix-incorrect-kernel-headers-search-path.patch +irqdomain-fix-association-race.patch +irqdomain-fix-disassociation-race.patch +irqdomain-look-for-existing-mapping-only-once.patch +irqdomain-drop-bogus-fwspec-mapping-error-handling.patch +irqdomain-refactor-__irq_domain_alloc_irqs.patch +irqdomain-fix-mapping-creation-race.patch +irqdomain-fix-domain-registration-race.patch +crypto-qat-fix-out-of-bounds-read.patch