Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ZFS crashes when reading from a block pointer with no valid DVAs #17077

Open
asomers opened this issue Feb 20, 2025 · 2 comments
Open

ZFS crashes when reading from a block pointer with no valid DVAs #17077

asomers opened this issue Feb 20, 2025 · 2 comments
Labels
Type: Defect Incorrect behavior (e.g. crash, hang)

Comments

@asomers
Copy link
Contributor

asomers commented Feb 20, 2025

System information

Type Version/Name
Distribution Name FreeBSD
Distribution Version 14.1-RELEASE and 15.0-CURRENT
Kernel Version custom builds based on 14.1-RELEASE and 15.0-CURRENT as of 0ebd9cf85d3627e50e6a7330b67719fce4d1a5fe
Architecture amd64
OpenZFS Version zfs-2.3.99-170-FreeBSD_g34205715e zfs-kmod-2.3.99-170-FreeBSD_g34205715e

Describe the problem you're observing

Somehow ZFS wrote a block pointer to an L0 block in such a way that the only DVA has an asize of 0. Yet the block pointer is neither embedded nor a hole. As far as I understand, that should be impossible. Yet it happened. Now ZFS crashes whenever it tries to read that block. And zdb crashes whenever it tries to display the block pointer.

Describe how to reproduce the problem

Now that the block pointer is corrupt on disk, the problem can be easily reproduced simply by trying to read the corrupt block with dd. It is 100% reproducible. But I have no idea how to reproduce the corruption in the first place.

The zdb crash can be reproduced with a command like zdb -vv -bbbb -O <DATASET> -U <CACHEFILE> <PATH/TO/FILE>

Include any warning/errors/backtraces from the system logs

The precise stack trace depends on whether INVARIANTS are enabled. If they are not, then the crash looks like this, in FreeBSD 14.1-RELEASE:

[733] Fatal trap 12: page fault while in kernel mode
[733] cpuid = 28; apic id = 98
[733] fault virtual address     = 0x39c0
[733] fault code                = supervisor write data, page not present
[733] instruction pointer       = 0x20:0xffffffff8244d455
[733] stack pointer             = 0x28:0xfffffe0fb183e570
[733] frame pointer             = 0x28:0xfffffe0fb183e5a0
[733] code segment              = base 0x0, limit 0xfffff, type 0x1b
[733]                   = DPL 0, pres 1, long 1, def32 0, gran 1
[733] processor eflags  = interrupt enabled, resume, IOPL = 0
[733] current process           = 3975 (cloudserver)
[733] rdi: 0000000000000000 rsi: 00000000fffffffb rdx: 03677c34f00b2a94
[733] rcx: ffffffff824d2c4c  r8: 0000000000000007  r9: 8abf927b6bcd6347
[733] rax: 0000000000000001 rbx: fffffe0fd8eb6c80 rbp: fffffe0fb183e5a0
[733] r10: 0000000000000007 r11: 062b0d8759af84e3 r12: 0000000000000000
[733] r13: fffffe0fb183e804 r14: fffffe0fb183e578 r15: fffff80b501e4000
[733] trap number               = 12
[733] panic: page fault
[733] cpuid = 28
[733] time = 1734312912
[733] KDB: stack backtrace:
[733] db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe0fb183e260
[733] vpanic() at vpanic+0x131/frame 0xfffffe0fb183e390
[733] panic() at panic+0x43/frame 0xfffffe0fb183e3f0
[733] trap_fatal() at trap_fatal+0x40b/frame 0xfffffe0fb183e450
[733] trap_pfault() at trap_pfault+0x46/frame 0xfffffe0fb183e4a0
[733] calltrap() at calltrap+0x8/frame 0xfffffe0fb183e4a0
[733] --- trap 0xc, rip = 0xffffffff8244d455, rsp = 0xfffffe0fb183e570, rbp = 0xfffffe0fb183e5a0 ---
[733] zio_checksum_verify() at zio_checksum_verify+0x75/frame 0xfffffe0fb183e5a0
[733] zio_execute() at zio_execute+0x38/frame 0xfffffe0fb183e5d0
[733] zio_vdev_io_start() at zio_vdev_io_start+0x203/frame 0xfffffe0fb183e620
[733] zio_nowait() at zio_nowait+0x98/frame 0xfffffe0fb183e660
[733] arc_read() at arc_read+0xfd0/frame 0xfffffe0fb183e720
[733] dbuf_read() at dbuf_read+0x9db/frame 0xfffffe0fb183e860
[733] dmu_buf_hold_array_by_dnode() at dmu_buf_hold_array_by_dnode+0x1ef/frame 0xfffffe0fb183e920
[733] dmu_read_uio_dnode() at dmu_read_uio_dnode+0x3a/frame 0xfffffe0fb183e990
[733] dmu_read_uio_dbuf() at dmu_read_uio_dbuf+0x3e/frame 0xfffffe0fb183e9c0
[733] zfs_read() at zfs_read+0x1da/frame 0xfffffe0fb183ea20
[733] zfs_freebsd_read() at zfs_freebsd_read+0x39/frame 0xfffffe0fb183ea40
[733] VOP_READ_APV() at VOP_READ_APV+0x20/frame 0xfffffe0fb183ea60
[733] vn_read() at vn_read+0x1ec/frame 0xfffffe0fb183eae0
[733] vn_io_fault_doio() at vn_io_fault_doio+0x45/frame 0xfffffe0fb183eb40
[733] vn_io_fault1() at vn_io_fault1+0x167/frame 0xfffffe0fb183ec90
[733] vn_io_fault() at vn_io_fault+0x151/frame 0xfffffe0fb183ed20
[733] dofileread() at dofileread+0x80/frame 0xfffffe0fb183ed70
[733] kern_preadv() at kern_preadv+0x61/frame 0xfffffe0fb183edb0
[733] sys_pread() at sys_pread+0x84/frame 0xfffffe0fb183ee00
[733] amd64_syscall() at amd64_syscall+0x67b/frame 0xfffffe0fb183ef30
[733] fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe0fb183ef30
[733] --- syscall (475, FreeBSD ELF64, pread), rip = 0x83e4ea, rsp = 0x8e36094b8, rbp = 0x8e3609520 ---
[733] KDB: enter: panic

