#!/bin/sh

# (pass0:ahcich1:0:0:0): xpt_action_default: CCB type 0x380 0x380 not supported
# panic: _free(0): addr 0xfffff802f7e5a7b8 slab 0xffffffffffffffff with unknown cookie 3
# cpuid = 8
# time = 1773835096
# KDB: stack backtrace:
# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe00ffe5fc60
# vpanic() at vpanic+0x136/frame 0xfffffe00ffe5fd90
# panic() at panic+0x43/frame 0xfffffe00ffe5fdf0
# free() at free+0x213/frame 0xfffffe00ffe5fe30
# xpt_release_ccb() at xpt_release_ccb+0x50/frame 0xfffffe00ffe5fe60
# xpt_done_process() at xpt_done_process+0x3e0/frame 0xfffffe00ffe5fea0
# xpt_done_td() at xpt_done_td+0x145/frame 0xfffffe00ffe5fef0
# fork_exit() at fork_exit+0x82/frame 0xfffffe00ffe5ff30
# fork_trampoline() at fork_trampoline+0xe/frame 0xfffffe00ffe5ff30
# --- trap 0, rip = 0, rsp = 0, rbp = 0 ---
# KDB: enter: panic
# [ thread pid 4 tid 100122 ]
# 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 293893] panic: _free(NUM): address ADDR(ADDR) has not been allocated

[ `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;
  //  sendfile arguments: [
  //    fd: fd (resource)
  //    s: sock_in (resource)
  //    offset: intptr = 0x4 (8 bytes)
  //    nbytes: int64 = 0x4 (8 bytes)
  //    hdtr: ptr[in, sf_hdtr] {
  //      sf_hdtr {
  //        headers: ptr[in, array[iovec_in]] {
  //          array[iovec_in] {
  //            iovec_in {
  //              addr: nil
  //              len: len = 0x0 (8 bytes)
  //            }
  //            iovec_in {
  //              addr: ptr[in, buffer] {
  //                buffer: {} (length 0x0)
  //              }
  //              len: len = 0x0 (8 bytes)
  //            }
  //          }
  //        }
  //        hdr_cnt: len = 0x2 (4 bytes)
  //        pad = 0x0 (4 bytes)
  //        trailers: nil
  //        trl_cnt: len = 0x0 (4 bytes)
  //        pad = 0x0 (4 bytes)
  //      }
  //    }
  //    sbytes: nil
  //    flags: sf_flags = 0x1 (8 bytes)
  //  ]
  *(uint64_t*)0x200000001ac0 = 0x200000000280;
  *(uint64_t*)0x200000000280 = 0;
  *(uint64_t*)0x200000000288 = 0;
  *(uint64_t*)0x200000000290 = 0x200000000380;
  *(uint64_t*)0x200000000298 = 0;
  *(uint32_t*)0x200000001ac8 = 2;
  *(uint64_t*)0x200000001ad0 = 0;
  *(uint32_t*)0x200000001ad8 = 0;
  syscall(SYS_sendfile, /*fd=*/(intptr_t)-1, /*s=*/(intptr_t)-1, /*offset=*/4ul,
          /*nbytes=*/4ul, /*hdtr=*/0x200000001ac0ul, /*sbytes=*/0ul,
          /*flags=SF_NODISKIO*/ 1ul);
  //  ioctl\$CAMIOQUEUE_pass_cdevsw arguments: [
  //    fd: fd_pass_pass_cdevsw (resource)
  //    cmd: const = 0x20001a04 (8 bytes)
  //    arg: ptr[in, ptr[in, ccb\$pass_cdevsw]] {
  //      nil
  //    }
  //  ]
  *(uint64_t*)0x200000000240 = 0;
  syscall(SYS_ioctl, /*fd=*/r[0], /*cmd=*/0x20001a04ul,
          /*arg=*/0x200000000240ul);
  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
