diff mbox series

[v2] fdt: automatically add /chosen/kaslr-seed if DM_RNG is enabled

Message ID 20240515205049.3005256-1-tharvey@gateworks.com
State Superseded
Delegated to: Tom Rini
Headers show
Series [v2] fdt: automatically add /chosen/kaslr-seed if DM_RNG is enabled | expand

Commit Message

Tim Harvey May 15, 2024, 8:50 p.m. UTC
If RANDOMIZE_BASE is enabled in the Linux kernel instructing it to
randomize the virtual address at which the kernel image is loaded, it
expects entropy to be provided by the bootloader by populating
/chosen/kaslr-seed with a 64-bit value from source of entropy at boot.

If we have DM_RNG enabled populate this value automatically when
fdt_chosen is called unless ARMV8_SEC_FIRMWARE_SUPPORT is enabled as
it's implementation uses a different source of entropy.

As this fdt node is added elsewhere create a library function and
use it to deduplicate code.

Note that the kalsrseed command (CMD_KASLRSEED) is likely pointless now
but left in place in case boot scripts exist that rely on this command
existing and returning success. An informational message is printed to
alert users of this command that it is likely no longer needed.

Signed-off-by: Tim Harvey <tharvey@gateworks.com>
---
v2:
 - fix typo in commit msg
 - use stack for seed to avoid unecessary malloc/free
 - move to a library function and deduplicate code by using it elsewhere
---
 board/xilinx/common/board.c | 35 -----------------------------
 boot/fdt_support.c          | 10 +++++++++
 boot/pxe_utils.c            | 35 +++--------------------------
 cmd/kaslrseed.c             | 45 ++++++-------------------------------
 include/kaslrseed.h         | 17 ++++++++++++++
 lib/Makefile                |  1 +
 lib/kaslrseed.c             | 34 ++++++++++++++++++++++++++++
 7 files changed, 72 insertions(+), 105 deletions(-)
 create mode 100644 include/kaslrseed.h
 create mode 100644 lib/kaslrseed.c

Comments

Marek Vasut May 15, 2024, 9:06 p.m. UTC | #1
On 5/15/24 10:50 PM, Tim Harvey wrote:

[...]