However, if INVARIANTS are enabled, the crash happens sooner. This is what it looks like on 15.0-CURRENT with INVARIANTS.

[376] panic: VERIFY(zio->io_error != 0) failed
[376] 
[376] cpuid = 8
[376] time = 1739981736
[376] KDB: stack backtrace:
[376] db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe04f9577350
[376] vpanic() at vpanic+0x13f/frame 0xfffffe04f9577480
[376] spl_panic() at spl_panic+0x3a/frame 0xfffffe04f95774e0
[376] zio_vdev_io_done() at zio_vdev_io_done+0x1d9/frame 0xfffffe04f9577520
[376] zio_execute() at zio_execute+0x78/frame 0xfffffe04f9577550
[376] zio_vdev_io_start() at zio_vdev_io_start+0x49e/frame 0xfffffe04f95775a0
[376] zio_nowait() at zio_nowait+0x10c/frame 0xfffffe04f95775e0
[376] arc_read() at arc_read+0x1206/frame 0xfffffe04f9577690
[376] dbuf_issue_final_prefetch() at dbuf_issue_final_prefetch+0x108/frame 0xfffffe04f95776f0
[376] dbuf_prefetch_impl() at dbuf_prefetch_impl+0x4d4/frame 0xfffffe04f9577810
[376] dmu_zfetch_run() at dmu_zfetch_run+0x1d1/frame 0xfffffe04f9577880
[376] dmu_buf_hold_array_by_dnode() at dmu_buf_hold_array_by_dnode+0x2e7/frame 0xfffffe04f9577940
[376] dmu_read_uio_dnode() at dmu_read_uio_dnode+0x47/frame 0xfffffe04f95779c0
[376] zfs_read() at zfs_read+0x2d5/frame 0xfffffe04f9577a40
[376] zfs_freebsd_read() at zfs_freebsd_read+0x7b/frame 0xfffffe04f9577a80
[376] VOP_READ_APV() at VOP_READ_APV+0x32/frame 0xfffffe04f9577aa0
[376] vn_read() at vn_read+0x20e/frame 0xfffffe04f9577b10
[376] vn_io_fault_doio() at vn_io_fault_doio+0x45/frame 0xfffffe04f9577b70
[376] vn_io_fault1() at vn_io_fault1+0x15e/frame 0xfffffe04f9577cb0
[376] vn_io_fault() at vn_io_fault+0x150/frame 0xfffffe04f9577d40
[376] dofileread() at dofileread+0x80/frame 0xfffffe04f9577d90
[376] sys_read() at sys_read+0xb7/frame 0xfffffe04f9577e00
[376] amd64_syscall() at amd64_syscall+0x424/frame 0xfffffe04f9577f30
[376] fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe04f9577f30
[376] --- syscall (3, FreeBSD ELF64, read), rip = 0x8979f4dd56a, rsp = 0x8979c40a488, rbp = 0x8979c40a4f0 ---
[376] KDB: enter: panic

The zdb crash looks like this:

