fix: harden mtm-ddwipe confirmation and wipe flow

Add strict shell options, root and block-device validation, and a typed-device confirmation prompt before wiping. Preserve the fallback wipe sequence through secure discard, zero discard, and dd, while tightening error handling and keeping messages concise.
This commit is contained in:
2026-04-27 23:32:45 +02:00
parent 7011426381
commit ecc6e5b038
2 changed files with 122 additions and 75 deletions
+13 -12
View File
@@ -4,25 +4,26 @@ description: mtm-ddwipe project conventions
# Project conventions
- Use English throughout the project.
- Keep shell scripts Bash-based when Bash is already used by the project.
- Preserve the current behavior of the main script:
- `mtm-ddwipe`: wipe devices.
- Strengthen destructive-action safety checks in `mtm-ddwipe` when making changes.
- Keep `mtm-ddwipe` interactive by default unless a change explicitly adds a safe opt-in flag.
- Keep user-facing messages short, clear, and in English.
- Prefer minimal, focused changes that do not alter the intent of the existing scripts, unless the script behavior is intentionally updated.
- Maintain `.continue/rules/project.md` whenever project conventions or script behavior change.
- Keep shell scripts Bash-based.
- Preserve the current behavior of the main script: `mtm-ddwipe` wipes block devices.
- Strengthen destructive-action safety checks in `mtm-ddwipe`.
- Keep `mtm-ddwipe` interactive by default.
- Require explicit confirmation before destructive actions.
- Keep user-facing messages short and clear.
- Keep error and help messages short and clear.
- Prefer minimal, focused changes that preserve intent.
- Keep `.continue/rules/project.md` aligned with project conventions and concise.
- `mtm-ddwipe` is a small Bash script with helper functions.
- Keep the host and line-number removal behavior intact.
- Keep the host and line-number removal behavior intact for related output processing.
- `mtm-ddwipe` must print a usage line and support `-h`/`--help`.
- Validate that wipe targets are real block devices before operating on them.
- Keep short, explicit confirmation prompts before destructive operations.
- Keep error and help messages short, clear, and in English.
- Prefer confirmation prompts that require typing the target device path.
- Keep help text concise and usage-first.
- When changing `mtm-ddwipe`, keep destructive safeguards strict and explicit.
- Keep destructive safeguards strict and explicit.
- If adding non-interactive support, make it an opt-in safety flag.
- Keep device identification prompts clear and specific.
- Preserve the fallback wipe flow unless the change is intentionally about wiping behavior.
- Preserve the fallback wipe flow: secure discard, zero discard, then zero-fill with `dd`.
# Project identity
- Main script: `mtm-ddwipe`
+108 -62
View File
@@ -1,108 +1,154 @@
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'
VERSION="0.0.3"
STARTDATE=""
STARTDATE=0
STARTDATESTRING=""
DEVICE_PATH=""
show_help() {
echo "Usage: mtm-ddwipe DEVICE"
echo "Wipe a block device."
echo "Version: ${VERSION}"
usage() {
cat <<EOF
Usage: mtm-ddwipe-2 DEVICE
Wipe a block device.
Version: ${VERSION}
EOF
}
log() {
echo "$*"
}
die() {
echo "Error: $*" >&2
exit 1
}
check_args() {
case "${1}" in
if [ $# -ne 1 ]; then
usage
exit 1
fi
case "$1" in
-h|--help)
show_help
usage
exit 0
;;
"")
show_help
exit 1
;;
-*)
echo "Invalid option."
show_help
exit 1
die "Invalid option."
;;
esac
}
check_dev_exist() {
if [ ! -e "${1}" ]; then
echo "Missing device."
exit 1
fi
}
check_device() {
local dev="$1"
check_dev_block() {
if [ ! -b "${1}" ]; then
echo "Not a block device."
exit 1
fi
[ -e "$dev" ] || die "Missing device: $dev"
[ -b "$dev" ] || die "Not a block device: $dev"
}
confirm_wipe() {
lsblk "${1}"
local dev="$1"
local choice=""
lsblk "$dev"
echo ""
read -r -p "Wipe ${1} (y/[n])? " CHOICE
case "${CHOICE}" in
y|Y)
read -r -p "Type the device path to confirm wipe: " choice
[ "$choice" = "$dev" ] || die "Canceled"
echo ""
;;
*)
echo "Canceled"
exit 1
;;
esac
}
confirm_root() {
if [ "${EUID:-$(id -u)}" -ne 0 ]; then
die "This tool must be run as root."
fi
}
print_time() {
local enddate calctime
echo ""
echo "Start date :"
echo "${STARTDATESTRING}"
echo "$STARTDATESTRING"
ENDDATE=$(date +%s)
enddate=$(date +%s)
echo ""
echo "End date :"
date
CALCTIME=$((ENDDATE-STARTDATE))
calctime=$((enddate - STARTDATE))
echo ""
echo "Total time :"
date -d@${CALCTIME} -u +%H:%M:%S
date -d@"${calctime}" -u +%H:%M:%S
}
wipe_with_blkdiscard_secure() {
local dev="$1"
log "blkdiscard secure"
blkdiscard -f -p 500M -s -v "$dev"
}
wipe_with_blkdiscard_zero() {
local dev="$1"
log "blkdiscard zero"
blkdiscard -f -p 500M -z -v "$dev"
}
wipe_with_dd() {
local dev="$1"
log "dd zero"
dd if=/dev/zero of="$dev" bs=1M status=progress conv=fsync
log "Wiped with dd, check if full size is written."
log "Otherwise use a mechanical destruction of the device."
}
wipe_dev() {
local dev="$1"
STARTDATE=$(date +%s)
STARTDATESTRING="$(date)"
echo "Begin wiping device ${1}"
DEVICE_PATH="$dev"
log "Begin wiping device $dev"
echo ""
echo "Start date :"
echo "${STARTDATESTRING}"
log "Start date :"
log "$STARTDATESTRING"
echo ""
echo "blkdiscard secure"
if ! blkdiscard -f -p 500M -s -v "${1}"; then
if wipe_with_blkdiscard_secure "$dev"; then
echo ""
echo "blkdiscard zero"
if ! blkdiscard -f -p 500M -z -v "${1}"; then
echo ""
echo "dd zero"
if ! dd if=/dev/zero of="${1}" bs=1M status=progress; then
echo "Wiped with dd, check if full size is writed."
echo "Otherwise use a mechanical destruction of the device."
print_time
exit 1
fi
fi
log "Device $dev wiped."
return
fi
echo ""
echo "Device ${1} wiped."
if wipe_with_blkdiscard_zero "$dev"; then
echo ""
log "Device $dev wiped."
return
fi
echo ""
if wipe_with_dd "$dev"; then
echo ""
log "Device $dev wiped."
return
fi
die "Wipe failed. The device may not be fully overwritten."
}
check_args "${1}"
check_dev_exist "${1}"
check_dev_block "${1}"
confirm_wipe "${1}"
wipe_dev "${1}"
print_time
main() {
check_args "$@"
confirm_root
check_device "$1"
confirm_wipe "$1"
wipe_dev "$1"
print_time
}
main "$@"