> diff --git a/boot/fdt_support.c b/boot/fdt_support.c
> index 874ca4d6f5af..3455d60d69dc 100644
> --- a/boot/fdt_support.c
> +++ b/boot/fdt_support.c
> @@ -8,6 +8,7 @@
>   
>   #include <abuf.h>
>   #include <env.h>
> +#include <kaslrseed.h>
>   #include <log.h>
>   #include <mapmem.h>
>   #include <net.h>
> @@ -300,6 +301,15 @@ int fdt_chosen(void *fdt)
>   	if (nodeoffset < 0)
>   		return nodeoffset;
>   
> +	if (IS_ENABLED(CONFIG_DM_RNG) && !IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)) {
> +		err = fdt_kaslrseed(fdt);
> +		if (err) {
> +			printf("WARNING: could not set kaslr-seed %s.\n",
> +			       fdt_strerror(err));
> +			return err;

Is this warning really a critical boot-breaking error ?

> +		}
> +	}
> +
>   	if (IS_ENABLED(CONFIG_BOARD_RNG_SEED) && !board_rng_seed(&buf)) {
>   		err = fdt_setprop(fdt, nodeoffset, "rng-seed",
>   				  abuf_data(&buf), abuf_size(&buf));

[...]

The rest looks good !
Tim Harvey May 15, 2024, 9:11 p.m. UTC | #2
On Wed, May 15, 2024 at 2:06 PM Marek Vasut <marex@denx.de> wrote:
>
> On 5/15/24 10:50 PM, Tim Harvey wrote:
>
> [...]
>
> > diff --git a/boot/fdt_support.c b/boot/fdt_support.c
> > index 874ca4d6f5af..3455d60d69dc 100644
> > --- a/boot/fdt_support.c
> > +++ b/boot/fdt_support.c
> > @@ -8,6 +8,7 @@
> >
> >   #include <abuf.h>
> >   #include <env.h>
> > +#include <kaslrseed.h>
> >   #include <log.h>
> >   #include <mapmem.h>
> >   #include <net.h>
> > @@ -300,6 +301,15 @@ int fdt_chosen(void *fdt)
> >       if (nodeoffset < 0)
> >               return nodeoffset;
> >
> > +     if (IS_ENABLED(CONFIG_DM_RNG) && !IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)) {
> > +             err = fdt_kaslrseed(fdt);
> > +             if (err) {
> > +                     printf("WARNING: could not set kaslr-seed %s.\n",
> > +                            fdt_strerror(err));
> > +                     return err;
>
> Is this warning really a critical boot-breaking error ?

no, and in fact I'm printing a warning inside of fdt_kaslrseed so I
can remove the duplication of error prints in the various other places
it's called as well.

Thanks for pointing that out!

Best Regards,

Tim

>
> > +             }
> > +     }
> > +
> >       if (IS_ENABLED(CONFIG_BOARD_RNG_SEED) && !board_rng_seed(&buf)) {
> >               err = fdt_setprop(fdt, nodeoffset, "rng-seed",
> >                                 abuf_data(&buf), abuf_size(&buf));
>
> [...]
>
> The rest looks good !
Marek Vasut May 15, 2024, 9:15 p.m. UTC | #3
On 5/15/24 11:11 PM, Tim Harvey wrote:
> On Wed, May 15, 2024 at 2:06 PM Marek Vasut <marex@denx.de> wrote:
>>
>> On 5/15/24 10:50 PM, Tim Harvey wrote:
>>
>> [...]
>>
>>> diff --git a/boot/fdt_support.c b/boot/fdt_support.c
>>> index 874ca4d6f5af..3455d60d69dc 100644
>>> --- a/boot/fdt_support.c
>>> +++ b/boot/fdt_support.c
>>> @@ -8,6 +8,7 @@
>>>
>>>    #include <abuf.h>
>>>    #include <env.h>
>>> +#include <kaslrseed.h>
>>>    #include <log.h>
>>>    #include <mapmem.h>
>>>    #include <net.h>
>>> @@ -300,6 +301,15 @@ int fdt_chosen(void *fdt)
>>>        if (nodeoffset < 0)
>>>                return nodeoffset;
>>>
>>> +     if (IS_ENABLED(CONFIG_DM_RNG) && !IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)) {
>>> +             err = fdt_kaslrseed(fdt);
>>> +             if (err) {
>>> +                     printf("WARNING: could not set kaslr-seed %s.\n",
>>> +                            fdt_strerror(err));
>>> +                     return err;
>>
>> Is this warning really a critical boot-breaking error ?
> 
> no, and in fact I'm printing a warning inside of fdt_kaslrseed so I
> can remove the duplication of error prints in the various other places
> it's called as well.
> 
> Thanks for pointing that out!

Glad I could help.
Tim Harvey May 16, 2024, 3:58 p.m. UTC | #4
On Wed, May 15, 2024 at 1:50 PM Tim Harvey <tharvey@gateworks.com> wrote:
>
> If RANDOMIZE_BASE is enabled in the Linux kernel instructing it to
> randomize the virtual address at which the kernel image is loaded, it
> expects entropy to be provided by the bootloader by populating
> /chosen/kaslr-seed with a 64-bit value from source of entropy at boot.
>
> If we have DM_RNG enabled populate this value automatically when
> fdt_chosen is called unless ARMV8_SEC_FIRMWARE_SUPPORT is enabled as
> it's implementation uses a different source of entropy.
>
> As this fdt node is added elsewhere create a library function and
> use it to deduplicate code.
>
> Note that the kalsrseed command (CMD_KASLRSEED) is likely pointless now
> but left in place in case boot scripts exist that rely on this command
> existing and returning success. An informational message is printed to
> alert users of this command that it is likely no longer needed.
>
> Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> ---
> v2:
>  - fix typo in commit msg
>  - use stack for seed to avoid unecessary malloc/free
>  - move to a library function and deduplicate code by using it elsewhere
> ---
>  board/xilinx/common/board.c | 35 -----------------------------
>  boot/fdt_support.c          | 10 +++++++++
>  boot/pxe_utils.c            | 35 +++--------------------------
>  cmd/kaslrseed.c             | 45 ++++++-------------------------------
>  include/kaslrseed.h         | 17 ++++++++++++++
>  lib/Makefile                |  1 +
>  lib/kaslrseed.c             | 34 ++++++++++++++++++++++++++++
>  7 files changed, 72 insertions(+), 105 deletions(-)
>  create mode 100644 include/kaslrseed.h
>  create mode 100644 lib/kaslrseed.c
>
> diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
> index 30a81376ac41..f741e8957818 100644
> --- a/board/xilinx/common/board.c
> +++ b/board/xilinx/common/board.c
> @@ -713,41 +713,6 @@ int ft_board_setup(void *blob, struct bd_info *bd)
>         if (IS_ENABLED(CONFIG_FDT_FIXUP_PARTITIONS) && IS_ENABLED(CONFIG_NAND_ZYNQ))
>                 fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
>
> -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> -               debug("No RNG device\n");
> -               return 0;
> -       }
> -
> -       if (dm_rng_read(dev, buf, n)) {
> -               debug("Reading RNG failed\n");
> -               return 0;
> -       }
> -
> -       if (!blob) {
> -               debug("No FDT memory address configured. Please configure\n"
> -                     "the FDT address via \"fdt addr <address>\" command.\n"
> -                     "Aborting!\n");
> -               return 0;
> -       }
> -
> -       ret = fdt_check_header(blob);
> -       if (ret < 0) {
> -               debug("fdt_chosen: %s\n", fdt_strerror(ret));
> -               return ret;
> -       }
> -
> -       nodeoffset = fdt_find_or_add_subnode(blob, 0, "chosen");
> -       if (nodeoffset < 0) {
> -               debug("Reading chosen node failed\n");
> -               return nodeoffset;
> -       }
> -
> -       ret = fdt_setprop(blob, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> -       if (ret < 0) {
> -               debug("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
> -               return ret;
> -       }
> -
>         return 0;
>  }
>  #endif
> diff --git a/boot/fdt_support.c b/boot/fdt_support.c
> index 874ca4d6f5af..3455d60d69dc 100644
> --- a/boot/fdt_support.c
> +++ b/boot/fdt_support.c
> @@ -8,6 +8,7 @@
>
>  #include <abuf.h>
>  #include <env.h>
> +#include <kaslrseed.h>
>  #include <log.h>
>  #include <mapmem.h>
>  #include <net.h>
> @@ -300,6 +301,15 @@ int fdt_chosen(void *fdt)
>         if (nodeoffset < 0)
>                 return nodeoffset;
>
> +       if (IS_ENABLED(CONFIG_DM_RNG) && !IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)) {
> +               err = fdt_kaslrseed(fdt);
> +               if (err) {
> +                       printf("WARNING: could not set kaslr-seed %s.\n",
> +                              fdt_strerror(err));
> +                       return err;
> +               }
> +       }
> +
>         if (IS_ENABLED(CONFIG_BOARD_RNG_SEED) && !board_rng_seed(&buf)) {
>                 err = fdt_setprop(fdt, nodeoffset, "rng-seed",
>                                   abuf_data(&buf), abuf_size(&buf));
> diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
> index 4b22bb6f525a..8d70233fc08d 100644
> --- a/boot/pxe_utils.c
> +++ b/boot/pxe_utils.c
> @@ -8,6 +8,7 @@
>  #include <dm.h>
>  #include <env.h>
>  #include <image.h>
> +#include <kaslrseed.h>
>  #include <log.h>
>  #include <malloc.h>
>  #include <mapmem.h>
> @@ -323,10 +324,6 @@ static void label_boot_kaslrseed(void)
>  #if CONFIG_IS_ENABLED(DM_RNG)
>         ulong fdt_addr;
>         struct fdt_header *working_fdt;
> -       size_t n = 0x8;
> -       struct udevice *dev;
> -       u64 *buf;
> -       int nodeoffset;
>         int err;
>
>         /* Get the main fdt and map it */
> @@ -342,35 +339,9 @@ static void label_boot_kaslrseed(void)
>         if (err <= 0)
>                 return;
>
> -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> -               printf("No RNG device\n");
> -               return;
> -       }
> -
> -       nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
> -       if (nodeoffset < 0) {
> -               printf("Reading chosen node failed\n");
> -               return;
> -       }
> -
> -       buf = malloc(n);
> -       if (!buf) {
> -               printf("Out of memory\n");
> -               return;
> -       }
> -
> -       if (dm_rng_read(dev, buf, n)) {
> -               printf("Reading RNG failed\n");
> -               goto err;
> -       }
> -
> -       err = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> -       if (err < 0) {
> +       err = fdt_kaslrseed(working_fdt);
> +       if (err < 0)
>                 printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
> -               goto err;
> -       }
> -err:
> -       free(buf);
>  #endif
>         return;
>  }
> diff --git a/cmd/kaslrseed.c b/cmd/kaslrseed.c
> index e0d3c7fe7489..ea5c07d729cf 100644
> --- a/cmd/kaslrseed.c
> +++ b/cmd/kaslrseed.c
> @@ -9,33 +9,16 @@
>  #include <command.h>
>  #include <dm.h>
>  #include <hexdump.h>
> +#include <kaslrseed.h>
>  #include <malloc.h>
>  #include <rng.h>
>  #include <fdt_support.h>
>
>  static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
>  {
> -       size_t n = 0x8;
> -       struct udevice *dev;
> -       u64 *buf;
> -       int nodeoffset;
> -       int ret = CMD_RET_SUCCESS;
> +       int err;
>
> -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> -               printf("No RNG device\n");
> -               return CMD_RET_FAILURE;
> -       }
> -
> -       buf = malloc(n);
> -       if (!buf) {
> -               printf("Out of memory\n");
> -               return CMD_RET_FAILURE;
> -       }
> -
> -       if (dm_rng_read(dev, buf, n)) {
> -               printf("Reading RNG failed\n");
> -               return CMD_RET_FAILURE;
> -       }
> +       printf("Notice: a /chosen/kaslr-seed is automatically added to the device-tree when booted via booti/bootm/bootz therefore using this command is likely no longer needed");
>
>         if (!working_fdt) {
>                 printf("No FDT memory address configured. Please configure\n"
> @@ -44,27 +27,13 @@ static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const
>                 return CMD_RET_FAILURE;
>         }
>
> -       ret = fdt_check_header(working_fdt);
> -       if (ret < 0) {
> -               printf("fdt_chosen: %s\n", fdt_strerror(ret));
> +       err = fdt_kaslrseed(working_fdt);
> +       if (err < 0) {
> +               printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
>                 return CMD_RET_FAILURE;
>         }
>
> -       nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
> -       if (nodeoffset < 0) {
> -               printf("Reading chosen node failed\n");
> -               return CMD_RET_FAILURE;
> -       }
> -
> -       ret = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> -       if (ret < 0) {
> -               printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
> -               return CMD_RET_FAILURE;
> -       }
> -
> -       free(buf);
> -
> -       return ret;
> +       return CMD_RET_SUCCESS;
>  }
>
>  U_BOOT_LONGHELP(kaslrseed,
> diff --git a/include/kaslrseed.h b/include/kaslrseed.h
> new file mode 100644
> index 000000000000..3fe82f418acf
> --- /dev/null
> +++ b/include/kaslrseed.h
> @@ -0,0 +1,17 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
> + */
> +
> +#if !defined _KASLRSEED_H_
> +#define _KASLRSEED_H_
> +
> +/**
> + * fdt_kaslrseed() - create a 'kaslr-seed' node in chosen
> + *
> + * @blob:      fdt blob
> + * Return:     0 if OK, -ve on error
> + */
> +int fdt_kaslrseed(void *blob);
> +
> +#endif /* _KASLRSEED_H_ */
> diff --git a/lib/Makefile b/lib/Makefile
> index 2a76acf100d0..20a0242055fa 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -149,6 +149,7 @@ obj-y += date.o
>  obj-y += rtc-lib.o
>  obj-$(CONFIG_LIB_ELF) += elf.o
>
> +obj-$(CONFIG_DM_RNG) += kaslrseed.o
>  obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += semihosting.o
>
>  #
> diff --git a/lib/kaslrseed.c b/lib/kaslrseed.c
> new file mode 100644
> index 000000000000..ad06bee2b88d
> --- /dev/null
> +++ b/lib/kaslrseed.c
> @@ -0,0 +1,34 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
> + */
> +#include <dm.h>
> +#include <rng.h>
> +#include <fdt_support.h>
> +
> +int fdt_kaslrseed(void *fdt)
> +{
> +       struct udevice *dev;
> +       int nodeoffset;
> +       u64 data;
> +       int err;
> +
> +       err = fdt_check_header(fdt);
> +       if (err < 0)
> +               return err;
> +
> +       /* find or create "/chosen" node. */
> +       nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
> +       if (nodeoffset < 0)
> +               return nodeoffset;
> +
> +       err = uclass_get_device(UCLASS_RNG, 0, &dev);
> +       if (!err)
> +               err = dm_rng_read(dev, &data, sizeof(data));
> +       if (!err)
> +               err = fdt_setprop(fdt, nodeoffset, "kaslr-seed", &data, sizeof(data));
> +       if (err < 0)
> +               printf("WARNING: could not set kaslr-seed %s.\n", fdt_strerror(err));
> +
> +       return err;
> +}
> --
> 2.25.1
>

I realized I forgot a few CC's here. Adding:

Michal Simek <michal.simek@amd.com> (board/xilinx/common/board.c and
configs/xilinx* which have CMD_KASLRSEED)
Andy Yan <andy.yan@rock-chips.com> (configs/evb-rk3308_defconfig and
configs/roc-cc-rk3308_defconfig which have CMD_KASLRSEED)
Akash Gajjar <gajjar04akash@gmail.com>
(configs/rock-pi-s-rk3308_defconfig which has CMD_KASLRSEED)
Ilias Apalodimas <ilias.apalodimas@linaro.org> (MEASURE_DEVICETREE,
MEASURED_BOOT)

Michal, I see that board/xilinx/common/board.c is adding
chosen/kaslr-seed in ft_board_setup as well as some of the
configs/xilinx boards enabling CMD_KASLRSEED - can we remove
CMD_ASLRSEED from those boards? (ie no bootscripts require it?)

Andy, if we automatically add chosen/kaslr-seed in fdt_chosen can we
remove CMD_KASLRSEED from configs/evb-rk3308_defconfig and
configs/roc-cc-rk3308_defconfig? (ie no bootscripts require it?)

Akash, if we automatically add chosen/kaslr-seed in fdt_chosen can we
remove CMD_KASLRSEED from configs/rock-pi-s-rk3308_defconfig? (ie no
bootscripts require it?)

Ilias, this patch adds chosen/kaslr-seed in fdt_chosen automatically
if DM_RNG is enabled, should I skip that for MEASURE_DEVICETREE?

Tom, can sec_firmware.c be moved to dm-rng to eliminate the need for a
separate fdt_fixup_kaslr?

Best Regards,

Tim
Tom Rini May 16, 2024, 4:15 p.m. UTC | #5
On Thu, May 16, 2024 at 08:58:09AM -0700, Tim Harvey wrote:
> On Wed, May 15, 2024 at 1:50 PM Tim Harvey <tharvey@gateworks.com> wrote:
> >
> > If RANDOMIZE_BASE is enabled in the Linux kernel instructing it to
> > randomize the virtual address at which the kernel image is loaded, it
> > expects entropy to be provided by the bootloader by populating
> > /chosen/kaslr-seed with a 64-bit value from source of entropy at boot.
> >
> > If we have DM_RNG enabled populate this value automatically when
> > fdt_chosen is called unless ARMV8_SEC_FIRMWARE_SUPPORT is enabled as
> > it's implementation uses a different source of entropy.
> >
> > As this fdt node is added elsewhere create a library function and
> > use it to deduplicate code.
> >
> > Note that the kalsrseed command (CMD_KASLRSEED) is likely pointless now
> > but left in place in case boot scripts exist that rely on this command
> > existing and returning success. An informational message is printed to
> > alert users of this command that it is likely no longer needed.
> >
> > Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> > ---
> > v2:
> >  - fix typo in commit msg
> >  - use stack for seed to avoid unecessary malloc/free
> >  - move to a library function and deduplicate code by using it elsewhere
> > ---
> >  board/xilinx/common/board.c | 35 -----------------------------
> >  boot/fdt_support.c          | 10 +++++++++
> >  boot/pxe_utils.c            | 35 +++--------------------------
> >  cmd/kaslrseed.c             | 45 ++++++-------------------------------
> >  include/kaslrseed.h         | 17 ++++++++++++++
> >  lib/Makefile                |  1 +
> >  lib/kaslrseed.c             | 34 ++++++++++++++++++++++++++++
> >  7 files changed, 72 insertions(+), 105 deletions(-)
> >  create mode 100644 include/kaslrseed.h
> >  create mode 100644 lib/kaslrseed.c
> >
> > diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
> > index 30a81376ac41..f741e8957818 100644
> > --- a/board/xilinx/common/board.c
> > +++ b/board/xilinx/common/board.c
> > @@ -713,41 +713,6 @@ int ft_board_setup(void *blob, struct bd_info *bd)
> >         if (IS_ENABLED(CONFIG_FDT_FIXUP_PARTITIONS) && IS_ENABLED(CONFIG_NAND_ZYNQ))
> >                 fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
> >
> > -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> > -               debug("No RNG device\n");
> > -               return 0;
> > -       }
> > -
> > -       if (dm_rng_read(dev, buf, n)) {
> > -               debug("Reading RNG failed\n");
> > -               return 0;
> > -       }
> > -
> > -       if (!blob) {
> > -               debug("No FDT memory address configured. Please configure\n"
> > -                     "the FDT address via \"fdt addr <address>\" command.\n"
> > -                     "Aborting!\n");
> > -               return 0;
> > -       }
> > -
> > -       ret = fdt_check_header(blob);
> > -       if (ret < 0) {
> > -               debug("fdt_chosen: %s\n", fdt_strerror(ret));
> > -               return ret;
> > -       }
> > -
> > -       nodeoffset = fdt_find_or_add_subnode(blob, 0, "chosen");
> > -       if (nodeoffset < 0) {
> > -               debug("Reading chosen node failed\n");
> > -               return nodeoffset;
> > -       }
> > -
> > -       ret = fdt_setprop(blob, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> > -       if (ret < 0) {
> > -               debug("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
> > -               return ret;
> > -       }
> > -
> >         return 0;
> >  }
> >  #endif
> > diff --git a/boot/fdt_support.c b/boot/fdt_support.c
> > index 874ca4d6f5af..3455d60d69dc 100644
> > --- a/boot/fdt_support.c
> > +++ b/boot/fdt_support.c
> > @@ -8,6 +8,7 @@
> >
> >  #include <abuf.h>
> >  #include <env.h>
> > +#include <kaslrseed.h>
> >  #include <log.h>
> >  #include <mapmem.h>
> >  #include <net.h>
> > @@ -300,6 +301,15 @@ int fdt_chosen(void *fdt)
> >         if (nodeoffset < 0)
> >                 return nodeoffset;
> >
> > +       if (IS_ENABLED(CONFIG_DM_RNG) && !IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)) {
> > +               err = fdt_kaslrseed(fdt);
> > +               if (err) {
> > +                       printf("WARNING: could not set kaslr-seed %s.\n",
> > +                              fdt_strerror(err));
> > +                       return err;
> > +               }
> > +       }
> > +
> >         if (IS_ENABLED(CONFIG_BOARD_RNG_SEED) && !board_rng_seed(&buf)) {
> >                 err = fdt_setprop(fdt, nodeoffset, "rng-seed",
> >                                   abuf_data(&buf), abuf_size(&buf));
> > diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
> > index 4b22bb6f525a..8d70233fc08d 100644
> > --- a/boot/pxe_utils.c
> > +++ b/boot/pxe_utils.c
> > @@ -8,6 +8,7 @@
> >  #include <dm.h>
> >  #include <env.h>
> >  #include <image.h>
> > +#include <kaslrseed.h>
> >  #include <log.h>
> >  #include <malloc.h>
> >  #include <mapmem.h>
> > @@ -323,10 +324,6 @@ static void label_boot_kaslrseed(void)
> >  #if CONFIG_IS_ENABLED(DM_RNG)
> >         ulong fdt_addr;
> >         struct fdt_header *working_fdt;
> > -       size_t n = 0x8;
> > -       struct udevice *dev;
> > -       u64 *buf;
> > -       int nodeoffset;
> >         int err;
> >
> >         /* Get the main fdt and map it */
> > @@ -342,35 +339,9 @@ static void label_boot_kaslrseed(void)
> >         if (err <= 0)
> >                 return;
> >
> > -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> > -               printf("No RNG device\n");
> > -               return;
> > -       }
> > -
> > -       nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
> > -       if (nodeoffset < 0) {
> > -               printf("Reading chosen node failed\n");
> > -               return;
> > -       }
> > -
> > -       buf = malloc(n);
> > -       if (!buf) {
> > -               printf("Out of memory\n");
> > -               return;
> > -       }
> > -
> > -       if (dm_rng_read(dev, buf, n)) {
> > -               printf("Reading RNG failed\n");
> > -               goto err;
> > -       }
> > -
> > -       err = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> > -       if (err < 0) {
> > +       err = fdt_kaslrseed(working_fdt);
> > +       if (err < 0)
> >                 printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
> > -               goto err;
> > -       }
> > -err:
> > -       free(buf);
> >  #endif
> >         return;
> >  }
> > diff --git a/cmd/kaslrseed.c b/cmd/kaslrseed.c
> > index e0d3c7fe7489..ea5c07d729cf 100644
> > --- a/cmd/kaslrseed.c
> > +++ b/cmd/kaslrseed.c
> > @@ -9,33 +9,16 @@
> >  #include <command.h>
> >  #include <dm.h>
> >  #include <hexdump.h>
> > +#include <kaslrseed.h>
> >  #include <malloc.h>
> >  #include <rng.h>
> >  #include <fdt_support.h>
> >
> >  static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> >  {
> > -       size_t n = 0x8;
> > -       struct udevice *dev;
> > -       u64 *buf;
> > -       int nodeoffset;
> > -       int ret = CMD_RET_SUCCESS;
> > +       int err;
> >
> > -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> > -               printf("No RNG device\n");
> > -               return CMD_RET_FAILURE;
> > -       }
> > -
> > -       buf = malloc(n);
> > -       if (!buf) {
> > -               printf("Out of memory\n");
> > -               return CMD_RET_FAILURE;
> > -       }
> > -
> > -       if (dm_rng_read(dev, buf, n)) {
> > -               printf("Reading RNG failed\n");
> > -               return CMD_RET_FAILURE;
> > -       }
> > +       printf("Notice: a /chosen/kaslr-seed is automatically added to the device-tree when booted via booti/bootm/bootz therefore using this command is likely no longer needed");
> >
> >         if (!working_fdt) {
> >                 printf("No FDT memory address configured. Please configure\n"
> > @@ -44,27 +27,13 @@ static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const
> >                 return CMD_RET_FAILURE;
> >         }
> >
> > -       ret = fdt_check_header(working_fdt);
> > -       if (ret < 0) {
> > -               printf("fdt_chosen: %s\n", fdt_strerror(ret));
> > +       err = fdt_kaslrseed(working_fdt);
> > +       if (err < 0) {
> > +               printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
> >                 return CMD_RET_FAILURE;
> >         }
> >
> > -       nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
> > -       if (nodeoffset < 0) {
> > -               printf("Reading chosen node failed\n");
> > -               return CMD_RET_FAILURE;
> > -       }
> > -
> > -       ret = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> > -       if (ret < 0) {
> > -               printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
> > -               return CMD_RET_FAILURE;
> > -       }
> > -
> > -       free(buf);
> > -
> > -       return ret;
> > +       return CMD_RET_SUCCESS;
> >  }
> >
> >  U_BOOT_LONGHELP(kaslrseed,
> > diff --git a/include/kaslrseed.h b/include/kaslrseed.h
> > new file mode 100644
> > index 000000000000..3fe82f418acf
> > --- /dev/null
> > +++ b/include/kaslrseed.h
> > @@ -0,0 +1,17 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
> > + */
> > +
> > +#if !defined _KASLRSEED_H_
> > +#define _KASLRSEED_H_
> > +
> > +/**
> > + * fdt_kaslrseed() - create a 'kaslr-seed' node in chosen
> > + *
> > + * @blob:      fdt blob
> > + * Return:     0 if OK, -ve on error
> > + */
> > +int fdt_kaslrseed(void *blob);
> > +
> > +#endif /* _KASLRSEED_H_ */
> > diff --git a/lib/Makefile b/lib/Makefile
> > index 2a76acf100d0..20a0242055fa 100644
> > --- a/lib/Makefile
> > +++ b/lib/Makefile
> > @@ -149,6 +149,7 @@ obj-y += date.o
> >  obj-y += rtc-lib.o
> >  obj-$(CONFIG_LIB_ELF) += elf.o
> >
> > +obj-$(CONFIG_DM_RNG) += kaslrseed.o
> >  obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += semihosting.o
> >
> >  #
> > diff --git a/lib/kaslrseed.c b/lib/kaslrseed.c
> > new file mode 100644
> > index 000000000000..ad06bee2b88d
> > --- /dev/null
> > +++ b/lib/kaslrseed.c
> > @@ -0,0 +1,34 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
> > + */
> > +#include <dm.h>
> > +#include <rng.h>
> > +#include <fdt_support.h>
> > +
> > +int fdt_kaslrseed(void *fdt)
> > +{
> > +       struct udevice *dev;
> > +       int nodeoffset;
> > +       u64 data;
> > +       int err;
> > +
> > +       err = fdt_check_header(fdt);
> > +       if (err < 0)
> > +               return err;
> > +
> > +       /* find or create "/chosen" node. */
> > +       nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
> > +       if (nodeoffset < 0)
> > +               return nodeoffset;
> > +
> > +       err = uclass_get_device(UCLASS_RNG, 0, &dev);
> > +       if (!err)
> > +               err = dm_rng_read(dev, &data, sizeof(data));
> > +       if (!err)
> > +               err = fdt_setprop(fdt, nodeoffset, "kaslr-seed", &data, sizeof(data));
> > +       if (err < 0)
> > +               printf("WARNING: could not set kaslr-seed %s.\n", fdt_strerror(err));
> > +
> > +       return err;
> > +}
[snip]
> Tom, can sec_firmware.c be moved to dm-rng to eliminate the need for a
> separate fdt_fixup_kaslr?

I'm really just the "last resort" on that file, and git history by
default is too short, in this case. Adding a few more people now.
Michal Simek May 20, 2024, 8:29 a.m. UTC | #6
Hi Tim,

On 5/16/24 17:58, Tim Harvey wrote:
> On Wed, May 15, 2024 at 1:50 PM Tim Harvey <tharvey@gateworks.com> wrote:
>>
>> If RANDOMIZE_BASE is enabled in the Linux kernel instructing it to
>> randomize the virtual address at which the kernel image is loaded, it
>> expects entropy to be provided by the bootloader by populating
>> /chosen/kaslr-seed with a 64-bit value from source of entropy at boot.
>>
>> If we have DM_RNG enabled populate this value automatically when
>> fdt_chosen is called unless ARMV8_SEC_FIRMWARE_SUPPORT is enabled as
>> it's implementation uses a different source of entropy.
>>
>> As this fdt node is added elsewhere create a library function and
>> use it to deduplicate code.
>>
>> Note that the kalsrseed command (CMD_KASLRSEED) is likely pointless now
>> but left in place in case boot scripts exist that rely on this command
>> existing and returning success. An informational message is printed to
>> alert users of this command that it is likely no longer needed.
>>
>> Signed-off-by: Tim Harvey <tharvey@gateworks.com>
>> ---
>> v2:
>>   - fix typo in commit msg
>>   - use stack for seed to avoid unecessary malloc/free
>>   - move to a library function and deduplicate code by using it elsewhere
>> ---
>>   board/xilinx/common/board.c | 35 -----------------------------
>>   boot/fdt_support.c          | 10 +++++++++
>>   boot/pxe_utils.c            | 35 +++--------------------------
>>   cmd/kaslrseed.c             | 45 ++++++-------------------------------
>>   include/kaslrseed.h         | 17 ++++++++++++++
>>   lib/Makefile                |  1 +
>>   lib/kaslrseed.c             | 34 ++++++++++++++++++++++++++++
>>   7 files changed, 72 insertions(+), 105 deletions(-)
>>   create mode 100644 include/kaslrseed.h
>>   create mode 100644 lib/kaslrseed.c
>>
>> diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
>> index 30a81376ac41..f741e8957818 100644
>> --- a/board/xilinx/common/board.c
>> +++ b/board/xilinx/common/board.c
>> @@ -713,41 +713,6 @@ int ft_board_setup(void *blob, struct bd_info *bd)
>>          if (IS_ENABLED(CONFIG_FDT_FIXUP_PARTITIONS) && IS_ENABLED(CONFIG_NAND_ZYNQ))
>>                  fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
>>
>> -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
>> -               debug("No RNG device\n");
>> -               return 0;
>> -       }
>> -
>> -       if (dm_rng_read(dev, buf, n)) {
>> -               debug("Reading RNG failed\n");
>> -               return 0;
>> -       }
>> -
>> -       if (!blob) {
>> -               debug("No FDT memory address configured. Please configure\n"
>> -                     "the FDT address via \"fdt addr <address>\" command.\n"
>> -                     "Aborting!\n");
>> -               return 0;
>> -       }
>> -
>> -       ret = fdt_check_header(blob);
>> -       if (ret < 0) {
>> -               debug("fdt_chosen: %s\n", fdt_strerror(ret));
>> -               return ret;
>> -       }
>> -
>> -       nodeoffset = fdt_find_or_add_subnode(blob, 0, "chosen");
>> -       if (nodeoffset < 0) {
>> -               debug("Reading chosen node failed\n");
>> -               return nodeoffset;
>> -       }
>> -
>> -       ret = fdt_setprop(blob, nodeoffset, "kaslr-seed", buf, sizeof(buf));
>> -       if (ret < 0) {
>> -               debug("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
>> -               return ret;
>> -       }
>> -
>>          return 0;
>>   }
>>   #endif
>> diff --git a/boot/fdt_support.c b/boot/fdt_support.c
>> index 874ca4d6f5af..3455d60d69dc 100644
>> --- a/boot/fdt_support.c
>> +++ b/boot/fdt_support.c
>> @@ -8,6 +8,7 @@
>>
>>   #include <abuf.h>
>>   #include <env.h>
>> +#include <kaslrseed.h>
>>   #include <log.h>
>>   #include <mapmem.h>
>>   #include <net.h>
>> @@ -300,6 +301,15 @@ int fdt_chosen(void *fdt)
>>          if (nodeoffset < 0)
>>                  return nodeoffset;
>>
>> +       if (IS_ENABLED(CONFIG_DM_RNG) && !IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)) {
>> +               err = fdt_kaslrseed(fdt);
>> +               if (err) {
>> +                       printf("WARNING: could not set kaslr-seed %s.\n",
>> +                              fdt_strerror(err));
>> +                       return err;
>> +               }
>> +       }
>> +
>>          if (IS_ENABLED(CONFIG_BOARD_RNG_SEED) && !board_rng_seed(&buf)) {
>>                  err = fdt_setprop(fdt, nodeoffset, "rng-seed",
>>                                    abuf_data(&buf), abuf_size(&buf));
>> diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
>> index 4b22bb6f525a..8d70233fc08d 100644
>> --- a/boot/pxe_utils.c
>> +++ b/boot/pxe_utils.c
>> @@ -8,6 +8,7 @@
>>   #include <dm.h>
>>   #include <env.h>
>>   #include <image.h>
>> +#include <kaslrseed.h>
>>   #include <log.h>
>>   #include <malloc.h>
>>   #include <mapmem.h>
>> @@ -323,10 +324,6 @@ static void label_boot_kaslrseed(void)
>>   #if CONFIG_IS_ENABLED(DM_RNG)
>>          ulong fdt_addr;
>>          struct fdt_header *working_fdt;
>> -       size_t n = 0x8;
>> -       struct udevice *dev;
>> -       u64 *buf;
>> -       int nodeoffset;
>>          int err;
>>
>>          /* Get the main fdt and map it */
>> @@ -342,35 +339,9 @@ static void label_boot_kaslrseed(void)
>>          if (err <= 0)
>>                  return;
>>
>> -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
>> -               printf("No RNG device\n");
>> -               return;
>> -       }
>> -
>> -       nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
>> -       if (nodeoffset < 0) {
>> -               printf("Reading chosen node failed\n");
>> -               return;
>> -       }
>> -
>> -       buf = malloc(n);
>> -       if (!buf) {
>> -               printf("Out of memory\n");
>> -               return;
>> -       }
>> -
>> -       if (dm_rng_read(dev, buf, n)) {
>> -               printf("Reading RNG failed\n");
>> -               goto err;
>> -       }
>> -
>> -       err = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
>> -       if (err < 0) {
>> +       err = fdt_kaslrseed(working_fdt);
>> +       if (err < 0)
>>                  printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
>> -               goto err;
>> -       }
>> -err:
>> -       free(buf);
>>   #endif
>>          return;
>>   }
>> diff --git a/cmd/kaslrseed.c b/cmd/kaslrseed.c
>> index e0d3c7fe7489..ea5c07d729cf 100644
>> --- a/cmd/kaslrseed.c
>> +++ b/cmd/kaslrseed.c
>> @@ -9,33 +9,16 @@
>>   #include <command.h>
>>   #include <dm.h>
>>   #include <hexdump.h>
>> +#include <kaslrseed.h>
>>   #include <malloc.h>
>>   #include <rng.h>
>>   #include <fdt_support.h>
>>
>>   static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
>>   {
>> -       size_t n = 0x8;
>> -       struct udevice *dev;
>> -       u64 *buf;
>> -       int nodeoffset;
>> -       int ret = CMD_RET_SUCCESS;
>> +       int err;
>>
>> -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
>> -               printf("No RNG device\n");
>> -               return CMD_RET_FAILURE;
>> -       }
>> -
>> -       buf = malloc(n);
>> -       if (!buf) {
>> -               printf("Out of memory\n");
>> -               return CMD_RET_FAILURE;
>> -       }
>> -
>> -       if (dm_rng_read(dev, buf, n)) {
>> -               printf("Reading RNG failed\n");
>> -               return CMD_RET_FAILURE;
>> -       }
>> +       printf("Notice: a /chosen/kaslr-seed is automatically added to the device-tree when booted via booti/bootm/bootz therefore using this command is likely no longer needed");
>>
>>          if (!working_fdt) {
>>                  printf("No FDT memory address configured. Please configure\n"
>> @@ -44,27 +27,13 @@ static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const
>>                  return CMD_RET_FAILURE;
>>          }
>>
>> -       ret = fdt_check_header(working_fdt);
>> -       if (ret < 0) {
>> -               printf("fdt_chosen: %s\n", fdt_strerror(ret));
>> +       err = fdt_kaslrseed(working_fdt);
>> +       if (err < 0) {
>> +               printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
>>                  return CMD_RET_FAILURE;
>>          }
>>
>> -       nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
>> -       if (nodeoffset < 0) {
>> -               printf("Reading chosen node failed\n");
>> -               return CMD_RET_FAILURE;
>> -       }
>> -
>> -       ret = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
>> -       if (ret < 0) {
>> -               printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
>> -               return CMD_RET_FAILURE;
>> -       }
>> -
>> -       free(buf);
>> -
>> -       return ret;
>> +       return CMD_RET_SUCCESS;
>>   }
>>
>>   U_BOOT_LONGHELP(kaslrseed,
>> diff --git a/include/kaslrseed.h b/include/kaslrseed.h
>> new file mode 100644
>> index 000000000000..3fe82f418acf
>> --- /dev/null
>> +++ b/include/kaslrseed.h
>> @@ -0,0 +1,17 @@
>> +/* SPDX-License-Identifier: GPL-2.0+ */
>> +/*
>> + * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
>> + */
>> +
>> +#if !defined _KASLRSEED_H_
>> +#define _KASLRSEED_H_
>> +
>> +/**
>> + * fdt_kaslrseed() - create a 'kaslr-seed' node in chosen
>> + *
>> + * @blob:      fdt blob
>> + * Return:     0 if OK, -ve on error
>> + */
>> +int fdt_kaslrseed(void *blob);
>> +
>> +#endif /* _KASLRSEED_H_ */
>> diff --git a/lib/Makefile b/lib/Makefile
>> index 2a76acf100d0..20a0242055fa 100644
>> --- a/lib/Makefile
>> +++ b/lib/Makefile
>> @@ -149,6 +149,7 @@ obj-y += date.o
>>   obj-y += rtc-lib.o
>>   obj-$(CONFIG_LIB_ELF) += elf.o
>>
>> +obj-$(CONFIG_DM_RNG) += kaslrseed.o
>>   obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += semihosting.o
>>
>>   #
>> diff --git a/lib/kaslrseed.c b/lib/kaslrseed.c
>> new file mode 100644
>> index 000000000000..ad06bee2b88d
>> --- /dev/null
>> +++ b/lib/kaslrseed.c
>> @@ -0,0 +1,34 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
>> + */
>> +#include <dm.h>
>> +#include <rng.h>
>> +#include <fdt_support.h>
>> +
>> +int fdt_kaslrseed(void *fdt)
>> +{
>> +       struct udevice *dev;
>> +       int nodeoffset;
>> +       u64 data;
>> +       int err;
>> +
>> +       err = fdt_check_header(fdt);
>> +       if (err < 0)
>> +               return err;
>> +
>> +       /* find or create "/chosen" node. */
>> +       nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
>> +       if (nodeoffset < 0)
>> +               return nodeoffset;
>> +
>> +       err = uclass_get_device(UCLASS_RNG, 0, &dev);
>> +       if (!err)
>> +               err = dm_rng_read(dev, &data, sizeof(data));
>> +       if (!err)
>> +               err = fdt_setprop(fdt, nodeoffset, "kaslr-seed", &data, sizeof(data));
>> +       if (err < 0)
>> +               printf("WARNING: could not set kaslr-seed %s.\n", fdt_strerror(err));

I have used debug messages to better track if error happens. I think it would be 
good if you can extend your code with it.
Because if this fails people have to start tracking if issue is that there is 
RNG device or reading fails or issue with setting up property.

In v1 it was said that you won't update it if the kaslr-seed property exists.
I can't see this in the code. Or do I read it incorrectly?


>> +
>> +       return err;
>> +}
>> --
>> 2.25.1
>>
> 
> I realized I forgot a few CC's here. Adding:
> 
> Michal Simek <michal.simek@amd.com> (board/xilinx/common/board.c and
> configs/xilinx* which have CMD_KASLRSEED)
> Andy Yan <andy.yan@rock-chips.com> (configs/evb-rk3308_defconfig and
> configs/roc-cc-rk3308_defconfig which have CMD_KASLRSEED)
> Akash Gajjar <gajjar04akash@gmail.com>
> (configs/rock-pi-s-rk3308_defconfig which has CMD_KASLRSEED)
> Ilias Apalodimas <ilias.apalodimas@linaro.org> (MEASURE_DEVICETREE,
> MEASURED_BOOT)
> 
> Michal, I see that board/xilinx/common/board.c is adding
> chosen/kaslr-seed in ft_board_setup as well as some of the
> configs/xilinx boards enabling CMD_KASLRSEED - can we remove
> CMD_ASLRSEED from those boards? (ie no bootscripts require it?)


Based on my note above that you shouldn't change kaslr-seed if exists.

What would also make sense is to extend kaslrseed command to pass one more 
parameter to pass which RNG instance should generate data on system with more 
RNGs. Then pretty much with command you can choose different RNG because current 
code hardcoded it to instance 0.

Do you have correct dependency in generic code when MEASURED_BOOT is enabled as 
was mentioned in v1? If yes it should be mentioned in commit message.

Thanks,
Michal
Tim Harvey May 20, 2024, 4:37 p.m. UTC | #7
On Mon, May 20, 2024 at 1:29 AM Michal Simek <michal.simek@amd.com> wrote:
>
> Hi Tim,
>
> On 5/16/24 17:58, Tim Harvey wrote:
> > On Wed, May 15, 2024 at 1:50 PM Tim Harvey <tharvey@gateworks.com> wrote:
> >>
> >> If RANDOMIZE_BASE is enabled in the Linux kernel instructing it to
> >> randomize the virtual address at which the kernel image is loaded, it
> >> expects entropy to be provided by the bootloader by populating
> >> /chosen/kaslr-seed with a 64-bit value from source of entropy at boot.
> >>
> >> If we have DM_RNG enabled populate this value automatically when
> >> fdt_chosen is called unless ARMV8_SEC_FIRMWARE_SUPPORT is enabled as
> >> it's implementation uses a different source of entropy.
> >>
> >> As this fdt node is added elsewhere create a library function and
> >> use it to deduplicate code.
> >>
> >> Note that the kalsrseed command (CMD_KASLRSEED) is likely pointless now
> >> but left in place in case boot scripts exist that rely on this command
> >> existing and returning success. An informational message is printed to
> >> alert users of this command that it is likely no longer needed.
> >>
> >> Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> >> ---
> >> v2:
> >>   - fix typo in commit msg
> >>   - use stack for seed to avoid unecessary malloc/free
> >>   - move to a library function and deduplicate code by using it elsewhere
> >> ---
> >>   board/xilinx/common/board.c | 35 -----------------------------
> >>   boot/fdt_support.c          | 10 +++++++++
> >>   boot/pxe_utils.c            | 35 +++--------------------------
> >>   cmd/kaslrseed.c             | 45 ++++++-------------------------------
> >>   include/kaslrseed.h         | 17 ++++++++++++++
> >>   lib/Makefile                |  1 +
> >>   lib/kaslrseed.c             | 34 ++++++++++++++++++++++++++++
> >>   7 files changed, 72 insertions(+), 105 deletions(-)
> >>   create mode 100644 include/kaslrseed.h
> >>   create mode 100644 lib/kaslrseed.c
> >>
> >> diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
> >> index 30a81376ac41..f741e8957818 100644
> >> --- a/board/xilinx/common/board.c
> >> +++ b/board/xilinx/common/board.c
> >> @@ -713,41 +713,6 @@ int ft_board_setup(void *blob, struct bd_info *bd)
> >>          if (IS_ENABLED(CONFIG_FDT_FIXUP_PARTITIONS) && IS_ENABLED(CONFIG_NAND_ZYNQ))
> >>                  fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
> >>
> >> -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> >> -               debug("No RNG device\n");
> >> -               return 0;
> >> -       }
> >> -
> >> -       if (dm_rng_read(dev, buf, n)) {
> >> -               debug("Reading RNG failed\n");
> >> -               return 0;
> >> -       }
> >> -
> >> -       if (!blob) {
> >> -               debug("No FDT memory address configured. Please configure\n"
> >> -                     "the FDT address via \"fdt addr <address>\" command.\n"
> >> -                     "Aborting!\n");
> >> -               return 0;
> >> -       }
> >> -
> >> -       ret = fdt_check_header(blob);
> >> -       if (ret < 0) {
> >> -               debug("fdt_chosen: %s\n", fdt_strerror(ret));
> >> -               return ret;
> >> -       }
> >> -
> >> -       nodeoffset = fdt_find_or_add_subnode(blob, 0, "chosen");
> >> -       if (nodeoffset < 0) {
> >> -               debug("Reading chosen node failed\n");
> >> -               return nodeoffset;
> >> -       }
> >> -
> >> -       ret = fdt_setprop(blob, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> >> -       if (ret < 0) {
> >> -               debug("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
> >> -               return ret;
> >> -       }
> >> -
> >>          return 0;
> >>   }
> >>   #endif
> >> diff --git a/boot/fdt_support.c b/boot/fdt_support.c
> >> index 874ca4d6f5af..3455d60d69dc 100644
> >> --- a/boot/fdt_support.c
> >> +++ b/boot/fdt_support.c
> >> @@ -8,6 +8,7 @@
> >>
> >>   #include <abuf.h>
> >>   #include <env.h>
> >> +#include <kaslrseed.h>
> >>   #include <log.h>
> >>   #include <mapmem.h>
> >>   #include <net.h>
> >> @@ -300,6 +301,15 @@ int fdt_chosen(void *fdt)
> >>          if (nodeoffset < 0)
> >>                  return nodeoffset;
> >>
> >> +       if (IS_ENABLED(CONFIG_DM_RNG) && !IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)) {
> >> +               err = fdt_kaslrseed(fdt);
> >> +               if (err) {
> >> +                       printf("WARNING: could not set kaslr-seed %s.\n",
> >> +                              fdt_strerror(err));
> >> +                       return err;
> >> +               }
> >> +       }
> >> +
> >>          if (IS_ENABLED(CONFIG_BOARD_RNG_SEED) && !board_rng_seed(&buf)) {
> >>                  err = fdt_setprop(fdt, nodeoffset, "rng-seed",
> >>                                    abuf_data(&buf), abuf_size(&buf));
> >> diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
> >> index 4b22bb6f525a..8d70233fc08d 100644
> >> --- a/boot/pxe_utils.c
> >> +++ b/boot/pxe_utils.c
> >> @@ -8,6 +8,7 @@
> >>   #include <dm.h>
> >>   #include <env.h>
> >>   #include <image.h>
> >> +#include <kaslrseed.h>
> >>   #include <log.h>
> >>   #include <malloc.h>
> >>   #include <mapmem.h>
> >> @@ -323,10 +324,6 @@ static void label_boot_kaslrseed(void)
> >>   #if CONFIG_IS_ENABLED(DM_RNG)
> >>          ulong fdt_addr;
> >>          struct fdt_header *working_fdt;
> >> -       size_t n = 0x8;
> >> -       struct udevice *dev;
> >> -       u64 *buf;
> >> -       int nodeoffset;
> >>          int err;
> >>
> >>          /* Get the main fdt and map it */
> >> @@ -342,35 +339,9 @@ static void label_boot_kaslrseed(void)
> >>          if (err <= 0)
> >>                  return;
> >>
> >> -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> >> -               printf("No RNG device\n");
> >> -               return;
> >> -       }
> >> -
> >> -       nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
> >> -       if (nodeoffset < 0) {
> >> -               printf("Reading chosen node failed\n");
> >> -               return;
> >> -       }
> >> -
> >> -       buf = malloc(n);
> >> -       if (!buf) {
> >> -               printf("Out of memory\n");
> >> -               return;
> >> -       }
> >> -
> >> -       if (dm_rng_read(dev, buf, n)) {
> >> -               printf("Reading RNG failed\n");
> >> -               goto err;
> >> -       }
> >> -
> >> -       err = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> >> -       if (err < 0) {
> >> +       err = fdt_kaslrseed(working_fdt);
> >> +       if (err < 0)
> >>                  printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
> >> -               goto err;
> >> -       }
> >> -err:
> >> -       free(buf);
> >>   #endif
> >>          return;
> >>   }
> >> diff --git a/cmd/kaslrseed.c b/cmd/kaslrseed.c
> >> index e0d3c7fe7489..ea5c07d729cf 100644
> >> --- a/cmd/kaslrseed.c
> >> +++ b/cmd/kaslrseed.c
> >> @@ -9,33 +9,16 @@
> >>   #include <command.h>
> >>   #include <dm.h>
> >>   #include <hexdump.h>
> >> +#include <kaslrseed.h>
> >>   #include <malloc.h>
> >>   #include <rng.h>
> >>   #include <fdt_support.h>
> >>
> >>   static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> >>   {
> >> -       size_t n = 0x8;
> >> -       struct udevice *dev;
> >> -       u64 *buf;
> >> -       int nodeoffset;
> >> -       int ret = CMD_RET_SUCCESS;
> >> +       int err;
> >>
> >> -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> >> -               printf("No RNG device\n");
> >> -               return CMD_RET_FAILURE;
> >> -       }
> >> -
> >> -       buf = malloc(n);
> >> -       if (!buf) {
> >> -               printf("Out of memory\n");
> >> -               return CMD_RET_FAILURE;
> >> -       }
> >> -
> >> -       if (dm_rng_read(dev, buf, n)) {
> >> -               printf("Reading RNG failed\n");
> >> -               return CMD_RET_FAILURE;
> >> -       }
> >> +       printf("Notice: a /chosen/kaslr-seed is automatically added to the device-tree when booted via booti/bootm/bootz therefore using this command is likely no longer needed");
> >>
> >>          if (!working_fdt) {
> >>                  printf("No FDT memory address configured. Please configure\n"
> >> @@ -44,27 +27,13 @@ static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const
> >>                  return CMD_RET_FAILURE;
> >>          }
> >>
> >> -       ret = fdt_check_header(working_fdt);
> >> -       if (ret < 0) {
> >> -               printf("fdt_chosen: %s\n", fdt_strerror(ret));
> >> +       err = fdt_kaslrseed(working_fdt);
> >> +       if (err < 0) {
> >> +               printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
> >>                  return CMD_RET_FAILURE;
> >>          }
> >>
> >> -       nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
> >> -       if (nodeoffset < 0) {
> >> -               printf("Reading chosen node failed\n");
> >> -               return CMD_RET_FAILURE;
> >> -       }
> >> -
> >> -       ret = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> >> -       if (ret < 0) {
> >> -               printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
> >> -               return CMD_RET_FAILURE;
> >> -       }
> >> -
> >> -       free(buf);
> >> -
> >> -       return ret;
> >> +       return CMD_RET_SUCCESS;
> >>   }
> >>
> >>   U_BOOT_LONGHELP(kaslrseed,
> >> diff --git a/include/kaslrseed.h b/include/kaslrseed.h
> >> new file mode 100644
> >> index 000000000000..3fe82f418acf
> >> --- /dev/null
> >> +++ b/include/kaslrseed.h
> >> @@ -0,0 +1,17 @@
> >> +/* SPDX-License-Identifier: GPL-2.0+ */
> >> +/*
> >> + * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
> >> + */
> >> +
> >> +#if !defined _KASLRSEED_H_
> >> +#define _KASLRSEED_H_
> >> +
> >> +/**
> >> + * fdt_kaslrseed() - create a 'kaslr-seed' node in chosen
> >> + *
> >> + * @blob:      fdt blob
> >> + * Return:     0 if OK, -ve on error
> >> + */
> >> +int fdt_kaslrseed(void *blob);
> >> +
> >> +#endif /* _KASLRSEED_H_ */
> >> diff --git a/lib/Makefile b/lib/Makefile
> >> index 2a76acf100d0..20a0242055fa 100644
> >> --- a/lib/Makefile
> >> +++ b/lib/Makefile
> >> @@ -149,6 +149,7 @@ obj-y += date.o
> >>   obj-y += rtc-lib.o
> >>   obj-$(CONFIG_LIB_ELF) += elf.o
> >>
> >> +obj-$(CONFIG_DM_RNG) += kaslrseed.o
> >>   obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += semihosting.o
> >>
> >>   #
> >> diff --git a/lib/kaslrseed.c b/lib/kaslrseed.c
> >> new file mode 100644
> >> index 000000000000..ad06bee2b88d
> >> --- /dev/null
> >> +++ b/lib/kaslrseed.c
> >> @@ -0,0 +1,34 @@
> >> +// SPDX-License-Identifier: GPL-2.0+
> >> +/*
> >> + * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
> >> + */
> >> +#include <dm.h>
> >> +#include <rng.h>
> >> +#include <fdt_support.h>
> >> +
> >> +int fdt_kaslrseed(void *fdt)
> >> +{
> >> +       struct udevice *dev;
> >> +       int nodeoffset;
> >> +       u64 data;
> >> +       int err;
> >> +
> >> +       err = fdt_check_header(fdt);
> >> +       if (err < 0)
> >> +               return err;
> >> +
> >> +       /* find or create "/chosen" node. */
> >> +       nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
> >> +       if (nodeoffset < 0)
> >> +               return nodeoffset;
> >> +
> >> +       err = uclass_get_device(UCLASS_RNG, 0, &dev);
> >> +       if (!err)
> >> +               err = dm_rng_read(dev, &data, sizeof(data));
> >> +       if (!err)
> >> +               err = fdt_setprop(fdt, nodeoffset, "kaslr-seed", &data, sizeof(data));
> >> +       if (err < 0)
> >> +               printf("WARNING: could not set kaslr-seed %s.\n", fdt_strerror(err));
>
> I have used debug messages to better track if error happens. I think it would be
> good if you can extend your code with it.
> Because if this fails people have to start tracking if issue is that there is
> RNG device or reading fails or issue with setting up property.

Hi Michal,

I'm assuming there is no valid case to have DM_RNG enabled and no
UCLASS_RNG driver which is why I'm printing an error if it ultimately
fails (vs a silent debug statement). If that is true then I should
probably printf errors for all the cases above vs debugs wouldn't you
think?

>
> In v1 it was said that you won't update it if the kaslr-seed property exists.
> I can't see this in the code. Or do I read it incorrectly?
>

That was a question posed in the discussion but I didn't get an answer
if that was what I should do. None of the three places I'm
deduplicating the functionality from check to see if it already
exists... they would overwrite an existing one. Is there a valid case
where you would not want to overwrite it?

>
> >> +
> >> +       return err;
> >> +}
> >> --
> >> 2.25.1
> >>
> >
> > I realized I forgot a few CC's here. Adding:
> >
> > Michal Simek <michal.simek@amd.com> (board/xilinx/common/board.c and
> > configs/xilinx* which have CMD_KASLRSEED)
> > Andy Yan <andy.yan@rock-chips.com> (configs/evb-rk3308_defconfig and
> > configs/roc-cc-rk3308_defconfig which have CMD_KASLRSEED)
> > Akash Gajjar <gajjar04akash@gmail.com>
> > (configs/rock-pi-s-rk3308_defconfig which has CMD_KASLRSEED)
> > Ilias Apalodimas <ilias.apalodimas@linaro.org> (MEASURE_DEVICETREE,
> > MEASURED_BOOT)
> >
> > Michal, I see that board/xilinx/common/board.c is adding
> > chosen/kaslr-seed in ft_board_setup as well as some of the
> > configs/xilinx boards enabling CMD_KASLRSEED - can we remove
> > CMD_ASLRSEED from those boards? (ie no bootscripts require it?)
>
>
> Based on my note above that you shouldn't change kaslr-seed if exists.

I can add that if you think it's the correct behavior, but that is not
what is done in the current code.

>
> What would also make sense is to extend kaslrseed command to pass one more
> parameter to pass which RNG instance should generate data on system with more
> RNGs. Then pretty much with command you can choose different RNG because current
> code hardcoded it to instance 0.

Do you mean extend the command or the fdt_kaslrseed function? I'm
trying to obsolete the command.

I can add an index to fdt_kaslrseed but would it be more useful to add
a udevice* that is used unless null? I can't see where someone wanting
to call this function would know the index of a specific UCLASS_RNG
device and not have the device * handy instead.

It sounds like with the question of not overwriting an existing value
you are anticipating board specific ft_board_setup functions that may
want to behave differently and choose a different rng source? If so,
ft_board_setup is called 'after' fdt_chosen so maybe fdt_kaslrseed
also needs a boolean to tell it to overwrite existing?

Are you open to removing CMD_KASLRSEED from the configs/xilinx* which
have it? If I can get everyone's approval for the few boards that
include CMD_KASLRSEED I would like to remove the command if we are
doing it automatically.

(adding Chris Morgan <macromorgan@hotmail.com> to cc who authored that cmd)

>
> Do you have correct dependency in generic code when MEASURED_BOOT is enabled as
> was mentioned in v1? If yes it should be mentioned in commit message.
>

Likely something is needed but I'm not sure if it's MEASURED_BOOT or
MEASURE_DEVICETREE - That's a question I posed to Ilias.

Best Regards,

Tim
Michal Simek May 21, 2024, 6:57 a.m. UTC | #8
On 5/20/24 18:37, Tim Harvey wrote:
> On Mon, May 20, 2024 at 1:29 AM Michal Simek <michal.simek@amd.com> wrote:
>>
>> Hi Tim,
>>
>> On 5/16/24 17:58, Tim Harvey wrote:
>>> On Wed, May 15, 2024 at 1:50 PM Tim Harvey <tharvey@gateworks.com> wrote:
>>>>
>>>> If RANDOMIZE_BASE is enabled in the Linux kernel instructing it to
>>>> randomize the virtual address at which the kernel image is loaded, it
>>>> expects entropy to be provided by the bootloader by populating
>>>> /chosen/kaslr-seed with a 64-bit value from source of entropy at boot.
>>>>
>>>> If we have DM_RNG enabled populate this value automatically when
>>>> fdt_chosen is called unless ARMV8_SEC_FIRMWARE_SUPPORT is enabled as
>>>> it's implementation uses a different source of entropy.
>>>>
>>>> As this fdt node is added elsewhere create a library function and
>>>> use it to deduplicate code.
>>>>
>>>> Note that the kalsrseed command (CMD_KASLRSEED) is likely pointless now
>>>> but left in place in case boot scripts exist that rely on this command
>>>> existing and returning success. An informational message is printed to
>>>> alert users of this command that it is likely no longer needed.
>>>>
>>>> Signed-off-by: Tim Harvey <tharvey@gateworks.com>
>>>> ---
>>>> v2:
>>>>    - fix typo in commit msg
>>>>    - use stack for seed to avoid unecessary malloc/free
>>>>    - move to a library function and deduplicate code by using it elsewhere
>>>> ---
>>>>    board/xilinx/common/board.c | 35 -----------------------------
>>>>    boot/fdt_support.c          | 10 +++++++++
>>>>    boot/pxe_utils.c            | 35 +++--------------------------
>>>>    cmd/kaslrseed.c             | 45 ++++++-------------------------------
>>>>    include/kaslrseed.h         | 17 ++++++++++++++
>>>>    lib/Makefile                |  1 +
>>>>    lib/kaslrseed.c             | 34 ++++++++++++++++++++++++++++
>>>>    7 files changed, 72 insertions(+), 105 deletions(-)
>>>>    create mode 100644 include/kaslrseed.h
>>>>    create mode 100644 lib/kaslrseed.c
>>>>
>>>> diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
>>>> index 30a81376ac41..f741e8957818 100644
>>>> --- a/board/xilinx/common/board.c
>>>> +++ b/board/xilinx/common/board.c
>>>> @@ -713,41 +713,6 @@ int ft_board_setup(void *blob, struct bd_info *bd)
>>>>           if (IS_ENABLED(CONFIG_FDT_FIXUP_PARTITIONS) && IS_ENABLED(CONFIG_NAND_ZYNQ))
>>>>                   fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
>>>>
>>>> -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
>>>> -               debug("No RNG device\n");
>>>> -               return 0;
>>>> -       }
>>>> -
>>>> -       if (dm_rng_read(dev, buf, n)) {
>>>> -               debug("Reading RNG failed\n");
>>>> -               return 0;
>>>> -       }
>>>> -
>>>> -       if (!blob) {
>>>> -               debug("No FDT memory address configured. Please configure\n"
>>>> -                     "the FDT address via \"fdt addr <address>\" command.\n"
>>>> -                     "Aborting!\n");
>>>> -               return 0;
>>>> -       }
>>>> -
>>>> -       ret = fdt_check_header(blob);
>>>> -       if (ret < 0) {
>>>> -               debug("fdt_chosen: %s\n", fdt_strerror(ret));
>>>> -               return ret;
>>>> -       }
>>>> -
>>>> -       nodeoffset = fdt_find_or_add_subnode(blob, 0, "chosen");
>>>> -       if (nodeoffset < 0) {
>>>> -               debug("Reading chosen node failed\n");
>>>> -               return nodeoffset;
>>>> -       }
>>>> -
>>>> -       ret = fdt_setprop(blob, nodeoffset, "kaslr-seed", buf, sizeof(buf));
>>>> -       if (ret < 0) {
>>>> -               debug("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
>>>> -               return ret;
>>>> -       }
>>>> -
>>>>           return 0;
>>>>    }
>>>>    #endif
>>>> diff --git a/boot/fdt_support.c b/boot/fdt_support.c
>>>> index 874ca4d6f5af..3455d60d69dc 100644
>>>> --- a/boot/fdt_support.c
>>>> +++ b/boot/fdt_support.c
>>>> @@ -8,6 +8,7 @@
>>>>
>>>>    #include <abuf.h>
>>>>    #include <env.h>
>>>> +#include <kaslrseed.h>
>>>>    #include <log.h>
>>>>    #include <mapmem.h>
>>>>    #include <net.h>
>>>> @@ -300,6 +301,15 @@ int fdt_chosen(void *fdt)
>>>>           if (nodeoffset < 0)
>>>>                   return nodeoffset;
>>>>
>>>> +       if (IS_ENABLED(CONFIG_DM_RNG) && !IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)) {
>>>> +               err = fdt_kaslrseed(fdt);
>>>> +               if (err) {
>>>> +                       printf("WARNING: could not set kaslr-seed %s.\n",
>>>> +                              fdt_strerror(err));
>>>> +                       return err;
>>>> +               }
>>>> +       }
>>>> +
>>>>           if (IS_ENABLED(CONFIG_BOARD_RNG_SEED) && !board_rng_seed(&buf)) {
>>>>                   err = fdt_setprop(fdt, nodeoffset, "rng-seed",
>>>>                                     abuf_data(&buf), abuf_size(&buf));
>>>> diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
>>>> index 4b22bb6f525a..8d70233fc08d 100644
>>>> --- a/boot/pxe_utils.c
>>>> +++ b/boot/pxe_utils.c
>>>> @@ -8,6 +8,7 @@
>>>>    #include <dm.h>
>>>>    #include <env.h>
>>>>    #include <image.h>
>>>> +#include <kaslrseed.h>
>>>>    #include <log.h>
>>>>    #include <malloc.h>
>>>>    #include <mapmem.h>
>>>> @@ -323,10 +324,6 @@ static void label_boot_kaslrseed(void)
>>>>    #if CONFIG_IS_ENABLED(DM_RNG)
>>>>           ulong fdt_addr;
>>>>           struct fdt_header *working_fdt;
>>>> -       size_t n = 0x8;
>>>> -       struct udevice *dev;
>>>> -       u64 *buf;
>>>> -       int nodeoffset;
>>>>           int err;
>>>>
>>>>           /* Get the main fdt and map it */
>>>> @@ -342,35 +339,9 @@ static void label_boot_kaslrseed(void)
>>>>           if (err <= 0)
>>>>                   return;
>>>>
>>>> -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
>>>> -               printf("No RNG device\n");
>>>> -               return;
>>>> -       }
>>>> -
>>>> -       nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
>>>> -       if (nodeoffset < 0) {
>>>> -               printf("Reading chosen node failed\n");
>>>> -               return;
>>>> -       }
>>>> -
>>>> -       buf = malloc(n);
>>>> -       if (!buf) {
>>>> -               printf("Out of memory\n");
>>>> -               return;
>>>> -       }
>>>> -
>>>> -       if (dm_rng_read(dev, buf, n)) {
>>>> -               printf("Reading RNG failed\n");
>>>> -               goto err;
>>>> -       }
>>>> -
>>>> -       err = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
>>>> -       if (err < 0) {
>>>> +       err = fdt_kaslrseed(working_fdt);
>>>> +       if (err < 0)
>>>>                   printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
>>>> -               goto err;
>>>> -       }
>>>> -err:
>>>> -       free(buf);
>>>>    #endif
>>>>           return;
>>>>    }
>>>> diff --git a/cmd/kaslrseed.c b/cmd/kaslrseed.c
>>>> index e0d3c7fe7489..ea5c07d729cf 100644
>>>> --- a/cmd/kaslrseed.c
>>>> +++ b/cmd/kaslrseed.c
>>>> @@ -9,33 +9,16 @@
>>>>    #include <command.h>
>>>>    #include <dm.h>
>>>>    #include <hexdump.h>
>>>> +#include <kaslrseed.h>
>>>>    #include <malloc.h>
>>>>    #include <rng.h>
>>>>    #include <fdt_support.h>
>>>>
>>>>    static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
>>>>    {
>>>> -       size_t n = 0x8;
>>>> -       struct udevice *dev;
>>>> -       u64 *buf;
>>>> -       int nodeoffset;
>>>> -       int ret = CMD_RET_SUCCESS;
>>>> +       int err;
>>>>
>>>> -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
>>>> -               printf("No RNG device\n");
>>>> -               return CMD_RET_FAILURE;
>>>> -       }
>>>> -
>>>> -       buf = malloc(n);
>>>> -       if (!buf) {
>>>> -               printf("Out of memory\n");
>>>> -               return CMD_RET_FAILURE;
>>>> -       }
>>>> -
>>>> -       if (dm_rng_read(dev, buf, n)) {
>>>> -               printf("Reading RNG failed\n");
>>>> -               return CMD_RET_FAILURE;
>>>> -       }
>>>> +       printf("Notice: a /chosen/kaslr-seed is automatically added to the device-tree when booted via booti/bootm/bootz therefore using this command is likely no longer needed");
>>>>
>>>>           if (!working_fdt) {
>>>>                   printf("No FDT memory address configured. Please configure\n"
>>>> @@ -44,27 +27,13 @@ static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const
>>>>                   return CMD_RET_FAILURE;
>>>>           }
>>>>
>>>> -       ret = fdt_check_header(working_fdt);
>>>> -       if (ret < 0) {
>>>> -               printf("fdt_chosen: %s\n", fdt_strerror(ret));
>>>> +       err = fdt_kaslrseed(working_fdt);
>>>> +       if (err < 0) {
>>>> +               printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
>>>>                   return CMD_RET_FAILURE;
>>>>           }
>>>>
>>>> -       nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
>>>> -       if (nodeoffset < 0) {
>>>> -               printf("Reading chosen node failed\n");
>>>> -               return CMD_RET_FAILURE;
>>>> -       }
>>>> -
>>>> -       ret = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
>>>> -       if (ret < 0) {
>>>> -               printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
>>>> -               return CMD_RET_FAILURE;
>>>> -       }
>>>> -
>>>> -       free(buf);
>>>> -
>>>> -       return ret;
>>>> +       return CMD_RET_SUCCESS;
>>>>    }
>>>>
>>>>    U_BOOT_LONGHELP(kaslrseed,
>>>> diff --git a/include/kaslrseed.h b/include/kaslrseed.h
>>>> new file mode 100644
>>>> index 000000000000..3fe82f418acf
>>>> --- /dev/null
>>>> +++ b/include/kaslrseed.h
>>>> @@ -0,0 +1,17 @@
>>>> +/* SPDX-License-Identifier: GPL-2.0+ */
>>>> +/*
>>>> + * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
>>>> + */
>>>> +
>>>> +#if !defined _KASLRSEED_H_
>>>> +#define _KASLRSEED_H_
>>>> +
>>>> +/**
>>>> + * fdt_kaslrseed() - create a 'kaslr-seed' node in chosen
>>>> + *
>>>> + * @blob:      fdt blob
>>>> + * Return:     0 if OK, -ve on error
>>>> + */
>>>> +int fdt_kaslrseed(void *blob);
>>>> +
>>>> +#endif /* _KASLRSEED_H_ */
>>>> diff --git a/lib/Makefile b/lib/Makefile
>>>> index 2a76acf100d0..20a0242055fa 100644
>>>> --- a/lib/Makefile
>>>> +++ b/lib/Makefile
>>>> @@ -149,6 +149,7 @@ obj-y += date.o
>>>>    obj-y += rtc-lib.o
>>>>    obj-$(CONFIG_LIB_ELF) += elf.o
>>>>
>>>> +obj-$(CONFIG_DM_RNG) += kaslrseed.o
>>>>    obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += semihosting.o
>>>>
>>>>    #
>>>> diff --git a/lib/kaslrseed.c b/lib/kaslrseed.c
>>>> new file mode 100644
>>>> index 000000000000..ad06bee2b88d
>>>> --- /dev/null
>>>> +++ b/lib/kaslrseed.c
>>>> @@ -0,0 +1,34 @@
>>>> +// SPDX-License-Identifier: GPL-2.0+
>>>> +/*
>>>> + * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
>>>> + */
>>>> +#include <dm.h>
>>>> +#include <rng.h>
>>>> +#include <fdt_support.h>
>>>> +
>>>> +int fdt_kaslrseed(void *fdt)
>>>> +{
>>>> +       struct udevice *dev;
>>>> +       int nodeoffset;
>>>> +       u64 data;
>>>> +       int err;
>>>> +
>>>> +       err = fdt_check_header(fdt);
>>>> +       if (err < 0)
>>>> +               return err;
>>>> +
>>>> +       /* find or create "/chosen" node. */
>>>> +       nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
>>>> +       if (nodeoffset < 0)
>>>> +               return nodeoffset;
>>>> +
>>>> +       err = uclass_get_device(UCLASS_RNG, 0, &dev);
>>>> +       if (!err)
>>>> +               err = dm_rng_read(dev, &data, sizeof(data));
>>>> +       if (!err)
>>>> +               err = fdt_setprop(fdt, nodeoffset, "kaslr-seed", &data, sizeof(data));
>>>> +       if (err < 0)
>>>> +               printf("WARNING: could not set kaslr-seed %s.\n", fdt_strerror(err));
>>
>> I have used debug messages to better track if error happens. I think it would be
>> good if you can extend your code with it.
>> Because if this fails people have to start tracking if issue is that there is
>> RNG device or reading fails or issue with setting up property.
> 
> Hi Michal,
> 
> I'm assuming there is no valid case to have DM_RNG enabled and no
> UCLASS_RNG driver which is why I'm printing an error if it ultimately
> fails (vs a silent debug statement). If that is true then I should
> probably printf errors for all the cases above vs debugs wouldn't you
> think?

You can have RNG in SOC or you can have RNG inside TPM for example.
It means DM_RNG can be enabled with two drivers but spi/i2c don't need to work 
and access to internal RNG doesn't need to be permitted.
debug() messages are not going to production systems but having them rightly 
written can help with debugging issues without writing own debug messsages.


> 
>>
>> In v1 it was said that you won't update it if the kaslr-seed property exists.
>> I can't see this in the code. Or do I read it incorrectly?
>>
> 
> That was a question posed in the discussion but I didn't get an answer
> if that was what I should do. None of the three places I'm
> deduplicating the functionality from check to see if it already
> exists... they would overwrite an existing one. Is there a valid case
> where you would not want to overwrite it?

In production system very likely not but I can imagine that developers can play 
with it.

>>>> +
>>>> +       return err;
>>>> +}
>>>> --
>>>> 2.25.1
>>>>
>>>
>>> I realized I forgot a few CC's here. Adding:
>>>
>>> Michal Simek <michal.simek@amd.com> (board/xilinx/common/board.c and
>>> configs/xilinx* which have CMD_KASLRSEED)
>>> Andy Yan <andy.yan@rock-chips.com> (configs/evb-rk3308_defconfig and
>>> configs/roc-cc-rk3308_defconfig which have CMD_KASLRSEED)
>>> Akash Gajjar <gajjar04akash@gmail.com>
>>> (configs/rock-pi-s-rk3308_defconfig which has CMD_KASLRSEED)
>>> Ilias Apalodimas <ilias.apalodimas@linaro.org> (MEASURE_DEVICETREE,
>>> MEASURED_BOOT)
>>>
>>> Michal, I see that board/xilinx/common/board.c is adding
>>> chosen/kaslr-seed in ft_board_setup as well as some of the
>>> configs/xilinx boards enabling CMD_KASLRSEED - can we remove
>>> CMD_ASLRSEED from those boards? (ie no bootscripts require it?)
>>
>>
>> Based on my note above that you shouldn't change kaslr-seed if exists.
> 
> I can add that if you think it's the correct behavior, but that is not
> what is done in the current code.

yes I know

> 
>>
>> What would also make sense is to extend kaslrseed command to pass one more
>> parameter to pass which RNG instance should generate data on system with more
>> RNGs. Then pretty much with command you can choose different RNG because current
>> code hardcoded it to instance 0.
> 
> Do you mean extend the command or the fdt_kaslrseed function? I'm
> trying to obsolete the command.

I am fully aware about this.

> 
> I can add an index to fdt_kaslrseed but would it be more useful to add
> a udevice* that is used unless null? I can't see where someone wanting
> to call this function would know the index of a specific UCLASS_RNG
> device and not have the device * handy instead.

Think about system as I described above with two RNGs in the system.
How do you provide a way to select which one is going to be used?
Index 0 means the first device which is bind. What user should do if they want 
to use the second device? Resort DT?
Use RNG DT aliases or so?


> It sounds like with the question of not overwriting an existing value
> you are anticipating board specific ft_board_setup functions that may
> want to behave differently and choose a different rng source? If so,
> ft_board_setup is called 'after' fdt_chosen so maybe fdt_kaslrseed
> also needs a boolean to tell it to overwrite existing?

This sounds good to me.

It means pretty much if you can change it to

int fdt_kaslrseed(void *fdt, int index, bool overwrite)

where generic call will call index as 0 and if users want to overwrite it they 
can. Default value for overwrite is tricky because I can understand setting it 
to both values.


> 
> Are you open to removing CMD_KASLRSEED from the configs/xilinx* which
> have it? If I can get everyone's approval for the few boards that
> include CMD_KASLRSEED I would like to remove the command if we are
> doing it automatically.

I think command itself can provide an easy way how to inject kaslr-seed to DT 
from other RNGs but also your current implementation takes care about DT used 
for booting one OS. I am not playing with Dom0-less systems but I can imagine 
that there could be a need to inject more then just one seed for other CPUs on 
heterogenios systems that's why I wouldn't really force to remove the command.
If people don't like they can simply disable it.

> 
> (adding Chris Morgan <macromorgan@hotmail.com> to cc who authored that cmd)
> 
>>
>> Do you have correct dependency in generic code when MEASURED_BOOT is enabled as
>> was mentioned in v1? If yes it should be mentioned in commit message.
>>
> 
> Likely something is needed but I'm not sure if it's MEASURED_BOOT or
> MEASURE_DEVICETREE - That's a question I posed to Ilias.

Ilias was at Linaro connect. When he gets back he will likely answer it.

Thanks,
Michal
Ilias Apalodimas May 21, 2024, 12:04 p.m. UTC | #9
Hi Tim

On Wed, 15 May 2024 at 23:50, Tim Harvey <tharvey@gateworks.com> wrote:
>
> If RANDOMIZE_BASE is enabled in the Linux kernel instructing it to
> randomize the virtual address at which the kernel image is loaded, it
> expects entropy to be provided by the bootloader by populating
> /chosen/kaslr-seed with a 64-bit value from source of entropy at boot.

Since you'll send a v2, mind adding some description for UEFI on the
commit message?
efi_try_purge_kaslr_seed() has a comment of the behaviour

Thanks
/Ilias
>
> If we have DM_RNG enabled populate this value automatically when
> fdt_chosen is called unless ARMV8_SEC_FIRMWARE_SUPPORT is enabled as
> it's implementation uses a different source of entropy.
>
> As this fdt node is added elsewhere create a library function and
> use it to deduplicate code.
>
> Note that the kalsrseed command (CMD_KASLRSEED) is likely pointless now
> but left in place in case boot scripts exist that rely on this command
> existing and returning success. An informational message is printed to
> alert users of this command that it is likely no longer needed.
>
> Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> ---
> v2:
>  - fix typo in commit msg
>  - use stack for seed to avoid unecessary malloc/free
>  - move to a library function and deduplicate code by using it elsewhere
> ---
>  board/xilinx/common/board.c | 35 -----------------------------
>  boot/fdt_support.c          | 10 +++++++++
>  boot/pxe_utils.c            | 35 +++--------------------------
>  cmd/kaslrseed.c             | 45 ++++++-------------------------------
>  include/kaslrseed.h         | 17 ++++++++++++++
>  lib/Makefile                |  1 +
>  lib/kaslrseed.c             | 34 ++++++++++++++++++++++++++++
>  7 files changed, 72 insertions(+), 105 deletions(-)
>  create mode 100644 include/kaslrseed.h
>  create mode 100644 lib/kaslrseed.c
>
> diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
> index 30a81376ac41..f741e8957818 100644
> --- a/board/xilinx/common/board.c
> +++ b/board/xilinx/common/board.c
> @@ -713,41 +713,6 @@ int ft_board_setup(void *blob, struct bd_info *bd)
>         if (IS_ENABLED(CONFIG_FDT_FIXUP_PARTITIONS) && IS_ENABLED(CONFIG_NAND_ZYNQ))
>                 fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
>
> -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> -               debug("No RNG device\n");
> -               return 0;
> -       }
> -
> -       if (dm_rng_read(dev, buf, n)) {
> -               debug("Reading RNG failed\n");
> -               return 0;
> -       }
> -
> -       if (!blob) {
> -               debug("No FDT memory address configured. Please configure\n"
> -                     "the FDT address via \"fdt addr <address>\" command.\n"
> -                     "Aborting!\n");
> -               return 0;
> -       }
> -
> -       ret = fdt_check_header(blob);
> -       if (ret < 0) {
> -               debug("fdt_chosen: %s\n", fdt_strerror(ret));
> -               return ret;
> -       }
> -
> -       nodeoffset = fdt_find_or_add_subnode(blob, 0, "chosen");
> -       if (nodeoffset < 0) {
> -               debug("Reading chosen node failed\n");
> -               return nodeoffset;
> -       }
> -
> -       ret = fdt_setprop(blob, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> -       if (ret < 0) {
> -               debug("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
> -               return ret;
> -       }
> -
>         return 0;
>  }
>  #endif
> diff --git a/boot/fdt_support.c b/boot/fdt_support.c
> index 874ca4d6f5af..3455d60d69dc 100644
> --- a/boot/fdt_support.c
> +++ b/boot/fdt_support.c
> @@ -8,6 +8,7 @@
>
>  #include <abuf.h>
>  #include <env.h>
> +#include <kaslrseed.h>
>  #include <log.h>
>  #include <mapmem.h>
>  #include <net.h>
> @@ -300,6 +301,15 @@ int fdt_chosen(void *fdt)
>         if (nodeoffset < 0)
>                 return nodeoffset;
>
> +       if (IS_ENABLED(CONFIG_DM_RNG) && !IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)) {
> +               err = fdt_kaslrseed(fdt);
> +               if (err) {
> +                       printf("WARNING: could not set kaslr-seed %s.\n",
> +                              fdt_strerror(err));
> +                       return err;
> +               }
> +       }
> +
>         if (IS_ENABLED(CONFIG_BOARD_RNG_SEED) && !board_rng_seed(&buf)) {
>                 err = fdt_setprop(fdt, nodeoffset, "rng-seed",
>                                   abuf_data(&buf), abuf_size(&buf));
> diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
> index 4b22bb6f525a..8d70233fc08d 100644
> --- a/boot/pxe_utils.c
> +++ b/boot/pxe_utils.c
> @@ -8,6 +8,7 @@
>  #include <dm.h>
>  #include <env.h>
>  #include <image.h>
> +#include <kaslrseed.h>
>  #include <log.h>
>  #include <malloc.h>
>  #include <mapmem.h>
> @@ -323,10 +324,6 @@ static void label_boot_kaslrseed(void)
>  #if CONFIG_IS_ENABLED(DM_RNG)
>         ulong fdt_addr;
>         struct fdt_header *working_fdt;
> -       size_t n = 0x8;
> -       struct udevice *dev;
> -       u64 *buf;
> -       int nodeoffset;
>         int err;
>
>         /* Get the main fdt and map it */
> @@ -342,35 +339,9 @@ static void label_boot_kaslrseed(void)
>         if (err <= 0)
>                 return;
>
> -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> -               printf("No RNG device\n");
> -               return;
> -       }
> -
> -       nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
> -       if (nodeoffset < 0) {
> -               printf("Reading chosen node failed\n");
> -               return;
> -       }
> -
> -       buf = malloc(n);
> -       if (!buf) {
> -               printf("Out of memory\n");
> -               return;
> -       }
> -
> -       if (dm_rng_read(dev, buf, n)) {
> -               printf("Reading RNG failed\n");
> -               goto err;
> -       }
> -
> -       err = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> -       if (err < 0) {
> +       err = fdt_kaslrseed(working_fdt);
> +       if (err < 0)
>                 printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
> -               goto err;
> -       }
> -err:
> -       free(buf);
>  #endif
>         return;
>  }
> diff --git a/cmd/kaslrseed.c b/cmd/kaslrseed.c
> index e0d3c7fe7489..ea5c07d729cf 100644
> --- a/cmd/kaslrseed.c
> +++ b/cmd/kaslrseed.c
> @@ -9,33 +9,16 @@
>  #include <command.h>
>  #include <dm.h>
>  #include <hexdump.h>
> +#include <kaslrseed.h>
>  #include <malloc.h>
>  #include <rng.h>
>  #include <fdt_support.h>
>
>  static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
>  {
> -       size_t n = 0x8;
> -       struct udevice *dev;
> -       u64 *buf;
> -       int nodeoffset;
> -       int ret = CMD_RET_SUCCESS;
> +       int err;
>
> -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> -               printf("No RNG device\n");
> -               return CMD_RET_FAILURE;
> -       }
> -
> -       buf = malloc(n);
> -       if (!buf) {
> -               printf("Out of memory\n");
> -               return CMD_RET_FAILURE;
> -       }
> -
> -       if (dm_rng_read(dev, buf, n)) {
> -               printf("Reading RNG failed\n");
> -               return CMD_RET_FAILURE;
> -       }
> +       printf("Notice: a /chosen/kaslr-seed is automatically added to the device-tree when booted via booti/bootm/bootz therefore using this command is likely no longer needed");
>
>         if (!working_fdt) {
>                 printf("No FDT memory address configured. Please configure\n"
> @@ -44,27 +27,13 @@ static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const
>                 return CMD_RET_FAILURE;
>         }
>
> -       ret = fdt_check_header(working_fdt);
> -       if (ret < 0) {
> -               printf("fdt_chosen: %s\n", fdt_strerror(ret));
> +       err = fdt_kaslrseed(working_fdt);
> +       if (err < 0) {
> +               printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
>                 return CMD_RET_FAILURE;
>         }
>
> -       nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
> -       if (nodeoffset < 0) {
> -               printf("Reading chosen node failed\n");
> -               return CMD_RET_FAILURE;
> -       }
> -
> -       ret = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> -       if (ret < 0) {
> -               printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
> -               return CMD_RET_FAILURE;
> -       }
> -
> -       free(buf);
> -
> -       return ret;
> +       return CMD_RET_SUCCESS;
>  }
>
>  U_BOOT_LONGHELP(kaslrseed,
> diff --git a/include/kaslrseed.h b/include/kaslrseed.h
> new file mode 100644
> index 000000000000..3fe82f418acf
> --- /dev/null
> +++ b/include/kaslrseed.h
> @@ -0,0 +1,17 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
> + */
> +
> +#if !defined _KASLRSEED_H_
> +#define _KASLRSEED_H_
> +
> +/**
> + * fdt_kaslrseed() - create a 'kaslr-seed' node in chosen
> + *
> + * @blob:      fdt blob
> + * Return:     0 if OK, -ve on error
> + */
> +int fdt_kaslrseed(void *blob);
> +
> +#endif /* _KASLRSEED_H_ */
> diff --git a/lib/Makefile b/lib/Makefile
> index 2a76acf100d0..20a0242055fa 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -149,6 +149,7 @@ obj-y += date.o
>  obj-y += rtc-lib.o
>  obj-$(CONFIG_LIB_ELF) += elf.o
>
> +obj-$(CONFIG_DM_RNG) += kaslrseed.o
>  obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += semihosting.o
>
>  #
> diff --git a/lib/kaslrseed.c b/lib/kaslrseed.c
> new file mode 100644
> index 000000000000..ad06bee2b88d
> --- /dev/null
> +++ b/lib/kaslrseed.c
> @@ -0,0 +1,34 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
> + */
> +#include <dm.h>
> +#include <rng.h>
> +#include <fdt_support.h>
> +
> +int fdt_kaslrseed(void *fdt)
> +{
> +       struct udevice *dev;
> +       int nodeoffset;
> +       u64 data;
> +       int err;
> +
> +       err = fdt_check_header(fdt);
> +       if (err < 0)
> +               return err;
> +
> +       /* find or create "/chosen" node. */
> +       nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
> +       if (nodeoffset < 0)
> +               return nodeoffset;
> +
> +       err = uclass_get_device(UCLASS_RNG, 0, &dev);
> +       if (!err)
> +               err = dm_rng_read(dev, &data, sizeof(data));
> +       if (!err)
> +               err = fdt_setprop(fdt, nodeoffset, "kaslr-seed", &data, sizeof(data));
> +       if (err < 0)
> +               printf("WARNING: could not set kaslr-seed %s.\n", fdt_strerror(err));
> +
> +       return err;
> +}
> --
> 2.25.1
>
Chris Morgan May 21, 2024, 3:50 p.m. UTC | #10
On Mon, May 20, 2024 at 09:37:21AM -0700, Tim Harvey wrote:
> On Mon, May 20, 2024 at 1:29 AM Michal Simek <michal.simek@amd.com> wrote:
> >
> > Hi Tim,
> >
> > On 5/16/24 17:58, Tim Harvey wrote:
> > > On Wed, May 15, 2024 at 1:50 PM Tim Harvey <tharvey@gateworks.com> wrote:
> > >>
> > >> If RANDOMIZE_BASE is enabled in the Linux kernel instructing it to
> > >> randomize the virtual address at which the kernel image is loaded, it
> > >> expects entropy to be provided by the bootloader by populating
> > >> /chosen/kaslr-seed with a 64-bit value from source of entropy at boot.
> > >>
> > >> If we have DM_RNG enabled populate this value automatically when
> > >> fdt_chosen is called unless ARMV8_SEC_FIRMWARE_SUPPORT is enabled as
> > >> it's implementation uses a different source of entropy.
> > >>
> > >> As this fdt node is added elsewhere create a library function and
> > >> use it to deduplicate code.
> > >>
> > >> Note that the kalsrseed command (CMD_KASLRSEED) is likely pointless now
> > >> but left in place in case boot scripts exist that rely on this command
> > >> existing and returning success. An informational message is printed to
> > >> alert users of this command that it is likely no longer needed.
> > >>
> > >> Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> > >> ---
> > >> v2:
> > >>   - fix typo in commit msg
> > >>   - use stack for seed to avoid unecessary malloc/free
> > >>   - move to a library function and deduplicate code by using it elsewhere
> > >> ---
> > >>   board/xilinx/common/board.c | 35 -----------------------------
> > >>   boot/fdt_support.c          | 10 +++++++++
> > >>   boot/pxe_utils.c            | 35 +++--------------------------
> > >>   cmd/kaslrseed.c             | 45 ++++++-------------------------------
> > >>   include/kaslrseed.h         | 17 ++++++++++++++
> > >>   lib/Makefile                |  1 +
> > >>   lib/kaslrseed.c             | 34 ++++++++++++++++++++++++++++
> > >>   7 files changed, 72 insertions(+), 105 deletions(-)
> > >>   create mode 100644 include/kaslrseed.h
> > >>   create mode 100644 lib/kaslrseed.c
> > >>
> > >> diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
> > >> index 30a81376ac41..f741e8957818 100644
> > >> --- a/board/xilinx/common/board.c
> > >> +++ b/board/xilinx/common/board.c
> > >> @@ -713,41 +713,6 @@ int ft_board_setup(void *blob, struct bd_info *bd)
> > >>          if (IS_ENABLED(CONFIG_FDT_FIXUP_PARTITIONS) && IS_ENABLED(CONFIG_NAND_ZYNQ))
> > >>                  fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
> > >>
> > >> -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> > >> -               debug("No RNG device\n");
> > >> -               return 0;
> > >> -       }
> > >> -
> > >> -       if (dm_rng_read(dev, buf, n)) {
> > >> -               debug("Reading RNG failed\n");
> > >> -               return 0;
> > >> -       }
> > >> -
> > >> -       if (!blob) {
> > >> -               debug("No FDT memory address configured. Please configure\n"
> > >> -                     "the FDT address via \"fdt addr <address>\" command.\n"
> > >> -                     "Aborting!\n");
> > >> -               return 0;
> > >> -       }
> > >> -
> > >> -       ret = fdt_check_header(blob);
> > >> -       if (ret < 0) {
> > >> -               debug("fdt_chosen: %s\n", fdt_strerror(ret));
> > >> -               return ret;
> > >> -       }
> > >> -
> > >> -       nodeoffset = fdt_find_or_add_subnode(blob, 0, "chosen");
> > >> -       if (nodeoffset < 0) {
> > >> -               debug("Reading chosen node failed\n");
> > >> -               return nodeoffset;
> > >> -       }
> > >> -
> > >> -       ret = fdt_setprop(blob, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> > >> -       if (ret < 0) {
> > >> -               debug("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
> > >> -               return ret;
> > >> -       }
> > >> -
> > >>          return 0;
> > >>   }
> > >>   #endif
> > >> diff --git a/boot/fdt_support.c b/boot/fdt_support.c
> > >> index 874ca4d6f5af..3455d60d69dc 100644
> > >> --- a/boot/fdt_support.c
> > >> +++ b/boot/fdt_support.c
> > >> @@ -8,6 +8,7 @@
> > >>
> > >>   #include <abuf.h>
> > >>   #include <env.h>
> > >> +#include <kaslrseed.h>
> > >>   #include <log.h>
> > >>   #include <mapmem.h>
> > >>   #include <net.h>
> > >> @@ -300,6 +301,15 @@ int fdt_chosen(void *fdt)
> > >>          if (nodeoffset < 0)
> > >>                  return nodeoffset;
> > >>
> > >> +       if (IS_ENABLED(CONFIG_DM_RNG) && !IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)) {
> > >> +               err = fdt_kaslrseed(fdt);
> > >> +               if (err) {
> > >> +                       printf("WARNING: could not set kaslr-seed %s.\n",
> > >> +                              fdt_strerror(err));
> > >> +                       return err;
> > >> +               }
> > >> +       }
> > >> +
> > >>          if (IS_ENABLED(CONFIG_BOARD_RNG_SEED) && !board_rng_seed(&buf)) {
> > >>                  err = fdt_setprop(fdt, nodeoffset, "rng-seed",
> > >>                                    abuf_data(&buf), abuf_size(&buf));
> > >> diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
> > >> index 4b22bb6f525a..8d70233fc08d 100644
> > >> --- a/boot/pxe_utils.c
> > >> +++ b/boot/pxe_utils.c
> > >> @@ -8,6 +8,7 @@
> > >>   #include <dm.h>
> > >>   #include <env.h>
> > >>   #include <image.h>
> > >> +#include <kaslrseed.h>
> > >>   #include <log.h>
> > >>   #include <malloc.h>
> > >>   #include <mapmem.h>
> > >> @@ -323,10 +324,6 @@ static void label_boot_kaslrseed(void)
> > >>   #if CONFIG_IS_ENABLED(DM_RNG)
> > >>          ulong fdt_addr;
> > >>          struct fdt_header *working_fdt;
> > >> -       size_t n = 0x8;
> > >> -       struct udevice *dev;
> > >> -       u64 *buf;
> > >> -       int nodeoffset;
> > >>          int err;
> > >>
> > >>          /* Get the main fdt and map it */
> > >> @@ -342,35 +339,9 @@ static void label_boot_kaslrseed(void)
> > >>          if (err <= 0)
> > >>                  return;
> > >>
> > >> -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> > >> -               printf("No RNG device\n");
> > >> -               return;
> > >> -       }
> > >> -
> > >> -       nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
> > >> -       if (nodeoffset < 0) {
> > >> -               printf("Reading chosen node failed\n");
> > >> -               return;
> > >> -       }
> > >> -
> > >> -       buf = malloc(n);
> > >> -       if (!buf) {
> > >> -               printf("Out of memory\n");
> > >> -               return;
> > >> -       }
> > >> -
> > >> -       if (dm_rng_read(dev, buf, n)) {
> > >> -               printf("Reading RNG failed\n");
> > >> -               goto err;
> > >> -       }
> > >> -
> > >> -       err = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> > >> -       if (err < 0) {
> > >> +       err = fdt_kaslrseed(working_fdt);
> > >> +       if (err < 0)
> > >>                  printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
> > >> -               goto err;
> > >> -       }
> > >> -err:
> > >> -       free(buf);
> > >>   #endif
> > >>          return;
> > >>   }
> > >> diff --git a/cmd/kaslrseed.c b/cmd/kaslrseed.c
> > >> index e0d3c7fe7489..ea5c07d729cf 100644
> > >> --- a/cmd/kaslrseed.c
> > >> +++ b/cmd/kaslrseed.c
> > >> @@ -9,33 +9,16 @@
> > >>   #include <command.h>
> > >>   #include <dm.h>
> > >>   #include <hexdump.h>
> > >> +#include <kaslrseed.h>
> > >>   #include <malloc.h>
> > >>   #include <rng.h>
> > >>   #include <fdt_support.h>
> > >>
> > >>   static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> > >>   {
> > >> -       size_t n = 0x8;
> > >> -       struct udevice *dev;
> > >> -       u64 *buf;
> > >> -       int nodeoffset;
> > >> -       int ret = CMD_RET_SUCCESS;
> > >> +       int err;
> > >>
> > >> -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> > >> -               printf("No RNG device\n");
> > >> -               return CMD_RET_FAILURE;
> > >> -       }
> > >> -
> > >> -       buf = malloc(n);
> > >> -       if (!buf) {
> > >> -               printf("Out of memory\n");
> > >> -               return CMD_RET_FAILURE;
> > >> -       }
> > >> -
> > >> -       if (dm_rng_read(dev, buf, n)) {
> > >> -               printf("Reading RNG failed\n");
> > >> -               return CMD_RET_FAILURE;
> > >> -       }
> > >> +       printf("Notice: a /chosen/kaslr-seed is automatically added to the device-tree when booted via booti/bootm/bootz therefore using this command is likely no longer needed");
> > >>
> > >>          if (!working_fdt) {
> > >>                  printf("No FDT memory address configured. Please configure\n"
> > >> @@ -44,27 +27,13 @@ static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const
> > >>                  return CMD_RET_FAILURE;
> > >>          }
> > >>
> > >> -       ret = fdt_check_header(working_fdt);
> > >> -       if (ret < 0) {
> > >> -               printf("fdt_chosen: %s\n", fdt_strerror(ret));
> > >> +       err = fdt_kaslrseed(working_fdt);
> > >> +       if (err < 0) {
> > >> +               printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
> > >>                  return CMD_RET_FAILURE;
> > >>          }
> > >>
> > >> -       nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
> > >> -       if (nodeoffset < 0) {
> > >> -               printf("Reading chosen node failed\n");
> > >> -               return CMD_RET_FAILURE;
> > >> -       }
> > >> -
> > >> -       ret = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> > >> -       if (ret < 0) {
> > >> -               printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
> > >> -               return CMD_RET_FAILURE;
> > >> -       }
> > >> -
> > >> -       free(buf);
> > >> -
> > >> -       return ret;
> > >> +       return CMD_RET_SUCCESS;
> > >>   }
> > >>
> > >>   U_BOOT_LONGHELP(kaslrseed,
> > >> diff --git a/include/kaslrseed.h b/include/kaslrseed.h
> > >> new file mode 100644
> > >> index 000000000000..3fe82f418acf
> > >> --- /dev/null
> > >> +++ b/include/kaslrseed.h
> > >> @@ -0,0 +1,17 @@
> > >> +/* SPDX-License-Identifier: GPL-2.0+ */
> > >> +/*
> > >> + * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
> > >> + */
> > >> +
> > >> +#if !defined _KASLRSEED_H_
> > >> +#define _KASLRSEED_H_
> > >> +
> > >> +/**
> > >> + * fdt_kaslrseed() - create a 'kaslr-seed' node in chosen
> > >> + *
> > >> + * @blob:      fdt blob
> > >> + * Return:     0 if OK, -ve on error
> > >> + */
> > >> +int fdt_kaslrseed(void *blob);
> > >> +
> > >> +#endif /* _KASLRSEED_H_ */
> > >> diff --git a/lib/Makefile b/lib/Makefile
> > >> index 2a76acf100d0..20a0242055fa 100644
> > >> --- a/lib/Makefile
> > >> +++ b/lib/Makefile
> > >> @@ -149,6 +149,7 @@ obj-y += date.o
> > >>   obj-y += rtc-lib.o
> > >>   obj-$(CONFIG_LIB_ELF) += elf.o
> > >>
> > >> +obj-$(CONFIG_DM_RNG) += kaslrseed.o
> > >>   obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += semihosting.o
> > >>
> > >>   #
> > >> diff --git a/lib/kaslrseed.c b/lib/kaslrseed.c
> > >> new file mode 100644
> > >> index 000000000000..ad06bee2b88d
> > >> --- /dev/null
> > >> +++ b/lib/kaslrseed.c
> > >> @@ -0,0 +1,34 @@
> > >> +// SPDX-License-Identifier: GPL-2.0+
> > >> +/*
> > >> + * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
> > >> + */
> > >> +#include <dm.h>
> > >> +#include <rng.h>
> > >> +#include <fdt_support.h>
> > >> +
> > >> +int fdt_kaslrseed(void *fdt)
> > >> +{
> > >> +       struct udevice *dev;
> > >> +       int nodeoffset;
> > >> +       u64 data;
> > >> +       int err;
> > >> +
> > >> +       err = fdt_check_header(fdt);
> > >> +       if (err < 0)
> > >> +               return err;
> > >> +
> > >> +       /* find or create "/chosen" node. */
> > >> +       nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
> > >> +       if (nodeoffset < 0)
> > >> +               return nodeoffset;
> > >> +
> > >> +       err = uclass_get_device(UCLASS_RNG, 0, &dev);
> > >> +       if (!err)
> > >> +               err = dm_rng_read(dev, &data, sizeof(data));
> > >> +       if (!err)
> > >> +               err = fdt_setprop(fdt, nodeoffset, "kaslr-seed", &data, sizeof(data));
> > >> +       if (err < 0)
> > >> +               printf("WARNING: could not set kaslr-seed %s.\n", fdt_strerror(err));
> >
> > I have used debug messages to better track if error happens. I think it would be
> > good if you can extend your code with it.
> > Because if this fails people have to start tracking if issue is that there is
> > RNG device or reading fails or issue with setting up property.
> 
> Hi Michal,
> 
> I'm assuming there is no valid case to have DM_RNG enabled and no
> UCLASS_RNG driver which is why I'm printing an error if it ultimately
> fails (vs a silent debug statement). If that is true then I should
> probably printf errors for all the cases above vs debugs wouldn't you
> think?
> 
> >
> > In v1 it was said that you won't update it if the kaslr-seed property exists.
> > I can't see this in the code. Or do I read it incorrectly?
> >
> 
> That was a question posed in the discussion but I didn't get an answer
> if that was what I should do. None of the three places I'm
> deduplicating the functionality from check to see if it already
> exists... they would overwrite an existing one. Is there a valid case
> where you would not want to overwrite it?
> 
> >
> > >> +
> > >> +       return err;
> > >> +}
> > >> --
> > >> 2.25.1
> > >>
> > >
> > > I realized I forgot a few CC's here. Adding:
> > >
> > > Michal Simek <michal.simek@amd.com> (board/xilinx/common/board.c and
> > > configs/xilinx* which have CMD_KASLRSEED)
> > > Andy Yan <andy.yan@rock-chips.com> (configs/evb-rk3308_defconfig and
> > > configs/roc-cc-rk3308_defconfig which have CMD_KASLRSEED)
> > > Akash Gajjar <gajjar04akash@gmail.com>
> > > (configs/rock-pi-s-rk3308_defconfig which has CMD_KASLRSEED)
> > > Ilias Apalodimas <ilias.apalodimas@linaro.org> (MEASURE_DEVICETREE,
> > > MEASURED_BOOT)
> > >
> > > Michal, I see that board/xilinx/common/board.c is adding
> > > chosen/kaslr-seed in ft_board_setup as well as some of the
> > > configs/xilinx boards enabling CMD_KASLRSEED - can we remove
> > > CMD_ASLRSEED from those boards? (ie no bootscripts require it?)
> >
> >
> > Based on my note above that you shouldn't change kaslr-seed if exists.
> 
> I can add that if you think it's the correct behavior, but that is not
> what is done in the current code.
> 
> >
> > What would also make sense is to extend kaslrseed command to pass one more
> > parameter to pass which RNG instance should generate data on system with more
> > RNGs. Then pretty much with command you can choose different RNG because current
> > code hardcoded it to instance 0.
> 
> Do you mean extend the command or the fdt_kaslrseed function? I'm
> trying to obsolete the command.
> 
> I can add an index to fdt_kaslrseed but would it be more useful to add
> a udevice* that is used unless null? I can't see where someone wanting
> to call this function would know the index of a specific UCLASS_RNG
> device and not have the device * handy instead.
> 
> It sounds like with the question of not overwriting an existing value
> you are anticipating board specific ft_board_setup functions that may
> want to behave differently and choose a different rng source? If so,
> ft_board_setup is called 'after' fdt_chosen so maybe fdt_kaslrseed
> also needs a boolean to tell it to overwrite existing?
> 
> Are you open to removing CMD_KASLRSEED from the configs/xilinx* which
> have it? If I can get everyone's approval for the few boards that
> include CMD_KASLRSEED I would like to remove the command if we are
> doing it automatically.
> 
> (adding Chris Morgan <macromorgan@hotmail.com> to cc who authored that cmd)

I'm fine with removing the command entirely if we can do it
automatically, as long as we don't break other users. I've actually
been simply duplicating the rng-seed command on my boards to also
seed the kaslr-seed value. This was just a command at the time I
thought was useful, but if there's better ways to do it I'm open to it.

Thank you,
Chris

> 
> >
> > Do you have correct dependency in generic code when MEASURED_BOOT is enabled as
> > was mentioned in v1? If yes it should be mentioned in commit message.
> >
> 
> Likely something is needed but I'm not sure if it's MEASURED_BOOT or
> MEASURE_DEVICETREE - That's a question I posed to Ilias.
> 
> Best Regards,
> 
> Tim
Tim Harvey May 21, 2024, 4:36 p.m. UTC | #11
On Tue, May 21, 2024 at 5:05 AM Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> Hi Tim
>
> On Wed, 15 May 2024 at 23:50, Tim Harvey <tharvey@gateworks.com> wrote:
> >
> > If RANDOMIZE_BASE is enabled in the Linux kernel instructing it to
> > randomize the virtual address at which the kernel image is loaded, it
> > expects entropy to be provided by the bootloader by populating
> > /chosen/kaslr-seed with a 64-bit value from source of entropy at boot.
>
> Since you'll send a v2, mind adding some description for UEFI on the
> commit message?
> efi_try_purge_kaslr_seed() has a comment of the behaviour
>

Hi  Ilias,

Ok, I will add the following to the commit log for clarity:
Note that the Kernel's EFI STUB only relies on EFI_RNG_PROTOCOL for
randomization and completely ignores the kaslr-seed for its own
randomness needs (i.e the randomization of the physical placement of
the kernel). It gets weeded out from the DTB that gets handed over via
efi_install_fdt() as it would also mess up the measured boot DTB TPM
measurements as well.

Does the above mean that I don't need to worry about protecting the
call to fdt_kaslrseed() with a check for MEASURED BOOT as
efi_install_fdt/efi_try_purge_kaslr_seed always gets called in that
case?

Best Regards,

Tim

> Thanks
> /Ilias
> >
> > If we have DM_RNG enabled populate this value automatically when
> > fdt_chosen is called unless ARMV8_SEC_FIRMWARE_SUPPORT is enabled as
> > it's implementation uses a different source of entropy.
> >
> > As this fdt node is added elsewhere create a library function and
> > use it to deduplicate code.
> >
> > Note that the kalsrseed command (CMD_KASLRSEED) is likely pointless now
> > but left in place in case boot scripts exist that rely on this command
> > existing and returning success. An informational message is printed to
> > alert users of this command that it is likely no longer needed.
> >
> > Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> > ---
> > v2:
> >  - fix typo in commit msg
> >  - use stack for seed to avoid unecessary malloc/free
> >  - move to a library function and deduplicate code by using it elsewhere
> > ---
> >  board/xilinx/common/board.c | 35 -----------------------------
> >  boot/fdt_support.c          | 10 +++++++++
> >  boot/pxe_utils.c            | 35 +++--------------------------
> >  cmd/kaslrseed.c             | 45 ++++++-------------------------------
> >  include/kaslrseed.h         | 17 ++++++++++++++
> >  lib/Makefile                |  1 +
> >  lib/kaslrseed.c             | 34 ++++++++++++++++++++++++++++
> >  7 files changed, 72 insertions(+), 105 deletions(-)
> >  create mode 100644 include/kaslrseed.h
> >  create mode 100644 lib/kaslrseed.c
> >
> > diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
> > index 30a81376ac41..f741e8957818 100644
> > --- a/board/xilinx/common/board.c
> > +++ b/board/xilinx/common/board.c
> > @@ -713,41 +713,6 @@ int ft_board_setup(void *blob, struct bd_info *bd)
> >         if (IS_ENABLED(CONFIG_FDT_FIXUP_PARTITIONS) && IS_ENABLED(CONFIG_NAND_ZYNQ))
> >                 fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
> >
> > -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> > -               debug("No RNG device\n");
> > -               return 0;
> > -       }
> > -
> > -       if (dm_rng_read(dev, buf, n)) {
> > -               debug("Reading RNG failed\n");
> > -               return 0;
> > -       }
> > -
> > -       if (!blob) {
> > -               debug("No FDT memory address configured. Please configure\n"
> > -                     "the FDT address via \"fdt addr <address>\" command.\n"
> > -                     "Aborting!\n");
> > -               return 0;
> > -       }
> > -
> > -       ret = fdt_check_header(blob);
> > -       if (ret < 0) {
> > -               debug("fdt_chosen: %s\n", fdt_strerror(ret));
> > -               return ret;
> > -       }
> > -
> > -       nodeoffset = fdt_find_or_add_subnode(blob, 0, "chosen");
> > -       if (nodeoffset < 0) {
> > -               debug("Reading chosen node failed\n");
> > -               return nodeoffset;
> > -       }
> > -
> > -       ret = fdt_setprop(blob, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> > -       if (ret < 0) {
> > -               debug("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
> > -               return ret;
> > -       }
> > -
> >         return 0;
> >  }
> >  #endif
> > diff --git a/boot/fdt_support.c b/boot/fdt_support.c
> > index 874ca4d6f5af..3455d60d69dc 100644
> > --- a/boot/fdt_support.c
> > +++ b/boot/fdt_support.c
> > @@ -8,6 +8,7 @@
> >
> >  #include <abuf.h>
> >  #include <env.h>
> > +#include <kaslrseed.h>
> >  #include <log.h>
> >  #include <mapmem.h>
> >  #include <net.h>
> > @@ -300,6 +301,15 @@ int fdt_chosen(void *fdt)
> >         if (nodeoffset < 0)
> >                 return nodeoffset;
> >
> > +       if (IS_ENABLED(CONFIG_DM_RNG) && !IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)) {
> > +               err = fdt_kaslrseed(fdt);
> > +               if (err) {
> > +                       printf("WARNING: could not set kaslr-seed %s.\n",
> > +                              fdt_strerror(err));
> > +                       return err;
> > +               }
> > +       }
> > +
> >         if (IS_ENABLED(CONFIG_BOARD_RNG_SEED) && !board_rng_seed(&buf)) {
> >                 err = fdt_setprop(fdt, nodeoffset, "rng-seed",
> >                                   abuf_data(&buf), abuf_size(&buf));
> > diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
> > index 4b22bb6f525a..8d70233fc08d 100644
> > --- a/boot/pxe_utils.c
> > +++ b/boot/pxe_utils.c
> > @@ -8,6 +8,7 @@
> >  #include <dm.h>
> >  #include <env.h>
> >  #include <image.h>
> > +#include <kaslrseed.h>
> >  #include <log.h>
> >  #include <malloc.h>
> >  #include <mapmem.h>
> > @@ -323,10 +324,6 @@ static void label_boot_kaslrseed(void)
> >  #if CONFIG_IS_ENABLED(DM_RNG)
> >         ulong fdt_addr;
> >         struct fdt_header *working_fdt;
> > -       size_t n = 0x8;
> > -       struct udevice *dev;
> > -       u64 *buf;
> > -       int nodeoffset;
> >         int err;
> >
> >         /* Get the main fdt and map it */
> > @@ -342,35 +339,9 @@ static void label_boot_kaslrseed(void)
> >         if (err <= 0)
> >                 return;
> >
> > -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> > -               printf("No RNG device\n");
> > -               return;
> > -       }
> > -
> > -       nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
> > -       if (nodeoffset < 0) {
> > -               printf("Reading chosen node failed\n");
> > -               return;
> > -       }
> > -
> > -       buf = malloc(n);
> > -       if (!buf) {
> > -               printf("Out of memory\n");
> > -               return;
> > -       }
> > -
> > -       if (dm_rng_read(dev, buf, n)) {
> > -               printf("Reading RNG failed\n");
> > -               goto err;
> > -       }
> > -
> > -       err = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> > -       if (err < 0) {
> > +       err = fdt_kaslrseed(working_fdt);
> > +       if (err < 0)
> >                 printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
> > -               goto err;
> > -       }
> > -err:
> > -       free(buf);
> >  #endif
> >         return;
> >  }
> > diff --git a/cmd/kaslrseed.c b/cmd/kaslrseed.c
> > index e0d3c7fe7489..ea5c07d729cf 100644
> > --- a/cmd/kaslrseed.c
> > +++ b/cmd/kaslrseed.c
> > @@ -9,33 +9,16 @@
> >  #include <command.h>
> >  #include <dm.h>
> >  #include <hexdump.h>
> > +#include <kaslrseed.h>
> >  #include <malloc.h>
> >  #include <rng.h>
> >  #include <fdt_support.h>
> >
> >  static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> >  {
> > -       size_t n = 0x8;
> > -       struct udevice *dev;
> > -       u64 *buf;
> > -       int nodeoffset;
> > -       int ret = CMD_RET_SUCCESS;
> > +       int err;
> >
> > -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> > -               printf("No RNG device\n");
> > -               return CMD_RET_FAILURE;
> > -       }
> > -
> > -       buf = malloc(n);
> > -       if (!buf) {
> > -               printf("Out of memory\n");
> > -               return CMD_RET_FAILURE;
> > -       }
> > -
> > -       if (dm_rng_read(dev, buf, n)) {
> > -               printf("Reading RNG failed\n");
> > -               return CMD_RET_FAILURE;
> > -       }
> > +       printf("Notice: a /chosen/kaslr-seed is automatically added to the device-tree when booted via booti/bootm/bootz therefore using this command is likely no longer needed");
> >
> >         if (!working_fdt) {
> >                 printf("No FDT memory address configured. Please configure\n"
> > @@ -44,27 +27,13 @@ static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const
> >                 return CMD_RET_FAILURE;
> >         }
> >
> > -       ret = fdt_check_header(working_fdt);
> > -       if (ret < 0) {
> > -               printf("fdt_chosen: %s\n", fdt_strerror(ret));
> > +       err = fdt_kaslrseed(working_fdt);
> > +       if (err < 0) {
> > +               printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
> >                 return CMD_RET_FAILURE;
> >         }
> >
> > -       nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
> > -       if (nodeoffset < 0) {
> > -               printf("Reading chosen node failed\n");
> > -               return CMD_RET_FAILURE;
> > -       }
> > -
> > -       ret = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> > -       if (ret < 0) {
> > -               printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
> > -               return CMD_RET_FAILURE;
> > -       }
> > -
> > -       free(buf);
> > -
> > -       return ret;
> > +       return CMD_RET_SUCCESS;
> >  }
> >
> >  U_BOOT_LONGHELP(kaslrseed,
> > diff --git a/include/kaslrseed.h b/include/kaslrseed.h
> > new file mode 100644
> > index 000000000000..3fe82f418acf
> > --- /dev/null
> > +++ b/include/kaslrseed.h
> > @@ -0,0 +1,17 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
> > + */
> > +
> > +#if !defined _KASLRSEED_H_
> > +#define _KASLRSEED_H_
> > +
> > +/**
> > + * fdt_kaslrseed() - create a 'kaslr-seed' node in chosen
> > + *
> > + * @blob:      fdt blob
> > + * Return:     0 if OK, -ve on error
> > + */
> > +int fdt_kaslrseed(void *blob);
> > +
> > +#endif /* _KASLRSEED_H_ */
> > diff --git a/lib/Makefile b/lib/Makefile
> > index 2a76acf100d0..20a0242055fa 100644
> > --- a/lib/Makefile
> > +++ b/lib/Makefile
> > @@ -149,6 +149,7 @@ obj-y += date.o
> >  obj-y += rtc-lib.o
> >  obj-$(CONFIG_LIB_ELF) += elf.o
> >
> > +obj-$(CONFIG_DM_RNG) += kaslrseed.o
> >  obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += semihosting.o
> >
> >  #
> > diff --git a/lib/kaslrseed.c b/lib/kaslrseed.c
> > new file mode 100644
> > index 000000000000..ad06bee2b88d
> > --- /dev/null
> > +++ b/lib/kaslrseed.c
> > @@ -0,0 +1,34 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
> > + */
> > +#include <dm.h>
> > +#include <rng.h>
> > +#include <fdt_support.h>
> > +
> > +int fdt_kaslrseed(void *fdt)
> > +{
> > +       struct udevice *dev;
> > +       int nodeoffset;
> > +       u64 data;
> > +       int err;
> > +
> > +       err = fdt_check_header(fdt);
> > +       if (err < 0)
> > +               return err;
> > +
> > +       /* find or create "/chosen" node. */
> > +       nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
> > +       if (nodeoffset < 0)
> > +               return nodeoffset;
> > +
> > +       err = uclass_get_device(UCLASS_RNG, 0, &dev);
> > +       if (!err)
> > +               err = dm_rng_read(dev, &data, sizeof(data));
> > +       if (!err)
> > +               err = fdt_setprop(fdt, nodeoffset, "kaslr-seed", &data, sizeof(data));
> > +       if (err < 0)
> > +               printf("WARNING: could not set kaslr-seed %s.\n", fdt_strerror(err));
> > +
> > +       return err;
> > +}
> > --
> > 2.25.1
> >
Ilias Apalodimas May 21, 2024, 4:53 p.m. UTC | #12
Hi Tim,

On Tue, 21 May 2024 at 19:37, Tim Harvey <tharvey@gateworks.com> wrote:
>
> On Tue, May 21, 2024 at 5:05 AM Ilias Apalodimas
> <ilias.apalodimas@linaro.org> wrote:
> >
> > Hi Tim
> >
> > On Wed, 15 May 2024 at 23:50, Tim Harvey <tharvey@gateworks.com> wrote:
> > >
> > > If RANDOMIZE_BASE is enabled in the Linux kernel instructing it to
> > > randomize the virtual address at which the kernel image is loaded, it
> > > expects entropy to be provided by the bootloader by populating
> > > /chosen/kaslr-seed with a 64-bit value from source of entropy at boot.
> >
> > Since you'll send a v2, mind adding some description for UEFI on the
> > commit message?
> > efi_try_purge_kaslr_seed() has a comment of the behaviour
> >
>
> Hi  Ilias,
>
> Ok, I will add the following to the commit log for clarity:
> Note that the Kernel's EFI STUB only relies on EFI_RNG_PROTOCOL for
> randomization and completely ignores the kaslr-seed for its own
> randomness needs (i.e the randomization of the physical placement of
> the kernel). It gets weeded out from the DTB that gets handed over via
> efi_install_fdt() as it would also mess up the measured boot DTB TPM
> measurements as well.
>
> Does the above mean that I don't need to worry about protecting the
> call to fdt_kaslrseed() with a check for MEASURED BOOT as
> efi_install_fdt/efi_try_purge_kaslr_seed always gets called in that
> case?

There are 2 ways to do measured boot. One is via the bootm command and
the other is via the EFI protocols.
CONFIG_MEASURED_BOOT  only applies to bootm.
OTOH kaslr-seed might still have value if EFI_RNG is disabled, even
when booting with EFI, since the kernel will randomize the virtual
placement if it finds that.

But in any case, a kaslr-seed entry can't be present in the DTB if you
plan to measure it.

Cheers
/Ilias

>
> Best Regards,
>
> Tim
>
> > Thanks
> > /Ilias
> > >
> > > If we have DM_RNG enabled populate this value automatically when
> > > fdt_chosen is called unless ARMV8_SEC_FIRMWARE_SUPPORT is enabled as
> > > it's implementation uses a different source of entropy.
> > >
> > > As this fdt node is added elsewhere create a library function and
> > > use it to deduplicate code.
> > >
> > > Note that the kalsrseed command (CMD_KASLRSEED) is likely pointless now
> > > but left in place in case boot scripts exist that rely on this command
> > > existing and returning success. An informational message is printed to
> > > alert users of this command that it is likely no longer needed.
> > >
> > > Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> > > ---
> > > v2:
> > >  - fix typo in commit msg
> > >  - use stack for seed to avoid unecessary malloc/free
> > >  - move to a library function and deduplicate code by using it elsewhere
> > > ---
> > >  board/xilinx/common/board.c | 35 -----------------------------
> > >  boot/fdt_support.c          | 10 +++++++++
> > >  boot/pxe_utils.c            | 35 +++--------------------------
> > >  cmd/kaslrseed.c             | 45 ++++++-------------------------------
> > >  include/kaslrseed.h         | 17 ++++++++++++++
> > >  lib/Makefile                |  1 +
> > >  lib/kaslrseed.c             | 34 ++++++++++++++++++++++++++++
> > >  7 files changed, 72 insertions(+), 105 deletions(-)
> > >  create mode 100644 include/kaslrseed.h
> > >  create mode 100644 lib/kaslrseed.c
> > >
> > > diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
> > > index 30a81376ac41..f741e8957818 100644
> > > --- a/board/xilinx/common/board.c
> > > +++ b/board/xilinx/common/board.c
> > > @@ -713,41 +713,6 @@ int ft_board_setup(void *blob, struct bd_info *bd)
> > >         if (IS_ENABLED(CONFIG_FDT_FIXUP_PARTITIONS) && IS_ENABLED(CONFIG_NAND_ZYNQ))
> > >                 fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
> > >
> > > -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> > > -               debug("No RNG device\n");
> > > -               return 0;
> > > -       }
> > > -
> > > -       if (dm_rng_read(dev, buf, n)) {
> > > -               debug("Reading RNG failed\n");
> > > -               return 0;
> > > -       }
> > > -
> > > -       if (!blob) {
> > > -               debug("No FDT memory address configured. Please configure\n"
> > > -                     "the FDT address via \"fdt addr <address>\" command.\n"
> > > -                     "Aborting!\n");
> > > -               return 0;
> > > -       }
> > > -
> > > -       ret = fdt_check_header(blob);
> > > -       if (ret < 0) {
> > > -               debug("fdt_chosen: %s\n", fdt_strerror(ret));
> > > -               return ret;
> > > -       }
> > > -
> > > -       nodeoffset = fdt_find_or_add_subnode(blob, 0, "chosen");
> > > -       if (nodeoffset < 0) {
> > > -               debug("Reading chosen node failed\n");
> > > -               return nodeoffset;
> > > -       }
> > > -
> > > -       ret = fdt_setprop(blob, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> > > -       if (ret < 0) {
> > > -               debug("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
> > > -               return ret;
> > > -       }
> > > -
> > >         return 0;
> > >  }
> > >  #endif
> > > diff --git a/boot/fdt_support.c b/boot/fdt_support.c
> > > index 874ca4d6f5af..3455d60d69dc 100644
> > > --- a/boot/fdt_support.c
> > > +++ b/boot/fdt_support.c
> > > @@ -8,6 +8,7 @@
> > >
> > >  #include <abuf.h>
> > >  #include <env.h>
> > > +#include <kaslrseed.h>
> > >  #include <log.h>
> > >  #include <mapmem.h>
> > >  #include <net.h>
> > > @@ -300,6 +301,15 @@ int fdt_chosen(void *fdt)
> > >         if (nodeoffset < 0)
> > >                 return nodeoffset;
> > >
> > > +       if (IS_ENABLED(CONFIG_DM_RNG) && !IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)) {
> > > +               err = fdt_kaslrseed(fdt);
> > > +               if (err) {
> > > +                       printf("WARNING: could not set kaslr-seed %s.\n",
> > > +                              fdt_strerror(err));
> > > +                       return err;
> > > +               }
> > > +       }
> > > +
> > >         if (IS_ENABLED(CONFIG_BOARD_RNG_SEED) && !board_rng_seed(&buf)) {
> > >                 err = fdt_setprop(fdt, nodeoffset, "rng-seed",
> > >                                   abuf_data(&buf), abuf_size(&buf));
> > > diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
> > > index 4b22bb6f525a..8d70233fc08d 100644
> > > --- a/boot/pxe_utils.c
> > > +++ b/boot/pxe_utils.c
> > > @@ -8,6 +8,7 @@
> > >  #include <dm.h>
> > >  #include <env.h>
> > >  #include <image.h>
> > > +#include <kaslrseed.h>
> > >  #include <log.h>
> > >  #include <malloc.h>
> > >  #include <mapmem.h>
> > > @@ -323,10 +324,6 @@ static void label_boot_kaslrseed(void)
> > >  #if CONFIG_IS_ENABLED(DM_RNG)
> > >         ulong fdt_addr;
> > >         struct fdt_header *working_fdt;
> > > -       size_t n = 0x8;
> > > -       struct udevice *dev;
> > > -       u64 *buf;
> > > -       int nodeoffset;
> > >         int err;
> > >
> > >         /* Get the main fdt and map it */
> > > @@ -342,35 +339,9 @@ static void label_boot_kaslrseed(void)
> > >         if (err <= 0)
> > >                 return;
> > >
> > > -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> > > -               printf("No RNG device\n");
> > > -               return;
> > > -       }
> > > -
> > > -       nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
> > > -       if (nodeoffset < 0) {
> > > -               printf("Reading chosen node failed\n");
> > > -               return;
> > > -       }
> > > -
> > > -       buf = malloc(n);
> > > -       if (!buf) {
> > > -               printf("Out of memory\n");
> > > -               return;
> > > -       }
> > > -
> > > -       if (dm_rng_read(dev, buf, n)) {
> > > -               printf("Reading RNG failed\n");
> > > -               goto err;
> > > -       }
> > > -
> > > -       err = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> > > -       if (err < 0) {
> > > +       err = fdt_kaslrseed(working_fdt);
> > > +       if (err < 0)
> > >                 printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
> > > -               goto err;
> > > -       }
> > > -err:
> > > -       free(buf);
> > >  #endif
> > >         return;
> > >  }
> > > diff --git a/cmd/kaslrseed.c b/cmd/kaslrseed.c
> > > index e0d3c7fe7489..ea5c07d729cf 100644
> > > --- a/cmd/kaslrseed.c
> > > +++ b/cmd/kaslrseed.c
> > > @@ -9,33 +9,16 @@
> > >  #include <command.h>
> > >  #include <dm.h>
> > >  #include <hexdump.h>
> > > +#include <kaslrseed.h>
> > >  #include <malloc.h>
> > >  #include <rng.h>
> > >  #include <fdt_support.h>
> > >
> > >  static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> > >  {
> > > -       size_t n = 0x8;
> > > -       struct udevice *dev;
> > > -       u64 *buf;
> > > -       int nodeoffset;
> > > -       int ret = CMD_RET_SUCCESS;
> > > +       int err;
> > >
> > > -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> > > -               printf("No RNG device\n");
> > > -               return CMD_RET_FAILURE;
> > > -       }
> > > -
> > > -       buf = malloc(n);
> > > -       if (!buf) {
> > > -               printf("Out of memory\n");
> > > -               return CMD_RET_FAILURE;
> > > -       }
> > > -
> > > -       if (dm_rng_read(dev, buf, n)) {
> > > -               printf("Reading RNG failed\n");
> > > -               return CMD_RET_FAILURE;
> > > -       }
> > > +       printf("Notice: a /chosen/kaslr-seed is automatically added to the device-tree when booted via booti/bootm/bootz therefore using this command is likely no longer needed");
> > >
> > >         if (!working_fdt) {
> > >                 printf("No FDT memory address configured. Please configure\n"
> > > @@ -44,27 +27,13 @@ static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const
> > >                 return CMD_RET_FAILURE;
> > >         }
> > >
> > > -       ret = fdt_check_header(working_fdt);
> > > -       if (ret < 0) {
> > > -               printf("fdt_chosen: %s\n", fdt_strerror(ret));
> > > +       err = fdt_kaslrseed(working_fdt);
> > > +       if (err < 0) {
> > > +               printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
> > >                 return CMD_RET_FAILURE;
> > >         }
> > >
> > > -       nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
> > > -       if (nodeoffset < 0) {
> > > -               printf("Reading chosen node failed\n");
> > > -               return CMD_RET_FAILURE;
> > > -       }
> > > -
> > > -       ret = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> > > -       if (ret < 0) {
> > > -               printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
> > > -               return CMD_RET_FAILURE;
> > > -       }
> > > -
> > > -       free(buf);
> > > -
> > > -       return ret;
> > > +       return CMD_RET_SUCCESS;
> > >  }
> > >
> > >  U_BOOT_LONGHELP(kaslrseed,
> > > diff --git a/include/kaslrseed.h b/include/kaslrseed.h
> > > new file mode 100644
> > > index 000000000000..3fe82f418acf
> > > --- /dev/null
> > > +++ b/include/kaslrseed.h
> > > @@ -0,0 +1,17 @@
> > > +/* SPDX-License-Identifier: GPL-2.0+ */
> > > +/*
> > > + * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
> > > + */
> > > +
> > > +#if !defined _KASLRSEED_H_
> > > +#define _KASLRSEED_H_
> > > +
> > > +/**
> > > + * fdt_kaslrseed() - create a 'kaslr-seed' node in chosen
> > > + *
> > > + * @blob:      fdt blob
> > > + * Return:     0 if OK, -ve on error
> > > + */
> > > +int fdt_kaslrseed(void *blob);
> > > +
> > > +#endif /* _KASLRSEED_H_ */
> > > diff --git a/lib/Makefile b/lib/Makefile
> > > index 2a76acf100d0..20a0242055fa 100644
> > > --- a/lib/Makefile
> > > +++ b/lib/Makefile
> > > @@ -149,6 +149,7 @@ obj-y += date.o
> > >  obj-y += rtc-lib.o
> > >  obj-$(CONFIG_LIB_ELF) += elf.o
> > >
> > > +obj-$(CONFIG_DM_RNG) += kaslrseed.o
> > >  obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += semihosting.o
> > >
> > >  #
> > > diff --git a/lib/kaslrseed.c b/lib/kaslrseed.c
> > > new file mode 100644
> > > index 000000000000..ad06bee2b88d
> > > --- /dev/null
> > > +++ b/lib/kaslrseed.c
> > > @@ -0,0 +1,34 @@
> > > +// SPDX-License-Identifier: GPL-2.0+
> > > +/*
> > > + * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
> > > + */
> > > +#include <dm.h>
> > > +#include <rng.h>
> > > +#include <fdt_support.h>
> > > +
> > > +int fdt_kaslrseed(void *fdt)
> > > +{
> > > +       struct udevice *dev;
> > > +       int nodeoffset;
> > > +       u64 data;
> > > +       int err;
> > > +
> > > +       err = fdt_check_header(fdt);
> > > +       if (err < 0)
> > > +               return err;
> > > +
> > > +       /* find or create "/chosen" node. */
> > > +       nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
> > > +       if (nodeoffset < 0)
> > > +               return nodeoffset;
> > > +
> > > +       err = uclass_get_device(UCLASS_RNG, 0, &dev);
> > > +       if (!err)
> > > +               err = dm_rng_read(dev, &data, sizeof(data));
> > > +       if (!err)
> > > +               err = fdt_setprop(fdt, nodeoffset, "kaslr-seed", &data, sizeof(data));
> > > +       if (err < 0)
> > > +               printf("WARNING: could not set kaslr-seed %s.\n", fdt_strerror(err));
> > > +
> > > +       return err;
> > > +}
> > > --
> > > 2.25.1
> > >
Tim Harvey May 21, 2024, 5:05 p.m. UTC | #13
On Tue, May 21, 2024 at 9:54 AM Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> Hi Tim,
>
> On Tue, 21 May 2024 at 19:37, Tim Harvey <tharvey@gateworks.com> wrote:
> >
> > On Tue, May 21, 2024 at 5:05 AM Ilias Apalodimas
> > <ilias.apalodimas@linaro.org> wrote:
> > >
> > > Hi Tim
> > >
> > > On Wed, 15 May 2024 at 23:50, Tim Harvey <tharvey@gateworks.com> wrote:
> > > >
> > > > If RANDOMIZE_BASE is enabled in the Linux kernel instructing it to
> > > > randomize the virtual address at which the kernel image is loaded, it
> > > > expects entropy to be provided by the bootloader by populating
> > > > /chosen/kaslr-seed with a 64-bit value from source of entropy at boot.
> > >
> > > Since you'll send a v2, mind adding some description for UEFI on the
> > > commit message?
> > > efi_try_purge_kaslr_seed() has a comment of the behaviour
> > >
> >
> > Hi  Ilias,
> >
> > Ok, I will add the following to the commit log for clarity:
> > Note that the Kernel's EFI STUB only relies on EFI_RNG_PROTOCOL for
> > randomization and completely ignores the kaslr-seed for its own
> > randomness needs (i.e the randomization of the physical placement of
> > the kernel). It gets weeded out from the DTB that gets handed over via
> > efi_install_fdt() as it would also mess up the measured boot DTB TPM
> > measurements as well.
> >
> > Does the above mean that I don't need to worry about protecting the
> > call to fdt_kaslrseed() with a check for MEASURED BOOT as
> > efi_install_fdt/efi_try_purge_kaslr_seed always gets called in that
> > case?
>
> There are 2 ways to do measured boot. One is via the bootm command and
> the other is via the EFI protocols.
> CONFIG_MEASURED_BOOT  only applies to bootm.
> OTOH kaslr-seed might still have value if EFI_RNG is disabled, even
> when booting with EFI, since the kernel will randomize the virtual
> placement if it finds that.
>
> But in any case, a kaslr-seed entry can't be present in the DTB if you
> plan to measure it.

ok, sounds like I need to use:

if (IS_ENABLED(CONFIG_DM_RNG) &&
!IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)) &&
!IS_ENABLED(CONFIG_MEASURED_BOOT) {
  fdt_kaslrseed...
}

Thanks,

I'll send a v3 hopefully later today.

Tim

>
> Cheers
> /Ilias
>
> >
> > Best Regards,
> >
> > Tim
> >
> > > Thanks
> > > /Ilias
> > > >
> > > > If we have DM_RNG enabled populate this value automatically when
> > > > fdt_chosen is called unless ARMV8_SEC_FIRMWARE_SUPPORT is enabled as
> > > > it's implementation uses a different source of entropy.
> > > >
> > > > As this fdt node is added elsewhere create a library function and
> > > > use it to deduplicate code.
> > > >
> > > > Note that the kalsrseed command (CMD_KASLRSEED) is likely pointless now
> > > > but left in place in case boot scripts exist that rely on this command
> > > > existing and returning success. An informational message is printed to
> > > > alert users of this command that it is likely no longer needed.
> > > >
> > > > Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> > > > ---
> > > > v2:
> > > >  - fix typo in commit msg
> > > >  - use stack for seed to avoid unecessary malloc/free
> > > >  - move to a library function and deduplicate code by using it elsewhere
> > > > ---
> > > >  board/xilinx/common/board.c | 35 -----------------------------
> > > >  boot/fdt_support.c          | 10 +++++++++
> > > >  boot/pxe_utils.c            | 35 +++--------------------------
> > > >  cmd/kaslrseed.c             | 45 ++++++-------------------------------
> > > >  include/kaslrseed.h         | 17 ++++++++++++++
> > > >  lib/Makefile                |  1 +
> > > >  lib/kaslrseed.c             | 34 ++++++++++++++++++++++++++++
> > > >  7 files changed, 72 insertions(+), 105 deletions(-)
> > > >  create mode 100644 include/kaslrseed.h
> > > >  create mode 100644 lib/kaslrseed.c
> > > >
> > > > diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
> > > > index 30a81376ac41..f741e8957818 100644
> > > > --- a/board/xilinx/common/board.c
> > > > +++ b/board/xilinx/common/board.c
> > > > @@ -713,41 +713,6 @@ int ft_board_setup(void *blob, struct bd_info *bd)
> > > >         if (IS_ENABLED(CONFIG_FDT_FIXUP_PARTITIONS) && IS_ENABLED(CONFIG_NAND_ZYNQ))
> > > >                 fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
> > > >
> > > > -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> > > > -               debug("No RNG device\n");
> > > > -               return 0;
> > > > -       }
> > > > -
> > > > -       if (dm_rng_read(dev, buf, n)) {
> > > > -               debug("Reading RNG failed\n");
> > > > -               return 0;
> > > > -       }
> > > > -
> > > > -       if (!blob) {
> > > > -               debug("No FDT memory address configured. Please configure\n"
> > > > -                     "the FDT address via \"fdt addr <address>\" command.\n"
> > > > -                     "Aborting!\n");
> > > > -               return 0;
> > > > -       }
> > > > -
> > > > -       ret = fdt_check_header(blob);
> > > > -       if (ret < 0) {
> > > > -               debug("fdt_chosen: %s\n", fdt_strerror(ret));
> > > > -               return ret;
> > > > -       }
> > > > -
> > > > -       nodeoffset = fdt_find_or_add_subnode(blob, 0, "chosen");
> > > > -       if (nodeoffset < 0) {
> > > > -               debug("Reading chosen node failed\n");
> > > > -               return nodeoffset;
> > > > -       }
> > > > -
> > > > -       ret = fdt_setprop(blob, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> > > > -       if (ret < 0) {
> > > > -               debug("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
> > > > -               return ret;
> > > > -       }
> > > > -
> > > >         return 0;
> > > >  }
> > > >  #endif
> > > > diff --git a/boot/fdt_support.c b/boot/fdt_support.c
> > > > index 874ca4d6f5af..3455d60d69dc 100644
> > > > --- a/boot/fdt_support.c
> > > > +++ b/boot/fdt_support.c
> > > > @@ -8,6 +8,7 @@
> > > >
> > > >  #include <abuf.h>
> > > >  #include <env.h>
> > > > +#include <kaslrseed.h>
> > > >  #include <log.h>
> > > >  #include <mapmem.h>
> > > >  #include <net.h>
> > > > @@ -300,6 +301,15 @@ int fdt_chosen(void *fdt)
> > > >         if (nodeoffset < 0)
> > > >                 return nodeoffset;
> > > >
> > > > +       if (IS_ENABLED(CONFIG_DM_RNG) && !IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)) {
> > > > +               err = fdt_kaslrseed(fdt);
> > > > +               if (err) {
> > > > +                       printf("WARNING: could not set kaslr-seed %s.\n",
> > > > +                              fdt_strerror(err));
> > > > +                       return err;
> > > > +               }
> > > > +       }
> > > > +
> > > >         if (IS_ENABLED(CONFIG_BOARD_RNG_SEED) && !board_rng_seed(&buf)) {
> > > >                 err = fdt_setprop(fdt, nodeoffset, "rng-seed",
> > > >                                   abuf_data(&buf), abuf_size(&buf));
> > > > diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
> > > > index 4b22bb6f525a..8d70233fc08d 100644
> > > > --- a/boot/pxe_utils.c
> > > > +++ b/boot/pxe_utils.c
> > > > @@ -8,6 +8,7 @@
> > > >  #include <dm.h>
> > > >  #include <env.h>
> > > >  #include <image.h>
> > > > +#include <kaslrseed.h>
> > > >  #include <log.h>
> > > >  #include <malloc.h>
> > > >  #include <mapmem.h>
> > > > @@ -323,10 +324,6 @@ static void label_boot_kaslrseed(void)
> > > >  #if CONFIG_IS_ENABLED(DM_RNG)
> > > >         ulong fdt_addr;
> > > >         struct fdt_header *working_fdt;
> > > > -       size_t n = 0x8;
> > > > -       struct udevice *dev;
> > > > -       u64 *buf;
> > > > -       int nodeoffset;
> > > >         int err;
> > > >
> > > >         /* Get the main fdt and map it */
> > > > @@ -342,35 +339,9 @@ static void label_boot_kaslrseed(void)
> > > >         if (err <= 0)
> > > >                 return;
> > > >
> > > > -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> > > > -               printf("No RNG device\n");
> > > > -               return;
> > > > -       }
> > > > -
> > > > -       nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
> > > > -       if (nodeoffset < 0) {
> > > > -               printf("Reading chosen node failed\n");
> > > > -               return;
> > > > -       }
> > > > -
> > > > -       buf = malloc(n);
> > > > -       if (!buf) {
> > > > -               printf("Out of memory\n");
> > > > -               return;
> > > > -       }
> > > > -
> > > > -       if (dm_rng_read(dev, buf, n)) {
> > > > -               printf("Reading RNG failed\n");
> > > > -               goto err;
> > > > -       }
> > > > -
> > > > -       err = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> > > > -       if (err < 0) {
> > > > +       err = fdt_kaslrseed(working_fdt);
> > > > +       if (err < 0)
> > > >                 printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
> > > > -               goto err;
> > > > -       }
> > > > -err:
> > > > -       free(buf);
> > > >  #endif
> > > >         return;
> > > >  }
> > > > diff --git a/cmd/kaslrseed.c b/cmd/kaslrseed.c
> > > > index e0d3c7fe7489..ea5c07d729cf 100644
> > > > --- a/cmd/kaslrseed.c
> > > > +++ b/cmd/kaslrseed.c
> > > > @@ -9,33 +9,16 @@
> > > >  #include <command.h>
> > > >  #include <dm.h>
> > > >  #include <hexdump.h>
> > > > +#include <kaslrseed.h>
> > > >  #include <malloc.h>
> > > >  #include <rng.h>
> > > >  #include <fdt_support.h>
> > > >
> > > >  static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> > > >  {
> > > > -       size_t n = 0x8;
> > > > -       struct udevice *dev;
> > > > -       u64 *buf;
> > > > -       int nodeoffset;
> > > > -       int ret = CMD_RET_SUCCESS;
> > > > +       int err;
> > > >
> > > > -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> > > > -               printf("No RNG device\n");
> > > > -               return CMD_RET_FAILURE;
> > > > -       }
> > > > -
> > > > -       buf = malloc(n);
> > > > -       if (!buf) {
> > > > -               printf("Out of memory\n");
> > > > -               return CMD_RET_FAILURE;
> > > > -       }
> > > > -
> > > > -       if (dm_rng_read(dev, buf, n)) {
> > > > -               printf("Reading RNG failed\n");
> > > > -               return CMD_RET_FAILURE;
> > > > -       }
> > > > +       printf("Notice: a /chosen/kaslr-seed is automatically added to the device-tree when booted via booti/bootm/bootz therefore using this command is likely no longer needed");
> > > >
> > > >         if (!working_fdt) {
> > > >                 printf("No FDT memory address configured. Please configure\n"
> > > > @@ -44,27 +27,13 @@ static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const
> > > >                 return CMD_RET_FAILURE;
> > > >         }
> > > >
> > > > -       ret = fdt_check_header(working_fdt);
> > > > -       if (ret < 0) {
> > > > -               printf("fdt_chosen: %s\n", fdt_strerror(ret));
> > > > +       err = fdt_kaslrseed(working_fdt);
> > > > +       if (err < 0) {
> > > > +               printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
> > > >                 return CMD_RET_FAILURE;
> > > >         }
> > > >
> > > > -       nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
> > > > -       if (nodeoffset < 0) {
> > > > -               printf("Reading chosen node failed\n");
> > > > -               return CMD_RET_FAILURE;
> > > > -       }
> > > > -
> > > > -       ret = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> > > > -       if (ret < 0) {
> > > > -               printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
> > > > -               return CMD_RET_FAILURE;
> > > > -       }
> > > > -
> > > > -       free(buf);
> > > > -
> > > > -       return ret;
> > > > +       return CMD_RET_SUCCESS;
> > > >  }
> > > >
> > > >  U_BOOT_LONGHELP(kaslrseed,
> > > > diff --git a/include/kaslrseed.h b/include/kaslrseed.h
> > > > new file mode 100644
> > > > index 000000000000..3fe82f418acf
> > > > --- /dev/null
> > > > +++ b/include/kaslrseed.h
> > > > @@ -0,0 +1,17 @@
> > > > +/* SPDX-License-Identifier: GPL-2.0+ */
> > > > +/*
> > > > + * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
> > > > + */
> > > > +
> > > > +#if !defined _KASLRSEED_H_
> > > > +#define _KASLRSEED_H_
> > > > +
> > > > +/**
> > > > + * fdt_kaslrseed() - create a 'kaslr-seed' node in chosen
> > > > + *
> > > > + * @blob:      fdt blob
> > > > + * Return:     0 if OK, -ve on error
> > > > + */
> > > > +int fdt_kaslrseed(void *blob);
> > > > +
> > > > +#endif /* _KASLRSEED_H_ */
> > > > diff --git a/lib/Makefile b/lib/Makefile
> > > > index 2a76acf100d0..20a0242055fa 100644
> > > > --- a/lib/Makefile
> > > > +++ b/lib/Makefile
> > > > @@ -149,6 +149,7 @@ obj-y += date.o
> > > >  obj-y += rtc-lib.o
> > > >  obj-$(CONFIG_LIB_ELF) += elf.o
> > > >
> > > > +obj-$(CONFIG_DM_RNG) += kaslrseed.o
> > > >  obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += semihosting.o
> > > >
> > > >  #
> > > > diff --git a/lib/kaslrseed.c b/lib/kaslrseed.c
> > > > new file mode 100644
> > > > index 000000000000..ad06bee2b88d
> > > > --- /dev/null
> > > > +++ b/lib/kaslrseed.c
> > > > @@ -0,0 +1,34 @@
> > > > +// SPDX-License-Identifier: GPL-2.0+
> > > > +/*
> > > > + * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
> > > > + */
> > > > +#include <dm.h>
> > > > +#include <rng.h>
> > > > +#include <fdt_support.h>
> > > > +
> > > > +int fdt_kaslrseed(void *fdt)
> > > > +{
> > > > +       struct udevice *dev;
> > > > +       int nodeoffset;
> > > > +       u64 data;
> > > > +       int err;
> > > > +
> > > > +       err = fdt_check_header(fdt);
> > > > +       if (err < 0)
> > > > +               return err;
> > > > +
> > > > +       /* find or create "/chosen" node. */
> > > > +       nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
> > > > +       if (nodeoffset < 0)
> > > > +               return nodeoffset;
> > > > +
> > > > +       err = uclass_get_device(UCLASS_RNG, 0, &dev);
> > > > +       if (!err)
> > > > +               err = dm_rng_read(dev, &data, sizeof(data));
> > > > +       if (!err)
> > > > +               err = fdt_setprop(fdt, nodeoffset, "kaslr-seed", &data, sizeof(data));
> > > > +       if (err < 0)
> > > > +               printf("WARNING: could not set kaslr-seed %s.\n", fdt_strerror(err));
> > > > +
> > > > +       return err;
> > > > +}
> > > > --
> > > > 2.25.1
> > > >
Ilias Apalodimas May 21, 2024, 5:29 p.m. UTC | #14
On Tue, 21 May 2024 at 20:06, Tim Harvey <tharvey@gateworks.com> wrote:
>
> On Tue, May 21, 2024 at 9:54 AM Ilias Apalodimas
> <ilias.apalodimas@linaro.org> wrote:
> >
> > Hi Tim,
> >
> > On Tue, 21 May 2024 at 19:37, Tim Harvey <tharvey@gateworks.com> wrote:
> > >
> > > On Tue, May 21, 2024 at 5:05 AM Ilias Apalodimas
> > > <ilias.apalodimas@linaro.org> wrote:
> > > >
> > > > Hi Tim
> > > >
> > > > On Wed, 15 May 2024 at 23:50, Tim Harvey <tharvey@gateworks.com> wrote:
> > > > >
> > > > > If RANDOMIZE_BASE is enabled in the Linux kernel instructing it to
> > > > > randomize the virtual address at which the kernel image is loaded, it
> > > > > expects entropy to be provided by the bootloader by populating
> > > > > /chosen/kaslr-seed with a 64-bit value from source of entropy at boot.
> > > >
> > > > Since you'll send a v2, mind adding some description for UEFI on the
> > > > commit message?
> > > > efi_try_purge_kaslr_seed() has a comment of the behaviour
> > > >
> > >
> > > Hi  Ilias,
> > >
> > > Ok, I will add the following to the commit log for clarity:
> > > Note that the Kernel's EFI STUB only relies on EFI_RNG_PROTOCOL for
> > > randomization and completely ignores the kaslr-seed for its own
> > > randomness needs (i.e the randomization of the physical placement of
> > > the kernel). It gets weeded out from the DTB that gets handed over via
> > > efi_install_fdt() as it would also mess up the measured boot DTB TPM
> > > measurements as well.
> > >
> > > Does the above mean that I don't need to worry about protecting the
> > > call to fdt_kaslrseed() with a check for MEASURED BOOT as
> > > efi_install_fdt/efi_try_purge_kaslr_seed always gets called in that
> > > case?
> >
> > There are 2 ways to do measured boot. One is via the bootm command and
> > the other is via the EFI protocols.
> > CONFIG_MEASURED_BOOT  only applies to bootm.
> > OTOH kaslr-seed might still have value if EFI_RNG is disabled, even
> > when booting with EFI, since the kernel will randomize the virtual
> > placement if it finds that.
> >
> > But in any case, a kaslr-seed entry can't be present in the DTB if you
> > plan to measure it.
>
> ok, sounds like I need to use:
>
> if (IS_ENABLED(CONFIG_DM_RNG) &&
> !IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)) &&
> !IS_ENABLED(CONFIG_MEASURED_BOOT) {
>   fdt_kaslrseed...
> }
>

Can't we measure the DT *before* adding the kaslr-seed?

Cheers
/Ilias
> Thanks,
>
> I'll send a v3 hopefully later today.
>
> Tim
>
> >
> > Cheers
> > /Ilias
> >
> > >
> > > Best Regards,
> > >
> > > Tim
> > >
> > > > Thanks
> > > > /Ilias
> > > > >
> > > > > If we have DM_RNG enabled populate this value automatically when
> > > > > fdt_chosen is called unless ARMV8_SEC_FIRMWARE_SUPPORT is enabled as
> > > > > it's implementation uses a different source of entropy.
> > > > >
> > > > > As this fdt node is added elsewhere create a library function and
> > > > > use it to deduplicate code.
> > > > >
> > > > > Note that the kalsrseed command (CMD_KASLRSEED) is likely pointless now
> > > > > but left in place in case boot scripts exist that rely on this command
> > > > > existing and returning success. An informational message is printed to
> > > > > alert users of this command that it is likely no longer needed.
> > > > >
> > > > > Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> > > > > ---
> > > > > v2:
> > > > >  - fix typo in commit msg
> > > > >  - use stack for seed to avoid unecessary malloc/free
> > > > >  - move to a library function and deduplicate code by using it elsewhere
> > > > > ---
> > > > >  board/xilinx/common/board.c | 35 -----------------------------
> > > > >  boot/fdt_support.c          | 10 +++++++++
> > > > >  boot/pxe_utils.c            | 35 +++--------------------------
> > > > >  cmd/kaslrseed.c             | 45 ++++++-------------------------------
> > > > >  include/kaslrseed.h         | 17 ++++++++++++++
> > > > >  lib/Makefile                |  1 +
> > > > >  lib/kaslrseed.c             | 34 ++++++++++++++++++++++++++++
> > > > >  7 files changed, 72 insertions(+), 105 deletions(-)
> > > > >  create mode 100644 include/kaslrseed.h
> > > > >  create mode 100644 lib/kaslrseed.c
> > > > >
> > > > > diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
> > > > > index 30a81376ac41..f741e8957818 100644
> > > > > --- a/board/xilinx/common/board.c
> > > > > +++ b/board/xilinx/common/board.c
> > > > > @@ -713,41 +713,6 @@ int ft_board_setup(void *blob, struct bd_info *bd)
> > > > >         if (IS_ENABLED(CONFIG_FDT_FIXUP_PARTITIONS) && IS_ENABLED(CONFIG_NAND_ZYNQ))
> > > > >                 fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
> > > > >
> > > > > -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> > > > > -               debug("No RNG device\n");
> > > > > -               return 0;
> > > > > -       }
> > > > > -
> > > > > -       if (dm_rng_read(dev, buf, n)) {
> > > > > -               debug("Reading RNG failed\n");
> > > > > -               return 0;
> > > > > -       }
> > > > > -
> > > > > -       if (!blob) {
> > > > > -               debug("No FDT memory address configured. Please configure\n"
> > > > > -                     "the FDT address via \"fdt addr <address>\" command.\n"
> > > > > -                     "Aborting!\n");
> > > > > -               return 0;
> > > > > -       }
> > > > > -
> > > > > -       ret = fdt_check_header(blob);
> > > > > -       if (ret < 0) {
> > > > > -               debug("fdt_chosen: %s\n", fdt_strerror(ret));
> > > > > -               return ret;
> > > > > -       }
> > > > > -
> > > > > -       nodeoffset = fdt_find_or_add_subnode(blob, 0, "chosen");
> > > > > -       if (nodeoffset < 0) {
> > > > > -               debug("Reading chosen node failed\n");
> > > > > -               return nodeoffset;
> > > > > -       }
> > > > > -
> > > > > -       ret = fdt_setprop(blob, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> > > > > -       if (ret < 0) {
> > > > > -               debug("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
> > > > > -               return ret;
> > > > > -       }
> > > > > -
> > > > >         return 0;
> > > > >  }
> > > > >  #endif
> > > > > diff --git a/boot/fdt_support.c b/boot/fdt_support.c
> > > > > index 874ca4d6f5af..3455d60d69dc 100644
> > > > > --- a/boot/fdt_support.c
> > > > > +++ b/boot/fdt_support.c
> > > > > @@ -8,6 +8,7 @@
> > > > >
> > > > >  #include <abuf.h>
> > > > >  #include <env.h>
> > > > > +#include <kaslrseed.h>
> > > > >  #include <log.h>
> > > > >  #include <mapmem.h>
> > > > >  #include <net.h>
> > > > > @@ -300,6 +301,15 @@ int fdt_chosen(void *fdt)
> > > > >         if (nodeoffset < 0)
> > > > >                 return nodeoffset;
> > > > >
> > > > > +       if (IS_ENABLED(CONFIG_DM_RNG) && !IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)) {
> > > > > +               err = fdt_kaslrseed(fdt);
> > > > > +               if (err) {
> > > > > +                       printf("WARNING: could not set kaslr-seed %s.\n",
> > > > > +                              fdt_strerror(err));
> > > > > +                       return err;
> > > > > +               }
> > > > > +       }
> > > > > +
> > > > >         if (IS_ENABLED(CONFIG_BOARD_RNG_SEED) && !board_rng_seed(&buf)) {
> > > > >                 err = fdt_setprop(fdt, nodeoffset, "rng-seed",
> > > > >                                   abuf_data(&buf), abuf_size(&buf));
> > > > > diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
> > > > > index 4b22bb6f525a..8d70233fc08d 100644
> > > > > --- a/boot/pxe_utils.c
> > > > > +++ b/boot/pxe_utils.c
> > > > > @@ -8,6 +8,7 @@
> > > > >  #include <dm.h>
> > > > >  #include <env.h>
> > > > >  #include <image.h>
> > > > > +#include <kaslrseed.h>
> > > > >  #include <log.h>
> > > > >  #include <malloc.h>
> > > > >  #include <mapmem.h>
> > > > > @@ -323,10 +324,6 @@ static void label_boot_kaslrseed(void)
> > > > >  #if CONFIG_IS_ENABLED(DM_RNG)
> > > > >         ulong fdt_addr;
> > > > >         struct fdt_header *working_fdt;
> > > > > -       size_t n = 0x8;
> > > > > -       struct udevice *dev;
> > > > > -       u64 *buf;
> > > > > -       int nodeoffset;
> > > > >         int err;
> > > > >
> > > > >         /* Get the main fdt and map it */
> > > > > @@ -342,35 +339,9 @@ static void label_boot_kaslrseed(void)
> > > > >         if (err <= 0)
> > > > >                 return;
> > > > >
> > > > > -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> > > > > -               printf("No RNG device\n");
> > > > > -               return;
> > > > > -       }
> > > > > -
> > > > > -       nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
> > > > > -       if (nodeoffset < 0) {
> > > > > -               printf("Reading chosen node failed\n");
> > > > > -               return;
> > > > > -       }
> > > > > -
> > > > > -       buf = malloc(n);
> > > > > -       if (!buf) {
> > > > > -               printf("Out of memory\n");
> > > > > -               return;
> > > > > -       }
> > > > > -
> > > > > -       if (dm_rng_read(dev, buf, n)) {
> > > > > -               printf("Reading RNG failed\n");
> > > > > -               goto err;
> > > > > -       }
> > > > > -
> > > > > -       err = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> > > > > -       if (err < 0) {
> > > > > +       err = fdt_kaslrseed(working_fdt);
> > > > > +       if (err < 0)
> > > > >                 printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
> > > > > -               goto err;
> > > > > -       }
> > > > > -err:
> > > > > -       free(buf);
> > > > >  #endif
> > > > >         return;
> > > > >  }
> > > > > diff --git a/cmd/kaslrseed.c b/cmd/kaslrseed.c
> > > > > index e0d3c7fe7489..ea5c07d729cf 100644
> > > > > --- a/cmd/kaslrseed.c
> > > > > +++ b/cmd/kaslrseed.c
> > > > > @@ -9,33 +9,16 @@
> > > > >  #include <command.h>
> > > > >  #include <dm.h>
> > > > >  #include <hexdump.h>
> > > > > +#include <kaslrseed.h>
> > > > >  #include <malloc.h>
> > > > >  #include <rng.h>
> > > > >  #include <fdt_support.h>
> > > > >
> > > > >  static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> > > > >  {
> > > > > -       size_t n = 0x8;
> > > > > -       struct udevice *dev;
> > > > > -       u64 *buf;
> > > > > -       int nodeoffset;
> > > > > -       int ret = CMD_RET_SUCCESS;
> > > > > +       int err;
> > > > >
> > > > > -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> > > > > -               printf("No RNG device\n");
> > > > > -               return CMD_RET_FAILURE;
> > > > > -       }
> > > > > -
> > > > > -       buf = malloc(n);
> > > > > -       if (!buf) {
> > > > > -               printf("Out of memory\n");
> > > > > -               return CMD_RET_FAILURE;
> > > > > -       }
> > > > > -
> > > > > -       if (dm_rng_read(dev, buf, n)) {
> > > > > -               printf("Reading RNG failed\n");
> > > > > -               return CMD_RET_FAILURE;
> > > > > -       }
> > > > > +       printf("Notice: a /chosen/kaslr-seed is automatically added to the device-tree when booted via booti/bootm/bootz therefore using this command is likely no longer needed");
> > > > >
> > > > >         if (!working_fdt) {
> > > > >                 printf("No FDT memory address configured. Please configure\n"
> > > > > @@ -44,27 +27,13 @@ static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const
> > > > >                 return CMD_RET_FAILURE;
> > > > >         }
> > > > >
> > > > > -       ret = fdt_check_header(working_fdt);
> > > > > -       if (ret < 0) {
> > > > > -               printf("fdt_chosen: %s\n", fdt_strerror(ret));
> > > > > +       err = fdt_kaslrseed(working_fdt);
> > > > > +       if (err < 0) {
> > > > > +               printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
> > > > >                 return CMD_RET_FAILURE;
> > > > >         }
> > > > >
> > > > > -       nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
> > > > > -       if (nodeoffset < 0) {
> > > > > -               printf("Reading chosen node failed\n");
> > > > > -               return CMD_RET_FAILURE;
> > > > > -       }
> > > > > -
> > > > > -       ret = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> > > > > -       if (ret < 0) {
> > > > > -               printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
> > > > > -               return CMD_RET_FAILURE;
> > > > > -       }
> > > > > -
> > > > > -       free(buf);
> > > > > -
> > > > > -       return ret;
> > > > > +       return CMD_RET_SUCCESS;
> > > > >  }
> > > > >
> > > > >  U_BOOT_LONGHELP(kaslrseed,
> > > > > diff --git a/include/kaslrseed.h b/include/kaslrseed.h
> > > > > new file mode 100644
> > > > > index 000000000000..3fe82f418acf
> > > > > --- /dev/null
> > > > > +++ b/include/kaslrseed.h
> > > > > @@ -0,0 +1,17 @@
> > > > > +/* SPDX-License-Identifier: GPL-2.0+ */
> > > > > +/*
> > > > > + * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
> > > > > + */
> > > > > +
> > > > > +#if !defined _KASLRSEED_H_
> > > > > +#define _KASLRSEED_H_
> > > > > +
> > > > > +/**
> > > > > + * fdt_kaslrseed() - create a 'kaslr-seed' node in chosen
> > > > > + *
> > > > > + * @blob:      fdt blob
> > > > > + * Return:     0 if OK, -ve on error
> > > > > + */
> > > > > +int fdt_kaslrseed(void *blob);
> > > > > +
> > > > > +#endif /* _KASLRSEED_H_ */
> > > > > diff --git a/lib/Makefile b/lib/Makefile
> > > > > index 2a76acf100d0..20a0242055fa 100644
> > > > > --- a/lib/Makefile
> > > > > +++ b/lib/Makefile
> > > > > @@ -149,6 +149,7 @@ obj-y += date.o
> > > > >  obj-y += rtc-lib.o
> > > > >  obj-$(CONFIG_LIB_ELF) += elf.o
> > > > >
> > > > > +obj-$(CONFIG_DM_RNG) += kaslrseed.o
> > > > >  obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += semihosting.o
> > > > >
> > > > >  #
> > > > > diff --git a/lib/kaslrseed.c b/lib/kaslrseed.c
> > > > > new file mode 100644
> > > > > index 000000000000..ad06bee2b88d
> > > > > --- /dev/null
> > > > > +++ b/lib/kaslrseed.c
> > > > > @@ -0,0 +1,34 @@
> > > > > +// SPDX-License-Identifier: GPL-2.0+
> > > > > +/*
> > > > > + * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
> > > > > + */
> > > > > +#include <dm.h>
> > > > > +#include <rng.h>
> > > > > +#include <fdt_support.h>
> > > > > +
> > > > > +int fdt_kaslrseed(void *fdt)
> > > > > +{
> > > > > +       struct udevice *dev;
> > > > > +       int nodeoffset;
> > > > > +       u64 data;
> > > > > +       int err;
> > > > > +
> > > > > +       err = fdt_check_header(fdt);
> > > > > +       if (err < 0)
> > > > > +               return err;
> > > > > +
> > > > > +       /* find or create "/chosen" node. */
> > > > > +       nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
> > > > > +       if (nodeoffset < 0)
> > > > > +               return nodeoffset;
> > > > > +
> > > > > +       err = uclass_get_device(UCLASS_RNG, 0, &dev);
> > > > > +       if (!err)
> > > > > +               err = dm_rng_read(dev, &data, sizeof(data));
> > > > > +       if (!err)
> > > > > +               err = fdt_setprop(fdt, nodeoffset, "kaslr-seed", &data, sizeof(data));
> > > > > +       if (err < 0)
> > > > > +               printf("WARNING: could not set kaslr-seed %s.\n", fdt_strerror(err));
> > > > > +
> > > > > +       return err;
> > > > > +}
> > > > > --
> > > > > 2.25.1
> > > > >
Tim Harvey May 21, 2024, 6:05 p.m. UTC | #15
On Tue, May 21, 2024 at 10:29 AM Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> On Tue, 21 May 2024 at 20:06, Tim Harvey <tharvey@gateworks.com> wrote:
> >
> > On Tue, May 21, 2024 at 9:54 AM Ilias Apalodimas
> > <ilias.apalodimas@linaro.org> wrote:
> > >
> > > Hi Tim,
> > >
> > > On Tue, 21 May 2024 at 19:37, Tim Harvey <tharvey@gateworks.com> wrote:
> > > >
> > > > On Tue, May 21, 2024 at 5:05 AM Ilias Apalodimas
> > > > <ilias.apalodimas@linaro.org> wrote:
> > > > >
> > > > > Hi Tim
> > > > >
> > > > > On Wed, 15 May 2024 at 23:50, Tim Harvey <tharvey@gateworks.com> wrote:
> > > > > >
> > > > > > If RANDOMIZE_BASE is enabled in the Linux kernel instructing it to
> > > > > > randomize the virtual address at which the kernel image is loaded, it
> > > > > > expects entropy to be provided by the bootloader by populating
> > > > > > /chosen/kaslr-seed with a 64-bit value from source of entropy at boot.
> > > > >
> > > > > Since you'll send a v2, mind adding some description for UEFI on the
> > > > > commit message?
> > > > > efi_try_purge_kaslr_seed() has a comment of the behaviour
> > > > >
> > > >
> > > > Hi  Ilias,
> > > >
> > > > Ok, I will add the following to the commit log for clarity:
> > > > Note that the Kernel's EFI STUB only relies on EFI_RNG_PROTOCOL for
> > > > randomization and completely ignores the kaslr-seed for its own
> > > > randomness needs (i.e the randomization of the physical placement of
> > > > the kernel). It gets weeded out from the DTB that gets handed over via
> > > > efi_install_fdt() as it would also mess up the measured boot DTB TPM
> > > > measurements as well.
> > > >
> > > > Does the above mean that I don't need to worry about protecting the
> > > > call to fdt_kaslrseed() with a check for MEASURED BOOT as
> > > > efi_install_fdt/efi_try_purge_kaslr_seed always gets called in that
> > > > case?
> > >
> > > There are 2 ways to do measured boot. One is via the bootm command and
> > > the other is via the EFI protocols.
> > > CONFIG_MEASURED_BOOT  only applies to bootm.
> > > OTOH kaslr-seed might still have value if EFI_RNG is disabled, even
> > > when booting with EFI, since the kernel will randomize the virtual
> > > placement if it finds that.
> > >
> > > But in any case, a kaslr-seed entry can't be present in the DTB if you
> > > plan to measure it.
> >
> > ok, sounds like I need to use:
> >
> > if (IS_ENABLED(CONFIG_DM_RNG) &&
> > !IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)) &&
> > !IS_ENABLED(CONFIG_MEASURED_BOOT) {
> >   fdt_kaslrseed...
> > }
> >
>
> Can't we measure the DT *before* adding the kaslr-seed?
>

You tell me... I'm deferring to you regarding what is needed for this
patch for measured boot.

What changes do I need to make and why?

Best Regards,

Tim

> Cheers
> /Ilias
> > Thanks,
> >
> > I'll send a v3 hopefully later today.
> >
> > Tim
> >
> > >
> > > Cheers
> > > /Ilias
> > >
> > > >
> > > > Best Regards,
> > > >
> > > > Tim
> > > >
> > > > > Thanks
> > > > > /Ilias
> > > > > >
> > > > > > If we have DM_RNG enabled populate this value automatically when
> > > > > > fdt_chosen is called unless ARMV8_SEC_FIRMWARE_SUPPORT is enabled as
> > > > > > it's implementation uses a different source of entropy.
> > > > > >
> > > > > > As this fdt node is added elsewhere create a library function and
> > > > > > use it to deduplicate code.
> > > > > >
> > > > > > Note that the kalsrseed command (CMD_KASLRSEED) is likely pointless now
> > > > > > but left in place in case boot scripts exist that rely on this command
> > > > > > existing and returning success. An informational message is printed to
> > > > > > alert users of this command that it is likely no longer needed.
> > > > > >
> > > > > > Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> > > > > > ---
> > > > > > v2:
> > > > > >  - fix typo in commit msg
> > > > > >  - use stack for seed to avoid unecessary malloc/free
> > > > > >  - move to a library function and deduplicate code by using it elsewhere
> > > > > > ---
> > > > > >  board/xilinx/common/board.c | 35 -----------------------------
> > > > > >  boot/fdt_support.c          | 10 +++++++++
> > > > > >  boot/pxe_utils.c            | 35 +++--------------------------
> > > > > >  cmd/kaslrseed.c             | 45 ++++++-------------------------------
> > > > > >  include/kaslrseed.h         | 17 ++++++++++++++
> > > > > >  lib/Makefile                |  1 +
> > > > > >  lib/kaslrseed.c             | 34 ++++++++++++++++++++++++++++
> > > > > >  7 files changed, 72 insertions(+), 105 deletions(-)
> > > > > >  create mode 100644 include/kaslrseed.h
> > > > > >  create mode 100644 lib/kaslrseed.c
> > > > > >
> > > > > > diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
> > > > > > index 30a81376ac41..f741e8957818 100644
> > > > > > --- a/board/xilinx/common/board.c
> > > > > > +++ b/board/xilinx/common/board.c
> > > > > > @@ -713,41 +713,6 @@ int ft_board_setup(void *blob, struct bd_info *bd)
> > > > > >         if (IS_ENABLED(CONFIG_FDT_FIXUP_PARTITIONS) && IS_ENABLED(CONFIG_NAND_ZYNQ))
> > > > > >                 fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
> > > > > >
> > > > > > -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> > > > > > -               debug("No RNG device\n");
> > > > > > -               return 0;
> > > > > > -       }
> > > > > > -
> > > > > > -       if (dm_rng_read(dev, buf, n)) {
> > > > > > -               debug("Reading RNG failed\n");
> > > > > > -               return 0;
> > > > > > -       }
> > > > > > -
> > > > > > -       if (!blob) {
> > > > > > -               debug("No FDT memory address configured. Please configure\n"
> > > > > > -                     "the FDT address via \"fdt addr <address>\" command.\n"
> > > > > > -                     "Aborting!\n");
> > > > > > -               return 0;
> > > > > > -       }
> > > > > > -
> > > > > > -       ret = fdt_check_header(blob);
> > > > > > -       if (ret < 0) {
> > > > > > -               debug("fdt_chosen: %s\n", fdt_strerror(ret));
> > > > > > -               return ret;
> > > > > > -       }
> > > > > > -
> > > > > > -       nodeoffset = fdt_find_or_add_subnode(blob, 0, "chosen");
> > > > > > -       if (nodeoffset < 0) {
> > > > > > -               debug("Reading chosen node failed\n");
> > > > > > -               return nodeoffset;
> > > > > > -       }
> > > > > > -
> > > > > > -       ret = fdt_setprop(blob, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> > > > > > -       if (ret < 0) {
> > > > > > -               debug("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
> > > > > > -               return ret;
> > > > > > -       }
> > > > > > -
> > > > > >         return 0;
> > > > > >  }
> > > > > >  #endif
> > > > > > diff --git a/boot/fdt_support.c b/boot/fdt_support.c
> > > > > > index 874ca4d6f5af..3455d60d69dc 100644
> > > > > > --- a/boot/fdt_support.c
> > > > > > +++ b/boot/fdt_support.c
> > > > > > @@ -8,6 +8,7 @@
> > > > > >
> > > > > >  #include <abuf.h>
> > > > > >  #include <env.h>
> > > > > > +#include <kaslrseed.h>
> > > > > >  #include <log.h>
> > > > > >  #include <mapmem.h>
> > > > > >  #include <net.h>
> > > > > > @@ -300,6 +301,15 @@ int fdt_chosen(void *fdt)
> > > > > >         if (nodeoffset < 0)
> > > > > >                 return nodeoffset;
> > > > > >
> > > > > > +       if (IS_ENABLED(CONFIG_DM_RNG) && !IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)) {
> > > > > > +               err = fdt_kaslrseed(fdt);
> > > > > > +               if (err) {
> > > > > > +                       printf("WARNING: could not set kaslr-seed %s.\n",
> > > > > > +                              fdt_strerror(err));
> > > > > > +                       return err;
> > > > > > +               }
> > > > > > +       }
> > > > > > +
> > > > > >         if (IS_ENABLED(CONFIG_BOARD_RNG_SEED) && !board_rng_seed(&buf)) {
> > > > > >                 err = fdt_setprop(fdt, nodeoffset, "rng-seed",
> > > > > >                                   abuf_data(&buf), abuf_size(&buf));
> > > > > > diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
> > > > > > index 4b22bb6f525a..8d70233fc08d 100644
> > > > > > --- a/boot/pxe_utils.c
> > > > > > +++ b/boot/pxe_utils.c
> > > > > > @@ -8,6 +8,7 @@
> > > > > >  #include <dm.h>
> > > > > >  #include <env.h>
> > > > > >  #include <image.h>
> > > > > > +#include <kaslrseed.h>
> > > > > >  #include <log.h>
> > > > > >  #include <malloc.h>
> > > > > >  #include <mapmem.h>
> > > > > > @@ -323,10 +324,6 @@ static void label_boot_kaslrseed(void)
> > > > > >  #if CONFIG_IS_ENABLED(DM_RNG)
> > > > > >         ulong fdt_addr;
> > > > > >         struct fdt_header *working_fdt;
> > > > > > -       size_t n = 0x8;
> > > > > > -       struct udevice *dev;
> > > > > > -       u64 *buf;
> > > > > > -       int nodeoffset;
> > > > > >         int err;
> > > > > >
> > > > > >         /* Get the main fdt and map it */
> > > > > > @@ -342,35 +339,9 @@ static void label_boot_kaslrseed(void)
> > > > > >         if (err <= 0)
> > > > > >                 return;
> > > > > >
> > > > > > -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> > > > > > -               printf("No RNG device\n");
> > > > > > -               return;
> > > > > > -       }
> > > > > > -
> > > > > > -       nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
> > > > > > -       if (nodeoffset < 0) {
> > > > > > -               printf("Reading chosen node failed\n");
> > > > > > -               return;
> > > > > > -       }
> > > > > > -
> > > > > > -       buf = malloc(n);
> > > > > > -       if (!buf) {
> > > > > > -               printf("Out of memory\n");
> > > > > > -               return;
> > > > > > -       }
> > > > > > -
> > > > > > -       if (dm_rng_read(dev, buf, n)) {
> > > > > > -               printf("Reading RNG failed\n");
> > > > > > -               goto err;
> > > > > > -       }
> > > > > > -
> > > > > > -       err = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> > > > > > -       if (err < 0) {
> > > > > > +       err = fdt_kaslrseed(working_fdt);
> > > > > > +       if (err < 0)
> > > > > >                 printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
> > > > > > -               goto err;
> > > > > > -       }
> > > > > > -err:
> > > > > > -       free(buf);
> > > > > >  #endif
> > > > > >         return;
> > > > > >  }
> > > > > > diff --git a/cmd/kaslrseed.c b/cmd/kaslrseed.c
> > > > > > index e0d3c7fe7489..ea5c07d729cf 100644
> > > > > > --- a/cmd/kaslrseed.c
> > > > > > +++ b/cmd/kaslrseed.c
> > > > > > @@ -9,33 +9,16 @@
> > > > > >  #include <command.h>
> > > > > >  #include <dm.h>
> > > > > >  #include <hexdump.h>
> > > > > > +#include <kaslrseed.h>
> > > > > >  #include <malloc.h>
> > > > > >  #include <rng.h>
> > > > > >  #include <fdt_support.h>
> > > > > >
> > > > > >  static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> > > > > >  {
> > > > > > -       size_t n = 0x8;
> > > > > > -       struct udevice *dev;
> > > > > > -       u64 *buf;
> > > > > > -       int nodeoffset;
> > > > > > -       int ret = CMD_RET_SUCCESS;
> > > > > > +       int err;
> > > > > >
> > > > > > -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> > > > > > -               printf("No RNG device\n");
> > > > > > -               return CMD_RET_FAILURE;
> > > > > > -       }
> > > > > > -
> > > > > > -       buf = malloc(n);
> > > > > > -       if (!buf) {
> > > > > > -               printf("Out of memory\n");
> > > > > > -               return CMD_RET_FAILURE;
> > > > > > -       }
> > > > > > -
> > > > > > -       if (dm_rng_read(dev, buf, n)) {
> > > > > > -               printf("Reading RNG failed\n");
> > > > > > -               return CMD_RET_FAILURE;
> > > > > > -       }
> > > > > > +       printf("Notice: a /chosen/kaslr-seed is automatically added to the device-tree when booted via booti/bootm/bootz therefore using this command is likely no longer needed");
> > > > > >
> > > > > >         if (!working_fdt) {
> > > > > >                 printf("No FDT memory address configured. Please configure\n"
> > > > > > @@ -44,27 +27,13 @@ static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const
> > > > > >                 return CMD_RET_FAILURE;
> > > > > >         }
> > > > > >
> > > > > > -       ret = fdt_check_header(working_fdt);
> > > > > > -       if (ret < 0) {
> > > > > > -               printf("fdt_chosen: %s\n", fdt_strerror(ret));
> > > > > > +       err = fdt_kaslrseed(working_fdt);
> > > > > > +       if (err < 0) {
> > > > > > +               printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
> > > > > >                 return CMD_RET_FAILURE;
> > > > > >         }
> > > > > >
> > > > > > -       nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
> > > > > > -       if (nodeoffset < 0) {
> > > > > > -               printf("Reading chosen node failed\n");
> > > > > > -               return CMD_RET_FAILURE;
> > > > > > -       }
> > > > > > -
> > > > > > -       ret = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> > > > > > -       if (ret < 0) {
> > > > > > -               printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
> > > > > > -               return CMD_RET_FAILURE;
> > > > > > -       }
> > > > > > -
> > > > > > -       free(buf);
> > > > > > -
> > > > > > -       return ret;
> > > > > > +       return CMD_RET_SUCCESS;
> > > > > >  }
> > > > > >
> > > > > >  U_BOOT_LONGHELP(kaslrseed,
> > > > > > diff --git a/include/kaslrseed.h b/include/kaslrseed.h
> > > > > > new file mode 100644
> > > > > > index 000000000000..3fe82f418acf
> > > > > > --- /dev/null
> > > > > > +++ b/include/kaslrseed.h
> > > > > > @@ -0,0 +1,17 @@
> > > > > > +/* SPDX-License-Identifier: GPL-2.0+ */
> > > > > > +/*
> > > > > > + * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
> > > > > > + */
> > > > > > +
> > > > > > +#if !defined _KASLRSEED_H_
> > > > > > +#define _KASLRSEED_H_
> > > > > > +
> > > > > > +/**
> > > > > > + * fdt_kaslrseed() - create a 'kaslr-seed' node in chosen
> > > > > > + *
> > > > > > + * @blob:      fdt blob
> > > > > > + * Return:     0 if OK, -ve on error
> > > > > > + */
> > > > > > +int fdt_kaslrseed(void *blob);
> > > > > > +
> > > > > > +#endif /* _KASLRSEED_H_ */
> > > > > > diff --git a/lib/Makefile b/lib/Makefile
> > > > > > index 2a76acf100d0..20a0242055fa 100644
> > > > > > --- a/lib/Makefile
> > > > > > +++ b/lib/Makefile
> > > > > > @@ -149,6 +149,7 @@ obj-y += date.o
> > > > > >  obj-y += rtc-lib.o
> > > > > >  obj-$(CONFIG_LIB_ELF) += elf.o
> > > > > >
> > > > > > +obj-$(CONFIG_DM_RNG) += kaslrseed.o
> > > > > >  obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += semihosting.o
> > > > > >
> > > > > >  #
> > > > > > diff --git a/lib/kaslrseed.c b/lib/kaslrseed.c
> > > > > > new file mode 100644
> > > > > > index 000000000000..ad06bee2b88d
> > > > > > --- /dev/null
> > > > > > +++ b/lib/kaslrseed.c
> > > > > > @@ -0,0 +1,34 @@
> > > > > > +// SPDX-License-Identifier: GPL-2.0+
> > > > > > +/*
> > > > > > + * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
> > > > > > + */
> > > > > > +#include <dm.h>
> > > > > > +#include <rng.h>
> > > > > > +#include <fdt_support.h>
> > > > > > +
> > > > > > +int fdt_kaslrseed(void *fdt)
> > > > > > +{
> > > > > > +       struct udevice *dev;
> > > > > > +       int nodeoffset;
> > > > > > +       u64 data;
> > > > > > +       int err;
> > > > > > +
> > > > > > +       err = fdt_check_header(fdt);
> > > > > > +       if (err < 0)
> > > > > > +               return err;
> > > > > > +
> > > > > > +       /* find or create "/chosen" node. */
> > > > > > +       nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
> > > > > > +       if (nodeoffset < 0)
> > > > > > +               return nodeoffset;
> > > > > > +
> > > > > > +       err = uclass_get_device(UCLASS_RNG, 0, &dev);
> > > > > > +       if (!err)
> > > > > > +               err = dm_rng_read(dev, &data, sizeof(data));
> > > > > > +       if (!err)
> > > > > > +               err = fdt_setprop(fdt, nodeoffset, "kaslr-seed", &data, sizeof(data));
> > > > > > +       if (err < 0)
> > > > > > +               printf("WARNING: could not set kaslr-seed %s.\n", fdt_strerror(err));
> > > > > > +
> > > > > > +       return err;
> > > > > > +}
> > > > > > --
> > > > > > 2.25.1
> > > > > >
Ilias Apalodimas May 21, 2024, 6:58 p.m. UTC | #16
On Tue, 21 May 2024 at 21:05, Tim Harvey <tharvey@gateworks.com> wrote:
>
> On Tue, May 21, 2024 at 10:29 AM Ilias Apalodimas
> <ilias.apalodimas@linaro.org> wrote:
> >
> > On Tue, 21 May 2024 at 20:06, Tim Harvey <tharvey@gateworks.com> wrote:
> > >
> > > On Tue, May 21, 2024 at 9:54 AM Ilias Apalodimas
> > > <ilias.apalodimas@linaro.org> wrote:
> > > >
> > > > Hi Tim,
> > > >
> > > > On Tue, 21 May 2024 at 19:37, Tim Harvey <tharvey@gateworks.com> wrote:
> > > > >
> > > > > On Tue, May 21, 2024 at 5:05 AM Ilias Apalodimas
> > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > >
> > > > > > Hi Tim
> > > > > >
> > > > > > On Wed, 15 May 2024 at 23:50, Tim Harvey <tharvey@gateworks.com> wrote:
> > > > > > >
> > > > > > > If RANDOMIZE_BASE is enabled in the Linux kernel instructing it to
> > > > > > > randomize the virtual address at which the kernel image is loaded, it
> > > > > > > expects entropy to be provided by the bootloader by populating
> > > > > > > /chosen/kaslr-seed with a 64-bit value from source of entropy at boot.
> > > > > >
> > > > > > Since you'll send a v2, mind adding some description for UEFI on the
> > > > > > commit message?
> > > > > > efi_try_purge_kaslr_seed() has a comment of the behaviour
> > > > > >
> > > > >
> > > > > Hi  Ilias,
> > > > >
> > > > > Ok, I will add the following to the commit log for clarity:
> > > > > Note that the Kernel's EFI STUB only relies on EFI_RNG_PROTOCOL for
> > > > > randomization and completely ignores the kaslr-seed for its own
> > > > > randomness needs (i.e the randomization of the physical placement of
> > > > > the kernel). It gets weeded out from the DTB that gets handed over via
> > > > > efi_install_fdt() as it would also mess up the measured boot DTB TPM
> > > > > measurements as well.
> > > > >
> > > > > Does the above mean that I don't need to worry about protecting the
> > > > > call to fdt_kaslrseed() with a check for MEASURED BOOT as
> > > > > efi_install_fdt/efi_try_purge_kaslr_seed always gets called in that
> > > > > case?
> > > >
> > > > There are 2 ways to do measured boot. One is via the bootm command and
> > > > the other is via the EFI protocols.
> > > > CONFIG_MEASURED_BOOT  only applies to bootm.
> > > > OTOH kaslr-seed might still have value if EFI_RNG is disabled, even
> > > > when booting with EFI, since the kernel will randomize the virtual
> > > > placement if it finds that.
> > > >
> > > > But in any case, a kaslr-seed entry can't be present in the DTB if you
> > > > plan to measure it.
> > >
> > > ok, sounds like I need to use:
> > >
> > > if (IS_ENABLED(CONFIG_DM_RNG) &&
> > > !IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)) &&
> > > !IS_ENABLED(CONFIG_MEASURED_BOOT) {
> > >   fdt_kaslrseed...
> > > }
> > >
> >
> > Can't we measure the DT *before* adding the kaslr-seed?
> >
>
> You tell me... I'm deferring to you regarding what is needed for this
> patch for measured boot.
>
> What changes do I need to make and why?

Ok, thinking it a bit more we can't reliably measure the DT before a
kaslr-seed gets injected, simply because an earlier stage bootloader
might have injected it....  That's why we had a config option (and at
least we mention it in aa2d3945ce6df43903d76cadde1c0669d6d5d43b but
not in great detail).
However, for a user that's far from ideal since he needs to be aware
of those details before enabling measurements for the DT.

