]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 14 Mar 2022 08:09:57 +0000 (09:09 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 14 Mar 2022 08:09:57 +0000 (09:09 +0100)
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

queue-5.10/series
queue-5.10/x86-boot-add-setup_indirect-support-in-early_memremap_is_setup_data.patch [new file with mode: 0644]
queue-5.10/x86-boot-fix-memremap-of-setup_indirect-structures.patch [new file with mode: 0644]
queue-5.10/x86-traps-mark-do_int3-nokprobe_symbol.patch [new file with mode: 0644]

index d5fe18e78049570932da70458318d113b68e73ec..27478a32f2070fc21c4014e6fb68c34acccc0199 100644 (file)
@@ -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 (file)
index 0000000..91d8fc5
--- /dev/null
@@ -0,0 +1,82 @@
+From 445c1470b6ef96440e7cfc42dfc160f5004fd149 Mon Sep 17 00:00:00 2001
+From: Ross Philipson <ross.philipson@oracle.com>
+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 <ross.philipson@oracle.com>
+
+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 <ross.philipson@oracle.com>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/1645668456-22036-3-git-send-email-ross.philipson@oracle.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..bbbb446
--- /dev/null
@@ -0,0 +1,393 @@
+From 7228918b34615ef6317edcd9a058a057bc54aa32 Mon Sep 17 00:00:00 2001
+From: Ross Philipson <ross.philipson@oracle.com>
+Date: Wed, 23 Feb 2022 21:07:35 -0500
+Subject: x86/boot: Fix memremap of setup_indirect structures
+
+From: Ross Philipson <ross.philipson@oracle.com>
+
+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 <ross.philipson@oracle.com>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/1645668456-22036-2-git-send-email-ross.philipson@oracle.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..b951c26
--- /dev/null
@@ -0,0 +1,34 @@
+From a365a65f9ca1ceb9cf1ac29db4a4f51df7c507ad Mon Sep 17 00:00:00 2001
+From: Li Huafei <lihuafei1@huawei.com>
+Date: Thu, 10 Mar 2022 20:09:15 +0800
+Subject: x86/traps: Mark do_int3() NOKPROBE_SYMBOL
+
+From: Li Huafei <lihuafei1@huawei.com>
+
+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 <lihuafei1@huawei.com>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20220310120915.63349-1-lihuafei1@huawei.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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)
+ {