linux/kernel/kexec_file.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * kexec: kexec_file_load system call
 *
 * Copyright (C) 2014 Red Hat Inc.
 * Authors:
 *      Vivek Goyal <[email protected]>
 */

#define pr_fmt(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/hash.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 "kexec_internal.h"

#ifdef CONFIG_KEXEC_SIG
static bool sig_enforce = IS_ENABLED();

void set_kexec_sig_enforced(void)
{}
#endif

static int kexec_calculate_store_digests(struct kimage *image);

/* Maximum size in bytes for kernel/initrd files. */
#define KEXEC_FILE_SIZE_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)
{}

static void *kexec_image_load_default(struct kimage *image)
{}

int kexec_image_post_load_cleanup_default(struct kimage *image)
{}

/*
 * 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)
{}

#ifdef CONFIG_KEXEC_SIG
#ifdef CONFIG_SIGNED_PE_FILE_VERIFICATION
int kexec_kernel_verify_pe_sig(const char *kernel, unsigned long kernel_len)
{}
#endif

static int kexec_image_verify_sig(struct kimage *image, void *buf,
				  unsigned long buf_len)
{}

static int
kimage_validate_signature(struct kimage *image)
{}
#endif

/*
 * In file mode list of segments is prepared by kernel. Copy relevant
 * data from user space, do error checking, prepare segment list
 */
static int
kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,
			     const char __user *cmdline_ptr,
			     unsigned long cmdline_len, unsigned flags)
{}

static int
kimage_file_alloc_init(struct kimage **rimage, int kernel_fd,
		       int initrd_fd, const char __user *cmdline_ptr,
		       unsigned long cmdline_len, unsigned long flags)
{}

SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd,
		unsigned long, cmdline_len, const char __user *, cmdline_ptr,
		unsigned long, flags)
{}

static int locate_mem_hole_top_down(unsigned long start, unsigned long end,
				    struct kexec_buf *kbuf)
{}

static int locate_mem_hole_bottom_up(unsigned long start, unsigned long end,
				     struct kexec_buf *kbuf)
{}

static int locate_mem_hole_callback(struct resource *res, void *arg)
{}

#ifdef CONFIG_ARCH_KEEP_MEMBLOCK
static int kexec_walk_memblock(struct kexec_buf *kbuf,
			       int (*func)(struct resource *, void *))
{
	int ret = 0;
	u64 i;
	phys_addr_t mstart, mend;
	struct resource res = { };

#ifdef CONFIG_CRASH_DUMP
	if (kbuf->image->type == KEXEC_TYPE_CRASH)
		return func(&crashk_res, kbuf);
#endif

	/*
	 * Using MEMBLOCK_NONE will properly skip MEMBLOCK_DRIVER_MANAGED. See
	 * IORESOURCE_SYSRAM_DRIVER_MANAGED handling in
	 * locate_mem_hole_callback().
	 */
	if (kbuf->top_down) {
		for_each_free_mem_range_reverse(i, NUMA_NO_NODE, MEMBLOCK_NONE,
						&mstart, &mend, NULL) {
			/*
			 * In memblock, end points to the first byte after the
			 * range while in kexec, end points to the last byte
			 * in the range.
			 */
			res.start = mstart;
			res.end = mend - 1;
			ret = func(&res, kbuf);
			if (ret)
				break;
		}
	} else {
		for_each_free_mem_range(i, NUMA_NO_NODE, MEMBLOCK_NONE,
					&mstart, &mend, NULL) {
			/*
			 * In memblock, end points to the first byte after the
			 * range while in kexec, end points to the last byte
			 * in the range.
			 */
			res.start = mstart;
			res.end = mend - 1;
			ret = func(&res, kbuf);
			if (ret)
				break;
		}
	}

	return ret;
}
#else
static int kexec_walk_memblock(struct kexec_buf *kbuf,
			       int (*func)(struct resource *, void *))
{}
#endif

/**
 * kexec_walk_resources - call func(data) on free memory regions
 * @kbuf:	Context info for the search. Also passed to @func.
 * @func:	Function to call for each memory region.
 *
 * Return: The memory walk will stop when func returns a non-zero value
 * and that value will be returned. If all free regions are visited without
 * func returning non-zero, then zero will be returned.
 */
static int kexec_walk_resources(struct kexec_buf *kbuf,
				int (*func)(struct resource *, void *))
{}

/**
 * kexec_locate_mem_hole - find free memory for the purgatory or the next kernel
 * @kbuf:	Parameters for the memory search.
 *
 * On success, kbuf->mem will have the start address of the memory region found.
 *
 * Return: 0 on success, negative errno on error.
 */
int kexec_locate_mem_hole(struct kexec_buf *kbuf)
{}

/**
 * kexec_add_buffer - place a buffer in a kexec segment
 * @kbuf:	Buffer contents and memory parameters.
 *
 * This function assumes that kexec_lock is held.
 * On successful return, @kbuf->mem will have the physical address of
 * the buffer in memory.
 *
 * Return: 0 on success, negative errno on error.
 */
int kexec_add_buffer(struct kexec_buf *kbuf)
{}

/* Calculate and store the digest of segments */
static int kexec_calculate_store_digests(struct kimage *image)
{}

#ifdef CONFIG_ARCH_SUPPORTS_KEXEC_PURGATORY
/*
 * kexec_purgatory_setup_kbuf - prepare buffer to load purgatory.
 * @pi:		Purgatory to be loaded.
 * @kbuf:	Buffer to setup.
 *
 * Allocates the memory needed for the buffer. Caller is responsible to free
 * the memory after use.
 *
 * Return: 0 on success, negative errno on error.
 */
static int kexec_purgatory_setup_kbuf(struct purgatory_info *pi,
				      struct kexec_buf *kbuf)
{}

/*
 * kexec_purgatory_setup_sechdrs - prepares the pi->sechdrs buffer.
 * @pi:		Purgatory to be loaded.
 * @kbuf:	Buffer prepared to store purgatory.
 *
 * Allocates the memory needed for the buffer. Caller is responsible to free
 * the memory after use.
 *
 * Return: 0 on success, negative errno on error.
 */
static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
					 struct kexec_buf *kbuf)
{}

static int kexec_apply_relocations(struct kimage *image)
{}

/*
 * kexec_load_purgatory - Load and relocate the purgatory object.
 * @image:	Image to add the purgatory to.
 * @kbuf:	Memory parameters to use.
 *
 * Allocates the memory needed for image->purgatory_info.sechdrs and
 * image->purgatory_info.purgatory_buf/kbuf->buffer. Caller is responsible
 * to free the memory after use.
 *
 * Return: 0 on success, negative errno on error.
 */
int kexec_load_purgatory(struct kimage *image, struct kexec_buf *kbuf)
{}

/*
 * kexec_purgatory_find_symbol - find a symbol in the purgatory
 * @pi:		Purgatory to search in.
 * @name:	Name of the symbol.
 *
 * Return: pointer to symbol in read-only symtab on success, NULL on error.
 */
static const Elf_Sym *kexec_purgatory_find_symbol(struct purgatory_info *pi,
						  const char *name)
{}

void *kexec_purgatory_get_symbol_addr(struct kimage *image, const char *name)
{}

/*
 * Get or set value of a symbol. If "get_value" is true, symbol value is
 * returned in buf otherwise symbol value is set based on value in buf.
 */
int kexec_purgatory_get_set_symbol(struct kimage *image, const char *name,
				   void *buf, unsigned int size, bool get_value)
{}
#endif /* CONFIG_ARCH_SUPPORTS_KEXEC_PURGATORY */