Looking at our EFI code we *try* to purge the kaslr-seed before
measuring the DT, but that doesn't guarantee it won't be there -- it
will be purged only if EFI_RNG is installed. But that only happens if
you have an RNG available.
To make things even worse, the kaslr-seed is not the only source of
randomness when measuring a DT, a mac address entry for example would
have the same effect.
On top of all these EFI code measures on PCR0 and bootm on PCR8. The
reason for that is that although the EFI spec has no guidance on
measuring a DT, it does have for ACPI and it uses PCR0 [0].

I think all these should be fixed and at least documented properly for
now, but that's unfair to you since it's irrelevant to what your patch
is trying to fix ...

As for recommendations, I haven't looked into bootm code for quite
some time. Can we inject kaslr-seed after we measure it? If yes, then
do that and let's add a comment about the current mess...


[0] https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClient_PFP_r1p05_v23_pub.pdf
3.3.4.1 PCR[0] – SRTM, POST BIOS, and Embedded Drivers



>
> Best Regards,
>
> Tim
>
> > Cheers
> > /Ilias
> > > Thanks,
> > >
> > > I'll send a v3 hopefully later today.
> > >
> > > Tim
> > >
> > > >
> > > > Cheers
> > > > /Ilias
> > > >
> > > > >
> > > > > Best Regards,
> > > > >
> > > > > Tim
> > > > >
> > > > > > Thanks
> > > > > > /Ilias
> > > > > > >
> > > > > > > If we have DM_RNG enabled populate this value automatically when
> > > > > > > fdt_chosen is called unless ARMV8_SEC_FIRMWARE_SUPPORT is enabled as
> > > > > > > it's implementation uses a different source of entropy.
> > > > > > >
> > > > > > > As this fdt node is added elsewhere create a library function and
> > > > > > > use it to deduplicate code.
> > > > > > >
> > > > > > > Note that the kalsrseed command (CMD_KASLRSEED) is likely pointless now
> > > > > > > but left in place in case boot scripts exist that rely on this command
> > > > > > > existing and returning success. An informational message is printed to
> > > > > > > alert users of this command that it is likely no longer needed.
> > > > > > >
> > > > > > > Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> > > > > > > ---
> > > > > > > v2:
> > > > > > >  - fix typo in commit msg
> > > > > > >  - use stack for seed to avoid unecessary malloc/free
> > > > > > >  - move to a library function and deduplicate code by using it elsewhere
> > > > > > > ---
> > > > > > >  board/xilinx/common/board.c | 35 -----------------------------
> > > > > > >  boot/fdt_support.c          | 10 +++++++++
> > > > > > >  boot/pxe_utils.c            | 35 +++--------------------------
> > > > > > >  cmd/kaslrseed.c             | 45 ++++++-------------------------------
> > > > > > >  include/kaslrseed.h         | 17 ++++++++++++++
> > > > > > >  lib/Makefile                |  1 +
> > > > > > >  lib/kaslrseed.c             | 34 ++++++++++++++++++++++++++++
> > > > > > >  7 files changed, 72 insertions(+), 105 deletions(-)
> > > > > > >  create mode 100644 include/kaslrseed.h
> > > > > > >  create mode 100644 lib/kaslrseed.c
> > > > > > >
> > > > > > > diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
> > > > > > > index 30a81376ac41..f741e8957818 100644
> > > > > > > --- a/board/xilinx/common/board.c
> > > > > > > +++ b/board/xilinx/common/board.c
> > > > > > > @@ -713,41 +713,6 @@ int ft_board_setup(void *blob, struct bd_info *bd)
> > > > > > >         if (IS_ENABLED(CONFIG_FDT_FIXUP_PARTITIONS) && IS_ENABLED(CONFIG_NAND_ZYNQ))
> > > > > > >                 fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
> > > > > > >
> > > > > > > -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> > > > > > > -               debug("No RNG device\n");
> > > > > > > -               return 0;
> > > > > > > -       }
> > > > > > > -
> > > > > > > -       if (dm_rng_read(dev, buf, n)) {
> > > > > > > -               debug("Reading RNG failed\n");
> > > > > > > -               return 0;
> > > > > > > -       }
> > > > > > > -
> > > > > > > -       if (!blob) {
> > > > > > > -               debug("No FDT memory address configured. Please configure\n"
> > > > > > > -                     "the FDT address via \"fdt addr <address>\" command.\n"
> > > > > > > -                     "Aborting!\n");
> > > > > > > -               return 0;
> > > > > > > -       }
> > > > > > > -
> > > > > > > -       ret = fdt_check_header(blob);
> > > > > > > -       if (ret < 0) {
> > > > > > > -               debug("fdt_chosen: %s\n", fdt_strerror(ret));
> > > > > > > -               return ret;
> > > > > > > -       }
> > > > > > > -
> > > > > > > -       nodeoffset = fdt_find_or_add_subnode(blob, 0, "chosen");
> > > > > > > -       if (nodeoffset < 0) {
> > > > > > > -               debug("Reading chosen node failed\n");
> > > > > > > -               return nodeoffset;
> > > > > > > -       }
> > > > > > > -
> > > > > > > -       ret = fdt_setprop(blob, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> > > > > > > -       if (ret < 0) {
> > > > > > > -               debug("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
> > > > > > > -               return ret;
> > > > > > > -       }
> > > > > > > -
> > > > > > >         return 0;
> > > > > > >  }
> > > > > > >  #endif
> > > > > > > diff --git a/boot/fdt_support.c b/boot/fdt_support.c
> > > > > > > index 874ca4d6f5af..3455d60d69dc 100644
> > > > > > > --- a/boot/fdt_support.c
> > > > > > > +++ b/boot/fdt_support.c
> > > > > > > @@ -8,6 +8,7 @@
> > > > > > >
> > > > > > >  #include <abuf.h>
> > > > > > >  #include <env.h>
> > > > > > > +#include <kaslrseed.h>
> > > > > > >  #include <log.h>
> > > > > > >  #include <mapmem.h>
> > > > > > >  #include <net.h>
> > > > > > > @@ -300,6 +301,15 @@ int fdt_chosen(void *fdt)
> > > > > > >         if (nodeoffset < 0)
> > > > > > >                 return nodeoffset;
> > > > > > >
> > > > > > > +       if (IS_ENABLED(CONFIG_DM_RNG) && !IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)) {
> > > > > > > +               err = fdt_kaslrseed(fdt);
> > > > > > > +               if (err) {
> > > > > > > +                       printf("WARNING: could not set kaslr-seed %s.\n",
> > > > > > > +                              fdt_strerror(err));
> > > > > > > +                       return err;
> > > > > > > +               }
> > > > > > > +       }
> > > > > > > +
> > > > > > >         if (IS_ENABLED(CONFIG_BOARD_RNG_SEED) && !board_rng_seed(&buf)) {
> > > > > > >                 err = fdt_setprop(fdt, nodeoffset, "rng-seed",
> > > > > > >                                   abuf_data(&buf), abuf_size(&buf));
> > > > > > > diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
> > > > > > > index 4b22bb6f525a..8d70233fc08d 100644
> > > > > > > --- a/boot/pxe_utils.c
> > > > > > > +++ b/boot/pxe_utils.c
> > > > > > > @@ -8,6 +8,7 @@
> > > > > > >  #include <dm.h>
> > > > > > >  #include <env.h>
> > > > > > >  #include <image.h>
> > > > > > > +#include <kaslrseed.h>
> > > > > > >  #include <log.h>
> > > > > > >  #include <malloc.h>
> > > > > > >  #include <mapmem.h>
> > > > > > > @@ -323,10 +324,6 @@ static void label_boot_kaslrseed(void)
> > > > > > >  #if CONFIG_IS_ENABLED(DM_RNG)
> > > > > > >         ulong fdt_addr;
> > > > > > >         struct fdt_header *working_fdt;
> > > > > > > -       size_t n = 0x8;
> > > > > > > -       struct udevice *dev;
> > > > > > > -       u64 *buf;
> > > > > > > -       int nodeoffset;
> > > > > > >         int err;
> > > > > > >
> > > > > > >         /* Get the main fdt and map it */
> > > > > > > @@ -342,35 +339,9 @@ static void label_boot_kaslrseed(void)
> > > > > > >         if (err <= 0)
> > > > > > >                 return;
> > > > > > >
> > > > > > > -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> > > > > > > -               printf("No RNG device\n");
> > > > > > > -               return;
> > > > > > > -       }
> > > > > > > -
> > > > > > > -       nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
> > > > > > > -       if (nodeoffset < 0) {
> > > > > > > -               printf("Reading chosen node failed\n");
> > > > > > > -               return;
> > > > > > > -       }
> > > > > > > -
> > > > > > > -       buf = malloc(n);
> > > > > > > -       if (!buf) {
> > > > > > > -               printf("Out of memory\n");
> > > > > > > -               return;
> > > > > > > -       }
> > > > > > > -
> > > > > > > -       if (dm_rng_read(dev, buf, n)) {
> > > > > > > -               printf("Reading RNG failed\n");
> > > > > > > -               goto err;
> > > > > > > -       }
> > > > > > > -
> > > > > > > -       err = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> > > > > > > -       if (err < 0) {
> > > > > > > +       err = fdt_kaslrseed(working_fdt);
> > > > > > > +       if (err < 0)
> > > > > > >                 printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
> > > > > > > -               goto err;
> > > > > > > -       }
> > > > > > > -err:
> > > > > > > -       free(buf);
> > > > > > >  #endif
> > > > > > >         return;
> > > > > > >  }
> > > > > > > diff --git a/cmd/kaslrseed.c b/cmd/kaslrseed.c
> > > > > > > index e0d3c7fe7489..ea5c07d729cf 100644
> > > > > > > --- a/cmd/kaslrseed.c
> > > > > > > +++ b/cmd/kaslrseed.c
> > > > > > > @@ -9,33 +9,16 @@
> > > > > > >  #include <command.h>
> > > > > > >  #include <dm.h>
> > > > > > >  #include <hexdump.h>
> > > > > > > +#include <kaslrseed.h>
> > > > > > >  #include <malloc.h>
> > > > > > >  #include <rng.h>
> > > > > > >  #include <fdt_support.h>
> > > > > > >
> > > > > > >  static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> > > > > > >  {
> > > > > > > -       size_t n = 0x8;
> > > > > > > -       struct udevice *dev;
> > > > > > > -       u64 *buf;
> > > > > > > -       int nodeoffset;
> > > > > > > -       int ret = CMD_RET_SUCCESS;
> > > > > > > +       int err;
> > > > > > >
> > > > > > > -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> > > > > > > -               printf("No RNG device\n");
> > > > > > > -               return CMD_RET_FAILURE;
> > > > > > > -       }
> > > > > > > -
> > > > > > > -       buf = malloc(n);
> > > > > > > -       if (!buf) {
> > > > > > > -               printf("Out of memory\n");
> > > > > > > -               return CMD_RET_FAILURE;
> > > > > > > -       }
> > > > > > > -
> > > > > > > -       if (dm_rng_read(dev, buf, n)) {
> > > > > > > -               printf("Reading RNG failed\n");
> > > > > > > -               return CMD_RET_FAILURE;
> > > > > > > -       }
> > > > > > > +       printf("Notice: a /chosen/kaslr-seed is automatically added to the device-tree when booted via booti/bootm/bootz therefore using this command is likely no longer needed");
> > > > > > >
> > > > > > >         if (!working_fdt) {
> > > > > > >                 printf("No FDT memory address configured. Please configure\n"
> > > > > > > @@ -44,27 +27,13 @@ static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const
> > > > > > >                 return CMD_RET_FAILURE;
> > > > > > >         }
> > > > > > >
> > > > > > > -       ret = fdt_check_header(working_fdt);
> > > > > > > -       if (ret < 0) {
> > > > > > > -               printf("fdt_chosen: %s\n", fdt_strerror(ret));
> > > > > > > +       err = fdt_kaslrseed(working_fdt);
> > > > > > > +       if (err < 0) {
> > > > > > > +               printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
> > > > > > >                 return CMD_RET_FAILURE;
> > > > > > >         }
> > > > > > >
> > > > > > > -       nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
> > > > > > > -       if (nodeoffset < 0) {
> > > > > > > -               printf("Reading chosen node failed\n");
> > > > > > > -               return CMD_RET_FAILURE;
> > > > > > > -       }
> > > > > > > -
> > > > > > > -       ret = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> > > > > > > -       if (ret < 0) {
> > > > > > > -               printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
> > > > > > > -               return CMD_RET_FAILURE;
> > > > > > > -       }
> > > > > > > -
> > > > > > > -       free(buf);
> > > > > > > -
> > > > > > > -       return ret;
> > > > > > > +       return CMD_RET_SUCCESS;
> > > > > > >  }
> > > > > > >
> > > > > > >  U_BOOT_LONGHELP(kaslrseed,
> > > > > > > diff --git a/include/kaslrseed.h b/include/kaslrseed.h
> > > > > > > new file mode 100644
> > > > > > > index 000000000000..3fe82f418acf
> > > > > > > --- /dev/null
> > > > > > > +++ b/include/kaslrseed.h
> > > > > > > @@ -0,0 +1,17 @@
> > > > > > > +/* SPDX-License-Identifier: GPL-2.0+ */
> > > > > > > +/*
> > > > > > > + * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
> > > > > > > + */
> > > > > > > +
> > > > > > > +#if !defined _KASLRSEED_H_
> > > > > > > +#define _KASLRSEED_H_
> > > > > > > +
> > > > > > > +/**
> > > > > > > + * fdt_kaslrseed() - create a 'kaslr-seed' node in chosen
> > > > > > > + *
> > > > > > > + * @blob:      fdt blob
> > > > > > > + * Return:     0 if OK, -ve on error
> > > > > > > + */
> > > > > > > +int fdt_kaslrseed(void *blob);
> > > > > > > +
> > > > > > > +#endif /* _KASLRSEED_H_ */
> > > > > > > diff --git a/lib/Makefile b/lib/Makefile
> > > > > > > index 2a76acf100d0..20a0242055fa 100644
> > > > > > > --- a/lib/Makefile
> > > > > > > +++ b/lib/Makefile
> > > > > > > @@ -149,6 +149,7 @@ obj-y += date.o
> > > > > > >  obj-y += rtc-lib.o
> > > > > > >  obj-$(CONFIG_LIB_ELF) += elf.o
> > > > > > >
> > > > > > > +obj-$(CONFIG_DM_RNG) += kaslrseed.o
> > > > > > >  obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += semihosting.o
> > > > > > >
> > > > > > >  #
> > > > > > > diff --git a/lib/kaslrseed.c b/lib/kaslrseed.c
> > > > > > > new file mode 100644
> > > > > > > index 000000000000..ad06bee2b88d
> > > > > > > --- /dev/null
> > > > > > > +++ b/lib/kaslrseed.c
> > > > > > > @@ -0,0 +1,34 @@
> > > > > > > +// SPDX-License-Identifier: GPL-2.0+
> > > > > > > +/*
> > > > > > > + * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
> > > > > > > + */
> > > > > > > +#include <dm.h>
> > > > > > > +#include <rng.h>
> > > > > > > +#include <fdt_support.h>
> > > > > > > +
> > > > > > > +int fdt_kaslrseed(void *fdt)
> > > > > > > +{
> > > > > > > +       struct udevice *dev;
> > > > > > > +       int nodeoffset;
> > > > > > > +       u64 data;
> > > > > > > +       int err;
> > > > > > > +
> > > > > > > +       err = fdt_check_header(fdt);
> > > > > > > +       if (err < 0)
> > > > > > > +               return err;
> > > > > > > +
> > > > > > > +       /* find or create "/chosen" node. */
> > > > > > > +       nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
> > > > > > > +       if (nodeoffset < 0)
> > > > > > > +               return nodeoffset;
> > > > > > > +
> > > > > > > +       err = uclass_get_device(UCLASS_RNG, 0, &dev);
> > > > > > > +       if (!err)
> > > > > > > +               err = dm_rng_read(dev, &data, sizeof(data));
> > > > > > > +       if (!err)
> > > > > > > +               err = fdt_setprop(fdt, nodeoffset, "kaslr-seed", &data, sizeof(data));
> > > > > > > +       if (err < 0)
> > > > > > > +               printf("WARNING: could not set kaslr-seed %s.\n", fdt_strerror(err));
> > > > > > > +
> > > > > > > +       return err;
> > > > > > > +}
> > > > > > > --
> > > > > > > 2.25.1
> > > > > > >
Tim Harvey May 21, 2024, 8:53 p.m. UTC | #17
On Tue, May 21, 2024 at 11:59 AM Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> On Tue, 21 May 2024 at 21:05, Tim Harvey <tharvey@gateworks.com> wrote:
> >
> > On Tue, May 21, 2024 at 10:29 AM Ilias Apalodimas
> > <ilias.apalodimas@linaro.org> wrote:
> > >
> > > On Tue, 21 May 2024 at 20:06, Tim Harvey <tharvey@gateworks.com> wrote:
> > > >
> > > > On Tue, May 21, 2024 at 9:54 AM Ilias Apalodimas
> > > > <ilias.apalodimas@linaro.org> wrote:
> > > > >
> > > > > Hi Tim,
> > > > >
> > > > > On Tue, 21 May 2024 at 19:37, Tim Harvey <tharvey@gateworks.com> wrote:
> > > > > >
> > > > > > On Tue, May 21, 2024 at 5:05 AM Ilias Apalodimas
> > > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > > >
> > > > > > > Hi Tim
> > > > > > >
> > > > > > > On Wed, 15 May 2024 at 23:50, Tim Harvey <tharvey@gateworks.com> wrote:
> > > > > > > >
> > > > > > > > If RANDOMIZE_BASE is enabled in the Linux kernel instructing it to
> > > > > > > > randomize the virtual address at which the kernel image is loaded, it
> > > > > > > > expects entropy to be provided by the bootloader by populating
> > > > > > > > /chosen/kaslr-seed with a 64-bit value from source of entropy at boot.
> > > > > > >
> > > > > > > Since you'll send a v2, mind adding some description for UEFI on the
> > > > > > > commit message?
> > > > > > > efi_try_purge_kaslr_seed() has a comment of the behaviour
> > > > > > >
> > > > > >
> > > > > > Hi  Ilias,
> > > > > >
> > > > > > Ok, I will add the following to the commit log for clarity:
> > > > > > Note that the Kernel's EFI STUB only relies on EFI_RNG_PROTOCOL for
> > > > > > randomization and completely ignores the kaslr-seed for its own
> > > > > > randomness needs (i.e the randomization of the physical placement of
> > > > > > the kernel). It gets weeded out from the DTB that gets handed over via
> > > > > > efi_install_fdt() as it would also mess up the measured boot DTB TPM
> > > > > > measurements as well.
> > > > > >
> > > > > > Does the above mean that I don't need to worry about protecting the
> > > > > > call to fdt_kaslrseed() with a check for MEASURED BOOT as
> > > > > > efi_install_fdt/efi_try_purge_kaslr_seed always gets called in that
> > > > > > case?
> > > > >
> > > > > There are 2 ways to do measured boot. One is via the bootm command and
> > > > > the other is via the EFI protocols.
> > > > > CONFIG_MEASURED_BOOT  only applies to bootm.
> > > > > OTOH kaslr-seed might still have value if EFI_RNG is disabled, even
> > > > > when booting with EFI, since the kernel will randomize the virtual
> > > > > placement if it finds that.
> > > > >
> > > > > But in any case, a kaslr-seed entry can't be present in the DTB if you
> > > > > plan to measure it.
> > > >
> > > > ok, sounds like I need to use:
> > > >
> > > > if (IS_ENABLED(CONFIG_DM_RNG) &&
> > > > !IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)) &&
> > > > !IS_ENABLED(CONFIG_MEASURED_BOOT) {
> > > >   fdt_kaslrseed...
> > > > }
> > > >
> > >
> > > Can't we measure the DT *before* adding the kaslr-seed?
> > >
> >
> > You tell me... I'm deferring to you regarding what is needed for this
> > patch for measured boot.
> >
> > What changes do I need to make and why?
>
> Ok, thinking it a bit more we can't reliably measure the DT before a
> kaslr-seed gets injected, simply because an earlier stage bootloader
> might have injected it....  That's why we had a config option (and at
> least we mention it in aa2d3945ce6df43903d76cadde1c0669d6d5d43b but
> not in great detail).
> However, for a user that's far from ideal since he needs to be aware
> of those details before enabling measurements for the DT.
>
> Looking at our EFI code we *try* to purge the kaslr-seed before
> measuring the DT, but that doesn't guarantee it won't be there -- it
> will be purged only if EFI_RNG is installed. But that only happens if
> you have an RNG available.
> To make things even worse, the kaslr-seed is not the only source of
> randomness when measuring a DT, a mac address entry for example would
> have the same effect.

