1288 lines · 32.3 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-only/* * kexec: kexec_file_load system call * * Copyright (C) 2014 Red Hat Inc. * Authors: *      Vivek Goyal <vgoyal@redhat.com> */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/capability.h>#include <linux/mm.h>#include <linux/file.h>#include <linux/slab.h>#include <linux/kexec.h>#include <linux/memblock.h>#include <linux/mutex.h>#include <linux/list.h>#include <linux/fs.h>#include <linux/ima.h>#include <crypto/sha2.h>#include <linux/elf.h>#include <linux/elfcore.h>#include <linux/kernel.h>#include <linux/kernel_read_file.h>#include <linux/syscalls.h>#include <linux/vmalloc.h>#include <linux/dma-map-ops.h>#include <linux/kexec_handover.h>#include "kexec_internal.h" #ifdef CONFIG_KEXEC_SIGstatic bool sig_enforce = IS_ENABLED(CONFIG_KEXEC_SIG_FORCE); void set_kexec_sig_enforced(void){	sig_enforce = true;}#endif #ifdef CONFIG_IMA_KEXECstatic bool check_ima_segment_index(struct kimage *image, int i){	if (image->is_ima_segment_index_set && i == image->ima_segment_index)		return true;	else		return false;}#elsestatic bool check_ima_segment_index(struct kimage *image, int i){	return false;}#endif static int kexec_calculate_store_digests(struct kimage *image); /* Maximum size in bytes for kernel/initrd files. */#define KEXEC_FILE_SIZE_MAX	min_t(s64, 4LL << 30, SSIZE_MAX) /* * Currently this is the only default function that is exported as some * architectures need it to do additional handlings. * In the future, other default functions may be exported too if required. */int kexec_image_probe_default(struct kimage *image, void *buf,			      unsigned long buf_len){	const struct kexec_file_ops * const *fops;	int ret = -ENOEXEC; 	for (fops = &kexec_file_loaders[0]; *fops && (*fops)->probe; ++fops) {		ret = (*fops)->probe(buf, buf_len);		if (!ret) {			image->fops = *fops;			return ret;		}	} 	return ret;} static void *kexec_image_load_default(struct kimage *image){	if (!image->fops || !image->fops->load)		return ERR_PTR(-ENOEXEC); 	return image->fops->load(image, image->kernel_buf,				 image->kernel_buf_len, image->initrd_buf,				 image->initrd_buf_len, image->cmdline_buf,				 image->cmdline_buf_len);} int kexec_image_post_load_cleanup_default(struct kimage *image){	if (!image->fops || !image->fops->cleanup)		return 0; 	return image->fops->cleanup(image->image_loader_data);} /* * Free up memory used by kernel, initrd, and command line. This is temporary * memory allocation which is not needed any more after these buffers have * been loaded into separate segments and have been copied elsewhere. */void kimage_file_post_load_cleanup(struct kimage *image){	struct purgatory_info *pi = &image->purgatory_info; 	vfree(image->kernel_buf);	image->kernel_buf = NULL; 	vfree(image->initrd_buf);	image->initrd_buf = NULL; 	kfree(image->cmdline_buf);	image->cmdline_buf = NULL; 	vfree(pi->purgatory_buf);	pi->purgatory_buf = NULL; 	vfree(pi->sechdrs);	pi->sechdrs = NULL; #ifdef CONFIG_IMA_KEXEC	vfree(image->ima_buffer);	image->ima_buffer = NULL;#endif /* CONFIG_IMA_KEXEC */ 	/* See if architecture has anything to cleanup post load */	arch_kimage_file_post_load_cleanup(image); 	/*	 * Above call should have called into bootloader to free up	 * any data stored in kimage->image_loader_data. It should	 * be ok now to free it up.	 */	kfree(image->image_loader_data);	image->image_loader_data = NULL; 	kexec_file_dbg_print = false;} #ifdef CONFIG_KEXEC_SIG#ifdef CONFIG_SIGNED_PE_FILE_VERIFICATIONint kexec_kernel_verify_pe_sig(const char *kernel, unsigned long kernel_len){	int ret; 	ret = verify_pefile_signature(kernel, kernel_len,				      VERIFY_USE_SECONDARY_KEYRING,				      VERIFYING_KEXEC_PE_SIGNATURE);	if (ret == -ENOKEY && IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING)) {		ret = verify_pefile_signature(kernel, kernel_len,					      VERIFY_USE_PLATFORM_KEYRING,					      VERIFYING_KEXEC_PE_SIGNATURE);	}	return ret;}#endif static int kexec_image_verify_sig(struct kimage *image, void *buf,				  unsigned long buf_len){	if (!image->fops || !image->fops->verify_sig) {		pr_debug("kernel loader does not support signature verification.\n");		return -EKEYREJECTED;	} 	return image->fops->verify_sig(buf, buf_len);} static intkimage_validate_signature(struct kimage *image){	int ret; 	ret = kexec_image_verify_sig(image, image->kernel_buf,				     image->kernel_buf_len);	if (ret) { 		if (sig_enforce) {			pr_notice("Enforced kernel signature verification failed (%d).\n", ret);			return ret;		} 		/*		 * If IMA is guaranteed to appraise a signature on the kexec		 * image, permit it even if the kernel is otherwise locked		 * down.		 */		if (!ima_appraise_signature(READING_KEXEC_IMAGE) &&		    security_locked_down(LOCKDOWN_KEXEC))			return -EPERM; 		pr_debug("kernel signature verification failed (%d).\n", ret);	} 	return 0;}#endif static int kexec_post_load(struct kimage *image, unsigned long flags){#ifdef CONFIG_IMA_KEXEC	if (!(flags & KEXEC_FILE_ON_CRASH))		ima_kexec_post_load(image);#endif	return machine_kexec_post_load(image);} /* * In file mode list of segments is prepared by kernel. Copy relevant * data from user space, do error checking, prepare segment list */static intkimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,			     const char __user *cmdline_ptr,			     unsigned long cmdline_len, unsigned flags){	ssize_t ret;	void *ldata; 	ret = kernel_read_file_from_fd(kernel_fd, 0, &image->kernel_buf,				       KEXEC_FILE_SIZE_MAX, NULL,				       READING_KEXEC_IMAGE);	if (ret < 0)		return ret;	image->kernel_buf_len = ret;	kexec_dprintk("kernel: %p kernel_size: %#lx\n",		      image->kernel_buf, image->kernel_buf_len); 	/* Call arch image probe handlers */	ret = arch_kexec_kernel_image_probe(image, image->kernel_buf,					    image->kernel_buf_len);	if (ret)		goto out; #ifdef CONFIG_KEXEC_SIG	ret = kimage_validate_signature(image); 	if (ret)		goto out;#endif	/* It is possible that there no initramfs is being loaded */	if (!(flags & KEXEC_FILE_NO_INITRAMFS)) {		ret = kernel_read_file_from_fd(initrd_fd, 0, &image->initrd_buf,					       KEXEC_FILE_SIZE_MAX, NULL,					       READING_KEXEC_INITRAMFS);		if (ret < 0)			goto out;		image->initrd_buf_len = ret;		ret = 0;	} 	image->no_cma = !!(flags & KEXEC_FILE_NO_CMA);	image->force_dtb = flags & KEXEC_FILE_FORCE_DTB; 	if (cmdline_len) {		image->cmdline_buf = memdup_user(cmdline_ptr, cmdline_len);		if (IS_ERR(image->cmdline_buf)) {			ret = PTR_ERR(image->cmdline_buf);			image->cmdline_buf = NULL;			goto out;		} 		image->cmdline_buf_len = cmdline_len; 		/* command line should be a string with last byte null */		if (image->cmdline_buf[cmdline_len - 1] != '\0') {			ret = -EINVAL;			goto out;		} 		ima_kexec_cmdline(kernel_fd, image->cmdline_buf,				  image->cmdline_buf_len - 1);	} 	/* IMA needs to pass the measurement list to the next kernel. */	ima_add_kexec_buffer(image); 	/* If KHO is active, add its images to the list */	ret = kho_fill_kimage(image);	if (ret)		goto out; 	/* Call image load handler */	ldata = kexec_image_load_default(image); 	if (IS_ERR(ldata)) {		ret = PTR_ERR(ldata);		goto out;	} 	image->image_loader_data = ldata;out:	/* In case of error, free up all allocated memory in this function */	if (ret)		kimage_file_post_load_cleanup(image);	return ret;} static intkimage_file_alloc_init(struct kimage **rimage, int kernel_fd,		       int initrd_fd, const char __user *cmdline_ptr,		       unsigned long cmdline_len, unsigned long flags){	int ret;	struct kimage *image;	bool kexec_on_panic = flags & KEXEC_FILE_ON_CRASH; 	image = do_kimage_alloc_init();	if (!image)		return -ENOMEM; 	kexec_file_dbg_print = !!(flags & KEXEC_FILE_DEBUG);	image->file_mode = 1; #ifdef CONFIG_CRASH_DUMP	if (kexec_on_panic) {		/* Enable special crash kernel control page alloc policy. */		image->control_page = crashk_res.start;		image->type = KEXEC_TYPE_CRASH;	}#endif 	ret = kimage_file_prepare_segments(image, kernel_fd, initrd_fd,					   cmdline_ptr, cmdline_len, flags);	if (ret)		goto out_free_image; 	ret = sanity_check_segment_list(image);	if (ret)		goto out_free_post_load_bufs; 	ret = -ENOMEM;	image->control_code_page = kimage_alloc_control_pages(image,					   get_order(KEXEC_CONTROL_PAGE_SIZE));	if (!image->control_code_page) {		pr_err("Could not allocate control_code_buffer\n");		goto out_free_post_load_bufs;	} 	if (!kexec_on_panic) {		image->swap_page = kimage_alloc_control_pages(image, 0);		if (!image->swap_page) {			pr_err("Could not allocate swap buffer\n");			goto out_free_control_pages;		}	} 	*rimage = image;	return 0;out_free_control_pages:	kimage_free_page_list(&image->control_pages);out_free_post_load_bufs:	kimage_file_post_load_cleanup(image);out_free_image:	kfree(image);	return ret;} SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd,		unsigned long, cmdline_len, const char __user *, cmdline_ptr,		unsigned long, flags){	int image_type = (flags & KEXEC_FILE_ON_CRASH) ?			 KEXEC_TYPE_CRASH : KEXEC_TYPE_DEFAULT;	struct kimage **dest_image, *image;	int ret = 0, i; 	/* We only trust the superuser with rebooting the system. */	if (!kexec_load_permitted(image_type))		return -EPERM; 	/* Make sure we have a legal set of flags */	if (flags != (flags & KEXEC_FILE_FLAGS))		return -EINVAL; 	image = NULL; 	if (!kexec_trylock())		return -EBUSY; #ifdef CONFIG_CRASH_DUMP	if (image_type == KEXEC_TYPE_CRASH) {		dest_image = &kexec_crash_image;		if (kexec_crash_image)			arch_kexec_unprotect_crashkres();	} else#endif		dest_image = &kexec_image; 	if (flags & KEXEC_FILE_UNLOAD)		goto exchange; 	/*	 * In case of crash, new kernel gets loaded in reserved region. It is	 * same memory where old crash kernel might be loaded. Free any	 * current crash dump kernel before we corrupt it.	 */	if (flags & KEXEC_FILE_ON_CRASH)		kimage_free(xchg(&kexec_crash_image, NULL)); 	ret = kimage_file_alloc_init(&image, kernel_fd, initrd_fd, cmdline_ptr,				     cmdline_len, flags);	if (ret)		goto out; #ifdef CONFIG_CRASH_HOTPLUG	if ((flags & KEXEC_FILE_ON_CRASH) && arch_crash_hotplug_support(image, flags))		image->hotplug_support = 1;#endif 	ret = machine_kexec_prepare(image);	if (ret)		goto out; 	/*	 * Some architecture(like S390) may touch the crash memory before	 * machine_kexec_prepare(), we must copy vmcoreinfo data after it.	 */	ret = kimage_crash_copy_vmcoreinfo(image);	if (ret)		goto out; 	ret = kexec_calculate_store_digests(image);	if (ret)		goto out; 	kexec_dprintk("nr_segments = %lu\n", image->nr_segments);	for (i = 0; i < image->nr_segments; i++) {		struct kexec_segment *ksegment; 		ksegment = &image->segment[i];		kexec_dprintk("segment[%d]: buf=0x%p bufsz=0x%zx mem=0x%lx memsz=0x%zx\n",			      i, ksegment->buf, ksegment->bufsz, ksegment->mem,			      ksegment->memsz); 		ret = kimage_load_segment(image, i);		if (ret)			goto out;	} 	kimage_terminate(image); 	ret = kexec_post_load(image, flags);	if (ret)		goto out; 	kexec_dprintk("kexec_file_load: type:%u, start:0x%lx head:0x%lx flags:0x%lx\n",		      image->type, image->start, image->head, flags);	/*	 * Free up any temporary buffers allocated which are not needed	 * after image has been loaded	 */	kimage_file_post_load_cleanup(image);exchange:	image = xchg(dest_image, image);out:#ifdef CONFIG_CRASH_DUMP	if ((flags & KEXEC_FILE_ON_CRASH) && kexec_crash_image)		arch_kexec_protect_crashkres();#endif 	kexec_unlock();	kimage_free(image);	return ret;} static int locate_mem_hole_top_down(unsigned long start, unsigned long end,				    struct kexec_buf *kbuf){	struct kimage *image = kbuf->image;	unsigned long temp_start, temp_end; 	temp_end = min(end, kbuf->buf_max);	temp_start = temp_end - kbuf->memsz + 1;	kexec_random_range_start(temp_start, temp_end, kbuf, &temp_start); 	do {		/* align down start */		temp_start = ALIGN_DOWN(temp_start, kbuf->buf_align); 		if (temp_start < start || temp_start < kbuf->buf_min)			return 0; 		temp_end = temp_start + kbuf->memsz - 1; 		/*		 * Make sure this does not conflict with any of existing		 * segments		 */		if (kimage_is_destination_range(image, temp_start, temp_end)) {			temp_start = temp_start - PAGE_SIZE;			continue;		} 

Lines 1–500 of 1288.