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 MFC after: 2 weeks
This commit is contained in:
parent
043fd51a74
commit
cb3450e26e
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=290140
@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
int
|
int
|
||||||
physio(struct cdev *dev, struct uio *uio, int ioflag)
|
physio(struct cdev *dev, struct uio *uio, int ioflag)
|
||||||
{
|
{
|
||||||
|
struct cdevsw *csw;
|
||||||
struct buf *pbuf;
|
struct buf *pbuf;
|
||||||
struct bio *bp;
|
struct bio *bp;
|
||||||
struct vm_page **pages;
|
struct vm_page **pages;
|
||||||
@ -46,6 +47,11 @@ physio(struct cdev *dev, struct uio *uio, int ioflag)
|
|||||||
int error, i, npages, maxpages;
|
int error, i, npages, maxpages;
|
||||||
vm_prot_t prot;
|
vm_prot_t prot;
|
||||||
|
|
||||||
|
csw = dev->si_devsw;
|
||||||
|
/* check if character device is being destroyed */
|
||||||
|
if (csw == NULL)
|
||||||
|
return (ENXIO);
|
||||||
|
|
||||||
/* XXX: sanity check */
|
/* XXX: sanity check */
|
||||||
if(dev->si_iosize_max < PAGE_SIZE) {
|
if(dev->si_iosize_max < PAGE_SIZE) {
|
||||||
printf("WARNING: %s si_iosize_max=%d, using DFLTPHYS.\n",
|
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)
|
if (uio->uio_rw == UIO_READ)
|
||||||
biowait(bp, "physrd");
|
biowait(bp, "physrd");
|
||||||
else
|
else
|
||||||
|
Loading…
Reference in New Issue
Block a user