#0  0x0000000801ba210a in thr_kill () from /tmp/be_mount.BHwF/lib/libc.so.7
#1  0x0000000801b1b404 in raise () from /tmp/be_mount.BHwF/lib/libc.so.7
#2  0x0000000801bce9d9 in abort () from /tmp/be_mount.BHwF/lib/libc.so.7
#3  0x000000080112511f in libspl_assertf () from /tmp/be_mount.BHwF/lib/libspl.so.2
#4  0x00000008013585e0 in snprintf_blkptr () from /tmp/be_mount.BHwF/lib/libzpool.so.2
#5  0x00000000010402a6 in snprintf_blkptr_compact (
    blkbuf=0x7fffffedbba0 "DVA[0]=<24:1d2c06600000:c000> [L0 ZFS plain file] fletcher4 zstd unencrypted LE contiguous unique single size=10000L/6000P birth=38944176L/38944176P fill=1 cksum=00000a318f71fae4:0085ab33e8c4c611:445c"..., 
    buflen=400, bp=0x94c1dcf80, bp_freed=B_FALSE) at /usr/src/sys/contrib/openzfs/cmd/zdb/zdb.c:2430
#6  0x0000000001043159 in print_indirect (spa=0x802c74800, bp=0x7fffffedbba0, zb=0x94c1dcf80, dnp=0x964515000) at /usr/src/sys/contrib/openzfs/cmd/zdb/zdb.c:2509
#7  visit_indirect (spa=spa@entry=0x802c74800, dnp=dnp@entry=0x964515000, bp=0x7fffffedbba0, bp@entry=0x102fdce, zb=0x94c1dcf80, zb@entry=0x7fffffedbda0) at /usr/src/sys/contrib/openzfs/cmd/zdb/zdb.c:2524
#8  0x000000000104363f in visit_indirect (spa=spa@entry=0x802c74800, dnp=dnp@entry=0x964515000, bp=0x94c1a5480, bp@entry=0x102fdce, zb=0x94c1dcf80, zb@entry=0x7fffffedbfa0) at /usr/src/sys/contrib/openzfs/cmd/zdb/zdb.c:2549
#9  0x000000000104363f in visit_indirect (spa=spa@entry=0x802c74800, dnp=dnp@entry=0x964515000, bp=0x94c17c000, bp@entry=0x102fdce, zb=0x94c1dcf80, zb@entry=0x7fffffedc1a0) at /usr/src/sys/contrib/openzfs/cmd/zdb/zdb.c:2549
#10 0x000000000104363f in visit_indirect (spa=0x802c74800, dnp=0x964515000, dnp@entry=0x7fffffedbba0, bp=0x964515040, bp@entry=0x94c1dcf80, zb=0x94c1dcf80, zb@entry=0x0) at /usr/src/sys/contrib/openzfs/cmd/zdb/zdb.c:2549
#11 0x000000000103ff62 in dump_indirect (dn=0x190) at /usr/src/sys/contrib/openzfs/cmd/zdb/zdb.c:2574
#12 dump_object (os=0x82c1ce800, os@entry=0x94c1dcf80, object=<optimized out>, verbosity=5, print_header=print_header@entry=0x7fffffedc71c, dnode_slots_used=dnode_slots_used@entry=0x0, flags=flags@entry=0)
    at /usr/src/sys/contrib/openzfs/cmd/zdb/zdb.c:3828
#13 0x000000000103f586 in dump_path_impl (os=0x94c1dcf80, obj=0, 
    name=0x7fffffedbba0 "DVA[0]=<24:1d2c06600000:c000> [L0 ZFS plain file] fletcher4 zstd unencrypted LE contiguous unique single size=10000L/6000P birth=38944176L/38944176P fill=1 cksum=00000a318f71fae4:0085ab33e8c4c611:445c"..., 
    name@entry=0x94c1dcf80 "", retobj=0x0, retobj@entry=0x7fffffedbba0) at /usr/src/sys/contrib/openzfs/cmd/zdb/zdb.c:4926
#14 0x0000000001038f93 in dump_path (ds=0x0, path=0x94c1dcf80 "", retobj=0x7fffffedbba0, retobj@entry=0x0) at /usr/src/sys/contrib/openzfs/cmd/zdb/zdb.c:4963
#15 0x000000000103662f in main (argc=2, argv=0x102fdce) at /usr/src/sys/contrib/openzfs/cmd/zdb/zdb.c:9297
@asomers asomers added the Type: Defect Incorrect behavior (e.g. crash, hang) label Feb 20, 2025
@amotin
Copy link
Member

amotin commented Feb 20, 2025

If we assume zero asize is illegal (it is definitely weird), then we could check for it in zfs_blkptr_verify() to prevent the panic.

@asomers
Copy link
Contributor Author

asomers commented Feb 20, 2025

If we assume zero asize is illegal (it is definitely weird), then we could check for it in zfs_blkptr_verify() to prevent the panic.

