diff mbox series

add kaslr-seed generation to extlinux.conf

Message ID tencent_DDDF45F7D8537BA60D9974E7446D83994106@qq.com
State Superseded
Delegated to: Tom Rini
Headers show
Series add kaslr-seed generation to extlinux.conf | expand

Commit Message

Zhang Ning Jan. 29, 2022, 2:06 a.m. UTC
add kaslrseed key word to extlinux.conf,
which means generate kaslr-seed for linux

with this patch exlinux.conf boot item looks like

label l0
        menu testing
        linux /boot/vmlinuz-5.15.16-arm
        initrd /boot/initramfs-5.15.16-arm.img
        fdtdir /boot/dtbs/5.15.16-arm/
        kaslrseed
        append root=UUID=92ae1e50-eeeb-4c5b-8939-7e1cd6cfb059 ro

Signed-off-by: Zhang Ning <zhangn1985@qq.com>
---
 boot/pxe_utils.c    | 69 +++++++++++++++++++++++++++++++++++++++++++++
 include/pxe_utils.h |  2 ++
 2 files changed, 71 insertions(+)

Comments

Ilias Apalodimas Jan. 29, 2022, 1:04 p.m. UTC | #1
Hi Zhang,

On Sat, Jan 29, 2022 at 10:06:53AM +0800, Zhang Ning wrote:
> add kaslrseed key word to extlinux.conf,
> which means generate kaslr-seed for linux
> 
> with this patch exlinux.conf boot item looks like

I am not too familiar with the extlinux stuff in U-Boot.  Does that boot
with efi or not?  On the efi booting kaslr-seed is close to useless for
linux.  In fact we explicitly strip it when booting with EFI and and RNG 
hardware is available. 

The EFI stub ignores it and uses the EFI_RNG_PROTOCOL. Since you
rely on an rng device to generate it the EFI_RNG_PROTOCOL will be
installed. 

> 
> label l0
>         menu testing
>         linux /boot/vmlinuz-5.15.16-arm
>         initrd /boot/initramfs-5.15.16-arm.img
>         fdtdir /boot/dtbs/5.15.16-arm/
>         kaslrseed
>         append root=UUID=92ae1e50-eeeb-4c5b-8939-7e1cd6cfb059 ro
> 
> Signed-off-by: Zhang Ning <zhangn1985@qq.com>
> ---
>  boot/pxe_utils.c    | 69 +++++++++++++++++++++++++++++++++++++++++++++
>  include/pxe_utils.h |  2 ++
>  2 files changed, 71 insertions(+)
> 
> diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
> index bb231b11a2..c7c422926e 100644
> --- a/boot/pxe_utils.c
> +++ b/boot/pxe_utils.c
> @@ -20,6 +20,11 @@
>  #include <errno.h>
>  #include <linux/list.h>
>  
> +#ifdef CONFIG_DM_RNG
> +#include <dm.h>
> +#include <rng.h>
> +#endif
> +
>  #include <splash.h>
>  #include <asm/io.h>
>  
> @@ -311,6 +316,61 @@ static int label_localboot(struct pxe_label *label)
>  	return run_command_list(localcmd, strlen(localcmd), 0);
>  }
>  
> +/*
> + * label_boot_kaslrseed generate kaslrseed from hw rng
> + */
> +
> +static void label_boot_kaslrseed(void)
> +{
> +#ifdef CONFIG_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 */
> +	fdt_addr = hextoul(env_get("fdt_addr_r"), NULL);
> +	working_fdt = map_sysmem(fdt_addr, 0);
> +	err = fdt_check_header(working_fdt);
> +	if (err)
> +		return;
> +
> +	if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> +		printf("No RNG device\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");
> +		return;
> +	}
> +
> +	nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
> +	if (nodeoffset < 0) {
> +		printf("Reading chosen node failed\n");
> +		return;
> +	}
> +
> +	err = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> +	if (err < 0) {
> +		printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
> +		return;
> +	}

Almost all of the return cases fail to free the buffer.  I'd write that a
bit differently as well.  Just allocate the buffer *after* you made sure
the hardware and required nodes are there.

