#!/bin/sh

# Reproducer obtained from: Jiaming Zhang <r772577952@gmail.com>
# Bug 293898 - panic: AUX register unsupported

# No problems seen.

[ `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 {
  //        cqa: ccb_que_ais\$pass_cdevsw {
  //          ccb_h: ccb_hdr\$pass_cdevsw {
  //            pinfo: cam_pinfo\$pass_cdevsw {
  //              priority: int32 = 0x0 (4 bytes)
  //              generation: int32 = 0x3 (4 bytes)
  //              index: int32 = 0x2000000 (4 bytes)
  //            }
  //            pad = 0x0 (4 bytes)
  //            xpt_links: camq_entry\$pass_cdevsw {
  //              links_next: intptr = 0xfea (8 bytes)
  //              priority: int32 = 0xfffffffb (4 bytes)
  //              pad = 0x0 (4 bytes)
  //            }
  //            sim_links: camq_entry\$pass_cdevsw {
  //              links_next: intptr = 0x2 (8 bytes)
  //              priority: int32 = 0x6 (4 bytes)
  //              pad = 0x0 (4 bytes)
  //            }
  //            periph_links: camq_entry\$pass_cdevsw {
  //              links_next: intptr = 0x83 (8 bytes)
  //              priority: int32 = 0xd (4 bytes)
  //              pad = 0x0 (4 bytes)
  //            }
  //            retry_count: int16 = 0x1 (2 bytes)
  //            alloc_flags: int16 = 0x6b4 (2 bytes)
  //            pad = 0x0 (4 bytes)
  //            cbfcnp: intptr = 0x0 (8 bytes)
  //            func_code: int32 = 0x918 (4 bytes)
  //            status: int32 = 0x4 (4 bytes)
  //            path: intptr = 0xfffffffffffffffc (8 bytes)
  //            path_id: int32 = 0x9 (4 bytes)
  //            target_id: int32 = 0x8 (4 bytes)
  //            target_lun: int64 = 0x7d44 (8 bytes)
  //            flags: int32 = 0x1 (4 bytes)
  //            xflags: int32 = 0xfffffff8 (4 bytes)
  //            periph_priv: buffer: {69 32 82 68 e7 3f ef 85 2d 76 56 88 e5 d9
  //            10 17} (length 0x10) sim_priv: buffer: {00 00 00 00 00 00 00 00
  //            00 00 00 00 00 00 80 00} (length 0x10) qos: buffer: {f6 7d 0f 00
  //            10 00 00 00 00 32 e5 67 b7 bc 75 2d} (length 0x10) timeout:
  //            int32 = 0xffffffff (4 bytes) pad = 0x0 (4 bytes) softtimeout:
  //            timeval {
  //              sec: intptr = 0x5 (8 bytes)
  //              usec: intptr = 0x4 (8 bytes)
  //            }
  //          }
  //          payload: buffer: {f5 6a 42 5c 52 f4 74 e3 39 a5 05 00 00 00 ce 58
  //          c0 19 28 cb 06 ee d4 11 85 f4 29 8a 46 09 8a 1d be bf 87 fb 73 a4
  //          9e 3f 64 4f f0 18 b6 64 8f ab 00 00 00 00 00 00 00 00 00 00 00 00
  //          00 00 00 00} (length 0x40)
  //        }
  //      }
  //    }
  //  ]
  *(uint32_t*)0x200000000000 = 0;
  *(uint32_t*)0x200000000004 = 3;
  *(uint32_t*)0x200000000008 = 0x2000000;
  *(uint64_t*)0x200000000010 = 0xfea;
  *(uint32_t*)0x200000000018 = 0xfffffffb;
  *(uint64_t*)0x200000000020 = 2;
  *(uint32_t*)0x200000000028 = 6;
  *(uint64_t*)0x200000000030 = 0x83;
  *(uint32_t*)0x200000000038 = 0xd;
  *(uint16_t*)0x200000000040 = 1;
  *(uint16_t*)0x200000000042 = 0x6b4;
  *(uint64_t*)0x200000000048 = 0;
  *(uint32_t*)0x200000000050 = 0x918;
  *(uint32_t*)0x200000000054 = 4;
  *(uint64_t*)0x200000000058 = 0xfffffffffffffffc;
  *(uint32_t*)0x200000000060 = 9;
  *(uint32_t*)0x200000000064 = 8;
  *(uint64_t*)0x200000000068 = 0x7d44;
  *(uint32_t*)0x200000000070 = 1;
  *(uint32_t*)0x200000000074 = 0xfffffff8;
  memcpy((void*)0x200000000078,
         "\x69\x32\x82\x68\xe7\x3f\xef\x85\x2d\x76\x56\x88\xe5\xd9\x10\x17",
         16);
  memcpy((void*)0x200000000088,
         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00",
         16);
  memcpy((void*)0x200000000098,
         "\xf6\x7d\x0f\x00\x10\x00\x00\x00\x00\x32\xe5\x67\xb7\xbc\x75\x2d",
         16);
  *(uint32_t*)0x2000000000a8 = -1;
  *(uint64_t*)0x2000000000b0 = 5;
  *(uint64_t*)0x2000000000b8 = 4;
  memcpy((void*)0x2000000000c0,
         "\xf5\x6a\x42\x5c\x52\xf4\x74\xe3\x39\xa5\x05\x00\x00\x00\xce\x58\xc0"
         "\x19\x28\xcb\x06\xee\xd4\x11\x85\xf4\x29\x8a\x46\x09\x8a\x1d\xbe\xbf"
         "\x87\xfb\x73\xa4\x9e\x3f\x64\x4f\xf0\x18\xb6\x64\x8f\xab\x00\x00\x00"
         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
         64);
  syscall(SYS_ioctl, /*fd=*/r[0], /*cmd=*/0xc4e01a02ul,
          /*arg=*/0x200000000000ul);
  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