Right... I've noticed that as well. There are many things that alter
the dt and it seems like you need to be able to disable them all if
you're going to measure the fdt.

I'm no security expert but I can't really understand the point of
measuring the dtb anyway assuming your boot code has been
measured/verified and the boot code is the thing that is altering the
fdt so it's trusted right? Unless you are worried about uboot env
hacks but I disable uboot env when securing a device.

I recently put together a measured boot example for a user and for
that I measured boot firmware (the entire emmc boot0 device) and the
FIT image which contained the kernel, ramdisk, and 'pre-altered' dtb.

> On top of all these EFI code measures on PCR0 and bootm on PCR8. The
> reason for that is that although the EFI spec has no guidance on
> measuring a DT, it does have for ACPI and it uses PCR0 [0].
>
> I think all these should be fixed and at least documented properly for
> now, but that's unfair to you since it's irrelevant to what your patch
> is trying to fix ...
>

yes... needs more of a general fix that covers the dozen other things
that alter dtb.

> As for recommendations, I haven't looked into bootm code for quite
> some time. Can we inject kaslr-seed after we measure it? If yes, then
> do that and let's add a comment about the current mess...
>

I don't know anything about EFI but bootm (and booti/bootz I believe)
starts with image_setup_linux which calls image_setup_libfdt which
calls fdt_chosen (when I'm inserting the seed as its in the chosen
node), and finally near the end calls ft_board_setup and
ft_system_setup. There are a bunch of other calls to functions that
can alter dt as well in there.

