Skip to content

Commit db5777a

Browse files
authored
Merge pull request #1262 from 3hhh/add-files
2 parents febff85 + d07df1e commit db5777a

File tree

5 files changed

+141
-10
lines changed

5 files changed

+141
-10
lines changed

initrd/bin/gui-init

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,15 @@ verify_global_hashes()
6666
# Check the hashes of all the files, ignoring signatures for now
6767
check_config /boot force
6868
TMP_HASH_FILE="/tmp/kexec/kexec_hashes.txt"
69+
TMP_TREE_FILE="/tmp/kexec/kexec_tree.txt"
6970
TMP_PACKAGE_TRIGGER_PRE="/tmp/kexec/kexec_package_trigger_pre.txt"
7071
TMP_PACKAGE_TRIGGER_POST="/tmp/kexec/kexec_package_trigger_post.txt"
7172

72-
if ( cd /boot && sha256sum -c "$TMP_HASH_FILE" > /tmp/hash_output ) then
73+
if verify_checksums /boot ; then
7374
return 0
74-
elif [ ! -f $TMP_HASH_FILE ]; then
75-
if (whiptail $BG_COLOR_ERROR --title 'ERROR: Missing Hash File!' \
76-
--yesno "The file containing hashes for /boot is missing!\n\nIf you are setting this system up for the first time, select Yes to update\nyour list of checksums.\n\nOtherwise this could indicate a compromise and you should select No to\nreturn to the main menu.\n\nWould you like to update your checksums now?" 0 80) then
75+
elif [[ ! -f "$TMP_HASH_FILE" || ! -f "$TMP_TREE_FILE" ]] ; then
76+
if (whiptail $BG_COLOR_ERROR --title 'ERROR: Missing File!' \
77+
--yesno "One of the files containing integrity information for /boot is missing!\n\nIf you are setting up heads for the first time or upgrading from an\nolder version, select Yes to create the missing files.\n\nOtherwise this could indicate a compromise and you should select No to\nreturn to the main menu.\n\nWould you like to create the missing files now?" 0 80) then
7778
if update_checksums ; then
7879
BG_COLOR_MAIN_MENU=""
7980
return 0;

initrd/bin/kexec-select-boot

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ verify_global_hashes()
5252
{
5353
echo "+++ Checking verified boot hash file "
5454
# Check the hashes of all the files
55-
if ( cd $bootdir && sha256sum -c "$TMP_HASH_FILE" > /tmp/hash_output ); then
55+
if verify_checksums "$bootdir" "$gui_menu" ; then
5656
echo "+++ Verified boot hashes "
5757
valid_hash='y'
5858
valid_global_hash='y'
@@ -326,6 +326,7 @@ while true; do
326326
TMP_DEFAULT_FILE=`find /tmp/kexec/kexec_default.*.txt 2>/dev/null | head -1` || true
327327
TMP_MENU_FILE="/tmp/kexec/kexec_menu.txt"
328328
TMP_HASH_FILE="/tmp/kexec/kexec_hashes.txt"
329+
TMP_TREE_FILE="/tmp/kexec/kexec_tree.txt"
329330
TMP_DEFAULT_HASH_FILE="/tmp/kexec/kexec_default_hashes.txt"
330331
TMP_ROLLBACK_FILE="/tmp/kexec/kexec_rollback.txt"
331332
TMP_KEY_DEVICES="/tmp/kexec/kexec_key_devices.txt"
@@ -385,4 +386,4 @@ while true; do
385386
fi
386387
done
387388

388-
die "!!! Shouldn't get here""
389+
die "!!! Shouldn't get here"

initrd/bin/kexec-sign-config

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,24 @@ fi
2121

2222
paramsdir="${paramsdir%%/}"
2323

24+
assert_signable
25+
2426
confirm_gpg_card
2527

2628
# update hashes in /boot before signing
2729
if [ "$update" = "y" ]; then
2830
(
2931
cd /boot
30-
find ./ -type f ! -name '*kexec*' -print0 | xargs -0 sha256sum > /boot/kexec_hashes.txt
32+
find ./ -type f ! -path './kexec*' -print0 | xargs -0 sha256sum > /boot/kexec_hashes.txt
3133
if [ -e /boot/kexec_default_hashes.txt ]; then
3234
DEFAULT_FILES=$(cat /boot/kexec_default_hashes.txt | cut -f3 -d ' ')
3335
echo $DEFAULT_FILES | xargs sha256sum > /boot/kexec_default_hashes.txt
3436
fi
37+
38+
#also save the file & directory structure to detect added files
39+
print_tree > /boot/kexec_tree.txt
3540
)
41+
[ $? -eq 0 ] || die "$paramsdir: Failed to update hashes."
3642

3743
# Remove any package trigger log files
3844
# We don't need them after the user decides to sign

initrd/bin/oem-factory-reset

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,9 +195,14 @@ generate_checksums()
195195
fi
196196

197197
# generate hashes
198-
find /boot -type f ! -name '*kexec*' -print0 \
199-
| xargs -0 sha256sum > /boot/kexec_hashes.txt 2>/dev/null \
200-
|| whiptail_error_die "Error generating kexec hashes"
198+
(
199+
set -e -o pipefail
200+
cd /boot
201+
find ./ -type f ! -path './kexec*' -print0 \
202+
| xargs -0 sha256sum > /boot/kexec_hashes.txt 2>/dev/null
203+
print_tree > /boot/kexec_tree.txt
204+
)
205+
[ $? -eq 0 ] || whiptail_error_die "Error generating kexec hashes"
201206

202207
param_files=`find /boot/kexec*.txt`
203208
[ -z "$param_files" ] \
@@ -553,6 +558,8 @@ if ! gpg --card-status >/dev/null 2>&1 ; then
553558
fi
554559
fi
555560

561+
assert_signable
562+
556563
# Action time...
557564

558565
# detect and set /boot device

initrd/etc/functions

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,122 @@ update_checksums()
335335
return $rv
336336
}
337337

