Re: [PATCH v1 2/2] boot: android: Add AVB verification support for different bootflow.

Simon Glass <[email protected]>
Newsgroups org.u-boot-project.lists.u-boot
Message-ID <CAFLszTiPKoju6E60qq5G8m-Lb4h7r+B2SS8V-DjFOetYjyWi9w@mail.gmail.com>
Hi Valentin,

On 2026-08-18T17:53:00, Valentin Liu <[email protected]> wrote:
> boot: android: Add AVB verification support for different bootflow.

Drop the trailing period from the subject.

>
> The different Android versions have their own partition layout,
> so the AVB verification process should be dynamic.
>
> In the new verification process, we need to use the header version
> fetched from boot partition, so we need to check the boot partition
> firstly to avoid the downgrade attacking.
>
> If we didn't check boot firstly, just use it, the attacker can
> bypass the AVB verification by flashing a boot image with header
> version 3 or earlier.

Please use present tense throughout, 'first' rather than 'firstly',
and 'downgrade attack' rather than 'downgrade attacking'. I also don't
follow the security argument: priv->header_version is populated by
scan_boot_part() from the unverified on-disk image and is not re-read
after the first AVB pass, so verifying boot on its own does not change
which partitions the second pass includes - an attacker who can flash
a signed v3 boot image would still get init_boot skipped. Can you
explain what the first pass actually protects against, or is the
intent to re-parse the header from the AVB-verified copy before the
second call?

>
> Signed-off-by: Valentin Liu <[email protected]>
>
> boot/bootmeth_android.c | 43 ++++++++++++++++++++++++++++++++++++++-----
>  1 file changed, 38 insertions(+), 5 deletions(-)

> diff --git a/boot/bootmeth_android.c b/boot/bootmeth_android.c
> @@ -479,11 +479,12 @@ static int avb_append_commandline(struct bootflow *bflow, char *cmdline)
>       return 0;
>  }
>
> -static int run_avb_verification(struct bootflow *bflow)
> +static int run_avb_verification(struct bootflow *bflow, const bool boot_only)

The const on a by-value parameter has no effect on callers and isn't
the style used elsewhere in this file - please drop it.

> diff --git a/boot/bootmeth_android.c b/boot/bootmeth_android.c
> @@ -493,6 +494,28 @@ static int run_avb_verification(struct bootflow *bflow)
>       bool unlocked = false;
>       int ret;
>
> +     /*
> +      * Always verify boot first.
> +      *
> +      * When boot_only is true, only verify the boot partition.
> +      * Otherwise, select additional partitions according to the
> +      * Android boot image header version.
> +      */
> +     requested_partitions[requested_partitions_num++] = "boot";
> +
> +     if (!boot_only) {
> +             if (priv->header_version >= 3)
> +                     requested_partitions[requested_partitions_num++] =
> +                             "vendor_boot";
> +
> +             if (priv->header_version >= 4 &&
> +                 priv->init_boot_img_size > 0)
> +                     requested_partitions[requested_partitions_num++] =
> +                             "init_boot";
> +     }
> +
> +     requested_partitions[requested_partitions_num] = NULL;

Please use BOOT_PART_NAME / VENDOR_BOOT_PART_NAME /
INIT_BOOT_PART_NAME instead of open-coded strings. Also 'n' or 'count'
would read better than requested_partitions_num, and the array bound 4
would benefit from a named constant or a comment for the boot +
vendor_boot + init_boot + NULL layout.

> diff --git a/boot/bootmeth_android.c b/boot/bootmeth_android.c
> @@ -562,9 +585,10 @@ static int run_avb_verification(struct bootflow *bflow)
>       return ret;
>  }
>  #else
> -static int run_avb_verification(struct bootflow *bflow)
> +static int run_avb_verification(struct bootflow *bflow, const bool boot_only)
>  {
>       int ret;
> +     (void)boot_only;

Can you use __maybe_unused on the parameter rather than a (void) cast?
That's the U-Boot convention for stubs.

> diff --git a/boot/bootmeth_android.c b/boot/bootmeth_android.c
> @@ -617,9 +641,13 @@ static int boot_android_normal(struct bootflow *bflow)
>       ulong iloadaddr = env_get_hex("init_boot_comp_addr_r", 0);
>       ulong vloadaddr = env_get_hex("vendor_boot_comp_addr_r", 0);
>
> -     ret = run_avb_verification(bflow);
> +     /*
> +      * Checking the boot partition firstly because the standard AVB
> +      * verification is rely on the header version from boot partition.
> +      */
> +     ret = run_avb_verification(bflow, true);

Grammar: 'Check the boot partition first, because the standard AVB
verification relies on the header version read from the boot
partition.' See my earlier comment - please clarify in the comment and
commit message what the first pass buys us, given that
priv->header_version is not re-read between the two calls.

> diff --git a/boot/bootmeth_android.c b/boot/bootmeth_android.c
> @@ -631,6 +659,11 @@ static int boot_android_normal(struct bootflow *bflow)
>       if (ret < 0)
>               return log_msg_ret("read boot", ret);
>
> +     /* Standard AVB verification */
> +     ret = run_avb_verification(bflow, false);
> +     if (ret < 0)
> +             return log_msg_ret("avb", ret);
> +

This re-verifies boot as well as vendor_boot/init_boot, so the boot
partition (which can be tens of MB) is hashed twice on every boot. Can
you split run_avb_verification() so the second call verifies only the
additional partitions? That would also avoid appending the same
androidboot.vbmeta/verifiedbootstate args twice and relying on
bootflow_cmdline_set_arg() to dedupe by key.

Regards,
Simon
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.