bootconfig: Add bootconfig magic word for indicating bootconfig explicitly

Add bootconfig magic word to the end of bootconfig on initrd
image for indicating explicitly the bootconfig is there.
Also tools/bootconfig treats wrong size or wrong checksum or
parse error as an error, because if there is a bootconfig magic
word, there must be a bootconfig.

The bootconfig magic word is "#BOOTCONFIG\n", 12 bytes word.
Thus the block image of the initrd file with bootconfig is
as follows.

[Initrd][bootconfig][size][csum][#BOOTCONFIG\n]

Link: http://lkml.kernel.org/r/158220112263.26565.3944814205960612841.stgit@devnote2

Suggested-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
This commit is contained in:
Masami Hiramatsu 2020-02-20 21:18:42 +09:00 committed by Steven Rostedt (VMware)
parent d8a953ddde
commit 85c46b78da
6 changed files with 49 additions and 17 deletions

View File

@ -102,9 +102,13 @@ Boot Kernel With a Boot Config
============================== ==============================
Since the boot configuration file is loaded with initrd, it will be added Since the boot configuration file is loaded with initrd, it will be added
to the end of the initrd (initramfs) image file. The Linux kernel decodes to the end of the initrd (initramfs) image file with size, checksum and
the last part of the initrd image in memory to get the boot configuration 12-byte magic word as below.
data.
[initrd][bootconfig][size(u32)][checksum(u32)][#BOOTCONFIG\n]
The Linux kernel decodes the last part of the initrd image in memory to
get the boot configuration data.
Because of this "piggyback" method, there is no need to change or Because of this "piggyback" method, there is no need to change or
update the boot loader and the kernel image itself. update the boot loader and the kernel image itself.

View File

@ -10,6 +10,9 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/types.h> #include <linux/types.h>
#define BOOTCONFIG_MAGIC "#BOOTCONFIG\n"
#define BOOTCONFIG_MAGIC_LEN 12
/* XBC tree node */ /* XBC tree node */
struct xbc_node { struct xbc_node {
u16 next; u16 next;

View File

@ -1222,7 +1222,7 @@ config BOOT_CONFIG
Extra boot config allows system admin to pass a config file as Extra boot config allows system admin to pass a config file as
complemental extension of kernel cmdline when booting. complemental extension of kernel cmdline when booting.
The boot config file must be attached at the end of initramfs The boot config file must be attached at the end of initramfs
with checksum and size. with checksum, size and magic word.
See <file:Documentation/admin-guide/bootconfig.rst> for details. See <file:Documentation/admin-guide/bootconfig.rst> for details.
If unsure, say Y. If unsure, say Y.

View File

@ -374,7 +374,11 @@ static void __init setup_boot_config(const char *cmdline)
if (!initrd_end) if (!initrd_end)
goto not_found; goto not_found;
hdr = (u32 *)(initrd_end - 8); data = (char *)initrd_end - BOOTCONFIG_MAGIC_LEN;
if (memcmp(data, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN))
goto not_found;
hdr = (u32 *)(data - 8);
size = hdr[0]; size = hdr[0];
csum = hdr[1]; csum = hdr[1];

View File

@ -131,15 +131,26 @@ int load_xbc_from_initrd(int fd, char **buf)
struct stat stat; struct stat stat;
int ret; int ret;
u32 size = 0, csum = 0, rcsum; u32 size = 0, csum = 0, rcsum;
char magic[BOOTCONFIG_MAGIC_LEN];
ret = fstat(fd, &stat); ret = fstat(fd, &stat);
if (ret < 0) if (ret < 0)
return -errno; return -errno;
if (stat.st_size < 8) if (stat.st_size < 8 + BOOTCONFIG_MAGIC_LEN)
return 0; return 0;
if (lseek(fd, -8, SEEK_END) < 0) { if (lseek(fd, -BOOTCONFIG_MAGIC_LEN, SEEK_END) < 0) {
pr_err("Failed to lseek: %d\n", -errno);
return -errno;
}
if (read(fd, magic, BOOTCONFIG_MAGIC_LEN) < 0)
return -errno;
/* Check the bootconfig magic bytes */
if (memcmp(magic, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN) != 0)
return 0;
if (lseek(fd, -(8 + BOOTCONFIG_MAGIC_LEN), SEEK_END) < 0) {
pr_err("Failed to lseek: %d\n", -errno); pr_err("Failed to lseek: %d\n", -errno);
return -errno; return -errno;
} }
@ -150,11 +161,14 @@ int load_xbc_from_initrd(int fd, char **buf)
if (read(fd, &csum, sizeof(u32)) < 0) if (read(fd, &csum, sizeof(u32)) < 0)
return -errno; return -errno;
/* Wrong size, maybe no boot config here */ /* Wrong size error */
if (stat.st_size < size + 8) if (stat.st_size < size + 8 + BOOTCONFIG_MAGIC_LEN) {
return 0; pr_err("bootconfig size is too big\n");
return -E2BIG;
}
if (lseek(fd, stat.st_size - 8 - size, SEEK_SET) < 0) { if (lseek(fd, stat.st_size - (size + 8 + BOOTCONFIG_MAGIC_LEN),
SEEK_SET) < 0) {
pr_err("Failed to lseek: %d\n", -errno); pr_err("Failed to lseek: %d\n", -errno);
return -errno; return -errno;
} }
@ -163,17 +177,17 @@ int load_xbc_from_initrd(int fd, char **buf)
if (ret < 0) if (ret < 0)
return ret; return ret;
/* Wrong Checksum, maybe no boot config here */ /* Wrong Checksum */
rcsum = checksum((unsigned char *)*buf, size); rcsum = checksum((unsigned char *)*buf, size);
if (csum != rcsum) { if (csum != rcsum) {
pr_err("checksum error: %d != %d\n", csum, rcsum); pr_err("checksum error: %d != %d\n", csum, rcsum);
return 0; return -EINVAL;
} }
ret = xbc_init(*buf); ret = xbc_init(*buf);
/* Wrong data, maybe no boot config here */ /* Wrong data */
if (ret < 0) if (ret < 0)
return 0; return ret;
return size; return size;
} }
@ -226,7 +240,8 @@ int delete_xbc(const char *path)
} else if (size > 0) { } else if (size > 0) {
ret = fstat(fd, &stat); ret = fstat(fd, &stat);
if (!ret) if (!ret)
ret = ftruncate(fd, stat.st_size - size - 8); ret = ftruncate(fd, stat.st_size
- size - 8 - BOOTCONFIG_MAGIC_LEN);
if (ret) if (ret)
ret = -errno; ret = -errno;
} /* Ignore if there is no boot config in initrd */ } /* Ignore if there is no boot config in initrd */
@ -295,6 +310,12 @@ int apply_xbc(const char *path, const char *xbc_path)
pr_err("Failed to apply a boot config: %d\n", ret); pr_err("Failed to apply a boot config: %d\n", ret);
return ret; return ret;
} }
/* Write a magic word of the bootconfig */
ret = write(fd, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN);
if (ret < 0) {
pr_err("Failed to apply a boot config magic: %d\n", ret);
return ret;
}
close(fd); close(fd);
free(data); free(data);

View File

@ -49,7 +49,7 @@ xpass $BOOTCONF -a $TEMPCONF $INITRD
new_size=$(stat -c %s $INITRD) new_size=$(stat -c %s $INITRD)
echo "File size check" echo "File size check"
xpass test $new_size -eq $(expr $bconf_size + $initrd_size + 9) xpass test $new_size -eq $(expr $bconf_size + $initrd_size + 9 + 12)
echo "Apply command repeat test" echo "Apply command repeat test"
xpass $BOOTCONF -a $TEMPCONF $INITRD xpass $BOOTCONF -a $TEMPCONF $INITRD