Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 59 additions & 14 deletions config/files/GRMLBASE/etc/udev/scripts/forensic-mark-readonly
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@ dir() {
}

is_ro() {
[ "$(blockdev --getro "$1")" = "1" ] && return 0 || return 1
# ASSUMPTION: Device paths can not contain spaces
while [ "$#" -gt 0 ]; do
[ "$(blockdev --getro "$1")" = "1" ] && return 0
shift
done
return 1
}

if [ -z "${1:-}" ] ; then
Expand All @@ -47,15 +52,51 @@ esac

SYS_DIR="$(get_blockdev_dir)"

patternsfile=
cleanup() {
if [ -f "$patternsfile" ] ; then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: use "${patternsfile}" instead of "$patternsfile" to keep coding style style consistent, same for e.g "$backingfile" etc further below

rm "$patternsfile"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's maybe use rm -f "${patternsfile}" to not (report) fail(ure) if removing should fail?

fi
}
trap cleanup EXIT

base_device=$(base "${BLOCK_DEVICE}")
if [ -n "${SYS_DIR}" ] && [ -n "${base_device}" ] ; then
tmp_parent="$(readlink -f "${SYS_DIR}"/*/"${base_device}")"
if [ -d "${tmp_parent}" ] ; then
parent_device=$(dir "${tmp_parent}")
parent_device=$(base "${parent_device}")
parent_device="/dev/${parent_device}"
if [ -z "${base_device##loop[0-9]*}" ] ; then
if [ -e "${SYS_DIR}"/"${base_device}"/loop/backing_file ] ; then
backingfile=$(cat "${SYS_DIR}"/"${base_device}"/loop/backing_file)
parent_devices=$(findmnt -n -o source --target "$backingfile")

# Set loop device to read-write, will be set to readonly later if need be
blockdev --setrw "${BLOCK_DEVICE}"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any reason why we should set this to rw by default instead of leaving it as-is?
E.g. the squashfs file that's usually behind /dev/sr0 is set to read-only already, no reason to set it temporarily to rw, nor?


# Check if either the backing file's block device or filesystem are read-only
if is_ro "$parent_devices" || findmnt -n -o OPTIONS --target "$backingfile" | grep -E '^ro,|,ro,|,ro$'; then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The grep returns its match on stdout, use grep -qE ... instead?

blockdev --setro "${BLOCK_DEVICE}"
logger -t forensic-mark-readonly "setting '${BLOCK_DEVICE}' with backing file (${backingfile}) (parent devices: '${parent_devices}') to read-only as its parent is present or mount point ($(findmnt -n -o TARGET --target "$backingfile")) is read-only"
fi
exit 0
fi
fi

tmp_parents="$(readlink -f "${SYS_DIR}"/*/"${base_device}")"
if [ -z "${tmp_parents}" ]; then
tmp_parents=
for DEV in "${SYS_DIR}"/*/holders/"${base_device}"; do
[ -d "$DEV" ] && tmp_parents="${tmp_parents:+${tmp_parents} }$(dir "$DEV")"
done
fi
unset tmp_parent
# ASSUMPTION: There should be no spaces in device names.
parent_devices=
for tmp_parent in ${tmp_parents}; do
if [ -d "${tmp_parent}" ] ; then
tmp_parent=$(dir "${tmp_parent}")
tmp_parent=$(base "${tmp_parent}")
tmp_parent="/dev/${tmp_parent}"
parent_devices="${parent_devices:+${parent_devices} }${tmp_parent}"
fi
done
unset tmp_parent tmp_parents
fi

# support configuration file
Expand All @@ -72,21 +113,25 @@ if [ -r /etc/grml/forensic.conf ] ; then
fi

if [ -n "${READONLY_IGNORE:-}" ] ; then
if printf "%s\n" "${READONLY_IGNORE:-}" | grep -qw "${parent_device}" ; then
if [ -n "${parent_device:-}" ] ; then
logger -t forensic-mark-readonly "not setting '${BLOCK_DEVICE}' (parent device: '${parent_device}') to read-only as present in ignore list"
else
logger -t forensic-mark-readonly "not setting '${BLOCK_DEVICE}' to read-only as present in ignore list"
if [ -n "${parent_devices}" ] ; then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: maybe use "${parent_devices:-}" also here, as it used to be?

patternsfile=$(mktemp /dev/shm/forensic-mark-readonly.patterns.XXXXXX)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any reason why we'd want to hard-code the directory /dev/shm/ here?
Otherwise I'd prefer mktemp -t forensic-mark-readonly.patterns.XXXXXX instead, so mktemp(1) can decide whether $TMPDIR is set, or use /tmp elsewhere.

echo "${parent_devices}" | sed "s| |\n|" > "${patternsfile}"
if echo "${READONLY_IGNORE:-}" | grep -qw -F "$patternsfile" ; then
logger -t forensic-mark-readonly "not setting '${BLOCK_DEVICE}' (parent devices: '${parent_devices}') to read-only as its parent is present in ignore list"
exit 0
fi
fi
if echo "${READONLY_IGNORE:-}" | grep -qw "${BLOCK_DEVICE}" ; then
logger -t forensic-mark-readonly "not setting '${BLOCK_DEVICE}' to read-only as present in ignore list"
exit 0
fi
fi
fi

if is_ro "${BLOCK_DEVICE}" ; then
logger -t forensic-mark-readonly "device ${BLOCK_DEVICE} already set to read-only mode, nothing to do"
elif [ -n "${parent_device}" ] && ! is_ro "${parent_device}" ; then
logger -t forensic-mark-readonly "parent device ${parent_device} is set read-write, not modifying"
elif [ -n "${parent_devices}" ] && ! is_ro "${parent_devices}" ; then
logger -t forensic-mark-readonly "all parent devices (${parent_devices}) are set read-write, not modifying"
logger -t forensic-mark-readonly "use blockdev --setro ${BLOCK_DEVICE} to set it manually"
else
logger -t forensic-mark-readonly "setting ${BLOCK_DEVICE} [${ID_SERIAL}] to read-only"
Expand Down
Loading