From: Greg Kroah-Hartman Date: Tue, 10 Dec 2024 09:35:23 +0000 (+0100) Subject: 5.10-stable patches X-Git-Tag: v6.6.65~25 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5f1727a5a6fabf05bd03cffb966f00bd445fefdc;p=thirdparty%2Fkernel%2Fstable-queue.git 5.10-stable patches added patches: bpf-fix-oob-devmap-writes-when-deleting-elements.patch dma-buf-fix-dma_fence_array_signaled-v4.patch mmc-core-further-prevent-card-detect-during-shutdown.patch mmc-sdhci-pci-add-dmi-quirk-for-missing-cd-gpio-on-vexia-edu-atla-10-tablet.patch regmap-detach-regmap-from-dev-on-regmap_exit.patch x86-kexec-restore-gdt-on-return-from-preserve_context-kexec.patch --- diff --git a/queue-5.10/bpf-fix-oob-devmap-writes-when-deleting-elements.patch b/queue-5.10/bpf-fix-oob-devmap-writes-when-deleting-elements.patch new file mode 100644 index 00000000000..22c53e3d144 --- /dev/null +++ b/queue-5.10/bpf-fix-oob-devmap-writes-when-deleting-elements.patch @@ -0,0 +1,110 @@ +From ab244dd7cf4c291f82faacdc50b45cc0f55b674d Mon Sep 17 00:00:00 2001 +From: Maciej Fijalkowski +Date: Fri, 22 Nov 2024 13:10:30 +0100 +Subject: bpf: fix OOB devmap writes when deleting elements +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Maciej Fijalkowski + +commit ab244dd7cf4c291f82faacdc50b45cc0f55b674d upstream. + +Jordy reported issue against XSKMAP which also applies to DEVMAP - the +index used for accessing map entry, due to being a signed integer, +causes the OOB writes. Fix is simple as changing the type from int to +u32, however, when compared to XSKMAP case, one more thing needs to be +addressed. + +When map is released from system via dev_map_free(), we iterate through +all of the entries and an iterator variable is also an int, which +implies OOB accesses. Again, change it to be u32. + +Example splat below: + +[ 160.724676] BUG: unable to handle page fault for address: ffffc8fc2c001000 +[ 160.731662] #PF: supervisor read access in kernel mode +[ 160.736876] #PF: error_code(0x0000) - not-present page +[ 160.742095] PGD 0 P4D 0 +[ 160.744678] Oops: Oops: 0000 [#1] PREEMPT SMP +[ 160.749106] CPU: 1 UID: 0 PID: 520 Comm: kworker/u145:12 Not tainted 6.12.0-rc1+ #487 +[ 160.757050] Hardware name: Intel Corporation S2600WFT/S2600WFT, BIOS SE5C620.86B.02.01.0008.031920191559 03/19/2019 +[ 160.767642] Workqueue: events_unbound bpf_map_free_deferred +[ 160.773308] RIP: 0010:dev_map_free+0x77/0x170 +[ 160.777735] Code: 00 e8 fd 91 ed ff e8 b8 73 ed ff 41 83 7d 18 19 74 6e 41 8b 45 24 49 8b bd f8 00 00 00 31 db 85 c0 74 48 48 63 c3 48 8d 04 c7 <48> 8b 28 48 85 ed 74 30 48 8b 7d 18 48 85 ff 74 05 e8 b3 52 fa ff +[ 160.796777] RSP: 0018:ffffc9000ee1fe38 EFLAGS: 00010202 +[ 160.802086] RAX: ffffc8fc2c001000 RBX: 0000000080000000 RCX: 0000000000000024 +[ 160.809331] RDX: 0000000000000000 RSI: 0000000000000024 RDI: ffffc9002c001000 +[ 160.816576] RBP: 0000000000000000 R08: 0000000000000023 R09: 0000000000000001 +[ 160.823823] R10: 0000000000000001 R11: 00000000000ee6b2 R12: dead000000000122 +[ 160.831066] R13: ffff88810c928e00 R14: ffff8881002df405 R15: 0000000000000000 +[ 160.838310] FS: 0000000000000000(0000) GS:ffff8897e0c40000(0000) knlGS:0000000000000000 +[ 160.846528] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 160.852357] CR2: ffffc8fc2c001000 CR3: 0000000005c32006 CR4: 00000000007726f0 +[ 160.859604] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +[ 160.866847] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +[ 160.874092] PKRU: 55555554 +[ 160.876847] Call Trace: +[ 160.879338] +[ 160.881477] ? __die+0x20/0x60 +[ 160.884586] ? page_fault_oops+0x15a/0x450 +[ 160.888746] ? search_extable+0x22/0x30 +[ 160.892647] ? search_bpf_extables+0x5f/0x80 +[ 160.896988] ? exc_page_fault+0xa9/0x140 +[ 160.900973] ? asm_exc_page_fault+0x22/0x30 +[ 160.905232] ? dev_map_free+0x77/0x170 +[ 160.909043] ? dev_map_free+0x58/0x170 +[ 160.912857] bpf_map_free_deferred+0x51/0x90 +[ 160.917196] process_one_work+0x142/0x370 +[ 160.921272] worker_thread+0x29e/0x3b0 +[ 160.925082] ? rescuer_thread+0x4b0/0x4b0 +[ 160.929157] kthread+0xd4/0x110 +[ 160.932355] ? kthread_park+0x80/0x80 +[ 160.936079] ret_from_fork+0x2d/0x50 +[ 160.943396] ? kthread_park+0x80/0x80 +[ 160.950803] ret_from_fork_asm+0x11/0x20 +[ 160.958482] + +Fixes: 546ac1ffb70d ("bpf: add devmap, a map for storing net device references") +CC: stable@vger.kernel.org +Reported-by: Jordy Zomer +Suggested-by: Jordy Zomer +Reviewed-by: Toke Høiland-Jørgensen +Acked-by: John Fastabend +Signed-off-by: Maciej Fijalkowski +Link: https://lore.kernel.org/r/20241122121030.716788-3-maciej.fijalkowski@intel.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Greg Kroah-Hartman +--- + kernel/bpf/devmap.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/kernel/bpf/devmap.c ++++ b/kernel/bpf/devmap.c +@@ -198,7 +198,7 @@ static struct bpf_map *dev_map_alloc(uni + static void dev_map_free(struct bpf_map *map) + { + struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map); +- int i; ++ u32 i; + + /* At this point bpf_prog->aux->refcnt == 0 and this map->refcnt == 0, + * so the programs (can be more than one that used this map) were +@@ -557,7 +557,7 @@ static int dev_map_delete_elem(struct bp + { + struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map); + struct bpf_dtab_netdev *old_dev; +- int k = *(u32 *)key; ++ u32 k = *(u32 *)key; + + if (k >= map->max_entries) + return -EINVAL; +@@ -579,7 +579,7 @@ static int dev_map_hash_delete_elem(stru + { + struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map); + struct bpf_dtab_netdev *old_dev; +- int k = *(u32 *)key; ++ u32 k = *(u32 *)key; + unsigned long flags; + int ret = -ENOENT; + diff --git a/queue-5.10/dma-buf-fix-dma_fence_array_signaled-v4.patch b/queue-5.10/dma-buf-fix-dma_fence_array_signaled-v4.patch new file mode 100644 index 00000000000..c84e446fb2f --- /dev/null +++ b/queue-5.10/dma-buf-fix-dma_fence_array_signaled-v4.patch @@ -0,0 +1,75 @@ +From 78ac1c3558810486d90aa533b0039aa70487a3da Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20K=C3=B6nig?= +Date: Fri, 8 Nov 2024 09:29:48 +0100 +Subject: dma-buf: fix dma_fence_array_signaled v4 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Christian König + +commit 78ac1c3558810486d90aa533b0039aa70487a3da upstream. + +The function silently assumed that signaling was already enabled for the +dma_fence_array. This meant that without enabling signaling first we would +never see forward progress. + +Fix that by falling back to testing each individual fence when signaling +isn't enabled yet. + +v2: add the comment suggested by Boris why this is done this way +v3: fix the underflow pointed out by Tvrtko +v4: atomic_read_acquire() as suggested by Tvrtko + +Signed-off-by: Christian König +Reviewed-by: Boris Brezillon +Tested-by: Chia-I Wu +Reviewed-by: Tvrtko Ursulin +Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/12094 +Cc: +Link: https://patchwork.freedesktop.org/patch/msgid/20241112121925.18464-1-christian.koenig@amd.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/dma-buf/dma-fence-array.c | 28 +++++++++++++++++++++++++++- + 1 file changed, 27 insertions(+), 1 deletion(-) + +--- a/drivers/dma-buf/dma-fence-array.c ++++ b/drivers/dma-buf/dma-fence-array.c +@@ -103,10 +103,36 @@ static bool dma_fence_array_enable_signa + static bool dma_fence_array_signaled(struct dma_fence *fence) + { + struct dma_fence_array *array = to_dma_fence_array(fence); ++ int num_pending; ++ unsigned int i; + +- if (atomic_read(&array->num_pending) > 0) ++ /* ++ * We need to read num_pending before checking the enable_signal bit ++ * to avoid racing with the enable_signaling() implementation, which ++ * might decrement the counter, and cause a partial check. ++ * atomic_read_acquire() pairs with atomic_dec_and_test() in ++ * dma_fence_array_enable_signaling() ++ * ++ * The !--num_pending check is here to account for the any_signaled case ++ * if we race with enable_signaling(), that means the !num_pending check ++ * in the is_signalling_enabled branch might be outdated (num_pending ++ * might have been decremented), but that's fine. The user will get the ++ * right value when testing again later. ++ */ ++ num_pending = atomic_read_acquire(&array->num_pending); ++ if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &array->base.flags)) { ++ if (num_pending <= 0) ++ goto signal; + return false; ++ } + ++ for (i = 0; i < array->num_fences; ++i) { ++ if (dma_fence_is_signaled(array->fences[i]) && !--num_pending) ++ goto signal; ++ } ++ return false; ++ ++signal: + dma_fence_array_clear_pending_error(array); + return true; + } diff --git a/queue-5.10/mmc-core-further-prevent-card-detect-during-shutdown.patch b/queue-5.10/mmc-core-further-prevent-card-detect-during-shutdown.patch new file mode 100644 index 00000000000..737d64b3e6f --- /dev/null +++ b/queue-5.10/mmc-core-further-prevent-card-detect-during-shutdown.patch @@ -0,0 +1,56 @@ +From 87a0d90fcd31c0f36da0332428c9e1a1e0f97432 Mon Sep 17 00:00:00 2001 +From: Ulf Hansson +Date: Mon, 25 Nov 2024 13:24:46 +0100 +Subject: mmc: core: Further prevent card detect during shutdown + +From: Ulf Hansson + +commit 87a0d90fcd31c0f36da0332428c9e1a1e0f97432 upstream. + +Disabling card detect from the host's ->shutdown_pre() callback turned out +to not be the complete solution. More precisely, beyond the point when the +mmc_bus->shutdown() has been called, to gracefully power off the card, we +need to prevent card detect. Otherwise the mmc_rescan work may poll for the +card with a CMD13, to see if it's still alive, which then will fail and +hang as the card has already been powered off. + +To fix this problem, let's disable mmc_rescan prior to power off the card +during shutdown. + +Reported-by: Anthony Pighin +Fixes: 66c915d09b94 ("mmc: core: Disable card detect during shutdown") +Cc: stable@vger.kernel.org +Signed-off-by: Ulf Hansson +Reviewed-by: Adrian Hunter +Closes: https://lore.kernel.org/all/BN0PR08MB695133000AF116F04C3A9FFE83212@BN0PR08MB6951.namprd08.prod.outlook.com/ +Tested-by: Anthony Pighin +Message-ID: <20241125122446.18684-1-ulf.hansson@linaro.org> +Signed-off-by: Greg Kroah-Hartman +--- + drivers/mmc/core/bus.c | 2 ++ + drivers/mmc/core/core.c | 3 +++ + 2 files changed, 5 insertions(+) + +--- a/drivers/mmc/core/bus.c ++++ b/drivers/mmc/core/bus.c +@@ -160,6 +160,8 @@ static void mmc_bus_shutdown(struct devi + if (dev->driver && drv->shutdown) + drv->shutdown(card); + ++ __mmc_stop_host(host); ++ + if (host->bus_ops->shutdown) { + ret = host->bus_ops->shutdown(host); + if (ret) +--- a/drivers/mmc/core/core.c ++++ b/drivers/mmc/core/core.c +@@ -2345,6 +2345,9 @@ void mmc_start_host(struct mmc_host *hos + + void __mmc_stop_host(struct mmc_host *host) + { ++ if (host->rescan_disable) ++ return; ++ + if (host->slot.cd_irq >= 0) { + mmc_gpio_set_cd_wake(host, false); + disable_irq(host->slot.cd_irq); diff --git a/queue-5.10/mmc-sdhci-pci-add-dmi-quirk-for-missing-cd-gpio-on-vexia-edu-atla-10-tablet.patch b/queue-5.10/mmc-sdhci-pci-add-dmi-quirk-for-missing-cd-gpio-on-vexia-edu-atla-10-tablet.patch new file mode 100644 index 00000000000..42828e27a3a --- /dev/null +++ b/queue-5.10/mmc-sdhci-pci-add-dmi-quirk-for-missing-cd-gpio-on-vexia-edu-atla-10-tablet.patch @@ -0,0 +1,155 @@ +From 7f0fa47ceebcff0e3591bb7e32a71a2cd7846149 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Mon, 18 Nov 2024 22:00:49 +0100 +Subject: mmc: sdhci-pci: Add DMI quirk for missing CD GPIO on Vexia Edu Atla 10 tablet +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Hans de Goede + +commit 7f0fa47ceebcff0e3591bb7e32a71a2cd7846149 upstream. + +The Vexia Edu Atla 10 tablet distributed to schools in the Spanish +Andalucía region has no ACPI fwnode associated with the SDHCI controller +for its microsd-slot and thus has no ACPI GPIO resource info. + +This causes the following error to be logged and the slot to not work: +[ 10.572113] sdhci-pci 0000:00:12.0: failed to setup card detect gpio + +Add a DMI quirk table for providing gpiod_lookup_tables with manually +provided CD GPIO info and use this DMI table to provide the CD GPIO info +on this tablet. This fixes the microsd-slot not working. + +Signed-off-by: Hans de Goede +Acked-by: Adrian Hunter +Cc: stable@vger.kernel.org +Message-ID: <20241118210049.311079-1-hdegoede@redhat.com> +Signed-off-by: Ulf Hansson +Signed-off-by: Greg Kroah-Hartman +--- + drivers/mmc/host/sdhci-pci-core.c | 72 ++++++++++++++++++++++++++++++++++++++ + drivers/mmc/host/sdhci-pci.h | 1 + 2 files changed, 73 insertions(+) + +--- a/drivers/mmc/host/sdhci-pci-core.c ++++ b/drivers/mmc/host/sdhci-pci-core.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1292,6 +1293,29 @@ static const struct sdhci_pci_fixes sdhc + .priv_size = sizeof(struct intel_host), + }; + ++/* DMI quirks for devices with missing or broken CD GPIO info */ ++static const struct gpiod_lookup_table vexia_edu_atla10_cd_gpios = { ++ .dev_id = "0000:00:12.0", ++ .table = { ++ GPIO_LOOKUP("INT33FC:00", 38, "cd", GPIO_ACTIVE_HIGH), ++ { } ++ }, ++}; ++ ++static const struct dmi_system_id sdhci_intel_byt_cd_gpio_override[] = { ++ { ++ /* Vexia Edu Atla 10 tablet 9V version */ ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), ++ DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"), ++ /* Above strings are too generic, also match on BIOS date */ ++ DMI_MATCH(DMI_BIOS_DATE, "08/25/2014"), ++ }, ++ .driver_data = (void *)&vexia_edu_atla10_cd_gpios, ++ }, ++ { } ++}; ++ + static const struct sdhci_pci_fixes sdhci_intel_byt_sd = { + #ifdef CONFIG_PM_SLEEP + .resume = byt_resume, +@@ -1310,6 +1334,7 @@ static const struct sdhci_pci_fixes sdhc + .add_host = byt_add_host, + .remove_slot = byt_remove_slot, + .ops = &sdhci_intel_byt_ops, ++ .cd_gpio_override = sdhci_intel_byt_cd_gpio_override, + .priv_size = sizeof(struct intel_host), + }; + +@@ -2101,6 +2126,42 @@ static const struct dev_pm_ops sdhci_pci + * * + \*****************************************************************************/ + ++static struct gpiod_lookup_table *sdhci_pci_add_gpio_lookup_table( ++ struct sdhci_pci_chip *chip) ++{ ++ struct gpiod_lookup_table *cd_gpio_lookup_table; ++ const struct dmi_system_id *dmi_id = NULL; ++ size_t count; ++ ++ if (chip->fixes && chip->fixes->cd_gpio_override) ++ dmi_id = dmi_first_match(chip->fixes->cd_gpio_override); ++ ++ if (!dmi_id) ++ return NULL; ++ ++ cd_gpio_lookup_table = dmi_id->driver_data; ++ for (count = 0; cd_gpio_lookup_table->table[count].key; count++) ++ ; ++ ++ cd_gpio_lookup_table = kmemdup(dmi_id->driver_data, ++ /* count + 1 terminating entry */ ++ struct_size(cd_gpio_lookup_table, table, count + 1), ++ GFP_KERNEL); ++ if (!cd_gpio_lookup_table) ++ return ERR_PTR(-ENOMEM); ++ ++ gpiod_add_lookup_table(cd_gpio_lookup_table); ++ return cd_gpio_lookup_table; ++} ++ ++static void sdhci_pci_remove_gpio_lookup_table(struct gpiod_lookup_table *lookup_table) ++{ ++ if (lookup_table) { ++ gpiod_remove_lookup_table(lookup_table); ++ kfree(lookup_table); ++ } ++} ++ + static struct sdhci_pci_slot *sdhci_pci_probe_slot( + struct pci_dev *pdev, struct sdhci_pci_chip *chip, int first_bar, + int slotno) +@@ -2205,8 +2266,19 @@ static struct sdhci_pci_slot *sdhci_pci_ + device_init_wakeup(&pdev->dev, true); + + if (slot->cd_idx >= 0) { ++ struct gpiod_lookup_table *cd_gpio_lookup_table; ++ ++ cd_gpio_lookup_table = sdhci_pci_add_gpio_lookup_table(chip); ++ if (IS_ERR(cd_gpio_lookup_table)) { ++ ret = PTR_ERR(cd_gpio_lookup_table); ++ goto remove; ++ } ++ + ret = mmc_gpiod_request_cd(host->mmc, "cd", slot->cd_idx, + slot->cd_override_level, 0); ++ ++ sdhci_pci_remove_gpio_lookup_table(cd_gpio_lookup_table); ++ + if (ret && ret != -EPROBE_DEFER) + ret = mmc_gpiod_request_cd(host->mmc, NULL, + slot->cd_idx, +--- a/drivers/mmc/host/sdhci-pci.h ++++ b/drivers/mmc/host/sdhci-pci.h +@@ -151,6 +151,7 @@ struct sdhci_pci_fixes { + #endif + + const struct sdhci_ops *ops; ++ const struct dmi_system_id *cd_gpio_override; + size_t priv_size; + }; + diff --git a/queue-5.10/regmap-detach-regmap-from-dev-on-regmap_exit.patch b/queue-5.10/regmap-detach-regmap-from-dev-on-regmap_exit.patch new file mode 100644 index 00000000000..5c572701862 --- /dev/null +++ b/queue-5.10/regmap-detach-regmap-from-dev-on-regmap_exit.patch @@ -0,0 +1,59 @@ +From 3061e170381af96d1e66799d34264e6414d428a7 Mon Sep 17 00:00:00 2001 +From: Cosmin Tanislav +Date: Thu, 28 Nov 2024 15:16:23 +0200 +Subject: regmap: detach regmap from dev on regmap_exit + +From: Cosmin Tanislav + +commit 3061e170381af96d1e66799d34264e6414d428a7 upstream. + +At the end of __regmap_init(), if dev is not NULL, regmap_attach_dev() +is called, which adds a devres reference to the regmap, to be able to +retrieve a dev's regmap by name using dev_get_regmap(). + +When calling regmap_exit, the opposite does not happen, and the +reference is kept until the dev is detached. + +Add a regmap_detach_dev() function and call it in regmap_exit() to make +sure that the devres reference is not kept. + +Cc: stable@vger.kernel.org +Fixes: 72b39f6f2b5a ("regmap: Implement dev_get_regmap()") +Signed-off-by: Cosmin Tanislav +Rule: add +Link: https://lore.kernel.org/stable/20241128130554.362486-1-demonsingur%40gmail.com +Link: https://patch.msgid.link/20241128131625.363835-1-demonsingur@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + drivers/base/regmap/regmap.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/drivers/base/regmap/regmap.c ++++ b/drivers/base/regmap/regmap.c +@@ -636,6 +636,17 @@ int regmap_attach_dev(struct device *dev + } + EXPORT_SYMBOL_GPL(regmap_attach_dev); + ++static int dev_get_regmap_match(struct device *dev, void *res, void *data); ++ ++static int regmap_detach_dev(struct device *dev, struct regmap *map) ++{ ++ if (!dev) ++ return 0; ++ ++ return devres_release(dev, dev_get_regmap_release, ++ dev_get_regmap_match, (void *)map->name); ++} ++ + static enum regmap_endian regmap_get_reg_endian(const struct regmap_bus *bus, + const struct regmap_config *config) + { +@@ -1493,6 +1504,7 @@ void regmap_exit(struct regmap *map) + { + struct regmap_async *async; + ++ regmap_detach_dev(map->dev, map); + regcache_exit(map); + regmap_debugfs_exit(map); + regmap_range_exit(map); diff --git a/queue-5.10/series b/queue-5.10/series index 613e7951608..56a6656346f 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -371,3 +371,9 @@ scsi-qla2xxx-fix-use-after-free-on-unload.patch scsi-qla2xxx-remove-check-req_sg_cnt-should-be-equal-to-rsp_sg_cnt.patch nilfs2-fix-potential-out-of-bounds-memory-access-in-nilfs_find_entry.patch bcache-revert-replacing-is_err_or_null-with-is_err-again.patch +x86-kexec-restore-gdt-on-return-from-preserve_context-kexec.patch +bpf-fix-oob-devmap-writes-when-deleting-elements.patch +dma-buf-fix-dma_fence_array_signaled-v4.patch +regmap-detach-regmap-from-dev-on-regmap_exit.patch +mmc-sdhci-pci-add-dmi-quirk-for-missing-cd-gpio-on-vexia-edu-atla-10-tablet.patch +mmc-core-further-prevent-card-detect-during-shutdown.patch diff --git a/queue-5.10/x86-kexec-restore-gdt-on-return-from-preserve_context-kexec.patch b/queue-5.10/x86-kexec-restore-gdt-on-return-from-preserve_context-kexec.patch new file mode 100644 index 00000000000..34f1e5ef08e --- /dev/null +++ b/queue-5.10/x86-kexec-restore-gdt-on-return-from-preserve_context-kexec.patch @@ -0,0 +1,82 @@ +From 07fa619f2a40c221ea27747a3323cabc59ab25eb Mon Sep 17 00:00:00 2001 +From: David Woodhouse +Date: Thu, 5 Dec 2024 15:05:07 +0000 +Subject: x86/kexec: Restore GDT on return from ::preserve_context kexec + +From: David Woodhouse + +commit 07fa619f2a40c221ea27747a3323cabc59ab25eb upstream. + +The restore_processor_state() function explicitly states that "the asm code +that gets us here will have restored a usable GDT". That wasn't true in the +case of returning from a ::preserve_context kexec. Make it so. + +Without this, the kernel was depending on the called function to reload a +GDT which is appropriate for the kernel before returning. + +Test program: + + #include + #include + #include + #include + #include + #include + #include + #include + + int main (void) + { + struct kexec_segment segment = {}; + unsigned char purgatory[] = { + 0x66, 0xba, 0xf8, 0x03, // mov $0x3f8, %dx + 0xb0, 0x42, // mov $0x42, %al + 0xee, // outb %al, (%dx) + 0xc3, // ret + }; + int ret; + + segment.buf = &purgatory; + segment.bufsz = sizeof(purgatory); + segment.mem = (void *)0x400000; + segment.memsz = 0x1000; + ret = syscall(__NR_kexec_load, 0x400000, 1, &segment, KEXEC_PRESERVE_CONTEXT); + if (ret) { + perror("kexec_load"); + exit(1); + } + + ret = syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_KEXEC); + if (ret) { + perror("kexec reboot"); + exit(1); + } + printf("Success\n"); + return 0; + } + +Signed-off-by: David Woodhouse +Signed-off-by: Ingo Molnar +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20241205153343.3275139-2-dwmw2@infradead.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kernel/relocate_kernel_64.S | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/arch/x86/kernel/relocate_kernel_64.S ++++ b/arch/x86/kernel/relocate_kernel_64.S +@@ -229,6 +229,13 @@ SYM_CODE_START_LOCAL_NOALIGN(virtual_map + movq CR0(%r8), %r8 + movq %rax, %cr3 + movq %r8, %cr0 ++ ++#ifdef CONFIG_KEXEC_JUMP ++ /* Saved in save_processor_state. */ ++ movq $saved_context, %rax ++ lgdt saved_context_gdt_desc(%rax) ++#endif ++ + movq %rbp, %rax + + popf