244 lines
6.4 KiB
Bash
244 lines
6.4 KiB
Bash
#!/bin/sh
|
|
set -eu
|
|
|
|
DURATION_SEC=300
|
|
DEVICES=""
|
|
EXCLUDE=""
|
|
FORMAT=""
|
|
TEST_SLICE_SECONDS=300
|
|
JOHN_DIR="/usr/local/lib/bee/john/run"
|
|
JOHN_BIN="${JOHN_DIR}/john"
|
|
export OCL_ICD_VENDORS="/etc/OpenCL/vendors"
|
|
export LD_LIBRARY_PATH="/usr/lib:/usr/local/lib${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"
|
|
|
|
usage() {
|
|
echo "usage: $0 [--seconds N] [--devices 0,1] [--exclude 2,3] [--format name]" >&2
|
|
exit 2
|
|
}
|
|
|
|
normalize_list() {
|
|
echo "${1:-}" | tr ',' '\n' | sed 's/[[:space:]]//g' | awk 'NF' | sort -n | uniq | paste -sd, -
|
|
}
|
|
|
|
contains_csv() {
|
|
needle="$1"
|
|
haystack="${2:-}"
|
|
echo ",${haystack}," | grep -q ",${needle},"
|
|
}
|
|
|
|
show_opencl_diagnostics() {
|
|
echo "-- OpenCL ICD vendors --" >&2
|
|
if [ -d /etc/OpenCL/vendors ]; then
|
|
ls -l /etc/OpenCL/vendors >&2 || true
|
|
for icd in /etc/OpenCL/vendors/*.icd; do
|
|
[ -f "${icd}" ] || continue
|
|
echo " file: ${icd}" >&2
|
|
sed 's/^/ /' "${icd}" >&2 || true
|
|
done
|
|
else
|
|
echo " /etc/OpenCL/vendors is missing" >&2
|
|
fi
|
|
echo "-- NVIDIA device nodes --" >&2
|
|
ls -l /dev/nvidia* >&2 || true
|
|
echo "-- ldconfig OpenCL/NVIDIA --" >&2
|
|
ldconfig -p 2>/dev/null | grep 'libOpenCL\|libcuda\|libnvidia-opencl' >&2 || true
|
|
if command -v clinfo >/dev/null 2>&1; then
|
|
echo "-- clinfo -l --" >&2
|
|
clinfo -l >&2 || true
|
|
fi
|
|
echo "-- john --list=opencl-devices --" >&2
|
|
./john --list=opencl-devices >&2 || true
|
|
}
|
|
|
|
refresh_nvidia_runtime() {
|
|
if [ "$(id -u)" != "0" ]; then
|
|
return 1
|
|
fi
|
|
if command -v bee-nvidia-load >/dev/null 2>&1; then
|
|
bee-nvidia-load >/dev/null 2>&1 || true
|
|
fi
|
|
ldconfig >/dev/null 2>&1 || true
|
|
return 0
|
|
}
|
|
|
|
ensure_nvidia_uvm() {
|
|
if lsmod 2>/dev/null | grep -q '^nvidia_uvm '; then
|
|
return 0
|
|
fi
|
|
if [ "$(id -u)" != "0" ]; then
|
|
return 1
|
|
fi
|
|
|
|
ko="/usr/local/lib/nvidia/nvidia-uvm.ko"
|
|
[ -f "${ko}" ] || return 1
|
|
|
|
if ! insmod "${ko}" >/dev/null 2>&1; then
|
|
return 1
|
|
fi
|
|
|
|
uvm_major=$(grep -m1 ' nvidia-uvm$' /proc/devices | awk '{print $1}')
|
|
if [ -n "${uvm_major}" ]; then
|
|
mknod -m 666 /dev/nvidia-uvm c "${uvm_major}" 0 2>/dev/null || true
|
|
mknod -m 666 /dev/nvidia-uvm-tools c "${uvm_major}" 1 2>/dev/null || true
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
ensure_opencl_ready() {
|
|
out=$(./john --list=opencl-devices 2>&1 || true)
|
|
if echo "${out}" | grep -q "Device #"; then
|
|
return 0
|
|
fi
|
|
|
|
if refresh_nvidia_runtime; then
|
|
out=$(./john --list=opencl-devices 2>&1 || true)
|
|
if echo "${out}" | grep -q "Device #"; then
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
if ensure_nvidia_uvm; then
|
|
out=$(./john --list=opencl-devices 2>&1 || true)
|
|
if echo "${out}" | grep -q "Device #"; then
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
echo "OpenCL devices are not available for John." >&2
|
|
if ! lsmod 2>/dev/null | grep -q '^nvidia_uvm '; then
|
|
echo "nvidia_uvm is not loaded." >&2
|
|
fi
|
|
if [ ! -e /dev/nvidia-uvm ]; then
|
|
echo "/dev/nvidia-uvm is missing." >&2
|
|
fi
|
|
show_opencl_diagnostics
|
|
return 1
|
|
}
|
|
|
|
while [ "$#" -gt 0 ]; do
|
|
case "$1" in
|
|
--seconds|-t) [ "$#" -ge 2 ] || usage; DURATION_SEC="$2"; shift 2 ;;
|
|
--devices) [ "$#" -ge 2 ] || usage; DEVICES="$2"; shift 2 ;;
|
|
--exclude) [ "$#" -ge 2 ] || usage; EXCLUDE="$2"; shift 2 ;;
|
|
--format) [ "$#" -ge 2 ] || usage; FORMAT="$2"; shift 2 ;;
|
|
*) usage ;;
|
|
esac
|
|
done
|
|
|
|
[ -x "${JOHN_BIN}" ] || { echo "john binary not found: ${JOHN_BIN}" >&2; exit 1; }
|
|
|
|
ALL_DEVICES=$(nvidia-smi --query-gpu=index --format=csv,noheader,nounits 2>/dev/null | sed 's/[[:space:]]//g' | awk 'NF' | paste -sd, -)
|
|
[ -n "${ALL_DEVICES}" ] || { echo "nvidia-smi found no NVIDIA GPUs" >&2; exit 1; }
|
|
|
|
DEVICES=$(normalize_list "${DEVICES}")
|
|
EXCLUDE=$(normalize_list "${EXCLUDE}")
|
|
SELECTED="${DEVICES}"
|
|
if [ -z "${SELECTED}" ]; then
|
|
SELECTED="${ALL_DEVICES}"
|
|
fi
|
|
|
|
FINAL=""
|
|
for id in $(echo "${SELECTED}" | tr ',' ' '); do
|
|
[ -n "${id}" ] || continue
|
|
if contains_csv "${id}" "${EXCLUDE}"; then
|
|
continue
|
|
fi
|
|
if [ -z "${FINAL}" ]; then
|
|
FINAL="${id}"
|
|
else
|
|
FINAL="${FINAL},${id}"
|
|
fi
|
|
done
|
|
|
|
[ -n "${FINAL}" ] || { echo "no NVIDIA GPUs selected after filters" >&2; exit 1; }
|
|
|
|
JOHN_DEVICES=""
|
|
for id in $(echo "${FINAL}" | tr ',' ' '); do
|
|
opencl_id=$((id + 1))
|
|
if [ -z "${JOHN_DEVICES}" ]; then
|
|
JOHN_DEVICES="${opencl_id}"
|
|
else
|
|
JOHN_DEVICES="${JOHN_DEVICES},${opencl_id}"
|
|
fi
|
|
done
|
|
|
|
echo "loader=john"
|
|
echo "selected_gpus=${FINAL}"
|
|
echo "john_devices=${JOHN_DEVICES}"
|
|
|
|
cd "${JOHN_DIR}"
|
|
|
|
ensure_opencl_ready || exit 1
|
|
|
|
choose_format() {
|
|
if [ -n "${FORMAT}" ]; then
|
|
echo "${FORMAT}"
|
|
return 0
|
|
fi
|
|
for candidate in sha512crypt-opencl pbkdf2-hmac-sha512-opencl 7z-opencl sha256crypt-opencl md5crypt-opencl; do
|
|
if ./john --test=1 --format="${candidate}" --devices="${JOHN_DEVICES}" >/dev/null 2>&1; then
|
|
echo "${candidate}"
|
|
return 0
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
CHOSEN_FORMAT=$(choose_format) || {
|
|
echo "no suitable john OpenCL format found" >&2
|
|
./john --list=opencl-devices >&2 || true
|
|
exit 1
|
|
}
|
|
|
|
run_john_loop() {
|
|
opencl_id="$1"
|
|
deadline="$2"
|
|
round=0
|
|
while :; do
|
|
now=$(date +%s)
|
|
remaining=$((deadline - now))
|
|
if [ "${remaining}" -le 0 ]; then
|
|
break
|
|
fi
|
|
round=$((round + 1))
|
|
slice="${remaining}"
|
|
if [ "${slice}" -gt "${TEST_SLICE_SECONDS}" ]; then
|
|
slice="${TEST_SLICE_SECONDS}"
|
|
fi
|
|
echo "device=${opencl_id} round=${round} remaining_sec=${remaining} slice_sec=${slice}"
|
|
./john --test="${slice}" --format="${CHOSEN_FORMAT}" --devices="${opencl_id}" || return 1
|
|
done
|
|
}
|
|
|
|
PIDS=""
|
|
cleanup() {
|
|
rc=$?
|
|
trap - EXIT INT TERM
|
|
for pid in ${PIDS}; do
|
|
kill "${pid}" 2>/dev/null || true
|
|
done
|
|
for pid in ${PIDS}; do
|
|
wait "${pid}" 2>/dev/null || true
|
|
done
|
|
exit "${rc}"
|
|
}
|
|
trap cleanup EXIT INT TERM
|
|
|
|
echo "format=${CHOSEN_FORMAT}"
|
|
echo "target_seconds=${DURATION_SEC}"
|
|
echo "slice_seconds=${TEST_SLICE_SECONDS}"
|
|
DEADLINE=$(( $(date +%s) + DURATION_SEC ))
|
|
_first=1
|
|
for opencl_id in $(echo "${JOHN_DEVICES}" | tr ',' ' '); do
|
|
[ "${_first}" = "1" ] || sleep 3
|
|
_first=0
|
|
run_john_loop "${opencl_id}" "${DEADLINE}" &
|
|
pid=$!
|
|
PIDS="${PIDS} ${pid}"
|
|
done
|
|
FAIL=0
|
|
for pid in ${PIDS}; do
|
|
wait "${pid}" || FAIL=$((FAIL+1))
|
|
done
|
|
[ "${FAIL}" -eq 0 ] || { echo "john: ${FAIL} device(s) failed" >&2; exit 1; }
|