From: Greg Kroah-Hartman Date: Mon, 14 Mar 2022 08:09:57 +0000 (+0100) Subject: 5.10-stable patches X-Git-Tag: v4.9.307~18 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f8caed9d1f19269676d9e553fe52ba838462be77;p=thirdparty%2Fkernel%2Fstable-queue.git 5.10-stable patches added patches: x86-boot-add-setup_indirect-support-in-early_memremap_is_setup_data.patch x86-boot-fix-memremap-of-setup_indirect-structures.patch x86-traps-mark-do_int3-nokprobe_symbol.patch --- diff --git a/queue-5.10/series b/queue-5.10/series index d5fe18e7804..27478a32f20 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -63,5 +63,8 @@ watch_queue-fix-the-alloc-bitmap-size-to-reflect-notes-allocated.patch watch_queue-free-the-alloc-bitmap-when-the-watch_queue-is-torn-down.patch watch_queue-fix-lack-of-barrier-sync-lock-between-post-and-read.patch watch_queue-make-comment-about-setting-defunct-more-accurate.patch +x86-boot-fix-memremap-of-setup_indirect-structures.patch +x86-boot-add-setup_indirect-support-in-early_memremap_is_setup_data.patch +x86-traps-mark-do_int3-nokprobe_symbol.patch arm-fix-thumb2-regression-with-spectre-bhb.patch watch_queue-fix-filter-limit-check.patch diff --git a/queue-5.10/x86-boot-add-setup_indirect-support-in-early_memremap_is_setup_data.patch b/queue-5.10/x86-boot-add-setup_indirect-support-in-early_memremap_is_setup_data.patch new file mode 100644 index 00000000000..91d8fc52e07 --- /dev/null +++ b/queue-5.10/x86-boot-add-setup_indirect-support-in-early_memremap_is_setup_data.patch @@ -0,0 +1,82 @@ +From 445c1470b6ef96440e7cfc42dfc160f5004fd149 Mon Sep 17 00:00:00 2001 +From: Ross Philipson +Date: Wed, 23 Feb 2022 21:07:36 -0500 +Subject: x86/boot: Add setup_indirect support in early_memremap_is_setup_data() + +From: Ross Philipson + +commit 445c1470b6ef96440e7cfc42dfc160f5004fd149 upstream. + +The x86 boot documentation describes the setup_indirect structures and +how they are used. Only one of the two functions in ioremap.c that needed +to be modified to be aware of the introduction of setup_indirect +functionality was updated. Adds comparable support to the other function +where it was missing. + +Fixes: b3c72fc9a78e ("x86/boot: Introduce setup_indirect") +Signed-off-by: Ross Philipson +Signed-off-by: Borislav Petkov +Reviewed-by: Daniel Kiper +Cc: +Link: https://lore.kernel.org/r/1645668456-22036-3-git-send-email-ross.philipson@oracle.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/mm/ioremap.c | 33 +++++++++++++++++++++++++++++++-- + 1 file changed, 31 insertions(+), 2 deletions(-) + +--- a/arch/x86/mm/ioremap.c ++++ b/arch/x86/mm/ioremap.c +@@ -694,22 +694,51 @@ static bool memremap_is_setup_data(resou + static bool __init early_memremap_is_setup_data(resource_size_t phys_addr, + unsigned long size) + { ++ struct setup_indirect *indirect; + struct setup_data *data; + u64 paddr, paddr_next; + + paddr = boot_params.hdr.setup_data; + while (paddr) { +- unsigned int len; ++ unsigned int len, size; + + if (phys_addr == paddr) + return true; + + data = early_memremap_decrypted(paddr, sizeof(*data)); ++ if (!data) { ++ pr_warn("failed to early memremap setup_data entry\n"); ++ return false; ++ } ++ ++ size = sizeof(*data); + + paddr_next = data->next; + len = data->len; + +- early_memunmap(data, sizeof(*data)); ++ if ((phys_addr > paddr) && (phys_addr < (paddr + len))) { ++ early_memunmap(data, sizeof(*data)); ++ return true; ++ } ++ ++ if (data->type == SETUP_INDIRECT) { ++ size += len; ++ early_memunmap(data, sizeof(*data)); ++ data = early_memremap_decrypted(paddr, size); ++ if (!data) { ++ pr_warn("failed to early memremap indirect setup_data\n"); ++ return false; ++ } ++ ++ indirect = (struct setup_indirect *)data->data; ++ ++ if (indirect->type != SETUP_INDIRECT) { ++ paddr = indirect->addr; ++ len = indirect->len; ++ } ++ } ++ ++ early_memunmap(data, size); + + if ((phys_addr > paddr) && (phys_addr < (paddr + len))) + return true; diff --git a/queue-5.10/x86-boot-fix-memremap-of-setup_indirect-structures.patch b/queue-5.10/x86-boot-fix-memremap-of-setup_indirect-structures.patch new file mode 100644 index 00000000000..bbbb4460ea6 --- /dev/null +++ b/queue-5.10/x86-boot-fix-memremap-of-setup_indirect-structures.patch @@ -0,0 +1,393 @@ +From 7228918b34615ef6317edcd9a058a057bc54aa32 Mon Sep 17 00:00:00 2001 +From: Ross Philipson +Date: Wed, 23 Feb 2022 21:07:35 -0500 +Subject: x86/boot: Fix memremap of setup_indirect structures + +From: Ross Philipson + +commit 7228918b34615ef6317edcd9a058a057bc54aa32 upstream. + +As documented, the setup_indirect structure is nested inside +the setup_data structures in the setup_data list. The code currently +accesses the fields inside the setup_indirect structure but only +the sizeof(struct setup_data) is being memremapped. No crash +occurred but this is just due to how the area is remapped under the +covers. + +Properly memremap both the setup_data and setup_indirect structures +in these cases before accessing them. + +Fixes: b3c72fc9a78e ("x86/boot: Introduce setup_indirect") +Signed-off-by: Ross Philipson +Signed-off-by: Borislav Petkov +Reviewed-by: Daniel Kiper +Cc: +Link: https://lore.kernel.org/r/1645668456-22036-2-git-send-email-ross.philipson@oracle.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kernel/e820.c | 41 +++++++++++++++++------ + arch/x86/kernel/kdebugfs.c | 35 +++++++++++++++----- + arch/x86/kernel/ksysfs.c | 77 +++++++++++++++++++++++++++++++++++---------- + arch/x86/kernel/setup.c | 34 +++++++++++++++---- + arch/x86/mm/ioremap.c | 24 +++++++++++--- + 5 files changed, 165 insertions(+), 46 deletions(-) + +--- a/arch/x86/kernel/e820.c ++++ b/arch/x86/kernel/e820.c +@@ -995,8 +995,10 @@ early_param("memmap", parse_memmap_opt); + */ + void __init e820__reserve_setup_data(void) + { ++ struct setup_indirect *indirect; + struct setup_data *data; +- u64 pa_data; ++ u64 pa_data, pa_next; ++ u32 len; + + pa_data = boot_params.hdr.setup_data; + if (!pa_data) +@@ -1004,6 +1006,14 @@ void __init e820__reserve_setup_data(voi + + while (pa_data) { + data = early_memremap(pa_data, sizeof(*data)); ++ if (!data) { ++ pr_warn("e820: failed to memremap setup_data entry\n"); ++ return; ++ } ++ ++ len = sizeof(*data); ++ pa_next = data->next; ++ + e820__range_update(pa_data, sizeof(*data)+data->len, E820_TYPE_RAM, E820_TYPE_RESERVED_KERN); + + /* +@@ -1015,18 +1025,27 @@ void __init e820__reserve_setup_data(voi + sizeof(*data) + data->len, + E820_TYPE_RAM, E820_TYPE_RESERVED_KERN); + +- if (data->type == SETUP_INDIRECT && +- ((struct setup_indirect *)data->data)->type != SETUP_INDIRECT) { +- e820__range_update(((struct setup_indirect *)data->data)->addr, +- ((struct setup_indirect *)data->data)->len, +- E820_TYPE_RAM, E820_TYPE_RESERVED_KERN); +- e820__range_update_kexec(((struct setup_indirect *)data->data)->addr, +- ((struct setup_indirect *)data->data)->len, +- E820_TYPE_RAM, E820_TYPE_RESERVED_KERN); ++ if (data->type == SETUP_INDIRECT) { ++ len += data->len; ++ early_memunmap(data, sizeof(*data)); ++ data = early_memremap(pa_data, len); ++ if (!data) { ++ pr_warn("e820: failed to memremap indirect setup_data\n"); ++ return; ++ } ++ ++ indirect = (struct setup_indirect *)data->data; ++ ++ if (indirect->type != SETUP_INDIRECT) { ++ e820__range_update(indirect->addr, indirect->len, ++ E820_TYPE_RAM, E820_TYPE_RESERVED_KERN); ++ e820__range_update_kexec(indirect->addr, indirect->len, ++ E820_TYPE_RAM, E820_TYPE_RESERVED_KERN); ++ } + } + +- pa_data = data->next; +- early_memunmap(data, sizeof(*data)); ++ pa_data = pa_next; ++ early_memunmap(data, len); + } + + e820__update_table(e820_table); +--- a/arch/x86/kernel/kdebugfs.c ++++ b/arch/x86/kernel/kdebugfs.c +@@ -88,11 +88,13 @@ create_setup_data_node(struct dentry *pa + + static int __init create_setup_data_nodes(struct dentry *parent) + { ++ struct setup_indirect *indirect; + struct setup_data_node *node; + struct setup_data *data; +- int error; ++ u64 pa_data, pa_next; + struct dentry *d; +- u64 pa_data; ++ int error; ++ u32 len; + int no = 0; + + d = debugfs_create_dir("setup_data", parent); +@@ -112,12 +114,29 @@ static int __init create_setup_data_node + error = -ENOMEM; + goto err_dir; + } ++ pa_next = data->next; + +- if (data->type == SETUP_INDIRECT && +- ((struct setup_indirect *)data->data)->type != SETUP_INDIRECT) { +- node->paddr = ((struct setup_indirect *)data->data)->addr; +- node->type = ((struct setup_indirect *)data->data)->type; +- node->len = ((struct setup_indirect *)data->data)->len; ++ if (data->type == SETUP_INDIRECT) { ++ len = sizeof(*data) + data->len; ++ memunmap(data); ++ data = memremap(pa_data, len, MEMREMAP_WB); ++ if (!data) { ++ kfree(node); ++ error = -ENOMEM; ++ goto err_dir; ++ } ++ ++ indirect = (struct setup_indirect *)data->data; ++ ++ if (indirect->type != SETUP_INDIRECT) { ++ node->paddr = indirect->addr; ++ node->type = indirect->type; ++ node->len = indirect->len; ++ } else { ++ node->paddr = pa_data; ++ node->type = data->type; ++ node->len = data->len; ++ } + } else { + node->paddr = pa_data; + node->type = data->type; +@@ -125,7 +144,7 @@ static int __init create_setup_data_node + } + + create_setup_data_node(d, no, node); +- pa_data = data->next; ++ pa_data = pa_next; + + memunmap(data); + no++; +--- a/arch/x86/kernel/ksysfs.c ++++ b/arch/x86/kernel/ksysfs.c +@@ -91,26 +91,41 @@ static int get_setup_data_paddr(int nr, + + static int __init get_setup_data_size(int nr, size_t *size) + { +- int i = 0; ++ u64 pa_data = boot_params.hdr.setup_data, pa_next; ++ struct setup_indirect *indirect; + struct setup_data *data; +- u64 pa_data = boot_params.hdr.setup_data; ++ int i = 0; ++ u32 len; + + while (pa_data) { + data = memremap(pa_data, sizeof(*data), MEMREMAP_WB); + if (!data) + return -ENOMEM; ++ pa_next = data->next; ++ + if (nr == i) { +- if (data->type == SETUP_INDIRECT && +- ((struct setup_indirect *)data->data)->type != SETUP_INDIRECT) +- *size = ((struct setup_indirect *)data->data)->len; +- else ++ if (data->type == SETUP_INDIRECT) { ++ len = sizeof(*data) + data->len; ++ memunmap(data); ++ data = memremap(pa_data, len, MEMREMAP_WB); ++ if (!data) ++ return -ENOMEM; ++ ++ indirect = (struct setup_indirect *)data->data; ++ ++ if (indirect->type != SETUP_INDIRECT) ++ *size = indirect->len; ++ else ++ *size = data->len; ++ } else { + *size = data->len; ++ } + + memunmap(data); + return 0; + } + +- pa_data = data->next; ++ pa_data = pa_next; + memunmap(data); + i++; + } +@@ -120,9 +135,11 @@ static int __init get_setup_data_size(in + static ssize_t type_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) + { ++ struct setup_indirect *indirect; ++ struct setup_data *data; + int nr, ret; + u64 paddr; +- struct setup_data *data; ++ u32 len; + + ret = kobj_to_setup_data_nr(kobj, &nr); + if (ret) +@@ -135,10 +152,20 @@ static ssize_t type_show(struct kobject + if (!data) + return -ENOMEM; + +- if (data->type == SETUP_INDIRECT) +- ret = sprintf(buf, "0x%x\n", ((struct setup_indirect *)data->data)->type); +- else ++ if (data->type == SETUP_INDIRECT) { ++ len = sizeof(*data) + data->len; ++ memunmap(data); ++ data = memremap(paddr, len, MEMREMAP_WB); ++ if (!data) ++ return -ENOMEM; ++ ++ indirect = (struct setup_indirect *)data->data; ++ ++ ret = sprintf(buf, "0x%x\n", indirect->type); ++ } else { + ret = sprintf(buf, "0x%x\n", data->type); ++ } ++ + memunmap(data); + return ret; + } +@@ -149,9 +176,10 @@ static ssize_t setup_data_data_read(stru + char *buf, + loff_t off, size_t count) + { ++ struct setup_indirect *indirect; ++ struct setup_data *data; + int nr, ret = 0; + u64 paddr, len; +- struct setup_data *data; + void *p; + + ret = kobj_to_setup_data_nr(kobj, &nr); +@@ -165,10 +193,27 @@ static ssize_t setup_data_data_read(stru + if (!data) + return -ENOMEM; + +- if (data->type == SETUP_INDIRECT && +- ((struct setup_indirect *)data->data)->type != SETUP_INDIRECT) { +- paddr = ((struct setup_indirect *)data->data)->addr; +- len = ((struct setup_indirect *)data->data)->len; ++ if (data->type == SETUP_INDIRECT) { ++ len = sizeof(*data) + data->len; ++ memunmap(data); ++ data = memremap(paddr, len, MEMREMAP_WB); ++ if (!data) ++ return -ENOMEM; ++ ++ indirect = (struct setup_indirect *)data->data; ++ ++ if (indirect->type != SETUP_INDIRECT) { ++ paddr = indirect->addr; ++ len = indirect->len; ++ } else { ++ /* ++ * Even though this is technically undefined, return ++ * the data as though it is a normal setup_data struct. ++ * This will at least allow it to be inspected. ++ */ ++ paddr += sizeof(*data); ++ len = data->len; ++ } + } else { + paddr += sizeof(*data); + len = data->len; +--- a/arch/x86/kernel/setup.c ++++ b/arch/x86/kernel/setup.c +@@ -371,21 +371,41 @@ static void __init parse_setup_data(void + + static void __init memblock_x86_reserve_range_setup_data(void) + { ++ struct setup_indirect *indirect; + struct setup_data *data; +- u64 pa_data; ++ u64 pa_data, pa_next; ++ u32 len; + + pa_data = boot_params.hdr.setup_data; + while (pa_data) { + data = early_memremap(pa_data, sizeof(*data)); ++ if (!data) { ++ pr_warn("setup: failed to memremap setup_data entry\n"); ++ return; ++ } ++ ++ len = sizeof(*data); ++ pa_next = data->next; ++ + memblock_reserve(pa_data, sizeof(*data) + data->len); + +- if (data->type == SETUP_INDIRECT && +- ((struct setup_indirect *)data->data)->type != SETUP_INDIRECT) +- memblock_reserve(((struct setup_indirect *)data->data)->addr, +- ((struct setup_indirect *)data->data)->len); ++ if (data->type == SETUP_INDIRECT) { ++ len += data->len; ++ early_memunmap(data, sizeof(*data)); ++ data = early_memremap(pa_data, len); ++ if (!data) { ++ pr_warn("setup: failed to memremap indirect setup_data\n"); ++ return; ++ } ++ ++ indirect = (struct setup_indirect *)data->data; ++ ++ if (indirect->type != SETUP_INDIRECT) ++ memblock_reserve(indirect->addr, indirect->len); ++ } + +- pa_data = data->next; +- early_memunmap(data, sizeof(*data)); ++ pa_data = pa_next; ++ early_memunmap(data, len); + } + } + +--- a/arch/x86/mm/ioremap.c ++++ b/arch/x86/mm/ioremap.c +@@ -633,6 +633,7 @@ static bool memremap_is_efi_data(resourc + static bool memremap_is_setup_data(resource_size_t phys_addr, + unsigned long size) + { ++ struct setup_indirect *indirect; + struct setup_data *data; + u64 paddr, paddr_next; + +@@ -645,6 +646,10 @@ static bool memremap_is_setup_data(resou + + data = memremap(paddr, sizeof(*data), + MEMREMAP_WB | MEMREMAP_DEC); ++ if (!data) { ++ pr_warn("failed to memremap setup_data entry\n"); ++ return false; ++ } + + paddr_next = data->next; + len = data->len; +@@ -654,10 +659,21 @@ static bool memremap_is_setup_data(resou + return true; + } + +- if (data->type == SETUP_INDIRECT && +- ((struct setup_indirect *)data->data)->type != SETUP_INDIRECT) { +- paddr = ((struct setup_indirect *)data->data)->addr; +- len = ((struct setup_indirect *)data->data)->len; ++ if (data->type == SETUP_INDIRECT) { ++ memunmap(data); ++ data = memremap(paddr, sizeof(*data) + len, ++ MEMREMAP_WB | MEMREMAP_DEC); ++ if (!data) { ++ pr_warn("failed to memremap indirect setup_data\n"); ++ return false; ++ } ++ ++ indirect = (struct setup_indirect *)data->data; ++ ++ if (indirect->type != SETUP_INDIRECT) { ++ paddr = indirect->addr; ++ len = indirect->len; ++ } + } + + memunmap(data); diff --git a/queue-5.10/x86-traps-mark-do_int3-nokprobe_symbol.patch b/queue-5.10/x86-traps-mark-do_int3-nokprobe_symbol.patch new file mode 100644 index 00000000000..b951c26d7e4 --- /dev/null +++ b/queue-5.10/x86-traps-mark-do_int3-nokprobe_symbol.patch @@ -0,0 +1,34 @@ +From a365a65f9ca1ceb9cf1ac29db4a4f51df7c507ad Mon Sep 17 00:00:00 2001 +From: Li Huafei +Date: Thu, 10 Mar 2022 20:09:15 +0800 +Subject: x86/traps: Mark do_int3() NOKPROBE_SYMBOL + +From: Li Huafei + +commit a365a65f9ca1ceb9cf1ac29db4a4f51df7c507ad upstream. + +Since kprobe_int3_handler() is called in do_int3(), probing do_int3() +can cause a breakpoint recursion and crash the kernel. Therefore, +do_int3() should be marked as NOKPROBE_SYMBOL. + +Fixes: 21e28290b317 ("x86/traps: Split int3 handler up") +Signed-off-by: Li Huafei +Signed-off-by: Borislav Petkov +Acked-by: Masami Hiramatsu +Cc: +Link: https://lore.kernel.org/r/20220310120915.63349-1-lihuafei1@huawei.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kernel/traps.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/x86/kernel/traps.c ++++ b/arch/x86/kernel/traps.c +@@ -651,6 +651,7 @@ static bool do_int3(struct pt_regs *regs + + return res == NOTIFY_STOP; + } ++NOKPROBE_SYMBOL(do_int3); + + static void do_int3_user(struct pt_regs *regs) + {