diff mbox series

[next,1/3] fs/common.mk: add optional hook to build a verity hash tree

Message ID 20260831125103.841338-1-fiona.klute@gmx.de
State New
Headers show
Series [next,1/3] fs/common.mk: add optional hook to build a verity hash tree | expand

Commit Message

Fiona Klute Aug. 31, 2026, 12:51 p.m. UTC
From: "Fiona Klute (othermo GmbH)" <fiona.klute@gmx.de>

Using dm-verity may be useful for any read-only filesystem read from a
block device, the new hook will build the required hash tree if
enabled by a per-filesystem config option.

Signed-off-by: Fiona Klute (othermo GmbH) <fiona.klute@gmx.de>
---
The change is small, but it's a new feature, so I assume it's for next.
;-)

 fs/common.mk | 9 +++++++++
 1 file changed, 9 insertions(+)

Comments

Peter Korsgaard Aug. 31, 2026, 7:16 p.m. UTC | #1
>>>>> "Fiona" == Fiona Klute via buildroot <buildroot@buildroot.org> writes:

 > From: "Fiona Klute (othermo GmbH)" <fiona.klute@gmx.de>
 > Using dm-verity may be useful for any read-only filesystem read from a
 > block device, the new hook will build the required hash tree if
 > enabled by a per-filesystem config option.

 > Signed-off-by: Fiona Klute (othermo GmbH) <fiona.klute@gmx.de>
 > ---
 > The change is small, but it's a new feature, so I assume it's for next.
 > ;-)

 >  fs/common.mk | 9 +++++++++
 >  1 file changed, 9 insertions(+)

 > diff --git a/fs/common.mk b/fs/common.mk
 > index 2f3f8bcc7e..794423476d 100644
 > --- a/fs/common.mk
 > +++ b/fs/common.mk
 > @@ -215,6 +215,15 @@ TARGETS_ROOTFS += rootfs-$(1)
 >  PACKAGES += $$(filter-out rootfs-%,$$(ROOTFS_$(2)_FINAL_RECURSIVE_DEPENDENCIES))
 >  endif
 
 > +ifeq ($$(BR2_TARGET_ROOTFS_$(2)_VERITY),y)
 > +ROOTFS_$(2)_DEPENDENCIES += host-cryptsetup
 > +define ROOTFS_$(2)_VERITY_FORMAT
 > +	@$$(call MESSAGE,"Generating verity hash tree $$(@F).verity")
 > +	$(HOST_DIR)/sbin/veritysetup format --root-hash-file $$@.verity.root-hash $$@ $$@.verity

What about the user configurable settings such as hash/data block size,
uuid, salt, ...?
Fiona Klute Aug. 31, 2026, 9:10 p.m. UTC | #2
Am 31.08.26 um 21:16 schrieb Peter Korsgaard:
>>>>>> "Fiona" == Fiona Klute via buildroot <buildroot@buildroot.org> writes:
> 
>   > From: "Fiona Klute (othermo GmbH)" <fiona.klute@gmx.de>
>   > Using dm-verity may be useful for any read-only filesystem read from a
>   > block device, the new hook will build the required hash tree if
>   > enabled by a per-filesystem config option.
> 
>   > Signed-off-by: Fiona Klute (othermo GmbH) <fiona.klute@gmx.de>
>   > ---
>   > The change is small, but it's a new feature, so I assume it's for next.
>   > ;-)
> 
>   >  fs/common.mk | 9 +++++++++
>   >  1 file changed, 9 insertions(+)
> 
>   > diff --git a/fs/common.mk b/fs/common.mk
>   > index 2f3f8bcc7e..794423476d 100644
>   > --- a/fs/common.mk
>   > +++ b/fs/common.mk
>   > @@ -215,6 +215,15 @@ TARGETS_ROOTFS += rootfs-$(1)
>   >  PACKAGES += $$(filter-out rootfs-%,$$(ROOTFS_$(2)_FINAL_RECURSIVE_DEPENDENCIES))
>   >  endif
>   
>   > +ifeq ($$(BR2_TARGET_ROOTFS_$(2)_VERITY),y)
>   > +ROOTFS_$(2)_DEPENDENCIES += host-cryptsetup
>   > +define ROOTFS_$(2)_VERITY_FORMAT
>   > +	@$$(call MESSAGE,"Generating verity hash tree $$(@F).verity")
>   > +	$(HOST_DIR)/sbin/veritysetup format --root-hash-file $$@.verity.root-hash $$@ $$@.verity
> 
> What about the user configurable settings such as hash/data block size,
> uuid, salt, ...?
How about an _EXTRA_ARGS option? I think adding options for all possible 
parameters would be a lot of code for little gain.

