[haiku-bugs] [Haiku] #15902: PANIC: IORequest::_CopyData(): invalid range: (684032, 3584)

  • From: "Haiku" <trac@xxxxxxxxxxxx>
  • To: undisclosed-recipients: ;
  • Date: Sat, 25 Apr 2020 05:17:38 -0000

#15902: PANIC: IORequest::_CopyData(): invalid range: (684032, 3584)
---------------------------+-----------------------------
 Reporter:  waddlesplash   |       Owner:  nobody
     Type:  bug            |      Status:  new
 Priority:  normal         |   Milestone:  Unscheduled
Component:  System/Kernel  |     Version:  R1/Development
 Keywords:                 |  Blocked By:
 Blocking:  14881          |    Platform:  All
---------------------------+-----------------------------
 I've run into this while working on refactoring nvme_disk driver to use
 DMAResource:

 {{{
 Offset: 684032; Length 2048

 PANIC: IORequest::_CopyData(): invalid range: (684032, 3584)
 Welcome to Kernel Debugging Land...
 Thread 356 "sync" running on CPU 0
 stack trace for thread 356 "sync"
     kernel stack: 0xffffffff814c1000 to 0xffffffff814c6000
       user stack: 0x00007f47bc2d7000 to 0x00007f47bd2d7000
 frame                       caller             <image>:function + offset
  0 ffffffff814c5618 (+  24) ffffffff8014e44c   <kernel_x86_64>
 arch_debug_call_with_fault_handler + 0x16
  1 ffffffff814c5630 (+  80) ffffffff800ad6d8   <kernel_x86_64>
 debug_call_with_fault_handler + 0x88
  2 ffffffff814c5680 (+  96) ffffffff800af061   <kernel_x86_64>
 kernel_debugger_loop(char const*, char const*, __va_list_tag*, int) + 0xf1
  3 ffffffff814c56e0 (+  80) ffffffff800af35e   <kernel_x86_64>
 kernel_debugger_internal(char const*, char const*, __va_list_tag*, int) +
 0x6e
  4 ffffffff814c5730 (+ 240) ffffffff800af6c7   <kernel_x86_64> panic +
 0xb7
  5 ffffffff814c5820 (+  96) ffffffff800db624   <kernel_x86_64>
 IORequest::_CopyData(void*, long, unsigned long, bool) + 0x154
  6 ffffffff814c5880 (+  96) ffffffff800dbb3c   <kernel_x86_64>
 IOOperation::Prepare(IORequest*) + 0x13c
  7 ffffffff814c58e0 (+ 192) ffffffff800d6ff2   <kernel_x86_64>
 DMAResource::TranslateNext(IORequest*, IOOperation*, unsigned long) +
 0x802
  8 ffffffff814c59a0 (+ 256) ffffffff8151956e   <nvme_disk>
 nvme_disk_io(void*, IORequest*) + 0xde
  9 ffffffff814c5aa0 (+ 352) ffffffff8151a331   <nvme_disk>
 nvme_disk_write(void*, long, void const*, unsigned long*) + 0x81
 10 ffffffff814c5c00 (+ 112) ffffffff800f1c18   <kernel_x86_64>
 _kern_writev + 0x118
 11 ffffffff814c5c70 (+  32) ffffffff8016b7e3   <kernel_x86_64> writev_pos
 + 0x13
 12 ffffffff814c5c90 (+ 384) ffffffff818b8e54   <bfs>
 _ZN7Journal22_WriteTransactionToLogEv.localalias.9 + 0x8f4
 13 ffffffff814c5e10 (+  48) ffffffff818b9138   <bfs>
 _ZN7Journal9_FlushLogEbb.localalias.8 + 0x78
 14 ffffffff814c5e40 (+ 224) ffffffff8010b59a   <kernel_x86_64> _kern_sync
 + 0x11a
 }}}

 That is, the IORequest itself is the offset/length on top, but then by the
 time it gets to IOOperation::Prepare(), it is trying to copy more data
 than is actually in the request.

 It appears this is due to DMAResource::TranslateNext aligning the length
 to "alignment", which in the case of nvme_disk, is actually B_PAGE_SIZE;
 and then it does not trim this down to only the length of the IORequest
 length.
 It looks like #14881 has the same or similar cause.

 I spent some time reading IORequest::Prepare, and I think the issue is in
 the loop that CopyData() occurs in. The offset and length are checked only
 against the endOffset, which is the total end offset, not the IORequest
 end offset for this operation (i.e. fOriginalOffset+fOriginalLength.) I
 tried adding a naive bounds check like in Finish() for read (out)
 transfers:
 {{{
 @@ -469,12 +470,17 @@ IOOperation::Prepare(IORequest* request)
                                 vecOffset = 0;

                                 if (base >= bounceBufferStart && base <
 bounceBufferEnd) {
                                         if (offset + (off_t)length >
 endOffset)
                                                 length = endOffset -
 offset;
 +
 +                                       generic_size_t copyLength =
 length;
 +                                       if (offset + (off_t)copyLength >
 originalEndOffset)
 +                                               copyLength =
 originalEndOffset - offset;
 +
                                         status_t error =
 fParent->CopyData(offset,
 -                                               bounceBuffer + (base -
 bounceBufferStart), length);
 +                                               bounceBuffer + (base -
 bounceBufferStart), copyLength);
 }}}
 but this resulted in a second panic:


 {{{
 PANIC: vm_page_fault: unhandled page fault in kernel space at
 0xffffffff00000600, ip 0xffffffff8016e373

 Welcome to Kernel Debugging Land...
 Thread 373 "sync" running on CPU 0
 stack trace for thread 373 "sync"
     kernel stack: 0xffffffff815e9000 to 0xffffffff815ee000
       user stack: 0x00007fdb308cd000 to 0x00007fdb318cd000
 frame                       caller             <image>:function + offset
  0 ffffffff815ed278 (+  24) ffffffff8014e46c   <kernel_x86_64>
 arch_debug_call_with_fault_handler + 0x16
  1 ffffffff815ed290 (+  80) ffffffff800ad6d8   <kernel_x86_64>
 debug_call_with_fault_handler + 0x88
  2 ffffffff815ed2e0 (+  96) ffffffff800af061   <kernel_x86_64>
 kernel_debugger_loop(char const*, char const*, __va_list_tag*, int) + 0xf1
  3 ffffffff815ed340 (+  80) ffffffff800af35e   <kernel_x86_64>
 kernel_debugger_internal(char const*, char const*, __va_list_tag*, int) +
 0x6e
  4 ffffffff815ed390 (+ 240) ffffffff800af6c7   <kernel_x86_64> panic +
 0xb7
  5 ffffffff815ed480 (+ 240) ffffffff80138c80   <kernel_x86_64>
 vm_page_fault + 0x260
  6 ffffffff815ed570 (+  64) ffffffff80158e70   <kernel_x86_64>
 x86_page_fault_exception + 0x160
  7 ffffffff815ed5b0 (+ 536) ffffffff8014fd12   <kernel_x86_64> int_bottom
 + 0x56
 kernel iframe at 0xffffffff815ed7c8 (end = 0xffffffff815ed890)
  rax 0xffffffff8040be00    rbx 0xffffffff00000600    rcx
 0xcccccccccc00c6cc
  rdx 0xcccccccccc00c6cc    rsi 0xffffffff00000600    rdi
 0xffffffff8040be00
  rbp 0xffffffff815ed8b0     r8 0x1                    r9 0x0
  r10 0xffffffff823dc340    r11 0x1                   r12
 0xffffffff815edab0
  r13 0xffffffff8040be00    r14 0xfffffffffffffa00    r15
 0xffffffff860db190
  rip 0xffffffff8016e373    rsp 0xffffffff815ed890 rflags 0x13292
  vector: 0xe, error code: 0x0
  8 ffffffff815ed7c8 (+ 232) ffffffff8016e373   <kernel_x86_64> memcpy +
 0x23
  9 ffffffff815ed8b0 (+  16) ffffffff800d941d   <kernel_x86_64>
 IORequest::_CopySimple(void*, unsigned long, unsigned long, int, bool) +
 0x5d
 10 ffffffff815ed8c0 (+  96) ffffffff800db59b   <kernel_x86_64>
 IORequest::_CopyData(void*, long, unsigned long, bool) + 0xcb
 11 ffffffff815ed920 (+ 128) ffffffff800db995   <kernel_x86_64>
 IOOperation::Finish() + 0x235
 12 ffffffff815ed9a0 (+ 256) ffffffff81519613   <nvme_disk>
 nvme_disk_io(void*, IORequest*) + 0x1f3
 13 ffffffff815edaa0 (+ 352) ffffffff8151a261   <nvme_disk>
 nvme_disk_write(void*, long, void const*, unsigned long*) + 0x81
 14 ffffffff815edc00 (+ 112) ffffffff800f1c38   <kernel_x86_64>
 _kern_writev + 0x118
 15 ffffffff815edc70 (+  32) ffffffff8016b803   <kernel_x86_64> writev_pos
 + 0x13
 16 ffffffff815edc90 (+ 384) ffffffff818b8e54   <bfs>
 _ZN7Journal22_WriteTransactionToLogEv.localalias.9 + 0x8f4
 17 ffffffff815ede10 (+  48) ffffffff818b9138   <bfs>
 _ZN7Journal9_FlushLogEbb.localalias.8 + 0x78
 18 ffffffff815ede40 (+ 224) ffffffff8010b5ba   <kernel_x86_64> _kern_sync
 + 0x11a
 }}}
-- 
Ticket URL: <https://dev.haiku-os.org/ticket/15902>
Haiku <https://dev.haiku-os.org>
The Haiku operating system.

Other related posts: