This is the first page of my wiki



Stuff I have been thinking about. General Linux stuff, personal stuff, Arch Linux stuff.

Extend kernel PCR with cmdline

The kernel doesn't checksum the cmdline which would be practical when we are already doing the vmlinuz image


Rewrite efibootmgr in go with go-uefi and improve usability.


Move pacman DbPath to /usr.


Implement .d directory overrides to hooks. We want to consolidate the hooks from several packages.

Kernel module signing

Just generally; how do we solve this without getting tied to a MOK?

Archweb nvchecker integration

Consider nvchecker;

All repositories can have a .NVCHECKER file like below;

source = "github"
github = "golang/go"
prefix = "go"
use_max_tag = true
exclude_regex = ".*(release|weekly|rc|alpha|beta).*"

The top part would be $pkgbase and rest of the configuration follows the nvchecker documentation.

The implementaiton for archweb would be a timer running "python nvchecker" which iterates over all PKGBASEs archweb know about.

We'd look up the following url;

If this file exists we fetch the pkgname, pkgver and the .NVCHECKER file.

We run nvchecker (how this is done.. not sure!) on this and flag OOD if there is a change.


  • How do we deal with secrets? Do we want to deal with secrets?
  • Timer could be once pr day
  • Configurable?

Witness logs

  • monitor
  • lvfs monitor


Misc ideas for sigstore


Needs a monitor given a type and upstream

Migrate transparency log?

Needs git-push certificate support

.pkg.tar support

Native support for pacman, obviously :)

Arch Linux

  • Fix ls-tags for reference replacing

  • repo should take a build order

  • Rewrite repo and buildpkg into Python

  • borg python-packaging new dependency

  • pull-requests in repro

  • crun might need crio as makedepend


  • Missing doc in the example.preset

Package notes

Updating a go dependency in go.sum

$ go mod edit -replace
$ go mod tidy
$ git diff > go-sum.patch


Note: This is not an install guide. Purely personal notes.

Two partition: gdisk /dev/nvme0n1

  • EFI system partition (ESP)
    • 512M
    • GPT GUID: EF00
  • System partition
    • all available disk
    • GPT GUID: 8304

Important to remember GPT GUIDs since we are using systemd initramfs and discoverable partitions for booting. Relevant for the initramfs section.

  • mkfs.vfat -F32 /dev/nvme0n1p1
  • cryptsetup luksFormat /dev/nvme0n1p2
  • cryptsetup open /dev/nvme0n1p2 root
  • cryptsetup --perf-no_read_workqueue --perf-no_write_workqueue --allow-discards --persistent refresh root
  • mkfs.btrfs /dev/mapper/root

We also add support

btrfs subvolumes

This list is currently inspired by the opensuse BTRFS setup.

  • /@root
  • /home@home
  • /srv@srv
  • /var@var

Note that we are adding @root-snapshots and @home-snapshots for snapper. But later.

Now we are making all the subvolumes. I like doing them on a pivot partitions. We don't care about access time and rest of the flags should be applied by btrfs automatically.

  • mkdir /mnt_tmp
  • mount -o relatime,compress=zstd /dev/mapper/root /mnt_tmp
  • btrfs subvolume create /mnt_tmp/@root

Create for each partition under /mnt_tmp, then umount /mnt_tmp. We also use btrfs subvolume set-default 256 / for systemd initramfs to specify the root subvolume.

Later if we DO need to mount the actual root we need to specify the subvolid 5 which is a magic number: mount -osubvolid=5 /dev/mapper/root /var/btrfs

Then mount each respective directory to /mnt. Don't forget to mount /dev/nvme0n1p1 to /efi.

  • mount -o relatime,compress=zstd,subvol=@root /dev/mapper/root /mnt
  • mount -o relatime,compress=zstd,subvol=@var /dev/mapper/root /mnt/var
  • mount -o relatime,compress=zstd,subvol=@srv /dev/mapper/root /mnt/srv
  • mkdir /mnt/efi
  • mount /dev/nvme0n1p1 /mnt/efi

We mount /dev/nvme0n1p1 to /mnt/efi because we are using the new UEFI stub system for mkinitcpio. See next section :)

This is the base packages. Rest are pulled inn by my system packages.

pacstrap /mnt base base-devel linux linux-firmware btrfs-progs

Create fstab: genfstab -U /mnt >> /mnt/etc/fstab

