[Bug 219701] crash in camperiphfree()

bugzilla-noreply at freebsd.org bugzilla-noreply at freebsd.org
Thu Jun 1 09:48:22 UTC 2017


https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=219701

            Bug ID: 219701
           Summary: crash in camperiphfree()
           Product: Base System
           Version: CURRENT
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Only Me
          Priority: ---
         Component: kern
          Assignee: freebsd-bugs at FreeBSD.org
          Reporter: avg at FreeBSD.org

It seems that camperiphfree() has some unsafe code that can lead to a crash
when a peripheral is freed at the same time as an unrelated peripheral driver
is added.

p_drv is a pointer into periph_drivers.  The pointer is used across
xpt_unlock_buses + xpt_lock_buses.  While the buses lock is dropped
periph_drivers could be pointed to a new memory location and the old memory
location would be freed.  See periphdriver_register() for details.
Thus, p_drv can end up pointing into the freed memory.  That would lead to a
crash or memory corruption while dereferencing the pointer.

I have actually experienced such a crash (happened during the kernel boot):
#3  0xffffffff80651f33 in panic (fmt=<unavailable>) at
/usr/src/sys/kern/kern_shutdown.c:594
#4  0xffffffff8085a190 in trap_fatal (frame=0xfffffe050536b430, eva=0) at
/usr/src/sys/amd64/amd64/trap.c:802
#5  0xffffffff80859737 in trap (frame=0xfffffe050536b430) at
/usr/src/sys/amd64/amd64/trap.c:198
#6  0xffffffff8085a4ba in trap_check (frame=0xfffffe050536b430) at
/usr/src/sys/amd64/amd64/trap.c:603
#7  <signal handler called>
#8  0xffffffff802a9cd8 in camperiphfree (periph=0xfffff800224f9300) at
/usr/src/sys/cam/cam_periph.c:712
#9  0xffffffff802a9bb2 in cam_periph_release_locked_buses
(periph=0xfffff800224f9300) at /usr/src/sys/cam/cam_periph.c:441
#10 0xffffffff802a9e7b in cam_periph_release_locked (periph=0xfffff800224f9300)
at /usr/src/sys/cam/cam_periph.c:452
#11 0xffffffff802bfeac in probedone (periph=<optimized out>,
done_ccb=0xfffff8000bfe1000) at /usr/src/sys/cam/scsi/scsi_xpt.c:1198
#12 0xffffffff802b13c3 in xpt_done_process (ccb_h=0xfffff8000bfe1000) at
/usr/src/sys/cam/cam_xpt.c:5452
#13 0xffffffff802b2965 in xpt_done_td (arg=0xffffffff80cf3880 <cam_doneqs>) at
/usr/src/sys/cam/cam_xpt.c:5479

(kgdb) fr 8
#8  0xffffffff802a9cd8 in camperiphfree (periph=0xfffff800224f9300) at
/usr/src/sys/cam/cam_periph.c:712
712             TAILQ_REMOVE(&(*p_drv)->units, periph, unit_links);
(kgdb) p p_drv
$1 = (struct periph_driver **) 0xfffff80007330030
(kgdb) p *p_drv
$2 = (struct periph_driver *) 0xdeadc0dedeadc0d
(kgdb) p periph_drivers
$9 = (struct periph_driver **) 0xfffff800a81f4880

I think that we should cache the actual pointer to the peripheral driver rather
than the pointer into the array of pointers.

-- 
You are receiving this mail because:
You are the assignee for the bug.


More information about the freebsd-bugs mailing list