OSDN Git Service

bootconfig: Add bootconfig magic word for indicating bootconfig explicitly
authorMasami Hiramatsu <mhiramat@kernel.org>
Thu, 20 Feb 2020 12:18:42 +0000 (21:18 +0900)
committerSteven Rostedt (VMware) <rostedt@goodmis.org>
Thu, 20 Feb 2020 22:52:34 +0000 (17:52 -0500)
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>
Documentation/admin-guide/bootconfig.rst
include/linux/bootconfig.h
init/Kconfig
init/main.c
tools/bootconfig/main.c
tools/bootconfig/test-bootconfig.sh

index b342a67..5e76099 100644 (file)
@@ -102,9 +102,13 @@ Boot Kernel With a Boot Config
 ==============================
 
 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
-the last part of the initrd image in memory to get the boot configuration
-data.
+to the end of the initrd (initramfs) image file with size, checksum and
+12-byte magic word as below.
+
+[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
 update the boot loader and the kernel image itself.
 
index 7e18c93..d11e183 100644 (file)
@@ -10,6 +10,9 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 
+#define BOOTCONFIG_MAGIC       "#BOOTCONFIG\n"
+#define BOOTCONFIG_MAGIC_LEN   12
+
 /* XBC tree node */
 struct xbc_node {
        u16 next;
index f586878..a84e7aa 100644 (file)
@@ -1222,7 +1222,7 @@ config BOOT_CONFIG
          Extra boot config allows system admin to pass a config file as
          complemental extension of kernel cmdline when booting.
          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.
 
          If unsure, say Y.
index d96cc5f..2fe8dec 100644 (file)
@@ -374,7 +374,11 @@ static void __init setup_boot_config(const char *cmdline)
        if (!initrd_end)
                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];
        csum = hdr[1];
 
index e18eeb0..742271f 100644 (file)
@@ -131,15 +131,26 @@ int load_xbc_from_initrd(int fd, char **buf)
        struct stat stat;
        int ret;
        u32 size = 0, csum = 0, rcsum;
+       char magic[BOOTCONFIG_MAGIC_LEN];
 
        ret = fstat(fd, &stat);
        if (ret < 0)
                return -errno;
 
-       if (stat.st_size < 8)
+       if (stat.st_size < 8 + BOOTCONFIG_MAGIC_LEN)
                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);
                return -errno;
        }
@@ -150,11 +161,14 @@ int load_xbc_from_initrd(int fd, char **buf)
        if (read(fd, &csum, sizeof(u32)) < 0)
                return -errno;
 
-       /* Wrong size, maybe no boot config here */
-       if (stat.st_size < size + 8)
-               return 0;
+       /* Wrong size error  */
+       if (stat.st_size < size + 8 + BOOTCONFIG_MAGIC_LEN) {
+               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);
                return -errno;
        }
@@ -163,17 +177,17 @@ int load_xbc_from_initrd(int fd, char **buf)
        if (ret < 0)
                return ret;
 
-       /* Wrong Checksum, maybe no boot config here */
+       /* Wrong Checksum */
        rcsum = checksum((unsigned char *)*buf, size);
        if (csum != rcsum) {
                pr_err("checksum error: %d != %d\n", csum, rcsum);
-               return 0;
+               return -EINVAL;
        }
 
        ret = xbc_init(*buf);
-       /* Wrong data, maybe no boot config here */
+       /* Wrong data */
        if (ret < 0)
-               return 0;
+               return ret;
 
        return size;
 }
@@ -226,7 +240,8 @@ int delete_xbc(const char *path)
        } else if (size > 0) {
                ret = fstat(fd, &stat);
                if (!ret)
-                       ret = ftruncate(fd, stat.st_size - size - 8);
+                       ret = ftruncate(fd, stat.st_size
+                                       - size - 8 - BOOTCONFIG_MAGIC_LEN);
                if (ret)
                        ret = -errno;
        } /* 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);
                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);
        free(data);
 
index 1de06de..adafb7c 100755 (executable)
@@ -49,7 +49,7 @@ xpass $BOOTCONF -a $TEMPCONF $INITRD
 new_size=$(stat -c %s $INITRD)
 
 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"
 xpass $BOOTCONF -a $TEMPCONF $INITRD