#!/bin/sh

# panic: cam_periph_ccbwait: proceeding with incomplete ccb: ccb=0xfffff80006171800, func_code=0x3, status=0, index=-1
# cpuid = 3
# time = 1773850497
# KDB: stack backtrace:
# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe01001de7e0
# vpanic() at vpanic+0x136/frame 0xfffffe01001de910
# panic() at panic+0x43/frame 0xfffffe01001de970
# cam_periph_runccb() at cam_periph_runccb+0x2ec/frame 0xfffffe01001deac0
# passsendccb() at passsendccb+0x160/frame 0xfffffe01001deb30
# passdoioctl() at passdoioctl+0x3a1/frame 0xfffffe01001deb80
# passioctl() at passioctl+0x22/frame 0xfffffe01001debc0
# devfs_ioctl() at devfs_ioctl+0xd1/frame 0xfffffe01001dec10
# VOP_IOCTL_APV() at VOP_IOCTL_APV+0x51/frame 0xfffffe01001dec40
# vn_ioctl() at vn_ioctl+0x160/frame 0xfffffe01001decb0
# devfs_ioctl_f() at devfs_ioctl_f+0x1e/frame 0xfffffe01001decd0
# kern_ioctl() at kern_ioctl+0x2a1/frame 0xfffffe01001ded40
# sys_ioctl() at sys_ioctl+0x12f/frame 0xfffffe01001dee00
# amd64_syscall() at amd64_syscall+0x169/frame 0xfffffe01001def30
# fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe01001def30
# --- syscall (0, FreeBSD ELF64, syscall), rip = 0x823b1eeca, rsp = 0x820adb1c8, rbp = 0x820adb1f0 ---
# KDB: enter: panic
# [ thread pid 4950 tid 100344 ]
# Stopped at      kdb_enter+0x33: movq    $0,0x15e9d32(%rip)
# db> x/s version
# version: FreeBSD 16.0-CURRENT #0 main-n284537-a8b9a05d3cad-dirty: Tue Mar 17 09:39:44 CET 2026
# pho@mercat1.netperf.freebsd.org:/usr/src/sys/amd64/compile/PHO
# db>

# Reproducer obtained from: Jiaming Zhang <r772577952@gmail.com>
# Bug 293899 - panic: cam_periph_ccbwait: proceeding with incomplete ccb: ccb=ADDR, func_code=0x3, status=NUM, index=-NUM 

