Wait for thread count to reach zero in destroy_devl() even when no purge
method is defined, to avoid memory being modified after free. Temporarily increase refcount in destroy_devl() to avoid a double free if dev_rel() is called while waiting for thread count to reach zero.
This commit is contained in:
parent
675e8ac08c
commit
e0c33ad529
@ -658,6 +658,7 @@ destroy_devl(struct cdev *dev)
|
||||
dev->si_flags &= ~SI_CLONELIST;
|
||||
}
|
||||
|
||||
dev->si_refcount++; /* Avoid race with dev_rel() */
|
||||
csw = dev->si_devsw;
|
||||
dev->si_devsw = NULL; /* already NULL for SI_ALIAS */
|
||||
while (csw != NULL && csw->d_purge != NULL && dev->si_threadcount) {
|
||||
@ -667,6 +668,10 @@ destroy_devl(struct cdev *dev)
|
||||
printf("Still %lu threads in %s\n",
|
||||
dev->si_threadcount, devtoname(dev));
|
||||
}
|
||||
while (dev->si_threadcount != 0) {
|
||||
/* Use unique dummy wait ident */
|
||||
msleep(&csw, &devmtx, PRIBIO, "devdrn", hz / 10);
|
||||
}
|
||||
|
||||
dev->si_drv1 = 0;
|
||||
dev->si_drv2 = 0;
|
||||
@ -681,6 +686,7 @@ destroy_devl(struct cdev *dev)
|
||||
fini_cdevsw(csw);
|
||||
}
|
||||
dev->si_flags &= ~SI_ALIAS;
|
||||
dev->si_refcount--; /* Avoid race with dev_rel() */
|
||||
|
||||
if (dev->si_refcount > 0) {
|
||||
LIST_INSERT_HEAD(&dead_cdevsw.d_devs, dev, si_list);
|
||||
|
Loading…
Reference in New Issue
Block a user