build_image, build_kernel_image, update_bootloaders: fix up rootfs_verification

This change adds
- --rootfs_hash_pad to specify the MBs reserved for the pad
- the implementation of the above flag
- check if total fs size + pad size exceeds the partition size
- hash appending in make_image_bootable()

Fixes:
- a style for ROOT_FS_HASH usage
- bad mount|grep
- bad bash subst for root devices in all boot paths
- fixed a typo in the update_bootloaders table creation
- disables verified usb for now

Adding the padding argument ensures that the generated hash tree for the root filesystem is appended to the image.  Assuming the rootfs is _never_ mounted read-write
again, that hash tree will be valid and vboot will be able to proceed.

BUG=chromium-os:2693
TEST=manual build_image

Review URL: http://codereview.chromium.org/3043011

Change-Id: I67d9b0f91cacdefa309c0cc2dd7fed1d2eddd7a7
This commit is contained in:
Will Drewry 2010-07-21 14:02:20 -05:00
parent e79e88eb0e
commit 78992a33f4
4 changed files with 52 additions and 19 deletions

View File

@ -51,6 +51,9 @@ DEFINE_integer rootfs_partition_size 1024 \
"rootfs parition size in MBs." "rootfs parition size in MBs."
DEFINE_integer rootfs_size 720 \ DEFINE_integer rootfs_size 720 \
"rootfs filesystem size in MBs." "rootfs filesystem size in MBs."
# ceil(0.1 * rootfs_size) is a good minimum.
DEFINE_integer rootfs_hash_pad 8 \
"MBs reserved at the end of the rootfs image."
DEFINE_integer statefulfs_size 1024 \ DEFINE_integer statefulfs_size 1024 \
"stateful filesystem size in MBs." "stateful filesystem size in MBs."
DEFINE_boolean preserve ${FLAGS_FALSE} \ DEFINE_boolean preserve ${FLAGS_FALSE} \
@ -91,8 +94,10 @@ if [ -z "${FLAGS_board}" ] ; then
exit 1 exit 1
fi fi
if [ "${FLAGS_rootfs_size}" -gt "${FLAGS_rootfs_partition_size}" ] ; then if [ "$((FLAGS_rootfs_size + FLAGS_rootfs_hash_pad))" -gt \
error "rootfs (${FLAGS_rootfs_size} MB) is bigger than partition (${FLAGS_rootfs_partition_size} MB)." "${FLAGS_rootfs_partition_size}" ] ; then
error "rootfs ($((FLAGS_rootfs_size + FLAGS_rootfs_hash_pad)) MB) is \
bigger than partition (${FLAGS_rootfs_partition_size} MB)."
exit 1 exit 1
fi fi
@ -293,8 +298,10 @@ make_image_bootable() {
--image "${image_name}" -r "${ROOT_FS_DIR}" \ --image "${image_name}" -r "${ROOT_FS_DIR}" \
-s "${STATEFUL_FS_DIR}" -s "${STATEFUL_FS_DIR}"
# The rootfs should never be mounted rw again after this point without
# re-calling make_image_bootable.
sudo mount -o remount,ro "${ROOT_FS_DIR}" sudo mount -o remount,ro "${ROOT_FS_DIR}"
root_dev=$(mount | grep -- "${ROOT_FS_DIR}" | cut -f1 -d' ' | tail -1) root_dev=$(mount | grep -- "on ${ROOT_FS_DIR} type" | cut -f1 -d' ' | tail -1)
DEVKEYSDIR="/usr/share/vboot/devkeys" DEVKEYSDIR="/usr/share/vboot/devkeys"
@ -308,7 +315,7 @@ make_image_bootable() {
--working_dir="${OUTPUT_DIR}" \ --working_dir="${OUTPUT_DIR}" \
--keep_work \ --keep_work \
--rootfs_image=${root_dev} \ --rootfs_image=${root_dev} \
--rootfs_hash=${OUTPUT_DIR}/rootfs.hash \ --rootfs_hash=${ROOT_FS_HASH} \
--verity_hash_alg=${FLAGS_verity_algorithm} \ --verity_hash_alg=${FLAGS_verity_algorithm} \
--verity_tree_depth=${FLAGS_verity_depth} \ --verity_tree_depth=${FLAGS_verity_depth} \
--verity_max_ios=${FLAGS_verity_max_ios} \ --verity_max_ios=${FLAGS_verity_max_ios} \
@ -316,6 +323,25 @@ make_image_bootable() {
--root=${cros_root} \ --root=${cros_root} \
--keys_dir="${DEVKEYSDIR}" --keys_dir="${DEVKEYSDIR}"
local rootfs_hash_size=$(stat -c '%s' ${ROOT_FS_HASH})
info "Appending rootfs.hash (${rootfs_hash_size} bytes) to the root fs"
if [[ ${rootfs_hash_size} -gt $((FLAGS_rootfs_hash_pad * 1024 * 1024)) ]]
then
die "--rootfs_hash_pad reserves less than the needed ${rootfs_hash_size}"
fi
# Unfortunately, mount_gpt_image uses mount and not losetup to create the
# loop devices. This means that they are not the correct size. We have to
# write directly to the image to append the hash tree data.
local hash_offset="$(partoffset ${OUTPUT_DIR}/${image_name} 3)"
hash_offset=$((hash_offset + ((1024 * 1024 * ${FLAGS_rootfs_size}) / 512)))
sudo dd bs=512 \
seek=${hash_offset} \
if="${ROOT_FS_HASH}" \
of="${OUTPUT_DIR}/${image_name}" \
conv=notrunc
# We don't need to keep the file around anymore.
sudo rm "${ROOT_FS_HASH}"
# Move the verification block needed for the hard disk install to the # Move the verification block needed for the hard disk install to the
# stateful partition. Mount stateful fs, copy file, and umount fs. # stateful partition. Mount stateful fs, copy file, and umount fs.
# In original CL: http://codereview.chromium.org/2868044, this was done in # In original CL: http://codereview.chromium.org/2868044, this was done in
@ -510,7 +536,18 @@ create_base_image() {
sudo losetup "${LOOP_DEV}" "${ROOT_FS_IMG}" sudo losetup "${LOOP_DEV}" "${ROOT_FS_IMG}"
sudo mkfs.ext3 "${LOOP_DEV}" sudo mkfs.ext3 "${LOOP_DEV}"
# Pad out 10% for the hash tree. This currently _exact_ for
# default configuration. More space may be needed for different options.
ROOT_HASH_PAD=$((FLAGS_rootfs_hash_pad * 1024 * 1024))
info "Padding the rootfs image by ${ROOT_HASH_PAD} bytes for hash data"
dd if=/dev/zero of="${ROOT_FS_IMG}" bs=1 count=1 \
seek=$((ROOT_SIZE_BYTES + ROOT_HASH_PAD - 1))
# Update to reflect the new capacity in the loop device.
sudo losetup -c "${LOOP_DEV}"
# Tune and mount rootfs. # Tune and mount rootfs.
# TODO(wad) rename the disk label to match the GPT since we
# can't change it later.
DISK_LABEL="C-KEYFOB" DISK_LABEL="C-KEYFOB"
sudo tune2fs -L "${DISK_LABEL}" -U "${UUID}" -c 0 -i 0 "${LOOP_DEV}" sudo tune2fs -L "${DISK_LABEL}" -U "${UUID}" -c 0 -i 0 "${LOOP_DEV}"
sudo mount "${LOOP_DEV}" "${ROOT_FS_DIR}" sudo mount "${LOOP_DEV}" "${ROOT_FS_DIR}"

View File

@ -58,17 +58,16 @@ set -e
verity_args= verity_args=
# Even with a rootfs_image, root= is not changed unless specified. # Even with a rootfs_image, root= is not changed unless specified.
if [[ -n "${FLAGS_rootfs_image}" && -n "${FLAGS_rootfs_hash}" ]]; then if [[ -n "${FLAGS_rootfs_image}" && -n "${FLAGS_rootfs_hash}" ]]; then
info "Determining root fs block count."
# Gets the number of blocks. 4096 byte blocks _are_ expected. # Gets the number of blocks. 4096 byte blocks _are_ expected.
root_fs_blocks=$(sudo dumpe2fs "${FLAGS_rootfs_image}" 2> /dev/null | root_fs_blocks=$(sudo dumpe2fs "${FLAGS_rootfs_image}" 2> /dev/null |
grep "Block count" | grep "Block count" |
tr -d ' ' | tr -d ' ' |
cut -f2 -d:) cut -f2 -d:)
info "Checking root fs block size."
root_fs_block_sz=$(sudo dumpe2fs "${FLAGS_rootfs_image}" 2> /dev/null | root_fs_block_sz=$(sudo dumpe2fs "${FLAGS_rootfs_image}" 2> /dev/null |
grep "Block size" | grep "Block size" |
tr -d ' ' | tr -d ' ' |
cut -f2 -d:) cut -f2 -d:)
info "rootfs is ${root_fs_blocks} blocks of ${root_fs_block_sz} bytes"
if [[ ${root_fs_block_sz} -ne 4096 ]]; then if [[ ${root_fs_block_sz} -ne 4096 ]]; then
error "Root file system blocks are not 4k!" error "Root file system blocks are not 4k!"
fi fi
@ -87,10 +86,10 @@ if [[ -n "${FLAGS_rootfs_image}" && -n "${FLAGS_rootfs_hash}" ]]; then
# the verified boot device. Doing so will claim /dev/sdDP out from # the verified boot device. Doing so will claim /dev/sdDP out from
# under the system. # under the system.
if [[ ${FLAGS_root} = "/dev/dm-0" ]]; then if [[ ${FLAGS_root} = "/dev/dm-0" ]]; then
table=${table//HASH_DEV/\/dev\/sd%D%P} table=${table//HASH_DEV//dev/sd%D%P}
table=${table//ROOT_DEV/\/dev\/sd%D%P} table=${table//ROOT_DEV//dev/sd%D%P}
fi fi
verity_args="dm=\"${table}\"" verity_args="dm=\"vroot none ro,${table}\""
info "dm-verity configuration: ${verity_args}" info "dm-verity configuration: ${verity_args}"
fi fi

View File

@ -99,15 +99,13 @@ EOF
info "Emitted ${SYSLINUX_DIR}/syslinux.cfg" info "Emitted ${SYSLINUX_DIR}/syslinux.cfg"
if [[ ${FLAGS_enable_rootfs_verification} -eq ${FLAGS_TRUE} ]]; then if [[ ${FLAGS_enable_rootfs_verification} -eq ${FLAGS_TRUE} ]]; then
# To change the active target, only this file needs to change. # TODO(wad, tgao) enable usb vbooting with initramfs or device probing.
cat <<EOF | sudo dd of="${SYSLINUX_DIR}/default.cfg" 2>/dev/null warn "USB booting will not use rootfs verification."
DEFAULT chromeos-vusb.A fi
EOF # To change the active target, only this file needs to change.
else cat <<EOF | sudo dd of="${SYSLINUX_DIR}/default.cfg" 2>/dev/null
cat <<EOF | sudo dd of="${SYSLINUX_DIR}/default.cfg" 2>/dev/null
DEFAULT chromeos-usb.A DEFAULT chromeos-usb.A
EOF EOF
fi
info "Emitted ${SYSLINUX_DIR}/default.cfg" info "Emitted ${SYSLINUX_DIR}/default.cfg"
cat <<EOF | sudo dd of="${SYSLINUX_DIR}/usb.A.cfg" 2>/dev/null cat <<EOF | sudo dd of="${SYSLINUX_DIR}/usb.A.cfg" 2>/dev/null

View File

@ -72,8 +72,7 @@ if ! type -p update_x86_bootloaders; then
sudo dd of="${esp_fs_dir}"/efi/boot/grub.cfg sudo dd of="${esp_fs_dir}"/efi/boot/grub.cfg
# Rewrite syslinux DM_TABLE # Rewrite syslinux DM_TABLE
usb_target="${FLAGS_usb_disk//\//\\\/}" syslinux_dm_table_usb=${dm_table//\/dev\/${old_root}/${FLAGS_usb_disk}}
syslinux_dm_table_usb=${dm_table//\/dev\/${old_root}/${usb_target}}
sed -e "s|DMTABLEA|${syslinux_dm_table_usb}|g" \ sed -e "s|DMTABLEA|${syslinux_dm_table_usb}|g" \
"${template_dir}"/syslinux/usb.A.cfg | "${template_dir}"/syslinux/usb.A.cfg |
sudo dd of="${esp_fs_dir}"/syslinux/usb.A.cfg sudo dd of="${esp_fs_dir}"/syslinux/usb.A.cfg
@ -84,7 +83,7 @@ if ! type -p update_x86_bootloaders; then
sudo dd of="${esp_fs_dir}"/syslinux/root.A.cfg sudo dd of="${esp_fs_dir}"/syslinux/root.A.cfg
syslinux_dm_table_b=${dm_table//\/dev\/${old_root}/HDROOTB} syslinux_dm_table_b=${dm_table//\/dev\/${old_root}/HDROOTB}
sed -e "s|DMTABLEA|${syslinux_dm_table_a}|g" \ sed -e "s|DMTABLEB|${syslinux_dm_table_b}|g" \
"${template_dir}"/syslinux/root.B.cfg | "${template_dir}"/syslinux/root.B.cfg |
sudo dd of="${esp_fs_dir}"/syslinux/root.B.cfg sudo dd of="${esp_fs_dir}"/syslinux/root.B.cfg