diff options
author | hselasky <hselasky@FreeBSD.org> | 2015-11-12 08:47:10 +0000 |
---|---|---|
committer | hselasky <hselasky@FreeBSD.org> | 2015-11-12 08:47:10 +0000 |
commit | 70e13c31cbd29d45dcd705fb54d683131825888c (patch) | |
tree | c9e024dafa7346f8c483c39d77ee3e223863a1ef | |
parent | a4ba623b63629f2de1042e3223af8ac94eb170d8 (diff) | |
download | FreeBSD-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.c | 8 |
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 |