For hash algorithm a specific option might sense if we could use that to 
ensure the matching hash is enabled in the kernel. But that'd require 
adding LINUX_CONFIG_FIXUPS infrastructure for fs/, not sure if worth it? 
Though enabling filesystems selected for rootfs in the kernel could be 
useful, too (I've been there, changed rootfs and forgot to enable it in 
the kernel – not often, but it happens).

The one reason I can imagine wanting to set uuid/salt is if someone 
wants a byte-identical verity partition. fs/erofs sets all-zero UUID, 
which we could do for verity too, but I'm not sure what the security 
implications of a fixed (or pseudorandom?) salt would be.

Best regards,
Fiona
Peter Korsgaard Sept. 1, 2026, 6:41 a.m. UTC | #3
>>>>> "Fiona" == Fiona Klute <fiona.klute@gmx.de> writes:

Hi,

 > How about an _EXTRA_ARGS option? I think adding options for all
 > possible parameters would be a lot of code for little gain.

Possibly, but should that then be per-fs or global? I wonder if it is
worth the complexity to add this logic versus how fairly simple it is to
just do it with whatever options you want in a post-image script.


 > For hash algorithm a specific option might sense if we could use that
 > to ensure the matching hash is enabled in the kernel. But that'd
 > require adding LINUX_CONFIG_FIXUPS infrastructure for fs/, not sure if
 > worth it? Though enabling filesystems selected for rootfs in the
 > kernel could be useful, too (I've been there, changed rootfs and
 > forgot to enable it in the kernel – not often, but it happens).

I would be OK with that. These fixups are a bit icky though as we do not
know what kernel version will be used and the dependencies may change
over time - So maintenance and testing is not so trivial.


 > The one reason I can imagine wanting to set uuid/salt is if someone
 > wants a byte-identical verity partition. fs/erofs sets all-zero UUID,
 > which we could do for verity too, but I'm not sure what the security
 > implications of a fixed (or pseudorandom?) salt would be.

Yes, it is also only in the context of reproducible builds that I have
ever used a fixed uuid/salt.

Security wise, as this is about hashing rather than encryption I *THINK*
it is fine as long as the hashing algorithm is strong enough (E.G. you
would need find same-size collisions).
Fiona Klute Sept. 1, 2026, 10:26 a.m. UTC | #4
Hi Peter!

Am 01.09.26 um 08:41 schrieb Peter Korsgaard:
>>>>>> "Fiona" == Fiona Klute <fiona.klute@gmx.de> writes:
>   > How about an _EXTRA_ARGS option? I think adding options for all
>   > possible parameters would be a lot of code for little gain.
> 
> Possibly, but should that then be per-fs or global? I wonder if it is
> worth the complexity to add this logic versus how fairly simple it is to
> just do it with whatever options you want in a post-image script.

I'd say per-fs. The logic could be shared like the general veritysetup 
call, just the option would need to be added for each fs (in Config.in). 
I don't think Kconfig has a kind of templating for that?

I agree running veritysetup in a post-image script isn't very 
complicated. Where I'm actually trying to do is to have the roothash of 
my rootfs before building an initramfs (using 
BR2_TARGET_ROOTFS_CPIO_DRACUT), so it can be included (and signed along 
with the initramfs, in my case in a FIT image). Of course these patches 
don't achieve that, they'd just provide the roothash as a start.

If you have a better idea how to do that I'm all ears. Post-build script 
can't do it (rootfs image isn't ready), post-image doesn't have the 
fakeroot environment for running Dracut (and other setup [1]). Maybe we 
should move building initramfs to a separate stage, after rootfs (I'd 
definitely need to order cpio after other fs types), and add a 
pre-initramfs script? Is there another non-messy way to use the fakeroot 
environment and variables from Buildroot config that I've missed so far 
(other than rules in external.mk)?

>   > For hash algorithm a specific option might sense if we could use that
>   > to ensure the matching hash is enabled in the kernel. But that'd
>   > require adding LINUX_CONFIG_FIXUPS infrastructure for fs/, not sure if
>   > worth it? Though enabling filesystems selected for rootfs in the
>   > kernel could be useful, too (I've been there, changed rootfs and
>   > forgot to enable it in the kernel – not often, but it happens).
> 
> I would be OK with that. These fixups are a bit icky though as we do not
> know what kernel version will be used and the dependencies may change
> over time - So maintenance and testing is not so trivial.

