kernel/vm: unlock cache before unmapping addresses
Unlock the current cache in `map_backing_store` before `unmap_address_range` is called, since `unmap_address_range` may call `delete_area` which would then also attempt to lock the same cache if that cache has already been mapped to an area in the conflicting address range. Fixes #18422. Change-Id: I6fc5301c43d11bb6df489a2e6d6bdcd6cd80d2b7 Reviewed-on: https://review.haiku-os.org/c/haiku/+/6392 Reviewed-by: Jérôme Duval <[email protected]>
This commit is contained in:
committed by
Jérôme Duval
parent
0450e7b802
commit
7be371792f
@@ -918,7 +918,7 @@ discard_address_range(VMAddressSpace* addressSpace, addr_t address, addr_t size,
|
|||||||
If \a addressSpec is \c B_EXACT_ADDRESS and the
|
If \a addressSpec is \c B_EXACT_ADDRESS and the
|
||||||
\c CREATE_AREA_UNMAP_ADDRESS_RANGE flag is specified, the caller must ensure
|
\c CREATE_AREA_UNMAP_ADDRESS_RANGE flag is specified, the caller must ensure
|
||||||
that no part of the specified address range (base \c *_virtualAddress, size
|
that no part of the specified address range (base \c *_virtualAddress, size
|
||||||
\a size) is wired.
|
\a size) is wired. The cache will also be temporarily unlocked.
|
||||||
*/
|
*/
|
||||||
static status_t
|
static status_t
|
||||||
map_backing_store(VMAddressSpace* addressSpace, VMCache* cache, off_t offset,
|
map_backing_store(VMAddressSpace* addressSpace, VMCache* cache, off_t offset,
|
||||||
@@ -1005,8 +1005,13 @@ map_backing_store(VMAddressSpace* addressSpace, VMCache* cache, off_t offset,
|
|||||||
|
|
||||||
if (addressRestrictions->address_specification == B_EXACT_ADDRESS
|
if (addressRestrictions->address_specification == B_EXACT_ADDRESS
|
||||||
&& (flags & CREATE_AREA_UNMAP_ADDRESS_RANGE) != 0) {
|
&& (flags & CREATE_AREA_UNMAP_ADDRESS_RANGE) != 0) {
|
||||||
|
// temporarily unlock the current cache since it might be mapped to
|
||||||
|
// some existing area, and unmap_address_range also needs to lock that
|
||||||
|
// cache to delete the area.
|
||||||
|
cache->Unlock();
|
||||||
status = unmap_address_range(addressSpace,
|
status = unmap_address_range(addressSpace,
|
||||||
(addr_t)addressRestrictions->address, size, kernel);
|
(addr_t)addressRestrictions->address, size, kernel);
|
||||||
|
cache->Lock();
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
goto err2;
|
goto err2;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ SimpleTest port_wakeup_test_9 : port_wakeup_test_9.cpp ;
|
|||||||
|
|
||||||
SimpleTest mmap_resize_test : mmap_resize_test.cpp ;
|
SimpleTest mmap_resize_test : mmap_resize_test.cpp ;
|
||||||
SimpleTest mmap_cut_tests : mmap_cut_tests.cpp ;
|
SimpleTest mmap_cut_tests : mmap_cut_tests.cpp ;
|
||||||
|
SimpleTest mmap_fixed_test : mmap_fixed_test.cpp ;
|
||||||
|
|
||||||
SimpleTest null_poll_test : null_poll_test.cpp ;
|
SimpleTest null_poll_test : null_poll_test.cpp ;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023, Trung Nguyen, trungnt282910@gmail.com.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
char tmpfile[] = "/tmp/mmap_fixed_test_XXXXXX";
|
||||||
|
int fd = mkstemp(tmpfile);
|
||||||
|
|
||||||
|
if (fd < 0) {
|
||||||
|
printf("cannot create temporary file.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unlink(tmpfile);
|
||||||
|
ftruncate(fd, 4096);
|
||||||
|
|
||||||
|
// Should not crash the kernel (#18422)
|
||||||
|
void* addr = mmap(NULL, 4096, PROT_NONE, MAP_SHARED, fd, 0);
|
||||||
|
void* addr1 = mmap(addr, 4096, PROT_NONE, MAP_SHARED | MAP_FIXED, fd, 0);
|
||||||
|
|
||||||
|
if (addr == MAP_FAILED || addr1 == MAP_FAILED) {
|
||||||
|
printf("mmap failed.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addr != addr1) {
|
||||||
|
printf("MAP_FIXED did not return same address.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user