Module Name: src Committed By: ad Date: Tue Apr 7 19:11:13 UTC 2020
Modified Files: src/sys/uvm: uvm_bio.c Log Message: PR kern/54759: vm.ubc_direct deadlock when read()/write() into mapping of itself Prevent ubc_uiomove_direct() on mapped vnodes. To generate a diff of this commit: cvs rdiff -u -r1.106 -r1.107 src/sys/uvm/uvm_bio.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/uvm/uvm_bio.c diff -u src/sys/uvm/uvm_bio.c:1.106 src/sys/uvm/uvm_bio.c:1.107 --- src/sys/uvm/uvm_bio.c:1.106 Tue Mar 17 18:31:39 2020 +++ src/sys/uvm/uvm_bio.c Tue Apr 7 19:11:13 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_bio.c,v 1.106 2020/03/17 18:31:39 ad Exp $ */ +/* $NetBSD: uvm_bio.c,v 1.107 2020/04/07 19:11:13 ad Exp $ */ /* * Copyright (c) 1998 Chuck Silvers. @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uvm_bio.c,v 1.106 2020/03/17 18:31:39 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uvm_bio.c,v 1.107 2020/04/07 19:11:13 ad Exp $"); #include "opt_uvmhist.h" #include "opt_ubc.h" @@ -734,8 +734,25 @@ ubc_uiomove(struct uvm_object *uobj, str ((flags & UBC_READ) != 0 && uio->uio_rw == UIO_READ)); #ifdef UBC_USE_PMAP_DIRECT - if (ubc_direct) { - return ubc_uiomove_direct(uobj, uio, todo, advice, flags); + if (ubc_direct && UVM_OBJ_IS_VNODE(uobj)) { + /* + * during direct access pages need to be held busy to + * prevent them disappearing. if the LWP reads or writes + * a vnode into a mapped view of same it could deadlock. + * prevent this by disallowing direct access if the vnode + * is visible somewhere via mmap(). + * + * the vnode flags are tested here, but at all points UBC is + * called for vnodes, the vnode is locked (thus preventing a + * new mapping via mmap() while busy here). + */ + + struct vnode *vp = (struct vnode *)uobj; + KASSERT(VOP_ISLOCKED(vp) != LK_NONE); + if ((vp->v_vflag & VV_MAPPED) == 0) { + return ubc_uiomove_direct(uobj, uio, todo, advice, + flags); + } } #endif