summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhselasky <hselasky@FreeBSD.org>2015-11-12 08:47:10 +0000
committerhselasky <hselasky@FreeBSD.org>2015-11-12 08:47:10 +0000
commit70e13c31cbd29d45dcd705fb54d683131825888c (patch)
treec9e024dafa7346f8c483c39d77ee3e223863a1ef
parenta4ba623b63629f2de1042e3223af8ac94eb170d8 (diff)
downloadFreeBSD-src-70e13c31cbd29d45dcd705fb54d683131825888c.zip
FreeBSD-src-70e13c31cbd29d45dcd705fb54d683131825888c.tar.gz
MFC r290140:
Add missing NULL check in physio(). 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
-rw-r--r--sys/kern/kern_physio.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/sys/kern/kern_physio.c b/sys/kern/kern_physio.c
index 71cfded..5d75304 100644
--- a/sys/kern/kern_physio.c
+++ b/sys/kern/kern_physio.c
@@ -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
OpenPOWER on IntegriCloud