| .. | .. | 
|---|
|  | 1 | +// SPDX-License-Identifier: GPL-2.0-only | 
|---|
| 1 | 2 | /* | 
|---|
| 2 | 3 | *	fs/proc/vmcore.c Interface for accessing the crash | 
|---|
| 3 | 4 | * 				 dump from the system's previous life. | 
|---|
| .. | .. | 
|---|
| 16 | 17 | #include <linux/slab.h> | 
|---|
| 17 | 18 | #include <linux/highmem.h> | 
|---|
| 18 | 19 | #include <linux/printk.h> | 
|---|
| 19 |  | -#include <linux/bootmem.h> | 
|---|
|  | 20 | +#include <linux/memblock.h> | 
|---|
| 20 | 21 | #include <linux/init.h> | 
|---|
| 21 | 22 | #include <linux/crash_dump.h> | 
|---|
| 22 | 23 | #include <linux/list.h> | 
|---|
|  | 24 | +#include <linux/moduleparam.h> | 
|---|
| 23 | 25 | #include <linux/mutex.h> | 
|---|
| 24 | 26 | #include <linux/vmalloc.h> | 
|---|
| 25 | 27 | #include <linux/pagemap.h> | 
|---|
| 26 | 28 | #include <linux/uaccess.h> | 
|---|
|  | 29 | +#include <linux/mem_encrypt.h> | 
|---|
| 27 | 30 | #include <asm/io.h> | 
|---|
| 28 | 31 | #include "internal.h" | 
|---|
| 29 | 32 |  | 
|---|
| .. | .. | 
|---|
| 51 | 54 | /* Device Dump list and mutex to synchronize access to list */ | 
|---|
| 52 | 55 | static LIST_HEAD(vmcoredd_list); | 
|---|
| 53 | 56 | static DEFINE_MUTEX(vmcoredd_mutex); | 
|---|
|  | 57 | + | 
|---|
|  | 58 | +static bool vmcoredd_disabled; | 
|---|
|  | 59 | +core_param(novmcoredd, vmcoredd_disabled, bool, 0); | 
|---|
| 54 | 60 | #endif /* CONFIG_PROC_VMCORE_DEVICE_DUMP */ | 
|---|
| 55 | 61 |  | 
|---|
| 56 | 62 | /* Device Dump Size */ | 
|---|
| .. | .. | 
|---|
| 97 | 103 | } | 
|---|
| 98 | 104 |  | 
|---|
| 99 | 105 | /* Reads a page from the oldmem device from given offset. */ | 
|---|
| 100 |  | -static ssize_t read_from_oldmem(char *buf, size_t count, | 
|---|
| 101 |  | -				u64 *ppos, int userbuf) | 
|---|
|  | 106 | +ssize_t read_from_oldmem(char *buf, size_t count, | 
|---|
|  | 107 | +			 u64 *ppos, int userbuf, | 
|---|
|  | 108 | +			 bool encrypted) | 
|---|
| 102 | 109 | { | 
|---|
| 103 | 110 | unsigned long pfn, offset; | 
|---|
| 104 | 111 | size_t nr_bytes; | 
|---|
| .. | .. | 
|---|
| 124 | 131 | else if (clear_user(buf, nr_bytes)) | 
|---|
| 125 | 132 | tmp = -EFAULT; | 
|---|
| 126 | 133 | } else { | 
|---|
| 127 |  | -			tmp = copy_oldmem_page(pfn, buf, nr_bytes, | 
|---|
| 128 |  | -						offset, userbuf); | 
|---|
|  | 134 | +			if (encrypted) | 
|---|
|  | 135 | +				tmp = copy_oldmem_page_encrypted(pfn, buf, | 
|---|
|  | 136 | +								 nr_bytes, | 
|---|
|  | 137 | +								 offset, | 
|---|
|  | 138 | +								 userbuf); | 
|---|
|  | 139 | +			else | 
|---|
|  | 140 | +				tmp = copy_oldmem_page(pfn, buf, nr_bytes, | 
|---|
|  | 141 | +						       offset, userbuf); | 
|---|
| 129 | 142 | } | 
|---|
| 130 | 143 | if (tmp < 0) | 
|---|
| 131 | 144 | return tmp; | 
|---|
| .. | .. | 
|---|
| 160 | 173 | */ | 
|---|
| 161 | 174 | ssize_t __weak elfcorehdr_read(char *buf, size_t count, u64 *ppos) | 
|---|
| 162 | 175 | { | 
|---|
| 163 |  | -	return read_from_oldmem(buf, count, ppos, 0); | 
|---|
|  | 176 | +	return read_from_oldmem(buf, count, ppos, 0, false); | 
|---|
| 164 | 177 | } | 
|---|
| 165 | 178 |  | 
|---|
| 166 | 179 | /* | 
|---|
| .. | .. | 
|---|
| 168 | 181 | */ | 
|---|
| 169 | 182 | ssize_t __weak elfcorehdr_read_notes(char *buf, size_t count, u64 *ppos) | 
|---|
| 170 | 183 | { | 
|---|
| 171 |  | -	return read_from_oldmem(buf, count, ppos, 0); | 
|---|
|  | 184 | +	return read_from_oldmem(buf, count, ppos, 0, mem_encrypt_active()); | 
|---|
| 172 | 185 | } | 
|---|
| 173 | 186 |  | 
|---|
| 174 | 187 | /* | 
|---|
| .. | .. | 
|---|
| 178 | 191 | unsigned long from, unsigned long pfn, | 
|---|
| 179 | 192 | unsigned long size, pgprot_t prot) | 
|---|
| 180 | 193 | { | 
|---|
|  | 194 | +	prot = pgprot_encrypted(prot); | 
|---|
| 181 | 195 | return remap_pfn_range(vma, from, pfn, size, prot); | 
|---|
| 182 | 196 | } | 
|---|
| 183 | 197 |  | 
|---|
| .. | .. | 
|---|
| 367 | 381 | m->offset + m->size - *fpos, | 
|---|
| 368 | 382 | buflen); | 
|---|
| 369 | 383 | start = m->paddr + *fpos - m->offset; | 
|---|
| 370 |  | -			tmp = read_from_oldmem(buffer, tsz, &start, userbuf); | 
|---|
|  | 384 | +			tmp = read_from_oldmem(buffer, tsz, &start, | 
|---|
|  | 385 | +					       userbuf, mem_encrypt_active()); | 
|---|
| 371 | 386 | if (tmp < 0) | 
|---|
| 372 | 387 | return tmp; | 
|---|
| 373 | 388 | buflen -= tsz; | 
|---|
| .. | .. | 
|---|
| 417 | 432 | if (rc < 0) { | 
|---|
| 418 | 433 | unlock_page(page); | 
|---|
| 419 | 434 | put_page(page); | 
|---|
| 420 |  | -			return (rc == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS; | 
|---|
|  | 435 | +			return vmf_error(rc); | 
|---|
| 421 | 436 | } | 
|---|
| 422 | 437 | SetPageUptodate(page); | 
|---|
| 423 | 438 | } | 
|---|
| .. | .. | 
|---|
| 656 | 671 | } | 
|---|
| 657 | 672 | #endif | 
|---|
| 658 | 673 |  | 
|---|
| 659 |  | -static const struct file_operations proc_vmcore_operations = { | 
|---|
| 660 |  | -	.read		= read_vmcore, | 
|---|
| 661 |  | -	.llseek		= default_llseek, | 
|---|
| 662 |  | -	.mmap		= mmap_vmcore, | 
|---|
|  | 674 | +static const struct proc_ops vmcore_proc_ops = { | 
|---|
|  | 675 | +	.proc_read	= read_vmcore, | 
|---|
|  | 676 | +	.proc_lseek	= default_llseek, | 
|---|
|  | 677 | +	.proc_mmap	= mmap_vmcore, | 
|---|
| 663 | 678 | }; | 
|---|
| 664 | 679 |  | 
|---|
| 665 | 680 | static struct vmcore* __init get_new_element(void) | 
|---|
| .. | .. | 
|---|
| 1445 | 1460 | size_t data_size; | 
|---|
| 1446 | 1461 | int ret; | 
|---|
| 1447 | 1462 |  | 
|---|
|  | 1463 | +	if (vmcoredd_disabled) { | 
|---|
|  | 1464 | +		pr_err_once("Device dump is disabled\n"); | 
|---|
|  | 1465 | +		return -EINVAL; | 
|---|
|  | 1466 | +	} | 
|---|
|  | 1467 | + | 
|---|
| 1448 | 1468 | if (!data || !strlen(data->dump_name) || | 
|---|
| 1449 | 1469 | !data->vmcoredd_callback || !data->size) | 
|---|
| 1450 | 1470 | return -EINVAL; | 
|---|
| .. | .. | 
|---|
| 1539 | 1559 | elfcorehdr_free(elfcorehdr_addr); | 
|---|
| 1540 | 1560 | elfcorehdr_addr = ELFCORE_ADDR_ERR; | 
|---|
| 1541 | 1561 |  | 
|---|
| 1542 |  | -	proc_vmcore = proc_create("vmcore", S_IRUSR, NULL, &proc_vmcore_operations); | 
|---|
|  | 1562 | +	proc_vmcore = proc_create("vmcore", S_IRUSR, NULL, &vmcore_proc_ops); | 
|---|
| 1543 | 1563 | if (proc_vmcore) | 
|---|
| 1544 | 1564 | proc_vmcore->size = vmcore_size; | 
|---|
| 1545 | 1565 | return 0; | 
|---|