initramfs - systemd

We do the systemd enabled initramfs. This allows us to simplify boot with discoverable partitions as we used the proper GPT GUIDs during partitioning earlier.

--- /etc/mkinitcpio.conf	2021-08-12 14:54:44.835669088 +0200
+++ /etc/mkinitcpio.conf	2021-07-22 20:30:18.593193125 +0200
@@ -49,7 +49,7 @@
 ##   NOTE: If you have /usr on a separate partition, you MUST include the
 #    usr, fsck and shutdown hooks.
-HOOKS=(base udev autodetect modconf block filesystems keyboard fsck)
+HOOKS=(base systemd autodetect modconf block keyboard sd-encrypt filesystems)

 # Use this to compress the initramfs image. By default, zstd compression

Changes to /etc/mkinitcpio.d/linux.preset. Note this requires mkinitcpio 31 and beyond.

--- /etc/mkinitcpio.d/linux.preset	2021-08-13 18:54:44.835669088 +0200
+++ /etc/mkinitcpio.d/linux.preset	2021-07-22 20:30:18.593193125 +0200
@@ -2,13 +2,10 @@


- PRESETS=('default' 'fallback')
+ PRESETS=('default')

+default_options="--splash /usr/share/systemd/bootctl/splash-arch.bmp"

For the kernel cmdline options we are using /etc/kernel/cmdline as that is what mkinitcpio will be using to read from to create our boot entry.

$ cat /etc/kernel/cmdline
rw quiet acpi_osi= acpi_backlight=thinkpad_screen acpi.ec_no_wakeup=1 nowatchdog

Those options are for my thinkpad. Your mileage might differ. Note that we do not specify disk UUIDs because systemd is going to figure out that for us automagically.

Regenerate the linux iniramfs with mkinitcpio so we get our options mkinitcpio -P. The important part is to have the UEFI stub generation.

==> Starting build: 5.13.10-arch1-1
  -> Running build hook: [base]
  -> Running build hook: [systemd]
  -> Running build hook: [autodetect]
  -> Running build hook: [modconf]
  -> Running build hook: [block]
  -> Running build hook: [keyboard]
  -> Running build hook: [sd-encrypt]
  -> Running build hook: [filesystems]
==> Generating module dependencies
==> Creating zstd-compressed initcpio image: /boot/initramfs-linux.img
==> Image generation successful
==> Creating UEFI executable: /efi/EFI/Linux/arch-linux.efi
  -> Using UEFI stub: /usr/lib/systemd/boot/efi/linuxx64.efi.stub
  -> Using kernel image: /lib/modules/5.13.10-arch1-1/vmlinuz
  -> Using os-release file /etc/os-release
==> UEFI executable generation successful


# bootctl install
Created "/efi/loader/entries".
Copied "/usr/lib/systemd/boot/efi/systemd-bootx64.efi" to "/efi/EFI/systemd/systemd-bootx64.efi".
Copied "/usr/lib/systemd/boot/efi/systemd-bootx64.efi" to "/efi/EFI/BOOT/BOOTX64.EFI".
Created "/efi/60a1f123aa5f451f8af104e458838efb".
Random seed file /efi/loader/random-seed successfully written (512 bytes).
Created EFI boot entry "Linux Boot Manager".
# efibootmgr -v // verify it works
BootCurrent: 0000
Timeout: 0 seconds
BootOrder: 0000
Boot0000* Linux Boot Manager	HD(1,GPT,d78d8c94-d277-4635-a73c-a68cd6ddb6ab,0x800,0xff801)/File(\EFI\systemd\systemd-bootx64.efi)


Tips and Tricks

Run makepkg as sudo

Never actually use this: env EUID=1000 makepkg -srcf

Disable work queues for cryptsetup

cryptsetup sector size

λ ~ » sudo blockdev --getpbsz /dev/nvme0n1
λ ~ » sudo nvme id-ns -H /dev/nvme0n1
LBA Format  0 : Metadata Size: 0   bytes - Data Size: 512 bytes - Relative Performance: 0 Best (in use)
                                                      ^^^^^^^^^ sector size
λ ~ » sudo cryptsetup luksDump /dev/nvme0n1p2 | grep sector
	sector: 512 [bytes]

This should be autoselected with new cryptsetup. But not sure if this applies to NVME? Note for the future: Get a NVME which supports sector size 4096?