Regards
/Ilias
> +
> +	free(buf);
> +#endif
> +	return;
> +}
> +
>  /**
>   * label_boot_fdtoverlay() - Loads fdt overlays specified in 'fdtoverlays'
>   *
> @@ -631,6 +691,9 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
>  				}
>  			}
>  
> +		if (label->kaslrseed)
> +			label_boot_kaslrseed();
> +
>  #ifdef CONFIG_OF_LIBFDT_OVERLAY
>  			if (label->fdtoverlays)
>  				label_boot_fdtoverlay(ctx, label);
> @@ -710,6 +773,7 @@ enum token_type {
>  	T_ONTIMEOUT,
>  	T_IPAPPEND,
>  	T_BACKGROUND,
> +	T_KASLRSEED,
>  	T_INVALID
>  };
>  
> @@ -741,6 +805,7 @@ static const struct token keywords[] = {
>  	{"ontimeout", T_ONTIMEOUT,},
>  	{"ipappend", T_IPAPPEND,},
>  	{"background", T_BACKGROUND,},
> +	{"kaslrseed", T_KASLRSEED,},
>  	{NULL, T_INVALID}
>  };
>  
> @@ -1194,6 +1259,10 @@ static int parse_label(char **c, struct pxe_menu *cfg)
>  			err = parse_integer(c, &label->ipappend);
>  			break;
>  
> +		case T_KASLRSEED:
> +			label->kaslrseed = 1;
> +			break;
> +
>  		case T_EOL:
>  			break;
>  
> diff --git a/include/pxe_utils.h b/include/pxe_utils.h
> index dad2668818..4a73b2aace 100644
> --- a/include/pxe_utils.h
> +++ b/include/pxe_utils.h
> @@ -33,6 +33,7 @@
>   * initrd - path to the initrd to use for this label.
>   * attempted - 0 if we haven't tried to boot this label, 1 if we have.
>   * localboot - 1 if this label specified 'localboot', 0 otherwise.
> + * kaslrseed - 1 if generate kaslrseed from hw_rng
>   * list - lets these form a list, which a pxe_menu struct will hold.
>   */
>  struct pxe_label {
> @@ -50,6 +51,7 @@ struct pxe_label {
>  	int attempted;
>  	int localboot;
>  	int localboot_val;
> +	int kaslrseed;
>  	struct list_head list;
>  };
>  
> -- 
> 2.34.1
>
ning Jan. 29, 2022, 3:40 p.m. UTC | #2
On Sat, Jan 29, 2022 at 03:04:48PM +0200, Ilias Apalodimas wrote:
> Hi Zhang,
> 
> On Sat, Jan 29, 2022 at 10:06:53AM +0800, Zhang Ning wrote:
> > add kaslrseed key word to extlinux.conf,
> > which means generate kaslr-seed for linux
> > 
> > with this patch exlinux.conf boot item looks like
> 
> I am not too familiar with the extlinux stuff in U-Boot.  Does that boot
> with efi or not?  On the efi booting kaslr-seed is close to useless for
> linux.  In fact we explicitly strip it when booting with EFI and and RNG 
> hardware is available. 
> 
> The EFI stub ignores it and uses the EFI_RNG_PROTOCOL. Since you
> rely on an rng device to generate it the EFI_RNG_PROTOCOL will be
> installed. 

thank you for your review.

extlinux is same as bootm cmd in uboot cmdline, thus no relationship with EFI boot.
I checked my old Uboot for khadas VIM, EFI_RNG_PROTOCOL is set, and kernel EFI_STUB
is set, and I use extlinux.conf, kernel still complain no kalsr seed.

> 
> > 
> > label l0
> >         menu testing
> >         linux /boot/vmlinuz-5.15.16-arm
> >         initrd /boot/initramfs-5.15.16-arm.img
> >         fdtdir /boot/dtbs/5.15.16-arm/
> >         kaslrseed
> >         append root=UUID=92ae1e50-eeeb-4c5b-8939-7e1cd6cfb059 ro
> > 
> > Signed-off-by: Zhang Ning <zhangn1985@qq.com>
> > ---
> >  boot/pxe_utils.c    | 69 +++++++++++++++++++++++++++++++++++++++++++++
> >  include/pxe_utils.h |  2 ++
> >  2 files changed, 71 insertions(+)
> > 
> > diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
> > index bb231b11a2..c7c422926e 100644
> > --- a/boot/pxe_utils.c
> > +++ b/boot/pxe_utils.c
> > @@ -20,6 +20,11 @@
> >  #include <errno.h>
> >  #include <linux/list.h>
> >  
> > +#ifdef CONFIG_DM_RNG
> > +#include <dm.h>
> > +#include <rng.h>
> > +#endif
> > +
> >  #include <splash.h>
> >  #include <asm/io.h>
> >  
> > @@ -311,6 +316,61 @@ static int label_localboot(struct pxe_label *label)
> >  	return run_command_list(localcmd, strlen(localcmd), 0);
> >  }
> >  
> > +/*
> > + * label_boot_kaslrseed generate kaslrseed from hw rng
> > + */
> > +
> > +static void label_boot_kaslrseed(void)
> > +{
> > +#ifdef CONFIG_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 */
> > +	fdt_addr = hextoul(env_get("fdt_addr_r"), NULL);
> > +	working_fdt = map_sysmem(fdt_addr, 0);
> > +	err = fdt_check_header(working_fdt);
> > +	if (err)
> > +		return;
> > +
> > +	if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
> > +		printf("No RNG device\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");
> > +		return;
> > +	}
> > +
> > +	nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
> > +	if (nodeoffset < 0) {
> > +		printf("Reading chosen node failed\n");
> > +		return;
> > +	}
> > +
> > +	err = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
> > +	if (err < 0) {
> > +		printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
> > +		return;
> > +	}
> 
> Almost all of the return cases fail to free the buffer.  I'd write that a
> bit differently as well.  Just allocate the buffer *after* you made sure
> the hardware and required nodes are there.
> 
these code are copied from cmd/kalsrseed.c, I will add buff free in next version.