338+
print_tree() {
339+
find ./ ! -path './kexec*' -print0 | sort -z
340+
}
341+
342+
# Escape zero-delimited standard input to safely display it to the user in e.g.
343+
# `whiptail`, `less`, `echo`, `cat`. Doesn't produce shell-escaped output.
344+
# Most printable characters are passed verbatim (exception: \).
345+
# These escapes are used to replace their corresponding characters: #n#r#t#v#b
346+
# Other characters are rendered as hexadecimal escapes.
347+
# escape_zero [prefix] [escape character]
348+
# prefix: \0 in the input will result in \n[prefix]
349+
# escape character: character to use for escapes (default: #); \ may be interpreted by `whiptail`
350+
escape_zero() {
351+
local prefix="$1"
352+
local echar="${2:-#}"
353+
local todo=""
354+
local echar_hex="$(echo -n "$echar" | xxd -p -c1)"
355+
[ ${#echar_hex} -eq 2 ] || die "Invalid escape character $echar passed to escape_zero(). Programming error?!"
356+
357+
echo -e -n "$prefix"
358+
xxd -p -c1 | tr -d '\n' |
359+
{
360+
while IFS= read -r -n2 -d '' ; do
361+
if [ -n "$todo" ] ; then
362+
#REPLY == " " is EOF
363+
[[ "$REPLY" == " " ]] && echo '' || echo -e -n "$todo"
364+
todo=""
365+
fi
366+
367+
case "$REPLY" in
368+
00)
369+
todo="\n$prefix"
370+
;;
371+
08)
372+
echo -n "${echar}b"
373+
;;
374+
09)
375+
echo -n "${echar}t"
376+
;;
377+
0a)
378+
echo -n "${echar}n"
379+
;;
380+
0b)
381+
echo -n "${echar}v"
382+
;;
383+
0d)
384+
echo -n "${echar}r"
385+
;;
386+
"$echar_hex")
387+
echo -n "$echar$echar"
388+
;;
389+
#interpreted characters:
390+
2[0-9a-f]|3[0-9a-f]|4[0-9a-f]|5[0-9abd-f]|6[0-9a-f]|7[0-9a-e])
391+
echo -e -n '\x'"$REPLY"
392+
;;
393+
# All others are escaped
394+
*)
395+
echo -n "${echar}x$REPLY"
396+
;;
397+
esac
398+
done
399+
}
400+
}
401+
402+
# Currently heads doesn't support signing file names with certain characters
403+
# due to https://bugs.busybox.net/show_bug.cgi?id=14226. Also, certain characters
404+
# may be intepreted by `whiptail`, `less` et al (e.g. \n, \b, ...).
405+
assert_signable() {
406+
# ensure /boot mounted
407+
if ! grep -q /boot /proc/mounts ; then
408+
mount -o ro /boot || die "Unable to mount /boot"
409+
fi
410+
411+
find /boot -print0 > /tmp/signable.ref
412+
local del='\001-\037\134\177-\377'
413+
LC_ALL=C tr -d "$del" < /tmp/signable.ref > /tmp/signable.del || die "Failed to execute tr."
414+
if ! cmp -s "/tmp/signable.ref" "/tmp/signable.del" &> /dev/null ; then
415+
local user_out="/tmp/hash_output_mismatches"
416+
local add="Please investigate!"
417+
[ -f "$user_out" ] && add="Please investigate the following relative paths to /boot (where # are sanitized invalid characters):"$'\n'"$(cat "$user_out")"
418+
recovery "Some /boot file names contain characters that are currently not supported by heads: $del"$'\n'"$add"
419+
fi
420+
rm -f /tmp/signable.*
421+
}
422+
423+
verify_checksums()
424+
{
425+
local boot_dir="$1"
426+
local gui="${2:-y}"
427+
428+
(
429+
set +e -o pipefail
430+
local ret=0
431+
cd "$boot_dir" || ret=1
432+
sha256sum -c "$TMP_HASH_FILE" > /tmp/hash_output || ret=1
433+
434+
# also make sure that the file & directory structure didn't change
435+
# (sha256sum won't detect added files)
436+
print_tree > /tmp/tree_output || ret=1
437+
if ! cmp -s "$TMP_TREE_FILE" /tmp/tree_output &> /dev/null ; then
438+
ret=1
439+
[[ "$gui" != "y" ]] && exit "$ret"
440+
# produce a diff that can safely be presented to the user
441+
# this is relatively hard as file names may e.g. contain backslashes etc.,
442+
# which are interpreted by whiptail, less, ...
443+
escape_zero "(new) " < "$TMP_TREE_FILE" > "${TMP_TREE_FILE}.user"
444+
escape_zero "(new) " < /tmp/tree_output > /tmp/tree_output.user
445+
diff "${TMP_TREE_FILE}.user" /tmp/tree_output.user | grep -E '^\+\(new\).*$' | sed -r 's/^\+\(new\)/(new)/g' >> /tmp/hash_output
446+
rm -f "${TMP_TREE_FILE}.user"
447+
rm -f /tmp/tree_output.user
448+
fi
449+
exit $ret
450+
)
451+
return $?
452+
}
453+
338454
# detect and set /boot device
339455
# mount /boot if successful
340456
detect_boot_device()

0 commit comments

Comments
 (0)