Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Masami Hiramatsu and committed by
Steven Rostedt (VMware)
85c46b78 d8a953dd

+49 -17
+7 -3
Documentation/admin-guide/bootconfig.rst
··· 102 102 ============================== 103 103 104 104 Since the boot configuration file is loaded with initrd, it will be added 105 - to the end of the initrd (initramfs) image file. The Linux kernel decodes 106 - the last part of the initrd image in memory to get the boot configuration 107 - data. 105 + to the end of the initrd (initramfs) image file with size, checksum and 106 + 12-byte magic word as below. 107 + 108 + [initrd][bootconfig][size(u32)][checksum(u32)][#BOOTCONFIG\n] 109 + 110 + The Linux kernel decodes the last part of the initrd image in memory to 111 + get the boot configuration data. 108 112 Because of this "piggyback" method, there is no need to change or 109 113 update the boot loader and the kernel image itself. 110 114
+3
include/linux/bootconfig.h
··· 10 10 #include <linux/kernel.h> 11 11 #include <linux/types.h> 12 12 13 + #define BOOTCONFIG_MAGIC "#BOOTCONFIG\n" 14 + #define BOOTCONFIG_MAGIC_LEN 12 15 + 13 16 /* XBC tree node */ 14 17 struct xbc_node { 15 18 u16 next;
+1 -1
init/Kconfig
··· 1222 1222 Extra boot config allows system admin to pass a config file as 1223 1223 complemental extension of kernel cmdline when booting. 1224 1224 The boot config file must be attached at the end of initramfs 1225 - with checksum and size. 1225 + with checksum, size and magic word. 1226 1226 See <file:Documentation/admin-guide/bootconfig.rst> for details. 1227 1227 1228 1228 If unsure, say Y.
+5 -1
init/main.c
··· 374 374 if (!initrd_end) 375 375 goto not_found; 376 376 377 - hdr = (u32 *)(initrd_end - 8); 377 + data = (char *)initrd_end - BOOTCONFIG_MAGIC_LEN; 378 + if (memcmp(data, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN)) 379 + goto not_found; 380 + 381 + hdr = (u32 *)(data - 8); 378 382 size = hdr[0]; 379 383 csum = hdr[1]; 380 384
+32 -11
tools/bootconfig/main.c
··· 131 131 struct stat stat; 132 132 int ret; 133 133 u32 size = 0, csum = 0, rcsum; 134 + char magic[BOOTCONFIG_MAGIC_LEN]; 134 135 135 136 ret = fstat(fd, &stat); 136 137 if (ret < 0) 137 138 return -errno; 138 139 139 - if (stat.st_size < 8) 140 + if (stat.st_size < 8 + BOOTCONFIG_MAGIC_LEN) 140 141 return 0; 141 142 142 - if (lseek(fd, -8, SEEK_END) < 0) { 143 + if (lseek(fd, -BOOTCONFIG_MAGIC_LEN, SEEK_END) < 0) { 144 + pr_err("Failed to lseek: %d\n", -errno); 145 + return -errno; 146 + } 147 + if (read(fd, magic, BOOTCONFIG_MAGIC_LEN) < 0) 148 + return -errno; 149 + /* Check the bootconfig magic bytes */ 150 + if (memcmp(magic, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN) != 0) 151 + return 0; 152 + 153 + if (lseek(fd, -(8 + BOOTCONFIG_MAGIC_LEN), SEEK_END) < 0) { 143 154 pr_err("Failed to lseek: %d\n", -errno); 144 155 return -errno; 145 156 } ··· 161 150 if (read(fd, &csum, sizeof(u32)) < 0) 162 151 return -errno; 163 152 164 - /* Wrong size, maybe no boot config here */ 165 - if (stat.st_size < size + 8) 166 - return 0; 153 + /* Wrong size error */ 154 + if (stat.st_size < size + 8 + BOOTCONFIG_MAGIC_LEN) { 155 + pr_err("bootconfig size is too big\n"); 156 + return -E2BIG; 157 + } 167 158 168 - if (lseek(fd, stat.st_size - 8 - size, SEEK_SET) < 0) { 159 + if (lseek(fd, stat.st_size - (size + 8 + BOOTCONFIG_MAGIC_LEN), 160 + SEEK_SET) < 0) { 169 161 pr_err("Failed to lseek: %d\n", -errno); 170 162 return -errno; 171 163 } ··· 177 163 if (ret < 0) 178 164 return ret; 179 165 180 - /* Wrong Checksum, maybe no boot config here */ 166 + /* Wrong Checksum */ 181 167 rcsum = checksum((unsigned char *)*buf, size); 182 168 if (csum != rcsum) { 183 169 pr_err("checksum error: %d != %d\n", csum, rcsum); 184 - return 0; 170 + return -EINVAL; 185 171 } 186 172 187 173 ret = xbc_init(*buf); 188 - /* Wrong data, maybe no boot config here */ 174 + /* Wrong data */ 189 175 if (ret < 0) 190 - return 0; 176 + return ret; 191 177 192 178 return size; 193 179 } ··· 240 226 } else if (size > 0) { 241 227 ret = fstat(fd, &stat); 242 228 if (!ret) 243 - ret = ftruncate(fd, stat.st_size - size - 8); 229 + ret = ftruncate(fd, stat.st_size 230 + - size - 8 - BOOTCONFIG_MAGIC_LEN); 244 231 if (ret) 245 232 ret = -errno; 246 233 } /* Ignore if there is no boot config in initrd */ ··· 308 293 ret = write(fd, data, size + 8); 309 294 if (ret < 0) { 310 295 pr_err("Failed to apply a boot config: %d\n", ret); 296 + return ret; 297 + } 298 + /* Write a magic word of the bootconfig */ 299 + ret = write(fd, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN); 300 + if (ret < 0) { 301 + pr_err("Failed to apply a boot config magic: %d\n", ret); 311 302 return ret; 312 303 } 313 304 close(fd);
+1 -1
tools/bootconfig/test-bootconfig.sh
··· 49 49 new_size=$(stat -c %s $INITRD) 50 50 51 51 echo "File size check" 52 - xpass test $new_size -eq $(expr $bconf_size + $initrd_size + 9) 52 + xpass test $new_size -eq $(expr $bconf_size + $initrd_size + 9 + 12) 53 53 54 54 echo "Apply command repeat test" 55 55 xpass $BOOTCONF -a $TEMPCONF $INITRD