tty_rel_free() can be called more than once for the same tty so make sure
that the tty is dequeued from 'tty_list' only the first time. The panic below was seen when a revoke(2) was issued on an nmdm device. In this case there was also a thread that was blocked on a read(2) on the device. The revoke(2) woke up the blocked thread which would typically return an error to userspace. In this case the reader also held the last reference on the file descriptor so fdrop() ended up calling tty_rel_free() via ttydev_close(). tty_rel_free() then tried to dequeue 'tp' again which led to the panic. panic: Bad link elm 0xfffff80042602400 prev->next != elm cpuid = 1 KDB: stack backtrace: db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe00f9c90460 kdb_backtrace() at kdb_backtrace+0x39/frame 0xfffffe00f9c90510 vpanic() at vpanic+0x189/frame 0xfffffe00f9c90590 panic() at panic+0x43/frame 0xfffffe00f9c905f0 tty_rel_free() at tty_rel_free+0x29b/frame 0xfffffe00f9c90640 ttydev_close() at ttydev_close+0x1f9/frame 0xfffffe00f9c90690 devfs_close() at devfs_close+0x298/frame 0xfffffe00f9c90720 VOP_CLOSE_APV() at VOP_CLOSE_APV+0x13c/frame 0xfffffe00f9c90770 vn_close() at vn_close+0x194/frame 0xfffffe00f9c90810 vn_closefile() at vn_closefile+0x48/frame 0xfffffe00f9c90890 devfs_close_f() at devfs_close_f+0x2c/frame 0xfffffe00f9c908c0 _fdrop() at _fdrop+0x29/frame 0xfffffe00f9c908e0 sys_read() at sys_read+0x63/frame 0xfffffe00f9c90980 amd64_syscall() at amd64_syscall+0x2b3/frame 0xfffffe00f9c90ab0 Xfast_syscall() at Xfast_syscall+0xfb/frame 0xfffffe00f9c90ab0 --- syscall (3, FreeBSD ELF64, sys_read), rip = 0x800b78d8a, rsp = 0x7fffffbfdaf8, rbp = 0x7fffffbfdb30 --- CR: https://reviews.freebsd.org/D851 Reviewed by: glebius, ed Reported by: Leon Dang Sponsored by: Nahanni Systems MFC after: 1 week
This commit is contained in:
parent
c6682d5906
commit
fbe602fb61
@ -1055,13 +1055,13 @@ tty_rel_free(struct tty *tp)
|
||||
tp->t_dev = NULL;
|
||||
tty_unlock(tp);
|
||||
|
||||
sx_xlock(&tty_list_sx);
|
||||
TAILQ_REMOVE(&tty_list, tp, t_list);
|
||||
tty_list_count--;
|
||||
sx_xunlock(&tty_list_sx);
|
||||
|
||||
if (dev != NULL)
|
||||
if (dev != NULL) {
|
||||
sx_xlock(&tty_list_sx);
|
||||
TAILQ_REMOVE(&tty_list, tp, t_list);
|
||||
tty_list_count--;
|
||||
sx_xunlock(&tty_list_sx);
|
||||
destroy_dev_sched_cb(dev, tty_dealloc, tp);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
Loading…
Reference in New Issue
Block a user