Yeah, and for something that you'll usually set up once and update only 
rarely, which is why I'm not sure it's worth it. And many filesystems 
have extra kernel options we can't guess anyway.

>   > The one reason I can imagine wanting to set uuid/salt is if someone
>   > wants a byte-identical verity partition. fs/erofs sets all-zero UUID,
>   > which we could do for verity too, but I'm not sure what the security
>   > implications of a fixed (or pseudorandom?) salt would be.
> 
> Yes, it is also only in the context of reproducible builds that I have
> ever used a fixed uuid/salt.
> 
> Security wise, as this is about hashing rather than encryption I *THINK*
> it is fine as long as the hashing algorithm is strong enough (E.G. you
> would need find same-size collisions).

I don't *see* any huge problem either, but making a fixed salt the 
default seems risky. If someone sets that via an _EXTRA_ARGS option 
that's their responsibility. ;-)

Best regards,
Fiona


[1] I have a bunch of fixes lined up to add environment variables Dracut 
needs for cross-building, but some will need the next Dracut release 
(unless we want to add a lot of patches), and the others aren't very 
useful on their own. Biggest still-open chunk: 
https://github.com/dracut-ng/dracut/pull/2588
Peter Korsgaard Sept. 1, 2026, 11:38 a.m. UTC | #5
>>>>> "Fiona" == Fiona Klute <fiona.klute@gmx.de> writes:

Hi,

 >> Possibly, but should that then be per-fs or global? I wonder if it
 >> is
 >> worth the complexity to add this logic versus how fairly simple it is to
 >> just do it with whatever options you want in a post-image script.

 > I'd say per-fs. The logic could be shared like the general veritysetup
 > call, just the option would need to be added for each fs (in
 > Config.in). I don't think Kconfig has a kind of templating for that?

 > I agree running veritysetup in a post-image script isn't very
 > complicated. Where I'm actually trying to do is to have the roothash
 > of my rootfs before building an initramfs (using
 > BR2_TARGET_ROOTFS_CPIO_DRACUT), so it can be included (and signed
 > along with the initramfs, in my case in a FIT image). Of course these
 > patches don't achieve that, they'd just provide the roothash as a
 > start.

 > If you have a better idea how to do that I'm all ears.

The way I have solved it in the past is to use "late" binding between
the kernel and rootfs, E.G. only when I build the FIT image by sticking
the root hash into a u-boot boot script that I generate in my post-image
script and embed in the FIT.

U-Boot can afaik source a boot script from a FIT image nowadays, but I
wanted it more integrated into the bootm flow, so I simply added the
bootscript as a type = "script" data file and referred to it from the
configuration with:

 kernel = "kernel-1";
 fdt = ..
 loadables = "script-1";

And then some trivial logic in my board code to handle such loadable:

/* support "script" loadables in FIT images */
static void board_script_handler(ulong addr, size_t size)
{
        run_command_list((char *)addr, size, 0);
}

U_BOOT_FIT_LOADABLE_HANDLER(IH_TYPE_SCRIPT, board_script_handler);


 > script can't do it (rootfs image isn't ready), post-image doesn't have
 > the fakeroot environment for running Dracut (and other setup [1]).
 > Maybe we should move building initramfs to a separate stage, after
 > rootfs (I'd definitely need to order cpio after other fs types), and
 > add a pre-initramfs script? Is there another non-messy way to use the
 > fakeroot environment and variables from Buildroot config that I've
 > missed so far (other than rules in external.mk)?

Initramfs is indeed annoying because of the circular dependencies. It
has been quite a while since I last used one. Out of interest, what do
you need the initramfs for?


 >> I would be OK with that. These fixups are a bit icky though as we do
 >> not
 >> know what kernel version will be used and the dependencies may change
 >> over time - So maintenance and testing is not so trivial.

 > Yeah, and for something that you'll usually set up once and update
 > only rarely, which is why I'm not sure it's worth it. And many
 > filesystems have extra kernel options we can't guess anyway.

Exactly!


 >> > The one reason I can imagine wanting to set uuid/salt is if someone
 >> > wants a byte-identical verity partition. fs/erofs sets all-zero UUID,
 >> > which we could do for verity too, but I'm not sure what the security
 >> > implications of a fixed (or pseudorandom?) salt would be.
 >> Yes, it is also only in the context of reproducible builds that I
 >> have
 >> ever used a fixed uuid/salt.
 >> Security wise, as this is about hashing rather than encryption I
 >> *THINK*
 >> it is fine as long as the hashing algorithm is strong enough (E.G. you
 >> would need find same-size collisions).

 > I don't *see* any huge problem either, but making a fixed salt the
 > default seems risky. If someone sets that via an _EXTRA_ARGS option
 > that's their responsibility. ;-)

;)
Fiona Klute Sept. 1, 2026, 12:53 p.m. UTC | #6
Am 01.09.26 um 13:38 schrieb Peter Korsgaard:
>>>>>> "Fiona" == Fiona Klute <fiona.klute@gmx.de> writes:
> 
> Hi,
> 
>   >> Possibly, but should that then be per-fs or global? I wonder if it
>   >> is
>   >> worth the complexity to add this logic versus how fairly simple it is to
>   >> just do it with whatever options you want in a post-image script.
> 
>   > I'd say per-fs. The logic could be shared like the general veritysetup
>   > call, just the option would need to be added for each fs (in
>   > Config.in). I don't think Kconfig has a kind of templating for that?
> 
>   > I agree running veritysetup in a post-image script isn't very
>   > complicated. Where I'm actually trying to do is to have the roothash
>   > of my rootfs before building an initramfs (using
>   > BR2_TARGET_ROOTFS_CPIO_DRACUT), so it can be included (and signed
>   > along with the initramfs, in my case in a FIT image). Of course these
>   > patches don't achieve that, they'd just provide the roothash as a
>   > start.
> 
>   > If you have a better idea how to do that I'm all ears.
> 
> The way I have solved it in the past is to use "late" binding between
> the kernel and rootfs, E.G. only when I build the FIT image by sticking
> the root hash into a u-boot boot script that I generate in my post-image
> script and embed in the FIT.

