Kernel: Return an error when unmap finds no intersecting region

We currently always crash if a user attempts to unmap a range that
does not intersect with an existing region, no matter the size. This
happens because we will never explicitly check to see if the search
for intersecting regions found anything, instead loop over the results,
which might be an empty vector. We then attempt to deallocate the
requested range from the `RangeAllocator` unconditionally, which will
be invalid if the specified range is not managed by the RangeAllocator.
We will assert validating m_total_range.contains(..) the range we are
requesting to deallocate.

This fix to this is straight forward, error out if we weren't able to
find any intersections.

You can get stress-ng to attempt this pattern with the following
arguments, which will attempt to unmap 0x0 through some large offset:

```
stress-ng --vm-segv 1
```

Fixes: #8483

Co-authored-by: Federico Guerinoni <guerinoni.federico@gmail.com>
This commit is contained in:
Brian Gianforcaro 2021-07-30 01:17:59 -07:00 committed by Andreas Kling
parent e7c5c3d507
commit 0fcb9efd86
Notes: sideshowbarker 2024-07-18 07:45:11 +09:00

View file

@ -45,7 +45,6 @@ KResult Space::unmap_mmap_range(VirtualAddress addr, size_t size)
auto range_or_error = Range::expand_to_page_boundaries(addr.get(), size);
if (range_or_error.is_error())
return range_or_error.error();
auto range_to_unmap = range_or_error.value();
if (!is_user_range(range_to_unmap))
@ -92,6 +91,8 @@ KResult Space::unmap_mmap_range(VirtualAddress addr, size_t size)
// Try again while checking multiple regions at a time.
auto const& regions = find_regions_intersecting(range_to_unmap);
if (regions.is_empty())
return EINVAL;
// Check if any of the regions is not mmap'ed, to not accidentally
// error out with just half a region map left.