⬢ DragonFlyBSD Kernel Audit
DF-5667 / vk_probe5.sh
← back to finding ↓ download raw
#!/bin/sh
# DF-5667 probe v5 (fixed-kernel introspection) — resolves why kernacc()
# still returns TRUE for dead per-CPU slots after the is_globaldata_space
# fix: reads kernel_map->{min_addr,max_addr} via /dev/kmem and probes
# kernacc() below / inside / above the per-CPU window via DDB (hex args).
set -u
VK=/usr/obj/usr/src/sys/VKERNEL64/kernel.debug
LOG=/tmp/vk5667.log
cd /usr/obj/usr/src/sys/VKERNEL64

pkill -9 -f kernel.debug 2>/dev/null; sleep 1
rm -f /tmp/vkin $LOG
mkfifo /tmp/vkin
(sleep 900 > /tmp/vkin 2>/dev/null) </dev/null &
HOLDER=$!
nsym() { nm $VK | awk -v s="$1" '$3==s{print "0x"$1}' | head -1; }
SYM_PRV=$(nsym CPU_prvspace); SYM_KMAP=$(nsym kernel_map)
F_KERNACC=$(nsym kernacc); F_KVAC=$(nsym kvm_access_check)
echo "DF5667V5 SYMS prv=$SYM_PRV kmap=$SYM_KMAP kernacc=$F_KERNACC kvac=$F_KVAC"

( exec 3> /tmp/vkin; echo "ufs:vkd0" >&3 ) &
./kernel.debug -m 512m -r /vkroot.img -n 2 -e init_path=/bin/vkinit \
      -s < /tmp/vkin 2>&1 | tee $LOG > /dev/console &
i=0; while [ $i -lt 150 ]; do
  grep -q "Mounting root from ufs:vkd0" $LOG 2>/dev/null && grep -q "^# " $LOG 2>/dev/null && break
  pgrep -f "kernel.debug -m 512m" >/dev/null 2>&1 || break
  sleep 1; i=$((i+1));
done
sleep 4
send() { ( exec 4> /tmp/vkin; echo "$1" >&4 ); }

send "echo DF5667V5_STAGE1"
send "dd if=/dev/kmem bs=8 count=1 skip=\$(( $SYM_PRV / 8 )) 2>/dev/null | od -An -tx1"
send "dd if=/dev/kmem bs=8 count=1 skip=\$(( $SYM_KMAP / 8 )) 2>/dev/null | od -An -tx1"
sleep 5
parse8() { grep -a -A1 "$2" $LOG | tail -1 | tr -d '\r' | awk -v pre="$1" '{v=pre; for(i=NF;i>=1;i--) v=v $i; print v}'; }
# re-extract the od line FOLLOWING each command
B=$(awk '/od -An/{getline; gsub(/\r/,""); v="0x"; n=split($0,a," "); for(i=n;i>=1;i--) v=v a[i]; print v; exit}' $LOG)
P=$(awk '/kernel_map|kmap/{found=1} found&&/od -An/{getline; getline; gsub(/\r/,""); v="0x"; n=split($0,a," "); for(i=n;i>=1;i--) v=v a[i]; print v; exit}' $LOG)
# fallback: second od output line
[ -z "$P" ] && P=$(awk '/od -An/{c++; if(c==2){getline; gsub(/\r/,""); v="0x"; n=split($0,a," "); for(i=n;i>=1;i--) v=v a[i]; print v; exit}}' $LOG)
echo "DF5667V5 BASE=$B KMAP_PTR=$P"
if [ -n "$P" ]; then
  send "dd if=/dev/kmem bs=128 count=1 skip=\$(( $P / 128 )) 2>/dev/null | od -An -tx1"
  sleep 4
fi
# DDB kernacc probes around the window (hex args!)
send "sysctl -w debug.enter_debugger=ddb"; sleep 4
( exec 5> /tmp/vkin
  printf 'call %s(0x8000300123, 8, 1)\n' "$F_KERNACC" >&5; sleep 2
  printf 'call %s(0x8000420123, 8, 1)\n' "$F_KERNACC" >&5; sleep 2
  printf 'call %s(0x8000c10123, 8, 1)\n' "$F_KERNACC" >&5; sleep 2
  printf 'call %s(0x7fff7000, 8, 1)\n'    "$F_KERNACC" >&5; sleep 2
  printf 'call %s(0x8000300000, 0x8000301000, 1)\n' "$F_KVAC" >&5; sleep 2 ) &
sleep 16
send "c"; sleep 3
send "echo DF5667V5_DONE; reboot"; sleep 6
echo "=== results ==="
sed -n "/DF5667V5_STAGE1/,/V5_DONE/p" $LOG | tail -60
kill $HOLDER 2>/dev/null; pkill -9 -f kernel.debug 2>/dev/null
echo "DF5667V5_DRIVER_DONE"