mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	bootconfig: Fix to remove bootconfig data from initrd while boot
If there is a bootconfig data in the tail of initrd/initramfs,
initrd image sanity check caused an error while decompression
stage as follows.
[    0.883882] Unpacking initramfs...
[    2.696429] Initramfs unpacking failed: invalid magic at start of compressed archive
This error will be ignored if CONFIG_BLK_DEV_RAM=n,
but CONFIG_BLK_DEV_RAM=y the kernel failed to mount rootfs
and causes a panic.
To fix this issue, shrink down the initrd_end for removing
tailing bootconfig data while boot the kernel.
Link: http://lkml.kernel.org/r/158788401014.24243.17424755854115077915.stgit@devnote2
Cc: Borislav Petkov <bp@alien8.de>
Cc: Kees Cook <keescook@chromium.org>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: stable@vger.kernel.org
Fixes: 7684b8582c ("bootconfig: Load boot config from the tail of initrd")
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
			
			
This commit is contained in:
		
							parent
							
								
									6a8b55ed40
								
							
						
					
					
						commit
						de462e5f10
					
				
					 1 changed files with 52 additions and 17 deletions
				
			
		
							
								
								
									
										69
									
								
								init/main.c
									
									
									
									
									
								
							
							
						
						
									
										69
									
								
								init/main.c
									
									
									
									
									
								
							| 
						 | 
					@ -257,6 +257,47 @@ static int __init loglevel(char *str)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
early_param("loglevel", loglevel);
 | 
					early_param("loglevel", loglevel);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_BLK_DEV_INITRD
 | 
				
			||||||
 | 
					static void * __init get_boot_config_from_initrd(u32 *_size, u32 *_csum)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						u32 size, csum;
 | 
				
			||||||
 | 
						char *data;
 | 
				
			||||||
 | 
						u32 *hdr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!initrd_end)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data = (char *)initrd_end - BOOTCONFIG_MAGIC_LEN;
 | 
				
			||||||
 | 
						if (memcmp(data, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN))
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hdr = (u32 *)(data - 8);
 | 
				
			||||||
 | 
						size = hdr[0];
 | 
				
			||||||
 | 
						csum = hdr[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data = ((void *)hdr) - size;
 | 
				
			||||||
 | 
						if ((unsigned long)data < initrd_start) {
 | 
				
			||||||
 | 
							pr_err("bootconfig size %d is greater than initrd size %ld\n",
 | 
				
			||||||
 | 
								size, initrd_end - initrd_start);
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Remove bootconfig from initramfs/initrd */
 | 
				
			||||||
 | 
						initrd_end = (unsigned long)data;
 | 
				
			||||||
 | 
						if (_size)
 | 
				
			||||||
 | 
							*_size = size;
 | 
				
			||||||
 | 
						if (_csum)
 | 
				
			||||||
 | 
							*_csum = csum;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return data;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					static void * __init get_boot_config_from_initrd(u32 *_size, u32 *_csum)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_BOOT_CONFIG
 | 
					#ifdef CONFIG_BOOT_CONFIG
 | 
				
			||||||
 | 
					
 | 
				
			||||||
char xbc_namebuf[XBC_KEYLEN_MAX] __initdata;
 | 
					char xbc_namebuf[XBC_KEYLEN_MAX] __initdata;
 | 
				
			||||||
| 
						 | 
					@ -357,9 +398,12 @@ static void __init setup_boot_config(const char *cmdline)
 | 
				
			||||||
	int pos;
 | 
						int pos;
 | 
				
			||||||
	u32 size, csum;
 | 
						u32 size, csum;
 | 
				
			||||||
	char *data, *copy;
 | 
						char *data, *copy;
 | 
				
			||||||
	u32 *hdr;
 | 
					 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data = get_boot_config_from_initrd(&size, &csum);
 | 
				
			||||||
 | 
						if (!data)
 | 
				
			||||||
 | 
							goto not_found;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
 | 
						strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
 | 
				
			||||||
	parse_args("bootconfig", tmp_cmdline, NULL, 0, 0, 0, NULL,
 | 
						parse_args("bootconfig", tmp_cmdline, NULL, 0, 0, 0, NULL,
 | 
				
			||||||
		   bootconfig_params);
 | 
							   bootconfig_params);
 | 
				
			||||||
| 
						 | 
					@ -367,27 +411,12 @@ static void __init setup_boot_config(const char *cmdline)
 | 
				
			||||||
	if (!bootconfig_found)
 | 
						if (!bootconfig_found)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!initrd_end)
 | 
					 | 
				
			||||||
		goto not_found;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	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];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (size >= XBC_DATA_MAX) {
 | 
						if (size >= XBC_DATA_MAX) {
 | 
				
			||||||
		pr_err("bootconfig size %d greater than max size %d\n",
 | 
							pr_err("bootconfig size %d greater than max size %d\n",
 | 
				
			||||||
			size, XBC_DATA_MAX);
 | 
								size, XBC_DATA_MAX);
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	data = ((void *)hdr) - size;
 | 
					 | 
				
			||||||
	if ((unsigned long)data < initrd_start)
 | 
					 | 
				
			||||||
		goto not_found;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (boot_config_checksum((unsigned char *)data, size) != csum) {
 | 
						if (boot_config_checksum((unsigned char *)data, size) != csum) {
 | 
				
			||||||
		pr_err("bootconfig checksum failed\n");
 | 
							pr_err("bootconfig checksum failed\n");
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
| 
						 | 
					@ -420,8 +449,14 @@ static void __init setup_boot_config(const char *cmdline)
 | 
				
			||||||
not_found:
 | 
					not_found:
 | 
				
			||||||
	pr_err("'bootconfig' found on command line, but no bootconfig found\n");
 | 
						pr_err("'bootconfig' found on command line, but no bootconfig found\n");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
#define setup_boot_config(cmdline)	do { } while (0)
 | 
					
 | 
				
			||||||
 | 
					static void __init setup_boot_config(const char *cmdline)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/* Remove bootconfig data from initrd */
 | 
				
			||||||
 | 
						get_boot_config_from_initrd(NULL, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __init warn_bootconfig(char *str)
 | 
					static int __init warn_bootconfig(char *str)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue