user_vm_map_file() was broken after recent changes; it didn't allow the
kernel to write to read-only userland areas. Cleanup. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7893 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+16
-9
@@ -998,7 +998,9 @@ region_id vm_create_null_region(aspace_id aid, char *name, void **address, int a
|
|||||||
return region->id;
|
return region->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
static region_id _vm_map_file(aspace_id aid, char *name, void **address, int addr_type,
|
|
||||||
|
static region_id
|
||||||
|
_vm_map_file(aspace_id aid, char *name, void **address, int addr_type,
|
||||||
addr_t size, int lock, int mapping, const char *path, off_t offset, bool kernel)
|
addr_t size, int lock, int mapping, const char *path, off_t offset, bool kernel)
|
||||||
{
|
{
|
||||||
vm_region *region;
|
vm_region *region;
|
||||||
@@ -1009,7 +1011,6 @@ static region_id _vm_map_file(aspace_id aid, char *name, void **address, int add
|
|||||||
// addr_t map_offset;
|
// addr_t map_offset;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
|
||||||
vm_address_space *aspace = vm_get_aspace_by_id(aid);
|
vm_address_space *aspace = vm_get_aspace_by_id(aid);
|
||||||
if (aspace == NULL)
|
if (aspace == NULL)
|
||||||
return ERR_VM_INVALID_ASPACE;
|
return ERR_VM_INVALID_ASPACE;
|
||||||
@@ -1065,22 +1066,25 @@ restart:
|
|||||||
err = map_backing_store(aspace, store, address, offset, size, addr_type, 0, lock, mapping, ®ion, name);
|
err = map_backing_store(aspace, store, address, offset, size, addr_type, 0, lock, mapping, ®ion, name);
|
||||||
vm_cache_release_ref(cache_ref);
|
vm_cache_release_ref(cache_ref);
|
||||||
vm_put_aspace(aspace);
|
vm_put_aspace(aspace);
|
||||||
if(err < 0) {
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
}
|
|
||||||
|
|
||||||
// modify the pointer returned to be offset back into the new region
|
// modify the pointer returned to be offset back into the new region
|
||||||
// the same way the physical address in was offset
|
// the same way the physical address in was offset
|
||||||
return region->id;
|
return region->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
region_id vm_map_file(aspace_id aid, char *name, void **address, int addr_type,
|
|
||||||
|
region_id
|
||||||
|
vm_map_file(aspace_id aid, char *name, void **address, int addr_type,
|
||||||
addr_t size, int lock, int mapping, const char *path, off_t offset)
|
addr_t size, int lock, int mapping, const char *path, off_t offset)
|
||||||
{
|
{
|
||||||
return _vm_map_file(aid, name, address, addr_type, size, lock, mapping, path, offset, true);
|
return _vm_map_file(aid, name, address, addr_type, size, lock, mapping, path, offset, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
region_id user_vm_map_file(char *uname, void **uaddress, int addr_type,
|
|
||||||
|
region_id
|
||||||
|
user_vm_map_file(char *uname, void **uaddress, int addr_type,
|
||||||
addr_t size, int lock, int mapping, const char *upath, off_t offset)
|
addr_t size, int lock, int mapping, const char *upath, off_t offset)
|
||||||
{
|
{
|
||||||
char name[B_OS_NAME_LENGTH];
|
char name[B_OS_NAME_LENGTH];
|
||||||
@@ -1094,6 +1098,9 @@ region_id user_vm_map_file(char *uname, void **uaddress, int addr_type,
|
|||||||
|| user_memcpy(&address, uaddress, sizeof(address)) < B_OK)
|
|| user_memcpy(&address, uaddress, sizeof(address)) < B_OK)
|
||||||
return B_BAD_ADDRESS;
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
|
// userland created areas can always be accessed by the kernel
|
||||||
|
lock |= B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA;
|
||||||
|
|
||||||
rc = _vm_map_file(vm_get_current_user_aspace_id(), name, &address, addr_type, size, lock, mapping, path, offset, false);
|
rc = _vm_map_file(vm_get_current_user_aspace_id(), name, &address, addr_type, size, lock, mapping, path, offset, false);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
return rc;
|
return rc;
|
||||||
@@ -2177,9 +2184,9 @@ vm_soft_fault(addr_t address, bool is_write, bool is_user)
|
|||||||
|
|
||||||
address = ROUNDOWN(address, PAGE_SIZE);
|
address = ROUNDOWN(address, PAGE_SIZE);
|
||||||
|
|
||||||
if (address >= KERNEL_BASE && address <= KERNEL_TOP) {
|
if (IS_KERNEL_ADDRESS(address)) {
|
||||||
aspace = vm_get_kernel_aspace();
|
aspace = vm_get_kernel_aspace();
|
||||||
} else if(address >= USER_BASE && address <= USER_TOP) {
|
} else if (IS_USER_ADDRESS(address)) {
|
||||||
aspace = vm_get_current_user_aspace();
|
aspace = vm_get_current_user_aspace();
|
||||||
if (aspace == NULL) {
|
if (aspace == NULL) {
|
||||||
if (is_user == false) {
|
if (is_user == false) {
|
||||||
@@ -2217,7 +2224,7 @@ vm_soft_fault(addr_t address, bool is_write, bool is_user)
|
|||||||
if (is_write && (region->lock & (B_WRITE_AREA | (is_user ? 0 : B_KERNEL_WRITE_AREA))) == 0) {
|
if (is_write && (region->lock & (B_WRITE_AREA | (is_user ? 0 : B_KERNEL_WRITE_AREA))) == 0) {
|
||||||
release_sem_etc(map->sem, READ_COUNT, 0);
|
release_sem_etc(map->sem, READ_COUNT, 0);
|
||||||
vm_put_aspace(aspace);
|
vm_put_aspace(aspace);
|
||||||
dprintf("write access attempted on read-only region\n");
|
dprintf("write access attempted on read-only region 0x%lx at %p\n", region->id, (void *)address);
|
||||||
return ERR_VM_PF_BAD_PERM; // BAD_PERMISSION
|
return ERR_VM_PF_BAD_PERM; // BAD_PERMISSION
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user