> Regards
> /Ilias
> > +
> > +	free(buf);
> > +#endif
> > +	return;
> > +}
> > +
> >  /**
> >   * label_boot_fdtoverlay() - Loads fdt overlays specified in 'fdtoverlays'
> >   *
> > @@ -631,6 +691,9 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
> >  				}
> >  			}
> >  
> > +		if (label->kaslrseed)
> > +			label_boot_kaslrseed();
> > +
> >  #ifdef CONFIG_OF_LIBFDT_OVERLAY
> >  			if (label->fdtoverlays)
> >  				label_boot_fdtoverlay(ctx, label);
> > @@ -710,6 +773,7 @@ enum token_type {
> >  	T_ONTIMEOUT,
> >  	T_IPAPPEND,
> >  	T_BACKGROUND,
> > +	T_KASLRSEED,
> >  	T_INVALID
> >  };
> >  
> > @@ -741,6 +805,7 @@ static const struct token keywords[] = {
> >  	{"ontimeout", T_ONTIMEOUT,},
> >  	{"ipappend", T_IPAPPEND,},
> >  	{"background", T_BACKGROUND,},
> > +	{"kaslrseed", T_KASLRSEED,},
> >  	{NULL, T_INVALID}
> >  };
> >  
> > @@ -1194,6 +1259,10 @@ static int parse_label(char **c, struct pxe_menu *cfg)
> >  			err = parse_integer(c, &label->ipappend);
> >  			break;
> >  
> > +		case T_KASLRSEED:
> > +			label->kaslrseed = 1;
> > +			break;
> > +
> >  		case T_EOL:
> >  			break;
> >  
> > diff --git a/include/pxe_utils.h b/include/pxe_utils.h
> > index dad2668818..4a73b2aace 100644
> > --- a/include/pxe_utils.h
> > +++ b/include/pxe_utils.h
> > @@ -33,6 +33,7 @@
> >   * initrd - path to the initrd to use for this label.
> >   * attempted - 0 if we haven't tried to boot this label, 1 if we have.
> >   * localboot - 1 if this label specified 'localboot', 0 otherwise.
> > + * kaslrseed - 1 if generate kaslrseed from hw_rng
> >   * list - lets these form a list, which a pxe_menu struct will hold.
> >   */
> >  struct pxe_label {
> > @@ -50,6 +51,7 @@ struct pxe_label {
> >  	int attempted;
> >  	int localboot;
> >  	int localboot_val;
> > +	int kaslrseed;
> >  	struct list_head list;
> >  };
> >  
> > -- 
> > 2.34.1
> >
diff mbox series

Patch

diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
index bb231b11a2..c7c422926e 100644
--- a/boot/pxe_utils.c
+++ b/boot/pxe_utils.c
@@ -20,6 +20,11 @@ 
 #include <errno.h>
 #include <linux/list.h>
 
+#ifdef CONFIG_DM_RNG
+#include <dm.h>
+#include <rng.h>
+#endif
+
 #include <splash.h>
 #include <asm/io.h>
 
@@ -311,6 +316,61 @@  static int label_localboot(struct pxe_label *label)
 	return run_command_list(localcmd, strlen(localcmd), 0);
 }
 