Test package for /etc/kernel/cmdline.d for laptop specific settings

misc stuff

xdg-mime default org.pwmt.zathura.desktop application/pdf
xdg-settings set default-web-browser org.qutebrowser.qutebrowser.desktop

Benchmarking BTRFS

This is some sporadic notes about looking at read/write speeds on btrfs with encryption and some recent features.

fio --rw={read,write} --ioengine=io_uring --bs=512k --size=100g --numjobs=1 --direct=1 --runtime=60 --name -test-btrfs

NB: Tests where just ran once or twice. Hardly science.

TL;DR: Compression doesn't matter. Any improvements in the encryption space is the important part.

No encryption

Baseline (btrfs, no compression)

Seqread: 1417 MiB/s Seqwrite: 2116 MiB/s

Btrfs + zstd:3

Seqread: 1340 MiB/s Seqwrite: 2025 MiB/s

Btrfs + zstd:1

Seqread: 1388 MiB/s Seqwrite: 2168 MiB/s



Baseline (btrfs, no compression)

Seqread: 605 MiB/s Seqwrite: 777 MiB/s

Btrfs + zstd:3

Seqread: 642 MiB/s Seqwrite: 736 MiB/s

Btrfs + zstd:1

Seqread: 605 MiB/s Seqwrite: 780 MiB/s

Encryption - --perf-no_{write,read}_workqeue

Defaults + --perf. Note: I skipped compression after this point. It doesn't matter.

Baseline (btrfs, no compression)

Seqread: 561 MiB/s Seqwrite: 808 MiB/s

Btrfs + zstd:3

Seqread: 607 MiB/s Seqwrite: 802 MiB/s

Encryption - --perf-no_{write,read}_workqeue + 4k sector size

Btrfs + zstd:3

Seqread: 746 MiB/s Seqwrite: 1500 MiB/s



Manages packages


Manages repositories


Manages builds


  • --repository

  • --commit

  • --nobump

  • --nocheck

  • buildctl rebuild [DEPENDENCY]|[SO-NAME] Flags --order

  • buildctl todo [URL]


Reduce package size

Remove test files.

Split race and dynlibs into seperate packages? This would reduce the overall size to around 200 MB.


