.. | .. |
---|
| 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; |
---|