+/*
+ * label_boot_kaslrseed generate kaslrseed from hw rng
+ */
+
+static void label_boot_kaslrseed(void)
+{
+#ifdef CONFIG_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 */
+	fdt_addr = hextoul(env_get("fdt_addr_r"), NULL);
+	working_fdt = map_sysmem(fdt_addr, 0);
+	err = fdt_check_header(working_fdt);
+	if (err)
+		return;
+
+	if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
+		printf("No RNG device\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");
+		return;
+	}
+
+	nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
+	if (nodeoffset < 0) {
+		printf("Reading chosen node failed\n");
+		return;
+	}
+
+	err = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
+	if (err < 0) {
+		printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
+		return;
+	}
+
+	free(buf);
+#endif
+	return;
+}
+
 /**
  * label_boot_fdtoverlay() - Loads fdt overlays specified in 'fdtoverlays'
  *
@@ -631,6 +691,9 @@  static int label_boot(struct pxe_context *ctx, struct pxe_label *label)
 				}
 			}
 
+		if (label->kaslrseed)
+			label_boot_kaslrseed();
+
 #ifdef CONFIG_OF_LIBFDT_OVERLAY
 			if (label->fdtoverlays)
 				label_boot_fdtoverlay(ctx, label);
@@ -710,6 +773,7 @@  enum token_type {
 	T_ONTIMEOUT,
 	T_IPAPPEND,
 	T_BACKGROUND,
+	T_KASLRSEED,
 	T_INVALID
 };
 
@@ -741,6 +805,7 @@  static const struct token keywords[] = {
 	{"ontimeout", T_ONTIMEOUT,},
 	{"ipappend", T_IPAPPEND,},
 	{"background", T_BACKGROUND,},
+	{"kaslrseed", T_KASLRSEED,},
 	{NULL, T_INVALID}
 };
 
@@ -1194,6 +1259,10 @@  static int parse_label(char **c, struct pxe_menu *cfg)
 			err = parse_integer(c, &label->ipappend);
 			break;
 
+		case T_KASLRSEED:
+			label->kaslrseed = 1;
+			break;
+
 		case T_EOL:
 			break;
 
diff --git a/include/pxe_utils.h b/include/pxe_utils.h
index dad2668818..4a73b2aace 100644
--- a/include/pxe_utils.h
+++ b/include/pxe_utils.h
@@ -33,6 +33,7 @@ 
  * initrd - path to the initrd to use for this label.
  * attempted - 0 if we haven't tried to boot this label, 1 if we have.
  * localboot - 1 if this label specified 'localboot', 0 otherwise.
+ * kaslrseed - 1 if generate kaslrseed from hw_rng
  * list - lets these form a list, which a pxe_menu struct will hold.
  */
 struct pxe_label {
@@ -50,6 +51,7 @@  struct pxe_label {
 	int attempted;
 	int localboot;
 	int localboot_val;
+	int kaslrseed;
 	struct list_head list;
 };