Mon Aug 27 00:56:38 2018 UTC ()
Handle uvm object reference counts in uvm_map more carefully.

Acquire a reference unconditionally first; then let uvm_map consume
it on success, and release it ourselves on failure.

As we did before -- acquiring a fresh reference on success -- another
thread might release the reference with a concurrent uvm_unmap before
we could acquire it back, thereby destroying the object.

XXX pullup-7
XXX pullup-8


(riastradh)
diff -r1.34 -r1.35 src/sys/external/bsd/drm2/dist/drm/i915/i915_gem.c

cvs diff -r1.34 -r1.35 src/sys/external/bsd/drm2/dist/drm/i915/i915_gem.c (expand / switch to unified diff)

--- src/sys/external/bsd/drm2/dist/drm/i915/i915_gem.c 2017/10/28 00:37:13 1.34
+++ src/sys/external/bsd/drm2/dist/drm/i915/i915_gem.c 2018/08/27 00:56:38 1.35
@@ -1761,40 +1761,42 @@ i915_gem_mmap_ioctl(struct drm_device *d @@ -1761,40 +1761,42 @@ i915_gem_mmap_ioctl(struct drm_device *d
1761 /* Also stolen objects (XXX can we get them here?) */ 1761 /* Also stolen objects (XXX can we get them here?) */
1762 if (obj->gemo_shm_uao == NULL) { 1762 if (obj->gemo_shm_uao == NULL) {
1763 drm_gem_object_unreference_unlocked(obj); 1763 drm_gem_object_unreference_unlocked(obj);
1764 return -EINVAL; 1764 return -EINVAL;
1765 } 1765 }
1766#else 1766#else
1767 if (!obj->filp) { 1767 if (!obj->filp) {
1768 drm_gem_object_unreference_unlocked(obj); 1768 drm_gem_object_unreference_unlocked(obj);
1769 return -EINVAL; 1769 return -EINVAL;
1770 } 1770 }
1771#endif 1771#endif
1772 1772
1773#ifdef __NetBSD__ 1773#ifdef __NetBSD__
 1774 /* Acquire a reference for uvm_map to consume. */
 1775 uao_reference(obj->gemo_shm_uao);
1774 addr = (*curproc->p_emul->e_vm_default_addr)(curproc, 1776 addr = (*curproc->p_emul->e_vm_default_addr)(curproc,
1775 (vaddr_t)curproc->p_vmspace->vm_daddr, args->size, 1777 (vaddr_t)curproc->p_vmspace->vm_daddr, args->size,
1776 curproc->p_vmspace->vm_map.flags & VM_MAP_TOPDOWN); 1778 curproc->p_vmspace->vm_map.flags & VM_MAP_TOPDOWN);
1777 /* XXX errno NetBSD->Linux */ 1779 /* XXX errno NetBSD->Linux */
1778 ret = -uvm_map(&curproc->p_vmspace->vm_map, &addr, args->size, 1780 ret = -uvm_map(&curproc->p_vmspace->vm_map, &addr, args->size,
1779 obj->gemo_shm_uao, args->offset, 0, 1781 obj->gemo_shm_uao, args->offset, 0,
1780 UVM_MAPFLAG((VM_PROT_READ | VM_PROT_WRITE), 1782 UVM_MAPFLAG((VM_PROT_READ | VM_PROT_WRITE),
1781 (VM_PROT_READ | VM_PROT_WRITE), UVM_INH_COPY, UVM_ADV_NORMAL, 1783 (VM_PROT_READ | VM_PROT_WRITE), UVM_INH_COPY, UVM_ADV_NORMAL,
1782 0)); 1784 0));
1783 if (ret) { 1785 if (ret) {
 1786 uao_detach(obj->gemo_shm_uao);
1784 drm_gem_object_unreference_unlocked(obj); 1787 drm_gem_object_unreference_unlocked(obj);
1785 return ret; 1788 return ret;
1786 } 1789 }
1787 uao_reference(obj->gemo_shm_uao); 
1788 drm_gem_object_unreference_unlocked(obj); 1790 drm_gem_object_unreference_unlocked(obj);
1789#else 1791#else
1790 addr = vm_mmap(obj->filp, 0, args->size, 1792 addr = vm_mmap(obj->filp, 0, args->size,
1791 PROT_READ | PROT_WRITE, MAP_SHARED, 1793 PROT_READ | PROT_WRITE, MAP_SHARED,
1792 args->offset); 1794 args->offset);
1793 drm_gem_object_unreference_unlocked(obj); 1795 drm_gem_object_unreference_unlocked(obj);
1794 if (IS_ERR((void *)addr)) 1796 if (IS_ERR((void *)addr))
1795 return addr; 1797 return addr;
1796#endif 1798#endif
1797 1799
1798 args->addr_ptr = (uint64_t) addr; 1800 args->addr_ptr = (uint64_t) addr;
1799 1801
1800 return 0; 1802 return 0;