That's exactly what I'm doing for now, with a config for the script in 
the FIT image running "source $loadaddr#set-roothash" works, but it 
seems kind of convoluted. Especially given Dracut explicitly provides 
the option to embed command line options in the initramfs. :D

>   > script can't do it (rootfs image isn't ready), post-image doesn't have
>   > the fakeroot environment for running Dracut (and other setup [1]).
>   > Maybe we should move building initramfs to a separate stage, after
>   > rootfs (I'd definitely need to order cpio after other fs types), and
>   > add a pre-initramfs script? Is there another non-messy way to use the
>   > fakeroot environment and variables from Buildroot config that I've
>   > missed so far (other than rules in external.mk)?
> 
> Initramfs is indeed annoying because of the circular dependencies. It
> has been quite a while since I last used one. Out of interest, what do
> you need the initramfs for?
Right now for setting up that dm-verity device, in the future probably 
dm-crypt, too. If it was *only* dm-verity I could use dm-mod.create 
(assemble parameters like in the test in post-image) and let the kernel 
handle the rest. Systemd has a bunch of automation for it, which is why 
I've been working on fixing Dracut. ;-)

We don't really need the circular dependency, we just have to order the 
initramfs after the rootfs. Kinda crude, but works (in external.mk):

$(BINARIES_DIR)/rootfs.cpio: $(BINARIES_DIR)/rootfs.squashfs

My general idea so far is to add something similar (but generic) 
conditional on BR2_TARGET_ROOTFS_CPIO_DRACUT=y. We might still need a 
script hook, but maybe a custom Dracut module would be enough (e.g. 
build a veritytab/crypttab and install it in the initramfs). I'm still 
working this out. :-)
diff mbox series

Patch

diff --git a/fs/common.mk b/fs/common.mk
index 2f3f8bcc7e..794423476d 100644
--- a/fs/common.mk
+++ b/fs/common.mk
@@ -215,6 +215,15 @@  TARGETS_ROOTFS += rootfs-$(1)
 PACKAGES += $$(filter-out rootfs-%,$$(ROOTFS_$(2)_FINAL_RECURSIVE_DEPENDENCIES))
 endif
 
+ifeq ($$(BR2_TARGET_ROOTFS_$(2)_VERITY),y)
+ROOTFS_$(2)_DEPENDENCIES += host-cryptsetup
+define ROOTFS_$(2)_VERITY_FORMAT
+	@$$(call MESSAGE,"Generating verity hash tree $$(@F).verity")
+	$(HOST_DIR)/sbin/veritysetup format --root-hash-file $$@.verity.root-hash $$@ $$@.verity
+endef
+ROOTFS_$(2)_POST_GEN_HOOKS += ROOTFS_$(2)_VERITY_FORMAT
+endif
+
 # Check for legacy POST_TARGETS rules
 ifneq ($$(ROOTFS_$(2)_POST_TARGETS),)
 $$(error Filesystem $(1) uses post-target rules, which are no longer supported.\