[Bug 259280] vtblk_maximum_segments can set nsegs too low, allowing panic on some non-aligned raw disk reads

From: <bugzilla-noreply_at_freebsd.org>
Date: Tue, 19 Oct 2021 17:32:56 UTC

            Bug ID: 259280
           Summary: vtblk_maximum_segments can set nsegs too low, allowing
                    panic on some non-aligned raw disk reads
           Product: Base System
           Version: CURRENT
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Only Me
          Priority: ---
         Component: kern
          Assignee: bugs@FreeBSD.org
          Reporter: rtm@lcs.mit.edu

The virtio block device code's vtblk_maximum_segments() sets
nsegs to 3 if the device doesn't have VIRTIO_BLK_F_SEG_MAX
set. However, a 4096-byte read() to a non-page-aligned memory
address can then panic in vtblk_request_execute() due to
using up all the segments, in this code:

    if (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE) {
        error = sglist_append_bio(sg, bp);
        if (error || sg->sg_nseg == sg->sg_maxseg) {            
            panic("%s: bio %p data buffer too big %d",
                __func__, bp, error);

sg_nseg and sg_maxseg both end up as three, triggering
the panic.

I actually got this panic, on the tinyemu RISC-V simulator,
running e2fsck on a broken ext2 file system. Here's a
program that panics on tinyemu (but not qemu, which sets

int main() {
  int fd = open("/dev/vtbd0", 0);
  char buf1[4*4096];
  char *buf = buf1;
  while(((unsigned long)buf) % 4096) buf++;
  read(fd, buf + 0xd00, 4096);

panic: vtblk_request_execute: bio 0xffffffd0019ded38 data buffer too big 0
cpuid = 0
time = 1634664503
KDB: stack backtrace:
db_trace_self() at db_trace_self
db_trace_self_wrapper() at db_trace_self_wrapper+0x38
kdb_backtrace() at kdb_backtrace+0x2c
vpanic() at vpanic+0x148
panic() at panic+0x2a
vtblk_request_execute() at vtblk_request_execute+0x23a
vtblk_startio() at vtblk_startio+0x198
vtblk_strategy() at vtblk_strategy+0x66
g_disk_start() at g_disk_start+0x2b0
g_io_schedule_down() at g_io_schedule_down+0x32a
g_down_procbody() at g_down_procbody+0x58
fork_exit() at fork_exit+0x68
fork_trampoline() at fork_trampoline+0xa
KDB: enter: panic
[ thread pid 13 tid 100019 ]

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