I'm not aiming to get involved with EFI or CONFIG_MEASURED_BOOT. I'll
add a !IS_ENABLED(CONFIG_MEASURED_BOOT) but honestly I think that's
pointless as if you are in that function you are likely already
altering the dtb.

Best Regards,

Tim

>
> [0] https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClient_PFP_r1p05_v23_pub.pdf
> 3.3.4.1 PCR[0] – SRTM, POST BIOS, and Embedded Drivers
>
>
>
> >
> > Best Regards,
> >
> > Tim
> >
> > > Cheers
> > > /Ilias
> > > > Thanks,
> > > >
> > > > I'll send a v3 hopefully later today.
> > > >
> > > > Tim
> > > >
> > > > >
> > > > > Cheers
> > > > > /Ilias
> > > > >
> > > > > >
> > > > > > Best Regards,
> > > > > >
> > > > > > Tim
> > > > > >
> > > > > > > Thanks
> > > > > > > /Ilias
> > > > > > > >
> > > > > > > > If we have DM_RNG enabled populate this value automatically when
> > > > > > > > fdt_chosen is called unless ARMV8_SEC_FIRMWARE_SUPPORT is enabled as
> > > > > > > > it's implementation uses a different source of entropy.
> > > > > > > >
> > > > > > > > As this fdt node is added elsewhere create a library function and
> > > > > > > > use it to deduplicate code.
> > > > > > > >
> > > > > > > > Note that the kalsrseed command (CMD_KASLRSEED) is likely pointless now
> > > > > > > > but left in place in case boot scripts exist that rely on this command
> > > > > > > > existing and returning success. An informational message is printed to
> > > > > > > > alert users of this command that it is likely no longer needed.
> > > > > > > >
> > > > > > > > Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> > > > > > > > ---
> > > > > > > > v2:
> > > > > > > >  - fix typo in commit msg
> > > > > > > >  - use stack for seed to avoid unecessary malloc/free
> > > > > > > >  - move to a library function and deduplicate code by using it elsewhere
> > > > > > > > ---
> > > > > > > >  board/xilinx/common/board.c | 35 -----------------------------
> > > > > > > >  boot/fdt_support.c          | 10 +++++++++
> > > > > > > >  boot/pxe_utils.c            | 35 +++--------------------------
> > > > > > > >  cmd/kaslrseed.c             | 45 ++++++-------------------------------
> > > > > > > >  include/kaslrseed.h         | 17 ++++++++++++++
> > > > > > > >  lib/Makefile                |  1 +
> > > > > > > >  lib/kaslrseed.c             | 34 ++++++++++++++++++++++++++++
> > > > > > > >  7 files changed, 72 insertions(+), 105 deletions(-)
> > > > > > > >  create mode 100644 include/kaslrseed.h
> > > > > > > >  create mode 100644 lib/kaslrseed.c
> > > > > > > >
> > > > > > > > diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
> > > > > > > > index 30a81376ac41..f741e8957818 100644
> > > > > > > > --- a/board/xilinx/common/board.c
> > > > > > > > +++ b/board/xilinx/common/board.c
> > > > > > > > @@ -713,41 +713,6 @@ int ft_board_setup(void *blob, struct bd_info *bd)
> > > > > > > >         if (IS_ENABLED(CONFIG_FDT_FIXUP_PARTITIONS) && IS_ENABLED(CONFIG_NAND_ZYNQ))
> > > > > > > >                 fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
> > > > > > > >
> > > > > > > > -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> > > > > > > > -               debug("No RNG device\n");
> > > > > > > > -               return 0;
> > > > > > > > -       }
> > > > > > > > -
> > > > > > > > -       if (dm_rng_read(dev, buf, n)) {
> > > > > > > > -               debug("Reading RNG failed\n");
> > > > > > > > -               return 0;
> > > > > > > > -       }
> > > > > > > > -
> > > > > > > > -       if (!blob) {
> > > > > > > > -               debug("No FDT memory address configured. Please configure\n"
> > > > > > > > -                     "the FDT address via \"fdt addr <address>\" command.\n"
> > > > > > > > -                     "Aborting!\n");
> > > > > > > > -               return 0;
> > > > > > > > -       }
> > > > > > > > -
> > > > > > > > -       ret = fdt_check_header(blob);
> > > > > > > > -       if (ret < 0) {
> > > > > > > > -               debug("fdt_chosen: %s\n", fdt_strerror(ret));
> > > > > > > > -               return ret;
> > > > > > > > -       }
> > > > > > > > -
> > > > > > > > -       nodeoffset = fdt_find_or_add_subnode(blob, 0, "chosen");
> > > > > > > > -       if (nodeoffset < 0) {
> > > > > > > > -               debug("Reading chosen node failed\n");
> > > > > > > > -               return nodeoffset;
> > > > > > > > -       }
> > > > > > > > -
> > > > > > > > -       ret = fdt_setprop(blob, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> > > > > > > > -       if (ret < 0) {
> > > > > > > > -               debug("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
> > > > > > > > -               return ret;
> > > > > > > > -       }
> > > > > > > > -
> > > > > > > >         return 0;
> > > > > > > >  }
> > > > > > > >  #endif
> > > > > > > > diff --git a/boot/fdt_support.c b/boot/fdt_support.c
> > > > > > > > index 874ca4d6f5af..3455d60d69dc 100644
> > > > > > > > --- a/boot/fdt_support.c
> > > > > > > > +++ b/boot/fdt_support.c
> > > > > > > > @@ -8,6 +8,7 @@
> > > > > > > >
> > > > > > > >  #include <abuf.h>
> > > > > > > >  #include <env.h>
> > > > > > > > +#include <kaslrseed.h>
> > > > > > > >  #include <log.h>
> > > > > > > >  #include <mapmem.h>
> > > > > > > >  #include <net.h>
> > > > > > > > @@ -300,6 +301,15 @@ int fdt_chosen(void *fdt)
> > > > > > > >         if (nodeoffset < 0)
> > > > > > > >                 return nodeoffset;
> > > > > > > >
> > > > > > > > +       if (IS_ENABLED(CONFIG_DM_RNG) && !IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)) {
> > > > > > > > +               err = fdt_kaslrseed(fdt);
> > > > > > > > +               if (err) {
> > > > > > > > +                       printf("WARNING: could not set kaslr-seed %s.\n",
> > > > > > > > +                              fdt_strerror(err));
> > > > > > > > +                       return err;
> > > > > > > > +               }
> > > > > > > > +       }
> > > > > > > > +
> > > > > > > >         if (IS_ENABLED(CONFIG_BOARD_RNG_SEED) && !board_rng_seed(&buf)) {
> > > > > > > >                 err = fdt_setprop(fdt, nodeoffset, "rng-seed",
> > > > > > > >                                   abuf_data(&buf), abuf_size(&buf));
> > > > > > > > diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
> > > > > > > > index 4b22bb6f525a..8d70233fc08d 100644
> > > > > > > > --- a/boot/pxe_utils.c
> > > > > > > > +++ b/boot/pxe_utils.c
> > > > > > > > @@ -8,6 +8,7 @@
> > > > > > > >  #include <dm.h>
> > > > > > > >  #include <env.h>
> > > > > > > >  #include <image.h>
> > > > > > > > +#include <kaslrseed.h>
> > > > > > > >  #include <log.h>
> > > > > > > >  #include <malloc.h>
> > > > > > > >  #include <mapmem.h>
> > > > > > > > @@ -323,10 +324,6 @@ static void label_boot_kaslrseed(void)
> > > > > > > >  #if CONFIG_IS_ENABLED(DM_RNG)
> > > > > > > >         ulong fdt_addr;
> > > > > > > >         struct fdt_header *working_fdt;
> > > > > > > > -       size_t n = 0x8;
> > > > > > > > -       struct udevice *dev;
> > > > > > > > -       u64 *buf;
> > > > > > > > -       int nodeoffset;
> > > > > > > >         int err;
> > > > > > > >
> > > > > > > >         /* Get the main fdt and map it */
> > > > > > > > @@ -342,35 +339,9 @@ static void label_boot_kaslrseed(void)
> > > > > > > >         if (err <= 0)
> > > > > > > >                 return;
> > > > > > > >
> > > > > > > > -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> > > > > > > > -               printf("No RNG device\n");
> > > > > > > > -               return;
> > > > > > > > -       }
> > > > > > > > -
> > > > > > > > -       nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
> > > > > > > > -       if (nodeoffset < 0) {
> > > > > > > > -               printf("Reading chosen node failed\n");
> > > > > > > > -               return;
> > > > > > > > -       }
> > > > > > > > -
> > > > > > > > -       buf = malloc(n);
> > > > > > > > -       if (!buf) {
> > > > > > > > -               printf("Out of memory\n");
> > > > > > > > -               return;
> > > > > > > > -       }
> > > > > > > > -
> > > > > > > > -       if (dm_rng_read(dev, buf, n)) {
> > > > > > > > -               printf("Reading RNG failed\n");
> > > > > > > > -               goto err;
> > > > > > > > -       }
> > > > > > > > -
> > > > > > > > -       err = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> > > > > > > > -       if (err < 0) {
> > > > > > > > +       err = fdt_kaslrseed(working_fdt);
> > > > > > > > +       if (err < 0)
> > > > > > > >                 printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
> > > > > > > > -               goto err;
> > > > > > > > -       }
> > > > > > > > -err:
> > > > > > > > -       free(buf);
> > > > > > > >  #endif
> > > > > > > >         return;
> > > > > > > >  }
> > > > > > > > diff --git a/cmd/kaslrseed.c b/cmd/kaslrseed.c
> > > > > > > > index e0d3c7fe7489..ea5c07d729cf 100644
> > > > > > > > --- a/cmd/kaslrseed.c
> > > > > > > > +++ b/cmd/kaslrseed.c
> > > > > > > > @@ -9,33 +9,16 @@
> > > > > > > >  #include <command.h>
> > > > > > > >  #include <dm.h>
> > > > > > > >  #include <hexdump.h>
> > > > > > > > +#include <kaslrseed.h>
> > > > > > > >  #include <malloc.h>
> > > > > > > >  #include <rng.h>
> > > > > > > >  #include <fdt_support.h>
> > > > > > > >
> > > > > > > >  static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> > > > > > > >  {
> > > > > > > > -       size_t n = 0x8;
> > > > > > > > -       struct udevice *dev;
> > > > > > > > -       u64 *buf;
> > > > > > > > -       int nodeoffset;
> > > > > > > > -       int ret = CMD_RET_SUCCESS;
> > > > > > > > +       int err;
> > > > > > > >
> > > > > > > > -       if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> > > > > > > > -               printf("No RNG device\n");
> > > > > > > > -               return CMD_RET_FAILURE;
> > > > > > > > -       }
> > > > > > > > -
> > > > > > > > -       buf = malloc(n);
> > > > > > > > -       if (!buf) {
> > > > > > > > -               printf("Out of memory\n");
> > > > > > > > -               return CMD_RET_FAILURE;
> > > > > > > > -       }
> > > > > > > > -
> > > > > > > > -       if (dm_rng_read(dev, buf, n)) {
> > > > > > > > -               printf("Reading RNG failed\n");
> > > > > > > > -               return CMD_RET_FAILURE;
> > > > > > > > -       }
> > > > > > > > +       printf("Notice: a /chosen/kaslr-seed is automatically added to the device-tree when booted via booti/bootm/bootz therefore using this command is likely no longer needed");
> > > > > > > >
> > > > > > > >         if (!working_fdt) {
> > > > > > > >                 printf("No FDT memory address configured. Please configure\n"
> > > > > > > > @@ -44,27 +27,13 @@ static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const
> > > > > > > >                 return CMD_RET_FAILURE;
> > > > > > > >         }
> > > > > > > >
> > > > > > > > -       ret = fdt_check_header(working_fdt);
> > > > > > > > -       if (ret < 0) {
> > > > > > > > -               printf("fdt_chosen: %s\n", fdt_strerror(ret));
> > > > > > > > +       err = fdt_kaslrseed(working_fdt);
> > > > > > > > +       if (err < 0) {
> > > > > > > > +               printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
> > > > > > > >                 return CMD_RET_FAILURE;
> > > > > > > >         }
> > > > > > > >
> > > > > > > > -       nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
> > > > > > > > -       if (nodeoffset < 0) {
> > > > > > > > -               printf("Reading chosen node failed\n");
> > > > > > > > -               return CMD_RET_FAILURE;
> > > > > > > > -       }
> > > > > > > > -
> > > > > > > > -       ret = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> > > > > > > > -       if (ret < 0) {
> > > > > > > > -               printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
> > > > > > > > -               return CMD_RET_FAILURE;
> > > > > > > > -       }
> > > > > > > > -
> > > > > > > > -       free(buf);
> > > > > > > > -
> > > > > > > > -       return ret;
> > > > > > > > +       return CMD_RET_SUCCESS;
> > > > > > > >  }
> > > > > > > >
> > > > > > > >  U_BOOT_LONGHELP(kaslrseed,
> > > > > > > > diff --git a/include/kaslrseed.h b/include/kaslrseed.h
> > > > > > > > new file mode 100644
> > > > > > > > index 000000000000..3fe82f418acf
> > > > > > > > --- /dev/null
> > > > > > > > +++ b/include/kaslrseed.h
> > > > > > > > @@ -0,0 +1,17 @@
> > > > > > > > +/* SPDX-License-Identifier: GPL-2.0+ */
> > > > > > > > +/*
> > > > > > > > + * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
> > > > > > > > + */
> > > > > > > > +
> > > > > > > > +#if !defined _KASLRSEED_H_
> > > > > > > > +#define _KASLRSEED_H_
> > > > > > > > +
> > > > > > > > +/**
> > > > > > > > + * fdt_kaslrseed() - create a 'kaslr-seed' node in chosen
> > > > > > > > + *
> > > > > > > > + * @blob:      fdt blob
> > > > > > > > + * Return:     0 if OK, -ve on error
> > > > > > > > + */
> > > > > > > > +int fdt_kaslrseed(void *blob);
> > > > > > > > +
> > > > > > > > +#endif /* _KASLRSEED_H_ */
> > > > > > > > diff --git a/lib/Makefile b/lib/Makefile
> > > > > > > > index 2a76acf100d0..20a0242055fa 100644
> > > > > > > > --- a/lib/Makefile
> > > > > > > > +++ b/lib/Makefile
> > > > > > > > @@ -149,6 +149,7 @@ obj-y += date.o
> > > > > > > >  obj-y += rtc-lib.o
> > > > > > > >  obj-$(CONFIG_LIB_ELF) += elf.o
> > > > > > > >
> > > > > > > > +obj-$(CONFIG_DM_RNG) += kaslrseed.o
> > > > > > > >  obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += semihosting.o
> > > > > > > >
> > > > > > > >  #
> > > > > > > > diff --git a/lib/kaslrseed.c b/lib/kaslrseed.c
> > > > > > > > new file mode 100644
> > > > > > > > index 000000000000..ad06bee2b88d
> > > > > > > > --- /dev/null
> > > > > > > > +++ b/lib/kaslrseed.c
> > > > > > > > @@ -0,0 +1,34 @@
> > > > > > > > +// SPDX-License-Identifier: GPL-2.0+
> > > > > > > > +/*
> > > > > > > > + * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
> > > > > > > > + */
> > > > > > > > +#include <dm.h>
> > > > > > > > +#include <rng.h>
> > > > > > > > +#include <fdt_support.h>
> > > > > > > > +
> > > > > > > > +int fdt_kaslrseed(void *fdt)
> > > > > > > > +{
> > > > > > > > +       struct udevice *dev;
> > > > > > > > +       int nodeoffset;
> > > > > > > > +       u64 data;
> > > > > > > > +       int err;
> > > > > > > > +
> > > > > > > > +       err = fdt_check_header(fdt);
> > > > > > > > +       if (err < 0)
> > > > > > > > +               return err;
> > > > > > > > +
> > > > > > > > +       /* find or create "/chosen" node. */
> > > > > > > > +       nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
> > > > > > > > +       if (nodeoffset < 0)
> > > > > > > > +               return nodeoffset;
> > > > > > > > +
> > > > > > > > +       err = uclass_get_device(UCLASS_RNG, 0, &dev);
> > > > > > > > +       if (!err)
> > > > > > > > +               err = dm_rng_read(dev, &data, sizeof(data));
> > > > > > > > +       if (!err)
> > > > > > > > +               err = fdt_setprop(fdt, nodeoffset, "kaslr-seed", &data, sizeof(data));
> > > > > > > > +       if (err < 0)
> > > > > > > > +               printf("WARNING: could not set kaslr-seed %s.\n", fdt_strerror(err));
> > > > > > > > +
> > > > > > > > +       return err;
> > > > > > > > +}
> > > > > > > > --
> > > > > > > > 2.25.1
> > > > > > > >
diff mbox series

Patch

diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
index 30a81376ac41..f741e8957818 100644
--- a/board/xilinx/common/board.c
+++ b/board/xilinx/common/board.c
@@ -713,41 +713,6 @@  int ft_board_setup(void *blob, struct bd_info *bd)
 	if (IS_ENABLED(CONFIG_FDT_FIXUP_PARTITIONS) && IS_ENABLED(CONFIG_NAND_ZYNQ))
 		fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
 
-	if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
-		debug("No RNG device\n");
-		return 0;
-	}
-
-	if (dm_rng_read(dev, buf, n)) {
-		debug("Reading RNG failed\n");
-		return 0;
-	}
-
-	if (!blob) {
-		debug("No FDT memory address configured. Please configure\n"
-		      "the FDT address via \"fdt addr <address>\" command.\n"
-		      "Aborting!\n");
-		return 0;
-	}
-
-	ret = fdt_check_header(blob);
-	if (ret < 0) {
-		debug("fdt_chosen: %s\n", fdt_strerror(ret));
-		return ret;
-	}
-
-	nodeoffset = fdt_find_or_add_subnode(blob, 0, "chosen");
-	if (nodeoffset < 0) {
-		debug("Reading chosen node failed\n");
-		return nodeoffset;
-	}
-
-	ret = fdt_setprop(blob, nodeoffset, "kaslr-seed", buf, sizeof(buf));
-	if (ret < 0) {
-		debug("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
-		return ret;
-	}
-
 	return 0;
 }
 #endif
diff --git a/boot/fdt_support.c b/boot/fdt_support.c
index 874ca4d6f5af..3455d60d69dc 100644
--- a/boot/fdt_support.c
+++ b/boot/fdt_support.c
@@ -8,6 +8,7 @@ 
 
 #include <abuf.h>
 #include <env.h>
+#include <kaslrseed.h>
 #include <log.h>
 #include <mapmem.h>
 #include <net.h>
@@ -300,6 +301,15 @@  int fdt_chosen(void *fdt)
 	if (nodeoffset < 0)
 		return nodeoffset;
 
+	if (IS_ENABLED(CONFIG_DM_RNG) && !IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)) {
+		err = fdt_kaslrseed(fdt);
+		if (err) {
+			printf("WARNING: could not set kaslr-seed %s.\n",
+			       fdt_strerror(err));
+			return err;
+		}
+	}
+
 	if (IS_ENABLED(CONFIG_BOARD_RNG_SEED) && !board_rng_seed(&buf)) {
 		err = fdt_setprop(fdt, nodeoffset, "rng-seed",
 				  abuf_data(&buf), abuf_size(&buf));
diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
index 4b22bb6f525a..8d70233fc08d 100644
--- a/boot/pxe_utils.c
+++ b/boot/pxe_utils.c
@@ -8,6 +8,7 @@ 
 #include <dm.h>
 #include <env.h>
 #include <image.h>
+#include <kaslrseed.h>
 #include <log.h>
 #include <malloc.h>
 #include <mapmem.h>
@@ -323,10 +324,6 @@  static void label_boot_kaslrseed(void)
 #if CONFIG_IS_ENABLED(DM_RNG)
 	ulong fdt_addr;
 	struct fdt_header *working_fdt;
-	size_t n = 0x8;
-	struct udevice *dev;
-	u64 *buf;
-	int nodeoffset;
 	int err;
 
 	/* Get the main fdt and map it */
@@ -342,35 +339,9 @@  static void label_boot_kaslrseed(void)
 	if (err <= 0)
 		return;
 
-	if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
-		printf("No RNG device\n");
-		return;
-	}
-
-	nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
-	if (nodeoffset < 0) {
-		printf("Reading chosen node failed\n");
-		return;
-	}
-
-	buf = malloc(n);
-	if (!buf) {
-		printf("Out of memory\n");
-		return;
-	}
-
-	if (dm_rng_read(dev, buf, n)) {
-		printf("Reading RNG failed\n");
-		goto err;
-	}
-
-	err = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
-	if (err < 0) {
+	err = fdt_kaslrseed(working_fdt);
+	if (err < 0)
 		printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
-		goto err;
-	}
-err:
-	free(buf);
 #endif
 	return;
 }