Yes, I have a patch that does exactly that, and I'll open a PR soon.

asomers added a commit to asomers/zfs that referenced this issue Feb 20, 2025
If a block pointer isn't embedded yet doesn't have any valid DVAs, that's
a data corruption bug.  zdb should be able to handle the situation
gracefully.

Issue openzfs#17077
Sponsored by:	ConnectWise
Signed-off-by:	Alan Somers <[email protected]>
asomers added a commit to asomers/zfs that referenced this issue Feb 20, 2025
If a block pointer isn't embedded yet doesn't have any valid DVAs, that's
a data corruption bug.  zdb should be able to handle the situation
gracefully.

Issue		openzfs#17077
Sponsored by:	ConnectWise
Signed-off-by:	Alan Somers <[email protected]>
asomers added a commit to asomers/zfs that referenced this issue Feb 20, 2025
Now instead of crashing when attempting to read the corrupt block
pointer, ZFS will return ECKSUM, in a stack that looks like this:

```
none:set-error
zfs.ko`arc_read+0x1d82
zfs.ko`dbuf_read+0xa8c
zfs.ko`dmu_buf_hold_array_by_dnode+0x292
zfs.ko`dmu_read_uio_dnode+0x47
zfs.ko`zfs_read+0x2d5
zfs.ko`zfs_freebsd_read+0x7b
kernel`VOP_READ_APV+0xd0
kernel`vn_read+0x20e
kernel`vn_io_fault_doio+0x45
kernel`vn_io_fault1+0x15e
kernel`vn_io_fault+0x150
kernel`dofileread+0x80
kernel`sys_read+0xb7
kernel`amd64_syscall+0x424
kernel`0xffffffff810633cb
```

This patch should hopefully also prevent such corrupt block pointers
from being written to disk in the first place.

Fixes		openzfs#17077
Sponsored by:	ConnectWise
Signed-off-by:	Alan Somers <[email protected]>
asomers added a commit to asomers/zfs that referenced this issue Feb 20, 2025
If a block pointer isn't embedded yet doesn't have any valid DVAs, that's
a data corruption bug.  zdb should be able to handle the situation
gracefully.

Issue		openzfs#17077
Sponsored by:	ConnectWise
Signed-off-by:	Alan Somers <[email protected]>
asomers added a commit to asomers/zfs that referenced this issue Feb 20, 2025
Now instead of crashing when attempting to read the corrupt block
pointer, ZFS will return ECKSUM, in a stack that looks like this:

```
none:set-error
zfs.ko`arc_read+0x1d82
zfs.ko`dbuf_read+0xa8c
zfs.ko`dmu_buf_hold_array_by_dnode+0x292
zfs.ko`dmu_read_uio_dnode+0x47
zfs.ko`zfs_read+0x2d5
zfs.ko`zfs_freebsd_read+0x7b
kernel`VOP_READ_APV+0xd0
kernel`vn_read+0x20e
kernel`vn_io_fault_doio+0x45
kernel`vn_io_fault1+0x15e
kernel`vn_io_fault+0x150
kernel`dofileread+0x80
kernel`sys_read+0xb7
kernel`amd64_syscall+0x424
kernel`0xffffffff810633cb
```

This patch should hopefully also prevent such corrupt block pointers
from being written to disk in the first place.

Fixes		openzfs#17077
Sponsored by:	ConnectWise
Signed-off-by:	Alan Somers <[email protected]>
asomers added a commit to asomers/zfs that referenced this issue Feb 20, 2025
Now instead of crashing when attempting to read the corrupt block
pointer, ZFS will return ECKSUM, in a stack that looks like this:

```
none:set-error
zfs.ko`arc_read+0x1d82
zfs.ko`dbuf_read+0xa8c
zfs.ko`dmu_buf_hold_array_by_dnode+0x292
zfs.ko`dmu_read_uio_dnode+0x47
zfs.ko`zfs_read+0x2d5
zfs.ko`zfs_freebsd_read+0x7b
kernel`VOP_READ_APV+0xd0
kernel`vn_read+0x20e
kernel`vn_io_fault_doio+0x45
kernel`vn_io_fault1+0x15e
kernel`vn_io_fault+0x150
kernel`dofileread+0x80
kernel`sys_read+0xb7
kernel`amd64_syscall+0x424
kernel`0xffffffff810633cb
```

This patch should hopefully also prevent such corrupt block pointers
from being written to disk in the first place.

Fixes		openzfs#17077
Sponsored by:	ConnectWise
Signed-off-by:	Alan Somers <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Defect Incorrect behavior (e.g. crash, hang)
Projects
None yet
Development

No branches or pull requests

2 participants