]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.15-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 14 Oct 2024 08:50:34 +0000 (10:50 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 14 Oct 2024 08:50:34 +0000 (10:50 +0200)
added patches:
resource-fix-region_intersects-vs-add_memory_driver_managed.patch

queue-5.15/resource-fix-region_intersects-vs-add_memory_driver_managed.patch [new file with mode: 0644]
queue-5.15/series

diff --git a/queue-5.15/resource-fix-region_intersects-vs-add_memory_driver_managed.patch b/queue-5.15/resource-fix-region_intersects-vs-add_memory_driver_managed.patch
new file mode 100644 (file)
index 0000000..02f0061
--- /dev/null
@@ -0,0 +1,174 @@
+From b4afe4183ec77f230851ea139d91e5cf2644c68b Mon Sep 17 00:00:00 2001
+From: Huang Ying <ying.huang@intel.com>
+Date: Fri, 6 Sep 2024 11:07:11 +0800
+Subject: resource: fix region_intersects() vs add_memory_driver_managed()
+
+From: Huang Ying <ying.huang@intel.com>
+
+commit b4afe4183ec77f230851ea139d91e5cf2644c68b upstream.
+
+On a system with CXL memory, the resource tree (/proc/iomem) related to
+CXL memory may look like something as follows.
+
+490000000-50fffffff : CXL Window 0
+  490000000-50fffffff : region0
+    490000000-50fffffff : dax0.0
+      490000000-50fffffff : System RAM (kmem)
+
+Because drivers/dax/kmem.c calls add_memory_driver_managed() during
+onlining CXL memory, which makes "System RAM (kmem)" a descendant of "CXL
+Window X".  This confuses region_intersects(), which expects all "System
+RAM" resources to be at the top level of iomem_resource.  This can lead to
+bugs.
+
+For example, when the following command line is executed to write some
+memory in CXL memory range via /dev/mem,
+
+ $ dd if=data of=/dev/mem bs=$((1 << 10)) seek=$((0x490000000 >> 10)) count=1
+ dd: error writing '/dev/mem': Bad address
+ 1+0 records in
+ 0+0 records out
+ 0 bytes copied, 0.0283507 s, 0.0 kB/s
+
+the command fails as expected.  However, the error code is wrong.  It
+should be "Operation not permitted" instead of "Bad address".  More
+seriously, the /dev/mem permission checking in devmem_is_allowed() passes
+incorrectly.  Although the accessing is prevented later because ioremap()
+isn't allowed to map system RAM, it is a potential security issue.  During
+command executing, the following warning is reported in the kernel log for
+calling ioremap() on system RAM.
+
+ ioremap on RAM at 0x0000000490000000 - 0x0000000490000fff
+ WARNING: CPU: 2 PID: 416 at arch/x86/mm/ioremap.c:216 __ioremap_caller.constprop.0+0x131/0x35d
+ Call Trace:
+  memremap+0xcb/0x184
+  xlate_dev_mem_ptr+0x25/0x2f
+  write_mem+0x94/0xfb
+  vfs_write+0x128/0x26d
+  ksys_write+0xac/0xfe
+  do_syscall_64+0x9a/0xfd
+  entry_SYSCALL_64_after_hwframe+0x4b/0x53
+
+The details of command execution process are as follows.  In the above
+resource tree, "System RAM" is a descendant of "CXL Window 0" instead of a
+top level resource.  So, region_intersects() will report no System RAM
+resources in the CXL memory region incorrectly, because it only checks the
+top level resources.  Consequently, devmem_is_allowed() will return 1
+(allow access via /dev/mem) for CXL memory region incorrectly.
+Fortunately, ioremap() doesn't allow to map System RAM and reject the
+access.
+
+So, region_intersects() needs to be fixed to work correctly with the
+resource tree with "System RAM" not at top level as above.  To fix it, if
+we found a unmatched resource in the top level, we will continue to search
+matched resources in its descendant resources.  So, we will not miss any
+matched resources in resource tree anymore.
+
+In the new implementation, an example resource tree
+
+|------------- "CXL Window 0" ------------|
+|-- "System RAM" --|
+
+will behave similar as the following fake resource tree for
+region_intersects(, IORESOURCE_SYSTEM_RAM, ),
+
+|-- "System RAM" --||-- "CXL Window 0a" --|
+
+Where "CXL Window 0a" is part of the original "CXL Window 0" that
+isn't covered by "System RAM".
+
+Link: https://lkml.kernel.org/r/20240906030713.204292-2-ying.huang@intel.com
+Fixes: c221c0b0308f ("device-dax: "Hotplug" persistent memory for use like normal RAM")
+Signed-off-by: "Huang, Ying" <ying.huang@intel.com>
+Cc: Dan Williams <dan.j.williams@intel.com>
+Cc: David Hildenbrand <david@redhat.com>
+Cc: Davidlohr Bueso <dave@stgolabs.net>
+Cc: Jonathan Cameron <jonathan.cameron@huawei.com>
+Cc: Dave Jiang <dave.jiang@intel.com>
+Cc: Alison Schofield <alison.schofield@intel.com>
+Cc: Vishal Verma <vishal.l.verma@intel.com>
+Cc: Ira Weiny <ira.weiny@intel.com>
+Cc: Alistair Popple <apopple@nvidia.com>
+Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+Cc: Baoquan He <bhe@redhat.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/resource.c |   58 ++++++++++++++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 50 insertions(+), 8 deletions(-)
+
+--- a/kernel/resource.c
++++ b/kernel/resource.c
+@@ -480,20 +480,62 @@ EXPORT_SYMBOL_GPL(page_is_ram);
+ static int __region_intersects(resource_size_t start, size_t size,
+                       unsigned long flags, unsigned long desc)
+ {
+-      struct resource res;
++      resource_size_t ostart, oend;
+       int type = 0; int other = 0;
+-      struct resource *p;
++      struct resource *p, *dp;
++      bool is_type, covered;
++      struct resource res;
+       res.start = start;
+       res.end = start + size - 1;
+       for (p = iomem_resource.child; p ; p = p->sibling) {
+-              bool is_type = (((p->flags & flags) == flags) &&
+-                              ((desc == IORES_DESC_NONE) ||
+-                               (desc == p->desc)));
+-
+-              if (resource_overlaps(p, &res))
+-                      is_type ? type++ : other++;
++              if (!resource_overlaps(p, &res))
++                      continue;
++              is_type = (p->flags & flags) == flags &&
++                      (desc == IORES_DESC_NONE || desc == p->desc);
++              if (is_type) {
++                      type++;
++                      continue;
++              }
++              /*
++               * Continue to search in descendant resources as if the
++               * matched descendant resources cover some ranges of 'p'.
++               *
++               * |------------- "CXL Window 0" ------------|
++               * |-- "System RAM" --|
++               *
++               * will behave similar as the following fake resource
++               * tree when searching "System RAM".
++               *
++               * |-- "System RAM" --||-- "CXL Window 0a" --|
++               */
++              covered = false;
++              ostart = max(res.start, p->start);
++              oend = min(res.end, p->end);
++              for (dp = p->child; dp; dp = next_resource(dp)) {
++                      if (!resource_overlaps(dp, &res))
++                              continue;
++                      is_type = (dp->flags & flags) == flags &&
++                              (desc == IORES_DESC_NONE || desc == dp->desc);
++                      if (is_type) {
++                              type++;
++                              /*
++                               * Range from 'ostart' to 'dp->start'
++                               * isn't covered by matched resource.
++                               */
++                              if (dp->start > ostart)
++                                      break;
++                              if (dp->end >= oend) {
++                                      covered = true;
++                                      break;
++                              }
++                              /* Remove covered range */
++                              ostart = max(ostart, dp->end + 1);
++                      }
++              }
++              if (!covered)
++                      other++;
+       }
+       if (type == 0)
index 605520337685e5e420bede064dcdf6783939a9b2..bda348316199a707aab8b805be6e3c5940eaa8f1 100644 (file)
@@ -669,3 +669,4 @@ hwmon-tmp513-add-missing-dependency-on-regmap_i2c.patch
 hwmon-adm9240-add-missing-dependency-on-regmap_i2c.patch
 hwmon-adt7470-add-missing-dependency-on-regmap_i2c.patch
 hid-amd_sfh-switch-to-device-managed-dmam_alloc_coherent.patch
+resource-fix-region_intersects-vs-add_memory_driver_managed.patch