diff --git a/cmd/kaslrseed.c b/cmd/kaslrseed.c
index e0d3c7fe7489..ea5c07d729cf 100644
--- a/cmd/kaslrseed.c
+++ b/cmd/kaslrseed.c
@@ -9,33 +9,16 @@ 
 #include <command.h>
 #include <dm.h>
 #include <hexdump.h>
+#include <kaslrseed.h>
 #include <malloc.h>
 #include <rng.h>
 #include <fdt_support.h>
 
 static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
-	size_t n = 0x8;
-	struct udevice *dev;
-	u64 *buf;
-	int nodeoffset;
-	int ret = CMD_RET_SUCCESS;
+	int err;
 
-	if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
-		printf("No RNG device\n");
-		return CMD_RET_FAILURE;
-	}
-
-	buf = malloc(n);
-	if (!buf) {
-		printf("Out of memory\n");
-		return CMD_RET_FAILURE;
-	}
-
-	if (dm_rng_read(dev, buf, n)) {
-		printf("Reading RNG failed\n");
-		return CMD_RET_FAILURE;
-	}
+	printf("Notice: a /chosen/kaslr-seed is automatically added to the device-tree when booted via booti/bootm/bootz therefore using this command is likely no longer needed");
 
 	if (!working_fdt) {
 		printf("No FDT memory address configured. Please configure\n"
@@ -44,27 +27,13 @@  static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const
 		return CMD_RET_FAILURE;
 	}
 
-	ret = fdt_check_header(working_fdt);
-	if (ret < 0) {
-		printf("fdt_chosen: %s\n", fdt_strerror(ret));
+	err = fdt_kaslrseed(working_fdt);
+	if (err < 0) {
+		printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
 		return CMD_RET_FAILURE;
 	}
 
-	nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
-	if (nodeoffset < 0) {
-		printf("Reading chosen node failed\n");
-		return CMD_RET_FAILURE;
-	}
-
-	ret = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
-	if (ret < 0) {
-		printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
-		return CMD_RET_FAILURE;
-	}
-
-	free(buf);
-
-	return ret;
+	return CMD_RET_SUCCESS;
 }
 
 U_BOOT_LONGHELP(kaslrseed,
diff --git a/include/kaslrseed.h b/include/kaslrseed.h
new file mode 100644
index 000000000000..3fe82f418acf
--- /dev/null
+++ b/include/kaslrseed.h
@@ -0,0 +1,17 @@ 
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
+ */
+
+#if !defined _KASLRSEED_H_
+#define _KASLRSEED_H_
+
+/**
+ * fdt_kaslrseed() - create a 'kaslr-seed' node in chosen
+ *
+ * @blob:	fdt blob
+ * Return:	0 if OK, -ve on error
+ */
+int fdt_kaslrseed(void *blob);
+
+#endif /* _KASLRSEED_H_ */
diff --git a/lib/Makefile b/lib/Makefile
index 2a76acf100d0..20a0242055fa 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -149,6 +149,7 @@  obj-y += date.o
 obj-y += rtc-lib.o
 obj-$(CONFIG_LIB_ELF) += elf.o
 
+obj-$(CONFIG_DM_RNG) += kaslrseed.o
 obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += semihosting.o
 
 #
diff --git a/lib/kaslrseed.c b/lib/kaslrseed.c
new file mode 100644
index 000000000000..ad06bee2b88d
--- /dev/null
+++ b/lib/kaslrseed.c
@@ -0,0 +1,34 @@ 
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2024 Tim Harvey <tharvey@gateworks.com>
+ */
+#include <dm.h>
+#include <rng.h>
+#include <fdt_support.h>
+
+int fdt_kaslrseed(void *fdt)
+{
+	struct udevice *dev;
+	int nodeoffset;
+	u64 data;
+	int err;
+
+	err = fdt_check_header(fdt);
+	if (err < 0)
+		return err;
+
+	/* find or create "/chosen" node. */
+	nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
+	if (nodeoffset < 0)
+		return nodeoffset;
+
+	err = uclass_get_device(UCLASS_RNG, 0, &dev);
+	if (!err)
+		err = dm_rng_read(dev, &data, sizeof(data));
+	if (!err)
+		err = fdt_setprop(fdt, nodeoffset, "kaslr-seed", &data, sizeof(data));
+	if (err < 0)
+		printf("WARNING: could not set kaslr-seed %s.\n", fdt_strerror(err));
+
+	return err;
+}