Date: Sun, 16 Feb 2025 12:00:39 +0000 From: bugzilla-noreply@freebsd.org To: bugs@FreeBSD.org Subject: [Bug 284847] SCSI CD table-of-contents can cause invalid overwrite Message-ID: <bug-284847-227@https.bugs.freebsd.org/bugzilla/>
index | next in thread | raw e-mail
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=284847 Bug ID: 284847 Summary: SCSI CD table-of-contents can cause invalid overwrite Product: Base System Version: CURRENT Hardware: Any OS: Any Status: New Severity: Affects Some People Priority: --- Component: kern Assignee: bugs@FreeBSD.org Reporter: rtm@lcs.mit.edu Attachment #257573 text/plain mime type: Created attachment 257573 --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=257573&action=edit supply bad CD TOC that causes crash A SCSI CD reader can supply table-of-contents values that cause this assignment in scsi_cd.c / cddone() to write beyond the end of the softc->toc.entries[] array: softc->toc.entries[cdindex - toch->starting_track] = leadout->entry; toch->starting_track comes directly from a READ TOC request to the CD reader, and cdindex is derived from that READ TOC data: toch = &softc->toc.header; ...; num_entries = toch->ending_track - toch->starting_track + 2; cdindex = toch->starting_track + num_entries - 1; toc.entries[] has 170 entries, but the CD device can cause num_entries to be larger than that. I've attached a demo consisting of a fake iscsi target, which responds to the initiator's first READ TOC with a valid table of contents, but to subsequent READ TOCs with starting_track / ending_track that produce num_entries = 171. The entries[] overrun causes softc->disk (which is shortly after entries[]) to be overwritten, and the crash happens next time softc->disk is dereferenced. # uname -a FreeBSD xxx 15.0-CURRENT FreeBSD 15.0-CURRENT #26 main-n274922-237e9b7f5e90: Wed Jan 22 17:43:39 AST 2025 root@xxx:/usr/obj/usr/src/amd64.amd64/sys/GENERIC amd64 # cc iscsi43b.c # ./a.out ... cd0 at iscsi1 bus 0 scbus0 target 0 lun 0 cd0: <FREEBSD CTLDISK 0001> Fixed CD-ROM SPC-5 SCSI device cd0: Serial Number cd0: 150.000MB/s transfers cd0: Command Queueing enabled cd0: 1MB (513 2048 byte sectors) ... Fatal trap 9: general protection fault while in kernel mode cpuid = 2; apic id = 02 instruction pointer = 0x20:0xffffffff803b7dc0 stack pointer = 0x28:0xfffffe00db05f920 frame pointer = 0x28:0xfffffe00db05fe60 code segment = base 0x0, limit 0xfffff, type 0x1b = DPL 0, pres 1, long 1, def32 0, gran 1 processor eflags = interrupt enabled, resume, IOPL = 0 current process = 4 (doneq0) rdi: fffff801a67c84e8 rsi: 0000000000000004 rdx: 00000000000000ab rcx: fffff80100000000 r8: fffff80104859000 r9: ffffffffffffffff rax: 800000043f8000e3 rbx: fffff801a0dd7300 rbp: fffffe00db05fe60 r10: ffffffff81c4feb0 r11: 0000000000000001 r12: 0000000000000000 r13: fffff801acfad854 r14: fffff801acfad800 r15: fffff801a34f3000 trap number = 9 panic: general protection fault cpuid = 2 time = 1739704567 KDB: stack backtrace: db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe00db05f6a0 vpanic() at vpanic+0x136/frame 0xfffffe00db05f7d0 panic() at panic+0x43/frame 0xfffffe00db05f830 trap_fatal() at trap_fatal+0x68/frame 0xfffffe00db05f850 calltrap() at calltrap+0x8/frame 0xfffffe00db05f850 --- trap 0x9, rip = 0xffffffff803b7dc0, rsp = 0xfffffe00db05f920, rbp = 0xfffffe00db05fe60 --- cddone() at cddone+0x960/frame 0xfffffe00db05fe60 xpt_done_process() at xpt_done_process+0x3db/frame 0xfffffe00db05fea0 xpt_done_td() at xpt_done_td+0x145/frame 0xfffffe00db05fef0 fork_exit() at fork_exit+0x82/frame 0xfffffe00db05ff30 fork_trampoline() at fork_trampoline+0xe/frame 0xfffffe00db05ff30 --- trap 0, rip = 0, rsp = 0, rbp = 0 --- KDB: enter: panic Here's a gdb backtrace from just before the offending write to toc.entries[]: (gdb) where #0 cddone (periph=0xffffffd00d5b1500, done_ccb=0xffffffd00d2ee800) at /usr/rtm/symbsd/src/sys/cam/scsi/scsi_cd.c:1635 #1 0xffffffc00001259a in xpt_done_process (ccb_h=0xffffffd00d2ee800) at /usr/rtm/symbsd/src/sys/cam/cam_xpt.c:5374 #2 0xffffffc000014032 in xpt_done_td (arg=0xffffffc000bab7c0 <cam_doneqs>) at /usr/rtm/symbsd/src/sys/cam/cam_xpt.c:5429 #3 0xffffffc0003f63f6 in fork_exit (callout=0xffffffc000013f5c <xpt_done_td>, arg=0xffffffc000bab7c0 <cam_doneqs>, frame=0xffffffc08262bc50) at /usr/rtm/symbsd/src/sys/kern/kern_fork.c:1152 #4 0xffffffc0007ec6ae in fork_trampoline () at /usr/rtm/symbsd/src/sys/riscv/riscv/swtch.S:370 (gdb) print sizeof(softc->toc.entries) / sizeof(softc->toc.entries[0]) $7 = 170 (gdb) print softc->toc.header $10 = {len = 8707, starting_track = 47 '/', ending_track = 218 '\332'} (gdb) print softc->toc.header.ending_track - softc->toc.header.starting_track $12 = 171 -- You are receiving this mail because: You are the assignee for the bug.home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-284847-227>