[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1

. ../default.cfg
set -u
prog=$(basename "$0" .sh)
cat > /tmp/$prog.c <<EOF
// autogenerated by syzkaller (https://github.com/google/syzkaller)

#define _GNU_SOURCE

#include <pwd.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/endian.h>
#include <sys/syscall.h>
#include <unistd.h>

uint64_t r[1] = {0xffffffffffffffff};

int main(void)
{
  syscall(SYS_mmap, /*addr=*/0x200000000000ul, /*len=*/0x1000000ul,
          /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/ 7ul,
          /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x1012ul,
          /*fd=*/(intptr_t)-1, /*offset=*/0ul);
  const char* reason;
  (void)reason;
  intptr_t res = 0;
  if (write(1, "executing program\n", sizeof("executing program\n") - 1)) {
  }
  //  openat\$pass_pass_cdevsw arguments: [
  //    fd: const = 0xffffffffffffff9c (8 bytes)
  //    file: ptr[in, buffer] {
  //      buffer: {2f 64 65 76 2f 70 61 73 73 30 00} (length 0xb)
  //    }
  //    flags: open_flags = 0x2 (4 bytes)
  //    mode: const = 0x0 (4 bytes)
  //  ]
  //  returns fd_pass_pass_cdevsw
  memcpy((void*)0x200000000100, "/dev/pass0\000", 11);
  res = syscall(SYS_openat, /*fd=*/0xffffffffffffff9cul,
                /*file=*/0x200000000100ul, /*flags=O_RDWR*/ 2, /*mode=*/0);
  if (res != -1)
    r[0] = res;
  //  ioctl\$CAMIOCOMMAND_pass_cdevsw arguments: [
  //    fd: fd_pass_pass_cdevsw (resource)
  //    cmd: const = 0xc4e01a02 (8 bytes)
  //    arg: ptr[inout, ccb\$pass_cdevsw] {
  //      union ccb\$pass_cdevsw {
  //        cqc: ccb_query_config\$pass_cdevsw {
  //          ccb_h: ccb_hdr\$pass_cdevsw {
  //            pinfo: cam_pinfo\$pass_cdevsw {
  //              priority: int32 = 0x7 (4 bytes)
  //              generation: int32 = 0x8 (4 bytes)
  //              index: int32 = 0x4 (4 bytes)
  //            }
  //            pad = 0x0 (4 bytes)
  //            xpt_links: camq_entry\$pass_cdevsw {
  //              links_next: intptr = 0xfffffffffffffffe (8 bytes)
  //              priority: int32 = 0xd (4 bytes)
  //              pad = 0x0 (4 bytes)
  //            }
  //            sim_links: camq_entry\$pass_cdevsw {
  //              links_next: intptr = 0x1000 (8 bytes)
  //              priority: int32 = 0x7fff (4 bytes)
  //              pad = 0x0 (4 bytes)
  //            }
  //            periph_links: camq_entry\$pass_cdevsw {
  //              links_next: intptr = 0x100000001 (8 bytes)
  //              priority: int32 = 0x3 (4 bytes)
  //              pad = 0x0 (4 bytes)
  //            }
  //            retry_count: int16 = 0x8 (2 bytes)
  //            alloc_flags: int16 = 0x84ce (2 bytes)
  //            pad = 0x0 (4 bytes)
  //            cbfcnp: intptr = 0xffffffff (8 bytes)
  //            func_code: int32 = 0x3 (4 bytes)
  //            status: int32 = 0x6 (4 bytes)
  //            path: intptr = 0x8000000000000001 (8 bytes)
  //            path_id: int32 = 0x3 (4 bytes)
  //            target_id: int32 = 0x800 (4 bytes)
  //            target_lun: int64 = 0x12 (8 bytes)
  //            flags: int32 = 0x5 (4 bytes)
  //            xflags: int32 = 0x8 (4 bytes)
  //            periph_priv: buffer: {ff 00 fc 8b be 26 59 c1 e3 be e5 97 9a b9
  //            a8 da} (length 0x10) sim_priv: buffer: {bc 62 8a da 83 8f 2b 49
  //            f1 67 50 3f 43 71 98 c8} (length 0x10) qos: buffer: {5e 98 6e af
  //            a2 b9 ac 4a 3a d1 ed 97 4e f6 f6 e2} (length 0x10) timeout:
  //            int32 = 0x8 (4 bytes) pad = 0x0 (4 bytes) softtimeout: timeval {
  //              sec: intptr = 0x4 (8 bytes)
  //              usec: intptr = 0x1 (8 bytes)
  //            }
  //          }
  //          payload: buffer: {ac f7 a5 7c b5 71 08 e5 db bd f4 df d0 16 4a 33
  //          68 b1 76 63 b8 c0 6b b7 31 4e 7d 97 28 be ee e6 5b 35 e8 8a cf a8
  //          49 62 11 9b 25 b5 fc 67 8f ef a1 44 b2 e5 a7 9b 5a 06 34 ae a0 56
  //          fe 95 69 61 27 4a ba aa 92 e2 b9 ea 97 e6 1c cf 24 6b 8e 8f f7 b7
  //          c8 3a cf b7 97 c8 32 12 f1 4d bc 0b 8b ef 30 11 62 5d f1 0f af c2
  //          67 76 65 be 11 2e 10 5f 65 70 58 e2 3b c2 91 99 3b 2e 00 00 00 00
  //          00 00} (length 0x80)
  //        }
  //      }
  //    }
  //  ]
  *(uint32_t*)0x200000000ec0 = 7;
  *(uint32_t*)0x200000000ec4 = 8;
  *(uint32_t*)0x200000000ec8 = 4;
  *(uint64_t*)0x200000000ed0 = 0xfffffffffffffffe;
  *(uint32_t*)0x200000000ed8 = 0xd;
  *(uint64_t*)0x200000000ee0 = 0x1000;
  *(uint32_t*)0x200000000ee8 = 0x7fff;
  *(uint64_t*)0x200000000ef0 = 0x100000001;
  *(uint32_t*)0x200000000ef8 = 3;
  *(uint16_t*)0x200000000f00 = 8;
  *(uint16_t*)0x200000000f02 = 0x84ce;
  *(uint64_t*)0x200000000f08 = 0xffffffff;
  *(uint32_t*)0x200000000f10 = 3;
  *(uint32_t*)0x200000000f14 = 6;
  *(uint64_t*)0x200000000f18 = 0x8000000000000001;
  *(uint32_t*)0x200000000f20 = 3;
  *(uint32_t*)0x200000000f24 = 0x800;
  *(uint64_t*)0x200000000f28 = 0x12;
  *(uint32_t*)0x200000000f30 = 5;
  *(uint32_t*)0x200000000f34 = 8;
  memcpy((void*)0x200000000f38,
         "\xff\x00\xfc\x8b\xbe\x26\x59\xc1\xe3\xbe\xe5\x97\x9a\xb9\xa8\xda",
         16);
  memcpy((void*)0x200000000f48,
         "\xbc\x62\x8a\xda\x83\x8f\x2b\x49\xf1\x67\x50\x3f\x43\x71\x98\xc8",
         16);
  memcpy((void*)0x200000000f58,
         "\x5e\x98\x6e\xaf\xa2\xb9\xac\x4a\x3a\xd1\xed\x97\x4e\xf6\xf6\xe2",
         16);
  *(uint32_t*)0x200000000f68 = 8;
  *(uint64_t*)0x200000000f70 = 4;
  *(uint64_t*)0x200000000f78 = 1;
  memcpy((void*)0x200000000f80,
         "\xac\xf7\xa5\x7c\xb5\x71\x08\xe5\xdb\xbd\xf4\xdf\xd0\x16\x4a\x33\x68"
         "\xb1\x76\x63\xb8\xc0\x6b\xb7\x31\x4e\x7d\x97\x28\xbe\xee\xe6\x5b\x35"
         "\xe8\x8a\xcf\xa8\x49\x62\x11\x9b\x25\xb5\xfc\x67\x8f\xef\xa1\x44\xb2"
         "\xe5\xa7\x9b\x5a\x06\x34\xae\xa0\x56\xfe\x95\x69\x61\x27\x4a\xba\xaa"
         "\x92\xe2\xb9\xea\x97\xe6\x1c\xcf\x24\x6b\x8e\x8f\xf7\xb7\xc8\x3a\xcf"
         "\xb7\x97\xc8\x32\x12\xf1\x4d\xbc\x0b\x8b\xef\x30\x11\x62\x5d\xf1\x0f"
         "\xaf\xc2\x67\x76\x65\xbe\x11\x2e\x10\x5f\x65\x70\x58\xe2\x3b\xc2\x91"
         "\x99\x3b\x2e\x00\x00\x00\x00\x00\x00",
         128);
  syscall(SYS_ioctl, /*fd=*/r[0], /*cmd=*/0xc4e01a02ul,
          /*arg=*/0x200000000ec0ul);
  return 0;
}
EOF
mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c || exit 1

timeout 3m /tmp/$prog > /dev/null 2>&1

rm -rf /tmp/$prog /tmp/$prog.c /tmp/$prog.core
exit 0
