Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/uvm PR kern/54759: vm.ubc_direct deadlock when read()/wr...



details:   https://anonhg.NetBSD.org/src/rev/10bcb5657622
branches:  trunk
changeset: 970950:10bcb5657622
user:      ad <ad%NetBSD.org@localhost>
date:      Tue Apr 07 19:11:13 2020 +0000

description:
PR kern/54759: vm.ubc_direct deadlock when read()/write() into mapping of itself

Prevent ubc_uiomove_direct() on mapped vnodes.

diffstat:

 sys/uvm/uvm_bio.c |  25 +++++++++++++++++++++----
 1 files changed, 21 insertions(+), 4 deletions(-)

diffs (46 lines):

diff -r 65bdf1964cd5 -r 10bcb5657622 sys/uvm/uvm_bio.c
--- a/sys/uvm/uvm_bio.c Tue Apr 07 18:28:31 2020 +0000
+++ b/sys/uvm/uvm_bio.c Tue Apr 07 19:11:13 2020 +0000
@@ -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 @@
            ((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
 



Home | Main Index | Thread Index | Old Index