]> xenbits.xensource.com Git - people/julieng/freebsd.git/commitdiff
Add missing NULL check in physio().
authorhselasky <hselasky@FreeBSD.org>
Thu, 29 Oct 2015 13:53:37 +0000 (13:53 +0000)
committerhselasky <hselasky@FreeBSD.org>
Thu, 29 Oct 2015 13:53:37 +0000 (13:53 +0000)
When destroying a character device the si_devsw field is set to NULL
before all references are gone, to indicate the character device is
going away. This can cause a NULL-dereference fault inside physio().

The callers of physio() should own a thread reference on the cdev and
if si_devsw is seen as non-NULL, it is usable during the execution of
the function. Else an ENXIO error code is returned.

Reviewed by: kib
MFC after: 2 weeks

sys/kern/kern_physio.c

index 71cfded32bb72de4ec17f8f196f6116fd77da27e..5d75304a339cbe0015a641a86b1919af0eb7f6a5 100644 (file)
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
 int
 physio(struct cdev *dev, struct uio *uio, int ioflag)
 {
+       struct cdevsw *csw;
        struct buf *pbuf;
        struct bio *bp;
        struct vm_page **pages;
@@ -46,6 +47,11 @@ physio(struct cdev *dev, struct uio *uio, int ioflag)
        int error, i, npages, maxpages;
        vm_prot_t prot;
 
+       csw = dev->si_devsw;
+       /* check if character device is being destroyed */
+       if (csw == NULL)
+               return (ENXIO);
+
        /* XXX: sanity check */
        if(dev->si_iosize_max < PAGE_SIZE) {
                printf("WARNING: %s si_iosize_max=%d, using DFLTPHYS.\n",
@@ -165,7 +171,7 @@ physio(struct cdev *dev, struct uio *uio, int ioflag)
                                }
                        }
 
-                       dev->si_devsw->d_strategy(bp);
+                       csw->d_strategy(bp);
                        if (uio->uio_rw == UIO_READ)
                                biowait(bp, "physrd");
                        else