DF-2938 / fix.diff
--- sys/vm/device_pager.c.orig +++ sys/vm/device_pager.c @@ -145,6 +145,15 @@ */ if (ops->cdev_pg_ctor == old_dev_pager_ctor) { dev = handle; + /* + * DF-2938: the OBJT_DEVICE pager object must pin + * the cdev. A mapping can outlive every other + * reference (close of the fd, driver teardown, + * clone GC, USB unplug); without this reference + * old_dev_pager_fault()/old_dev_pager_dtor() + * operate on freed memory. + */ + reference_dev(dev); dev->si_object = object; } @@ -342,6 +351,12 @@ if (dev != NULL) { KKASSERT(dev->si_object); dev->si_object = NULL; + /* + * DF-2938: drop the reference cdev_pager_allocate() + * took when it created the object for this device + * (runs exactly once per pager object). + */ + release_dev(dev); } } |