xpmem: Make sure vm_range is used under memory_range_lock

Change-Id: I856ee9d401e7dcfd74559bad5b22a69d53a61e2f
This commit is contained in:
Yoshihisa Morizumi
2021-01-08 17:21:44 +09:00
committed by Masamichi Takagi
parent 4ac9dcdccd
commit 5dd989450d
2 changed files with 27 additions and 13 deletions

View File

@ -331,6 +331,7 @@ static void xpmem_ap_deref(struct xpmem_access_permit *ap);
static void xpmem_att_deref(struct xpmem_attachment *att); static void xpmem_att_deref(struct xpmem_attachment *att);
static int xpmem_validate_access(struct xpmem_access_permit *, off_t, size_t, static int xpmem_validate_access(struct xpmem_access_permit *, off_t, size_t,
int, unsigned long *); int, unsigned long *);
static int is_remote_vm(struct process_vm *vm);
/* /*
* Inlines that mark an internal driver structure as being destroyable or not. * Inlines that mark an internal driver structure as being destroyable or not.

View File

@ -1119,16 +1119,18 @@ static int xpmem_attach(
existing_vmr = lookup_process_memory_range(vm, vaddr, existing_vmr = lookup_process_memory_range(vm, vaddr,
vaddr + size); vaddr + size);
ihk_rwspinlock_read_unlock_noirq(&vm->memory_range_lock);
for (; existing_vmr && existing_vmr->start < vaddr + size; for (; existing_vmr && existing_vmr->start < vaddr + size;
existing_vmr = next_process_memory_range(vm, existing_vmr = next_process_memory_range(vm,
existing_vmr)) { existing_vmr)) {
if (xpmem_is_private_data(existing_vmr)) { if (xpmem_is_private_data(existing_vmr)) {
ret = -EINVAL; ret = -EINVAL;
ihk_rwspinlock_read_unlock_noirq(
&vm->memory_range_lock);
goto out_2; goto out_2;
} }
} }
ihk_rwspinlock_read_unlock_noirq(&vm->memory_range_lock);
} }
flags |= MAP_ANONYMOUS; flags |= MAP_ANONYMOUS;
@ -1423,20 +1425,18 @@ static void xpmem_detach_att(
XPMEM_DEBUG("detaching att->vm=0x%p", (void *)att->vm); XPMEM_DEBUG("detaching att->vm=0x%p", (void *)att->vm);
vm = att->vm;
ihk_rwspinlock_read_lock_noirq(&vm->memory_range_lock);
mcs_rwlock_writer_lock(&att->at_lock, &at_lock); mcs_rwlock_writer_lock(&att->at_lock, &at_lock);
if (att->flags & XPMEM_FLAG_DESTROYING) { if (att->flags & XPMEM_FLAG_DESTROYING) {
mcs_rwlock_writer_unlock(&att->at_lock, &at_lock); mcs_rwlock_writer_unlock(&att->at_lock, &at_lock);
ihk_rwspinlock_read_unlock_noirq(&vm->memory_range_lock);
XPMEM_DEBUG("return: XPMEM_FLAG_DESTROYING"); XPMEM_DEBUG("return: XPMEM_FLAG_DESTROYING");
return; return;
} }
att->flags |= XPMEM_FLAG_DESTROYING; att->flags |= XPMEM_FLAG_DESTROYING;
vm = att->vm;
ihk_rwspinlock_read_lock_noirq(&vm->memory_range_lock);
range = lookup_process_memory_range(vm, range = lookup_process_memory_range(vm,
att->at_vaddr, att->at_vaddr + 1); att->at_vaddr, att->at_vaddr + 1);
@ -1676,10 +1676,8 @@ int xpmem_remove_process_memory_range(
mcs_rwlock_writer_lock(&att->at_lock, &at_lock); mcs_rwlock_writer_lock(&att->at_lock, &at_lock);
if (att->flags & XPMEM_FLAG_DESTROYING) { if (att->flags & XPMEM_FLAG_DESTROYING) {
mcs_rwlock_writer_unlock(&att->at_lock, &at_lock);
xpmem_att_deref(att);
XPMEM_DEBUG("already cleaned up"); XPMEM_DEBUG("already cleaned up");
return 0; goto out;
} }
if (vmr->start == att->at_vaddr && if (vmr->start == att->at_vaddr &&
@ -1910,13 +1908,13 @@ static int xpmem_remap_pte(
"seg_vaddr=0x%lx", "seg_vaddr=0x%lx",
vmr, vaddr, reason, seg->segid, seg_vaddr); vmr, vaddr, reason, seg->segid, seg_vaddr);
ihk_rwspinlock_read_lock_noirq(&seg_tg->vm->memory_range_lock); if (is_remote_vm(seg_tg->vm)) {
ihk_rwspinlock_read_lock_noirq(&seg_tg->vm->memory_range_lock);
}
seg_vmr = lookup_process_memory_range(seg_tg->vm, seg_vaddr, seg_vmr = lookup_process_memory_range(seg_tg->vm, seg_vaddr,
seg_vaddr + 1); seg_vaddr + 1);
ihk_rwspinlock_read_unlock_noirq(&seg_tg->vm->memory_range_lock);
if (!seg_vmr) { if (!seg_vmr) {
ret = -EFAULT; ret = -EFAULT;
ekprintf("%s: ERROR: lookup_process_memory_range() failed\n", ekprintf("%s: ERROR: lookup_process_memory_range() failed\n",
@ -1989,6 +1987,10 @@ static int xpmem_remap_pte(
} }
out: out:
if (is_remote_vm(seg_tg->vm)) {
ihk_rwspinlock_read_unlock_noirq(&seg_tg->vm->memory_range_lock);
}
XPMEM_DEBUG("return: ret=%d", ret); XPMEM_DEBUG("return: ret=%d", ret);
return ret; return ret;
@ -2336,3 +2338,14 @@ static int xpmem_validate_access(
return 0; return 0;
} }
static int is_remote_vm(struct process_vm *vm)
{
int ret = 0;
if (cpu_local_var(current)->proc->vm != vm) {
/* vm is not mine */
ret = 1;
}
return ret;
}