Depends on Include = /etc/repositories.d/*.conf is appended to pacman.conf

$ prm list
Available repositories:

    Maintainer: George Rawlinson
    Description: AUR packages maintained by the user as well as some experimental packages.
    Key-ID: 9D120F4AAF400B8313A87EF2369552B2069123EE

    Maintainer: Orhun Parmaksiz
    Description: Personal repository with AUR and custom packages.
    Key-ID: N/A

$ prm select grawlinson
Writing to /etc/repositories.d/grawlinson.conf

$ prm show
Selected repositories:

* [grawlinson]


This is me learning about firewalld and networkmanager

Supply Chain Security

Research and projects around Transparency Logs


This is just some notes about my gnupg keys.

Key Setup

  • rsa4096/9C02FF419FECBE16
    • card-no: 0006 07800345
    • Certificate / Signing
  • rsa4096/DF2502D0C726D1C0
    • card-no: 0006 07800345
    • Encryption
  • rsa4096/06F6BDC766FCDC53
    • card-no: 0006 07800345
    • Auth
  • rsa4096/E742683BA08CB2FF
    • Signing

Revoked Keys

  • rsa4096/41A82494FF2B717B
    • this key was a mistake

openssl rand -hex 32 > token

ssh-keygen -Y sign -n ownership-proof -f ~/.ssh/id_ed25519 token

ssh-keygen -Y verify -n ownership-proof -f <(echo 'kyrias ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFIHU6QpZkcnicveoF7UjfhaEH93YmgrVLV6v7mXbjkJ') -I kyrias -s token.sig < token

Secure Boot

This is some notes regarding secure boot quirks and misc issues I encounter.


Microsoft Authenticode apparently relied on crc in ancient iterations. This is important because this implies padding has no effect on checksums, thus the resulting X509 certificate we append to the binaries.

However with cryptographic checksums these do affect the resulting checksum.

This is with Trammells checksum patch:

λ signtest » sbsign --hash-only ./fwupdx64.efi # No certificates
λ signtest » sbsign --hash-only ./fwupdx64.efi.signed.gosign # Has certificates

This is made more explicit with pesign:

λ signtest » pesign --hash --nopadding --in ./fwupdx64.efi
./fwupdx64.efi 788408ea495d2cd55f6d2d3b5e5d56e130c738917068f9e40b07d69ae79dfd51
λ signtest » pesign --hash --padding --in ./fwupdx64.efi
./fwupdx64.efi 33c1bfe9f9d60822df8c099f88ee841ded43f80471b71a9c2ec65a9a4a2ec132

This implies that if you where to enroll a SHA256 sum into the db security database, the checksum would be different depending if the binary has an certificate or not. "Yay".

sbverify doesn't need to care about this distinction since it will never actually have to deal with unsigned executables. Thus it can only care about the padded binaries.

Eventlogs and OpROM


Secure Boot uses two types of signatures. PKCS7 and CMS.

CMS is mandated by Microsoft Authenticode

Security Expectations in Linux

Secure Boot History

  • MOK was invented by SUSE (see mjg blogpost)
    • MOK gives back the key management control to users and/or security admins
  • shim was written for security pivot
    • Can't be GPL licensed since the key material is part of the source


  • shim
    • loads the grub2 binary
  • MOKList
    • user enabled db autorization list
  • MokManager
    • UEFI program to manipulate the MOK database
  • mokutil
    • Userspace utility to issue requests to MokManager

Kernel Module Signing

Work in Progress

UEFI certificate stores

  • MOK - Machine Owner Keys
  • db - UEFI key database


  • .builtin_trusted_keys
  • .secondary_trusted_keys
  • .platform
  • .ima
  • .blacklist


machine owners -> end users


Impute -> to attribute or credit to

Impute value to something. Impute value to academics

Impute value to keys?

Imputed trust vs Transitive trust

Source of trust in the kernel

3 Built in sources of trust:

  • Built-in trust
    • Inherent to the system
  • Imputed trust
    • Where did it come from?
  • Transitive trust
    • Who is vouching for it?

Kernel keyrings

  • .builtin_trusted keys

    • built-in trust
    • Keys fixed at build time
    • Stored in the kernel image
    • Added to reserved memory in the kernel, then the kernel is signed
  • .platform and .machine

    • Imputed trust
    • User-provided machine owner keys (MOK) impute trust to keys in the machine keyring
  • .secondary_trusted_keys

    • Transitive
    • Any key signed by a key that's already trusted is automatically trusted
    • If a CAs key is trusted, then all the keys signed by that CA are trusted
    • CAs are here imputed trust


  • .builtin_trusted

    • Built-in trust by being compiled or inserted into the kernel
    • Used to verify:
      • keys
      • kernel modules
      • kexec'd kernel images
  • .secondary_trusted_keys

    • Transitive trust from the root user(?)
    • Used to verify:
      • keys
      • kernel modules
      • kexec'd kernel images
  • .ima

    • Transitive trust:
      • Root user
      • Signed by .built-intrusted_keys or .secondary_trusted_keys
    • Used to verify:
      • kexecd kernel images
      • kernel modules
      • files
    • Disabled when .machine is configured (see below)
  • .blacklist

    • Built-in trust
    • Imputed Trust:
      • UEFI secure boot (dbx)
      • MOK dbx
      • Root user (? patch series)
    • Blocks:
      • File digests
      • Certificate TBS(?)
  • .platform

    • Imputed trust:
      • UEFI secure boot firmware,
      • Machine Owner Keys
    • Used to verify:
      • kexecd kernel images
  • .machine

    • With v5.18
    • Imputed Trust:
      • Management system
      • Machine Owner Keys (MOK)
      • (Conditionally on kernel config and UEFI variables)
    • Linked to secondary_trusted_keys


Kernel configs



Introduced: dm verity: Add support for signature verification with 2nd keyring

db-verity signatures can be verified against the secondary trusted keyring.


Introduced: integrity: Introduce a Linux keyring called machine

Load keys from MOK and db into the machine keyring. Optionally able to trust them in a later patch.


Introduced: x86/ima: require signed kernel modules

Enforce kernel module signatures when secure boot is enabled. This kernel overrides the lockdown LSM. (See another section)

Loading Secure Boot keys into something trusted

The goal is to have some use supplied keys we can use for validating kernel modules. mokutils can load a signature list into MokListRT, and if MokTrustedRT is set with mokutil --trusted then we append any keys from the MOK List into the machine keyring.

The issue is that the shim binary throws all Mok* variables into an EFI configuration table. See import_mok_state.

First the kernel attempts to read the MokListRT variable from the EFI configuration table. If this list is not found, it will attempt to read it from efivarfs. This is fine as we will end up reading this list into the platform keyring by default. But the platform keyring is not the keyring we will be using to validate kernel modules.

If we want the kernel to read the certificate list into the machine keyring, we will query the MokListTrustedRT from the EFI configuration table only. This means we are bound to the shim loading the variable during early boot, and can't trust this set of certificates without utilizing the shim.

Note: There are fallbacks to diglim and other LSM hooks, but not investigated stuff there yet.

Relevant code snippets

static int __init load_moklist_certs(void)
	mokvar_entry = efi_mokvar_entry_find("MokListRT");
	if (mokvar_entry) {
		rc = parse_efi_signature_list("UEFI:MokListRT (MOKvar table)",

	mok = get_cert_list(L"MokListRT", &mok_var, &moksize, &status);
	if (mok) {
		rc = parse_efi_signature_list("UEFI:MokListRT",
					      mok, moksize, get_handler_for_mok);

__init efi_element_handler_t get_handler_for_mok(const efi_guid_t *sig_type)
	if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0) {
			return add_to_machine_keyring;
			return add_to_platform_keyring;
	return NULL;
  • security/integrity/platform_certs/load_uefi.c:load_moklist_certs
  • security/integrity/platform_certs/keyring_handler.c:get_handler_for_mok
  • security/integrity/platform_certs/machine_keyring.c:trust_moklist
  • security/integrity/platform_certs/machine_keyring.c:uefi_check_trust_mok_keys

Kernel module validation

is_module_sig_enforced (enforced by ARCH_POLICY)

if false

call LSM hook into lockdown: security_locked_down(LOCKDOWN_MODULE_SIGNATURE)
  • kernel/module/signing.c:module_sig_check

  • lockdown_mode=integrity -> deny module loading

  • Is there others?

Lockdown implementation




  • Rename hook form ZZ to zz

Figure out UEFI Class 3+

We need a reliable way to tell if the CPU is post 2020'ish and carries oprom.

  • Parse TPM Eventlog
  • Scan for known issues?
  • Laptop models

Subcommand: expert

Debug information. Read out variables WIP/POC functionality

Should be hidden by default?

sbctl expert enroll
    --pk, --kek, --db, --dbx

sbctl expert print
sbctl enroll-keys --vendor-keys="vendor microsoft"
sbctl enroll-keys --enroll-oprom

Subcommand: setup

Subcommand: rotate-key

resolved and dns-sd

Some quick notes about how to resolve dns-sd services with resolved. This is mostly handy for scripting things like chromecast lookups without having to have avahi and such installed.

λ bin » resolvectl --type=PTR query _googlecast._tcp.local
_googlecast._tcp.local IN PTR Chromecast-Ultra-e6437103e5d642323014c80ddffc76dc._googlecast._tcp.local -- link: enp0s31f6

Link collections

Mic Secure Attestation

DRTM on Linux


Talks from me

This is a list of all the live records of talks I have held. Apparently there are more then one :o

Slides for my presentations can be found in my talks repository.


Open Source Firmware Conference

BSides Oslo




Bergen Linux User Group




# sudo modprobe v4l2loopback video_nr=4,5 max_buffers=2 exclusive_caps=1,1
# gphoto2 --set-config /main/actions/autofocus=1
# gphoto2 --stdout --capture-movie | gst-launch-1.0 fdsrc ! decodebin3 name=dec ! queue !  videoconvert ! v4l2sink device=/dev/video4

gstreamer notes

Split one v4l2 device into two other video devices:

λ ~ » gst-launch-1.0 v4l2src device=/dev/video0 ! tee name=t \
t. ! queue ! videoconvert ! v4l2sink device=/dev/video4 \
t. ! queue ! videoconvert ! v4l2sink device=/dev/video5

Usecase: Record webcam/camera in OBS while also having it in video conferencing

Using v4l2loopback to make new devices.

sudo modprobe v4l2loopback video_nr=4,5 max_buffers=2 exclusive_caps=1,1

Capture video from gphoto2

$ gphoto2 --stdout --capture-movie | gst-launch-1.0 fdsrc ! decodebin3 ! queue !  videoconvert ! v4l2sink device=/dev/video4