You are not logged in.

#1 2021-02-27 09:20:41

tameddysphoria
Member
Registered: 2020-01-19
Posts: 4

Building a initramfs hook that relies on variables and blkid but fails

What I am trying to achieve..
So basically I am trying to build a hook that recognises the available block devices, compares them to a list of known UUIDs; and then uses the associated non-persistent device id to the device to create a file that was split and hidden in several locations on that device. The reason for using the non-persistent ID was because I ran into a lot of trouble trying to figure out how to address a whole device in a consistent way and ended just matching the UUIDs to the non-persistent ID.

What I think the issue is..
I think the issue is either something about variables just works differently in /bin/busybox (if so I can't find the documentation). OR Something about the user level of the hook prevents the output of 'blkid'. OR Despite my mkiniticipio.conf config, the hook build config, I still failed to get the modules and binaries correctly configured.

So yeah... please help? because I am completely out of ideas as to what I am doing wrong

My hook
BTW, I know the syntax is all over the place and I can use piping and condense this a lot. I will rewrite this before implementation. The current structure is a result of me trying to figure out WTF I was doing wrong/was going wrong and writing it in a way for me to follow where things break. FYI things break here blkid > /mnt/ramdisk/ABD, and variables don't seem to work either...

#!/usr/bin/ash
run_hook() {
	modprobe dm-crypt -a -q dm-crypt >/dev/null 2>&1
	modprobe loop
	modprobe uas
	modprobe ehci_hcd
	modprobe uhci_hcd
	modprobe usb_storage

	mkdir -p /mnt/ramdisk
	mount -t tmpfs -o size=512m tmpfs /mnt/ramdisk

	blkid > /mnt/ramdisk/ABD

	grubdevp1="n"
	until [ "$grubdevp1" = "y" ]; do
		if [ ! -e "/mnt/ramdisk/ANBD" ]; then
			grep -f /files/grubdev.lookup /mnt/ramdisk/ABD > /mnt/ramdisk/ANBD
		elif [ -e "/mnt/ramdisk/ANBD" ]; then
			if [ "cat /mnt/ramdisk/ANBD" != "$?" ]; then #Pass=output
				rm /mnt/ramdisk/ABD
				grubdevp1="y"
			elif [ "cat /mnt/ramdisk/ANBD" = "$?" ]; then #Pass=no output
				sleep 1
				echo "/mnt/ramdisk/ANBD gen failed retrying"
			fi
		fi
	done
	if [ "cat /mnt/ramdisk/ANBD" = "$?" ]; then #Pass=no output
		echo "All attempts failed"
	fi

	grubdevp2="n"
	until [ "$grubdevp2" = "y" ]; do
		if [ ! -e "/mnt/ramdisk/AGBD" ]; then
			grep -E -o '\/dev\/sd[a-z]+' /mnt/ramdisk/ANBD >> /mnt/ramdisk/AGBD
			grep -E -o '\/dev\/mmcblk[0-9]+' /mnt/ramdisk/ANBD >> /mnt/ramdisk/AGBD
			grep -E -o '\/dev\/nvme[0-9]n[0-9]+' /mnt/ramdisk/ANBD >> /mnt/ramdisk/AGBD
		elif [ -e "/mnt/ramdisk/AGBD" ]; then
			if [ "cat /mnt/ramdisk/AGBD" != "$?" ]; then #Pass=output
				rm /mnt/ramdisk/ANBD
				grubdevp2="y"
			elif [ "cat /mnt/ramdisk/AGBD" = "$?" ]; then #Pass=no output
				sleep 1
				echo "/mnt/ramdisk/AGBD gen failed retrying"
			fi
		fi
	done
	if [ "cat /mnt/ramdisk/AGBD" = "$?" ]; then #Pass=no output
		echo "All attempts failed"
	fi
	
	if [ "cat /mnt/ramdisk/AGBD" != "$?" ]; then
		old_IFS="$IFS"
		IFS="$'\n'" grubdevarray="$(</mnt/ramdisk/AGBD)"
		elcount="${#grubdevarray[@]}"
			if [ "$elcount" != "1" ]; then
				echo "The number of available grub devices is equal to "${#grubdevarray[@]}". This script will not work correctly if this value is not equal to 1"
			elif [ "$elcount" = "1" ]; then
				echo "A single compatible grub block device was detected. Proceeding to decryption."
				grubdevpass="y"
				grubdev="$(</mnt/ramdisk/AGBD)"
			fi
		IFS="${old_IFS}"
	else
		echo "Output of test for known devices yielded result incompatible with parameters of decryption hook for known grub devices." ; echo "See below" ;	echo "" ; echo "" ; echo "/mnt/ramdisk/ABD" ; echo "" ; cat /mnt/ramdisk/ABD ; echo "" ; echo "" ; echo "/mnt/ramdisk/ANBD" ; echo "" ; cat /mnt/ramdisk/ANBD ; echo "" ; echo "" ; echo "/mnt/ramdisk/ARBD" ; echo "" ; cat /mnt/ramdisk/AGBD ; sleep 20
	fi
	if [ "$grubdevpass" = "y" ]; then
		sleep "0.5"
		dd if=$grubdev skip="###" of=/mnt/ramdisk/CryptStor.kf bs=512 count="#" conv=notrunc 1>/dev/null
		sleep "0.5"
		dd if=$grubdev skip="###" seek="###" of=/mnt/ramdisk/CryptStor.kf bs=512 count="#" conv=notrunc 1>/dev/null
		sleep "0.5"
		dd if=$grubdev skip="###" seek="###" of=/mnt/ramdisk/CryptStor.kf bs=512 count="#" conv=notrunc 1>/dev/null
		sleep "0.5"
		dd if=$grubdev skip="###" seek="###" of=/mnt/ramdisk/CryptStor.kf bs=512 count="#" conv=notrunc 1>/dev/null
		sleep "0.5"
		cryptsetup luksOpen --key-file=/mnt/ramdisk/CryptStor.kf "$grubdev""#" BootCrypt
		sleep 1
		mkdir -p /mnt/BootCrypt
		sleep "0.5"
		mount /dev/mapper/BootCrypt /mnt/BootCrypt
	else
		echo "grubdevpass failed"
	fi
}.

My Build Hook
It is a modified 'encrypt' hook

#!/bin/bash

build() {
    local mod

    add_module "dm-crypt"
    add_module "dm-integrity"
    add_module "uas"
    add_module "ehci_hcd"
    add_module "uhci_hcd"
    add_module "usb_storage"
    if [[ $CRYPTO_MODULES ]]; then
        for mod in $CRYPTO_MODULES; do
            add_module "$mod"
        done
    else
        add_all_modules "/crypto/"
    fi

    add_binary "cryptsetup"
    add_binary "dmsetup"
    add_binary "blkid"
    add_file "/usr/lib/udev/rules.d/10-dm.rules"
    add_file "/usr/lib/udev/rules.d/13-dm-disk.rules"
    add_file "/usr/lib/udev/rules.d/95-dm-notify.rules"
    add_file "/usr/lib/initcpio/udev/11-dm-initramfs.rules" "/usr/lib/udev/rules.d/11-dm-initramfs.rules"

    # cryptsetup calls pthread_create(), which dlopen()s libgcc_s.so.1
    add_binary "/usr/lib/libgcc_s.so.1"

    add_runscript
}

help() {
    cat <<HELPEOF
This hook allows for an encrypted root device. Users should specify the device
to be unlocked using 'cryptdevice=device:dmname' on the kernel command line,
where 'device' is the path to the raw device, and 'dmname' is the name given to
the device after unlocking, and will be available as /dev/mapper/dmname.

For unlocking via keyfile, 'cryptkey=device:fstype:path' should be specified on
the kernel cmdline, where 'device' represents the raw block device where the key
exists, 'fstype' is the filesystem type of 'device' (or auto), and 'path' is
the absolute path of the keyfile within the device.

Without specifying a keyfile, you will be prompted for the password at runtime.
This means you must have a keyboard available to input it, and you may need
the keymap hook as well to ensure that the keyboard is using the layout you
expect.
HELPEOF
}
# vim: set ft=sh ts=4 sw=4 et:.

My mkinitcpio.conf

MODULES=(uas ehci_hcd uhci_hcd usb_storage dm-crypt loop dm_mod ahci ext4)
BINARIES=(blkid) #this may not be needed. Test it!
FILES=(/files/grubdev.lookup /files/rootdev.lookup)
#HOOKS=(base udev block keyboard autodetect modconf keymap myhook lvm2 filesystems fsck)
HOOKS=(base udev autodetect modconf block filesystems keyboard keymap fsck myhook lvm2).

Thank you humanoids for going through this and telling me how I am a dumb dumb, if you can...

Offline

#2 2021-02-27 11:43:00

Ropid
Member
Registered: 2015-03-09
Posts: 1,069

Re: Building a initramfs hook that relies on variables and blkid but fails

I don't know anything about this, but I noticed you have a "." at the very end of the code you posted here, at the end of the run_hook() function after the "}". Is that "." also in your real file? That would then be a mistake.

Offline

#3 2021-03-04 00:59:38

tameddysphoria
Member
Registered: 2020-01-19
Posts: 4

Re: Building a initramfs hook that relies on variables and blkid but fails

That was an artifact of the code bracket syntax for the arch forums and my lack of familiarity with its use.

UPDATE:
I am still having issues with my script. I was able to confirm that variables are working fine but it was the change of the shell in the emergency shell that didn't maintain the variables that confused me on that point. This was my own derp. I should have figured this out a lot faster and before posting anything.

As for the issue with blkid not picking up any devices: Through trial and error I was able to get it to recognise the devices by sleeping for 13 secs before the script runs. I think I may need to put this in a loop with a timer though. As I have a weird issue where the time it takes for the blkid command to complete appears to be long enough that I am having trouble cating the output into a file, echoing the output into an array, or piping the output into another command.

Any advice would be appreciated as I have yet to get things working correctly.

Offline

Board footer

Powered by FluxBB