From: David Hildenbrand <hidden> Date: 2021-09-02 16:25:57
I think this might be a good fit for the -mm tree, as the actual virtio-mem
changes are rather small.
--
Let's add the basic infrastructure to exclude some physical memory
regions marked as "IORESOURCE_SYSTEM_RAM" completely from /dev/mem access,
even though they are not marked IORESOURCE_BUSY and even though
"iomem=relaxed" is set. Resource IORESOURCE_EXCLUSIVE for that purpose
instead of adding new flags to express something similar to
"soft-busy" or "not busy yet, but already prepared by a driver and not
to be mapped by user space".
Use it for virtio-mem, to disallow mapping any virtio-mem memory via
/dev/mem to user space after the virtio-mem driver was loaded.
Details can be found in patch #2 and #3.
v3 -> v4:
- Added Dans RBs (thanks!)
- Actually send the patches to the CC list ...
v2 -> v3:
- "kernel/resource: clean up and optimize iomem_is_exclusive()"
-- Reshuffled and moved for_each_resource() etc. into this patch
- "kernel/resource: disallow access to exclusive system RAM regions"
-- Leave CONFIG_STRICT_DEVMEM=n alone. Hoog into iomem_is_exclusive()
instead.
-- Improve comments
- "virtio-mem: disallow mapping virtio-mem memory via /dev/mem"
-- Don't allow building virtio_mem without CONFIG_STRICT_DEVMEM when we
have CONFIG_DEVMEM, where we don't have any guarantees.
- Rework all patch descriptions
v1 -> v2:
- "/dev/mem: disallow access to explicitly excluded system RAM regions"
-- Introduce and use for_each_resource() and next_resource_skip_children()
-- s/iomem_range_contains_excluded/iomem_range_contains_excluded_devmem/
- "kernel/resource: cleanup and optimize iomem_is_exclusive()"
-- Use for_each_resource()
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Jason Wang <redacted>
Cc: "Rafael J. Wysocki" <redacted>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Dan Williams <redacted>
Cc: Hanjun Guo <guohanjun@huawei.com>
Cc: Andy Shevchenko <redacted>
Cc: virtualization@lists.linux-foundation.org
Cc: linux-mm@kvack.org
David Hildenbrand (3):
kernel/resource: clean up and optimize iomem_is_exclusive()
kernel/resource: disallow access to exclusive system RAM regions
virtio-mem: disallow mapping virtio-mem memory via /dev/mem
drivers/virtio/Kconfig | 1 +
drivers/virtio/virtio_mem.c | 4 ++-
kernel/resource.c | 54 ++++++++++++++++++++++++++-----------
3 files changed, 43 insertions(+), 16 deletions(-)
base-commit: 7d2a07b769330c34b4deabeed939325c77a7ec2f
--
2.31.1
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
From: David Hildenbrand <hidden> Date: 2021-09-02 16:25:57
virtio-mem dynamically exposes memory inside a device memory region as
system RAM to Linux, coordinating with the hypervisor which parts are
actually "plugged" and consequently usable/accessible. On the one hand, the
virtio-mem driver adds/removes whole memory blocks, creating/removing busy
IORESOURCE_SYSTEM_RAM resources, on the other hand, it logically (un)plugs
memory inside added memory blocks, dynamically either exposing them to
the buddy or hiding them from the buddy and marking them PG_offline.
In contrast to physical devices, like a DIMM, the virtio-mem driver
is required to actually make use of any of the device-provided memory,
because it performs the handshake with the hypervisor. virtio-mem memory
cannot simply be access via /dev/mem without a driver.
There is no safe way to:
a) Access plugged memory blocks via /dev/mem, as they might contain
unplugged holes or might get silently unplugged by the virtio-mem
driver and consequently turned inaccessible.
b) Access unplugged memory blocks via /dev/mem because the virtio-mem
driver is required to make them actually accessible first.
The virtio-spec states that unplugged memory blocks MUST NOT be
written, and only selected unplugged memory blocks MAY be read. We want
to make sure, this is the case in sane environments -- where the
virtio-mem driver was loaded.
We want to make sure that in a sane environment, nobody "accidentially"
accesses unplugged memory inside the device managed region. For example,
a user might spot a memory region in /proc/iomem and try accessing it via
/dev/mem via gdb or dumping it via something else. By the time the mmap()
happens, the memory might already have been removed by the virtio-mem
driver silently: the mmap() would succeeed and user space might
accidentially access unplugged memory.
So once the driver was loaded and detected the device along the
device-managed region, we just want to disallow any access via
/dev/mem to it.
In an ideal world, we would mark the whole region as busy ("owned by a
driver") and exclude it; however, that would be wrong, as we don't
really have actual system RAM at these ranges added to Linux ("busy system
RAM"). Instead, we want to mark such ranges as "not actual busy system RAM
but still soft-reserved and prepared by a driver for future use."
Let's teach iomem_is_exclusive() to reject access to any range
with "IORESOURCE_SYSTEM_RAM | IORESOURCE_EXCLUSIVE", even if not busy
and even if "iomem=relaxed" is set.
For now, there are no applicable ranges and we'll modify virtio-mem next to
properly set IORESOURCE_EXCLUSIVE on the parent resource container it
creates to contain all actual busy system RAM added via
add_memory_driver_managed().
Reviewed-by: Dan Williams <redacted>
Signed-off-by: David Hildenbrand <redacted>
---
kernel/resource.c | 29 +++++++++++++++++++----------
1 file changed, 19 insertions(+), 10 deletions(-)
From: David Hildenbrand <hidden> Date: 2021-09-02 16:25:57
We don't want user space to be able to map virtio-mem device memory
directly (e.g., via /dev/mem) in order to have guarantees that in a sane
setup we'll never accidentially access unplugged memory within the
device-managed region of a virtio-mem device, just as required by the
virtio-spec.
As soon as the virtio-mem driver is loaded, the device region is visible
in /proc/iomem via the parent device region. From that point on user space
is aware of the device region and we want to disallow mapping anything
inside that region (where we will dynamically (un)plug memory) until
the driver has been unloaded cleanly and e.g., another driver might take
over.
By creating our parent IORESOURCE_SYSTEM_RAM resource with
IORESOURCE_EXCLUSIVE, we will disallow any /dev/mem access to our
device region until the driver was unloaded cleanly and removed the
parent region. This will work even though only some memory blocks are
actually currently added to Linux and appear as busy in the resource tree.
So access to the region from user space is only possible
a) if we don't load the virtio-mem driver.
b) after unloading the virtio-mem driver cleanly.
Don't build virtio-mem if access to /dev/mem cannot be restricticted --
if we have CONFIG_DEVMEM=y but CONFIG_STRICT_DEVMEM is not set.
Reviewed-by: Dan Williams <redacted>
Signed-off-by: David Hildenbrand <redacted>
---
drivers/virtio/Kconfig | 1 +
drivers/virtio/virtio_mem.c | 4 +++-
2 files changed, 4 insertions(+), 1 deletion(-)
From: David Hildenbrand <hidden> Date: 2021-09-02 16:25:58
We end up traversing subtrees of ranges we are not interested in; let's
optimize this case, skipping such subtrees, cleaning up the function a bit.
Reviewed-by: Dan Williams <redacted>
Signed-off-by: David Hildenbrand <redacted>
---
kernel/resource.c | 25 ++++++++++++++++++++-----
1 file changed, 20 insertions(+), 5 deletions(-)
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2021-09-03 07:02:18
On Thu, Sep 02, 2021 at 06:09:19PM +0200, David Hildenbrand wrote:
We don't want user space to be able to map virtio-mem device memory
directly (e.g., via /dev/mem) in order to have guarantees that in a sane
setup we'll never accidentially access unplugged memory within the
device-managed region of a virtio-mem device, just as required by the
virtio-spec.
As soon as the virtio-mem driver is loaded, the device region is visible
in /proc/iomem via the parent device region. From that point on user space
is aware of the device region and we want to disallow mapping anything
inside that region (where we will dynamically (un)plug memory) until
the driver has been unloaded cleanly and e.g., another driver might take
over.
By creating our parent IORESOURCE_SYSTEM_RAM resource with
IORESOURCE_EXCLUSIVE, we will disallow any /dev/mem access to our
device region until the driver was unloaded cleanly and removed the
parent region. This will work even though only some memory blocks are
actually currently added to Linux and appear as busy in the resource tree.
So access to the region from user space is only possible
a) if we don't load the virtio-mem driver.
b) after unloading the virtio-mem driver cleanly.
Don't build virtio-mem if access to /dev/mem cannot be restricticted --
if we have CONFIG_DEVMEM=y but CONFIG_STRICT_DEVMEM is not set.
Reviewed-by: Dan Williams <redacted>
Signed-off-by: David Hildenbrand <redacted>
It would be nicer if there was a symbol in the MEMORY_ namespace
we can depend on exported by mm and depending on !DEVMEM ||
STRICT_DEVMEM.
E.g.
config MEMORY_EXCLUSIVE
def_bool y
depends on !DEVMEM || STRICT_DEVMEM
and then in virtio
depends on MEMORY_EXCLUSIVE
the virtio change itself is ok though:
Acked-by: Michael S. Tsirkin <mst@redhat.com>
for merging through -mm.
From: David Hildenbrand <hidden> Date: 2021-09-14 09:45:32
On 03.09.21 09:02, Michael S. Tsirkin wrote:
On Thu, Sep 02, 2021 at 06:09:19PM +0200, David Hildenbrand wrote:
quoted
We don't want user space to be able to map virtio-mem device memory
directly (e.g., via /dev/mem) in order to have guarantees that in a sane
setup we'll never accidentially access unplugged memory within the
device-managed region of a virtio-mem device, just as required by the
virtio-spec.
As soon as the virtio-mem driver is loaded, the device region is visible
in /proc/iomem via the parent device region. From that point on user space
is aware of the device region and we want to disallow mapping anything
inside that region (where we will dynamically (un)plug memory) until
the driver has been unloaded cleanly and e.g., another driver might take
over.
By creating our parent IORESOURCE_SYSTEM_RAM resource with
IORESOURCE_EXCLUSIVE, we will disallow any /dev/mem access to our
device region until the driver was unloaded cleanly and removed the
parent region. This will work even though only some memory blocks are
actually currently added to Linux and appear as busy in the resource tree.
So access to the region from user space is only possible
a) if we don't load the virtio-mem driver.
b) after unloading the virtio-mem driver cleanly.
Don't build virtio-mem if access to /dev/mem cannot be restricticted --
if we have CONFIG_DEVMEM=y but CONFIG_STRICT_DEVMEM is not set.
Reviewed-by: Dan Williams <redacted>
Signed-off-by: David Hildenbrand <redacted>
It would be nicer if there was a symbol in the MEMORY_ namespace
we can depend on exported by mm and depending on !DEVMEM ||
STRICT_DEVMEM.
E.g.
config MEMORY_EXCLUSIVE
def_bool y
depends on !DEVMEM || STRICT_DEVMEM
and then in virtio
depends on MEMORY_EXCLUSIVE
Yes, but I'm not able to come up with an expressive name.
MEMORY_EXCLUSIVE can be highly misleading ...
the virtio change itself is ok though:
Acked-by: Michael S. Tsirkin <mst@redhat.com>
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2021-09-14 11:52:25
On Tue, Sep 14, 2021 at 11:45:25AM +0200, David Hildenbrand wrote:
On 03.09.21 09:02, Michael S. Tsirkin wrote:
quoted
On Thu, Sep 02, 2021 at 06:09:19PM +0200, David Hildenbrand wrote:
quoted
We don't want user space to be able to map virtio-mem device memory
directly (e.g., via /dev/mem) in order to have guarantees that in a sane
setup we'll never accidentially access unplugged memory within the
device-managed region of a virtio-mem device, just as required by the
virtio-spec.
As soon as the virtio-mem driver is loaded, the device region is visible
in /proc/iomem via the parent device region. From that point on user space
is aware of the device region and we want to disallow mapping anything
inside that region (where we will dynamically (un)plug memory) until
the driver has been unloaded cleanly and e.g., another driver might take
over.
By creating our parent IORESOURCE_SYSTEM_RAM resource with
IORESOURCE_EXCLUSIVE, we will disallow any /dev/mem access to our
device region until the driver was unloaded cleanly and removed the
parent region. This will work even though only some memory blocks are
actually currently added to Linux and appear as busy in the resource tree.
So access to the region from user space is only possible
a) if we don't load the virtio-mem driver.
b) after unloading the virtio-mem driver cleanly.
Don't build virtio-mem if access to /dev/mem cannot be restricticted --
if we have CONFIG_DEVMEM=y but CONFIG_STRICT_DEVMEM is not set.
Reviewed-by: Dan Williams <redacted>
Signed-off-by: David Hildenbrand <redacted>
It would be nicer if there was a symbol in the MEMORY_ namespace
we can depend on exported by mm and depending on !DEVMEM ||
STRICT_DEVMEM.
E.g.
config MEMORY_EXCLUSIVE
def_bool y
depends on !DEVMEM || STRICT_DEVMEM
and then in virtio
depends on MEMORY_EXCLUSIVE
Yes, but I'm not able to come up with an expressive name. MEMORY_EXCLUSIVE
can be highly misleading ...
I mean ... it enables IORESOURCE_EXCLUSIVE ... but ok ...
MEMORY_EXCLUSIVE_KERNEL_MAP ?
quoted
the virtio change itself is ok though:
Acked-by: Michael S. Tsirkin <mst@redhat.com>
From: David Hildenbrand <hidden> Date: 2021-09-14 11:57:36
On 14.09.21 13:52, Michael S. Tsirkin wrote:
On Tue, Sep 14, 2021 at 11:45:25AM +0200, David Hildenbrand wrote:
quoted
On 03.09.21 09:02, Michael S. Tsirkin wrote:
quoted
On Thu, Sep 02, 2021 at 06:09:19PM +0200, David Hildenbrand wrote:
quoted
We don't want user space to be able to map virtio-mem device memory
directly (e.g., via /dev/mem) in order to have guarantees that in a sane
setup we'll never accidentially access unplugged memory within the
device-managed region of a virtio-mem device, just as required by the
virtio-spec.
As soon as the virtio-mem driver is loaded, the device region is visible
in /proc/iomem via the parent device region. From that point on user space
is aware of the device region and we want to disallow mapping anything
inside that region (where we will dynamically (un)plug memory) until
the driver has been unloaded cleanly and e.g., another driver might take
over.
By creating our parent IORESOURCE_SYSTEM_RAM resource with
IORESOURCE_EXCLUSIVE, we will disallow any /dev/mem access to our
device region until the driver was unloaded cleanly and removed the
parent region. This will work even though only some memory blocks are
actually currently added to Linux and appear as busy in the resource tree.
So access to the region from user space is only possible
a) if we don't load the virtio-mem driver.
b) after unloading the virtio-mem driver cleanly.
Don't build virtio-mem if access to /dev/mem cannot be restricticted --
if we have CONFIG_DEVMEM=y but CONFIG_STRICT_DEVMEM is not set.
Reviewed-by: Dan Williams <redacted>
Signed-off-by: David Hildenbrand <redacted>
It would be nicer if there was a symbol in the MEMORY_ namespace
we can depend on exported by mm and depending on !DEVMEM ||
STRICT_DEVMEM.
E.g.
config MEMORY_EXCLUSIVE
def_bool y
depends on !DEVMEM || STRICT_DEVMEM
and then in virtio
depends on MEMORY_EXCLUSIVE
Yes, but I'm not able to come up with an expressive name. MEMORY_EXCLUSIVE
can be highly misleading ...
I mean ... it enables IORESOURCE_EXCLUSIVE ... but ok ...
MEMORY_EXCLUSIVE_KERNEL_MAP ?
It enables IORESOURCE_EXCLUSIVE for IORESOURCE_SYSTEM_RAM ... and
notably not for IORESOURCE_MEM.
MEMORY_EXCLUSIVE_SYSTEM_RAM ?
quoted
quoted
the virtio change itself is ok though:
Acked-by: Michael S. Tsirkin <mst@redhat.com>
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2021-09-14 12:04:21
On Tue, Sep 14, 2021 at 01:57:25PM +0200, David Hildenbrand wrote:
On 14.09.21 13:52, Michael S. Tsirkin wrote:
quoted
On Tue, Sep 14, 2021 at 11:45:25AM +0200, David Hildenbrand wrote:
quoted
On 03.09.21 09:02, Michael S. Tsirkin wrote:
quoted
On Thu, Sep 02, 2021 at 06:09:19PM +0200, David Hildenbrand wrote:
quoted
We don't want user space to be able to map virtio-mem device memory
directly (e.g., via /dev/mem) in order to have guarantees that in a sane
setup we'll never accidentially access unplugged memory within the
device-managed region of a virtio-mem device, just as required by the
virtio-spec.
As soon as the virtio-mem driver is loaded, the device region is visible
in /proc/iomem via the parent device region. From that point on user space
is aware of the device region and we want to disallow mapping anything
inside that region (where we will dynamically (un)plug memory) until
the driver has been unloaded cleanly and e.g., another driver might take
over.
By creating our parent IORESOURCE_SYSTEM_RAM resource with
IORESOURCE_EXCLUSIVE, we will disallow any /dev/mem access to our
device region until the driver was unloaded cleanly and removed the
parent region. This will work even though only some memory blocks are
actually currently added to Linux and appear as busy in the resource tree.
So access to the region from user space is only possible
a) if we don't load the virtio-mem driver.
b) after unloading the virtio-mem driver cleanly.
Don't build virtio-mem if access to /dev/mem cannot be restricticted --
if we have CONFIG_DEVMEM=y but CONFIG_STRICT_DEVMEM is not set.
Reviewed-by: Dan Williams <redacted>
Signed-off-by: David Hildenbrand <redacted>
It would be nicer if there was a symbol in the MEMORY_ namespace
we can depend on exported by mm and depending on !DEVMEM ||
STRICT_DEVMEM.
E.g.
config MEMORY_EXCLUSIVE
def_bool y
depends on !DEVMEM || STRICT_DEVMEM
and then in virtio
depends on MEMORY_EXCLUSIVE
Yes, but I'm not able to come up with an expressive name. MEMORY_EXCLUSIVE
can be highly misleading ...
I mean ... it enables IORESOURCE_EXCLUSIVE ... but ok ...
MEMORY_EXCLUSIVE_KERNEL_MAP ?
It enables IORESOURCE_EXCLUSIVE for IORESOURCE_SYSTEM_RAM ... and notably
not for IORESOURCE_MEM.
MEMORY_EXCLUSIVE_SYSTEM_RAM ?
OK.
quoted
quoted
quoted
the virtio change itself is ok though:
Acked-by: Michael S. Tsirkin <mst@redhat.com>