/[packages]/updates/6/kernel/current/PATCHES/patches/stable-efi-capsule-loader-reinstate-virtual-capsule-mapping.patch
ViewVC logotype

Contents of /updates/6/kernel/current/PATCHES/patches/stable-efi-capsule-loader-reinstate-virtual-capsule-mapping.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1190848 - (show annotations) (download)
Sat Jan 6 13:15:18 2018 UTC (6 years, 3 months ago) by tmb
File size: 6365 byte(s)
- update to 4.14.12
- add current -stable queue
- add BFQ performance updates from upstream
- enable PAGE_TABLE_ISOLATION on all x86_64 kernels
 (can be disabled at boot time with pti=off on kernel command line)
- iwlwifi: pcie: fix DMA memory mapping / unmapping
- update conflicts on microcode


1 From f24c4d478013d82bd1b943df566fff3561d52864 Mon Sep 17 00:00:00 2001
2 From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
3 Date: Tue, 2 Jan 2018 17:21:10 +0000
4 Subject: efi/capsule-loader: Reinstate virtual capsule mapping
5
6 From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
7
8 commit f24c4d478013d82bd1b943df566fff3561d52864 upstream.
9
10 Commit:
11
12 82c3768b8d68 ("efi/capsule-loader: Use a cached copy of the capsule header")
13
14 ... refactored the capsule loading code that maps the capsule header,
15 to avoid having to map it several times.
16
17 However, as it turns out, the vmap() call we ended up removing did not
18 just map the header, but the entire capsule image, and dropping this
19 virtual mapping breaks capsules that are processed by the firmware
20 immediately (i.e., without a reboot).
21
22 Unfortunately, that change was part of a larger refactor that allowed
23 a quirk to be implemented for Quark, which has a non-standard memory
24 layout for capsules, and we have slightly painted ourselves into a
25 corner by allowing quirk code to mangle the capsule header and memory
26 layout.
27
28 So we need to fix this without breaking Quark. Fortunately, Quark does
29 not appear to care about the virtual mapping, and so we can simply
30 do a partial revert of commit:
31
32 2a457fb31df6 ("efi/capsule-loader: Use page addresses rather than struct page pointers")
33
34 ... and create a vmap() mapping of the entire capsule (including header)
35 based on the reinstated struct page array, unless running on Quark, in
36 which case we pass the capsule header copy as before.
37
38 Reported-by: Ge Song <ge.song@hxt-semitech.com>
39 Tested-by: Bryan O'Donoghue <pure.logic@nexus-software.ie>
40 Tested-by: Ge Song <ge.song@hxt-semitech.com>
41 Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
42 Cc: Dave Young <dyoung@redhat.com>
43 Cc: Linus Torvalds <torvalds@linux-foundation.org>
44 Cc: Matt Fleming <matt@codeblueprint.co.uk>
45 Cc: Peter Zijlstra <peterz@infradead.org>
46 Cc: Thomas Gleixner <tglx@linutronix.de>
47 Cc: linux-efi@vger.kernel.org
48 Fixes: 82c3768b8d68 ("efi/capsule-loader: Use a cached copy of the capsule header")
49 Link: http://lkml.kernel.org/r/20180102172110.17018-3-ard.biesheuvel@linaro.org
50 Signed-off-by: Ingo Molnar <mingo@kernel.org>
51 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
52
53 ---
54 arch/x86/platform/efi/quirks.c | 13 +++++++++
55 drivers/firmware/efi/capsule-loader.c | 45 +++++++++++++++++++++++++++-------
56 include/linux/efi.h | 4 ++-
57 3 files changed, 52 insertions(+), 10 deletions(-)
58
59 --- a/arch/x86/platform/efi/quirks.c
60 +++ b/arch/x86/platform/efi/quirks.c
61 @@ -592,7 +592,18 @@ static int qrk_capsule_setup_info(struct
62 /*
63 * Update the first page pointer to skip over the CSH header.
64 */
65 - cap_info->pages[0] += csh->headersize;
66 + cap_info->phys[0] += csh->headersize;
67 +
68 + /*
69 + * cap_info->capsule should point at a virtual mapping of the entire
70 + * capsule, starting at the capsule header. Our image has the Quark
71 + * security header prepended, so we cannot rely on the default vmap()
72 + * mapping created by the generic capsule code.
73 + * Given that the Quark firmware does not appear to care about the
74 + * virtual mapping, let's just point cap_info->capsule at our copy
75 + * of the capsule header.
76 + */
77 + cap_info->capsule = &cap_info->header;
78
79 return 1;
80 }
81 --- a/drivers/firmware/efi/capsule-loader.c
82 +++ b/drivers/firmware/efi/capsule-loader.c
83 @@ -20,10 +20,6 @@
84
85 #define NO_FURTHER_WRITE_ACTION -1
86
87 -#ifndef phys_to_page
88 -#define phys_to_page(x) pfn_to_page((x) >> PAGE_SHIFT)
89 -#endif
90 -
91 /**
92 * efi_free_all_buff_pages - free all previous allocated buffer pages
93 * @cap_info: pointer to current instance of capsule_info structure
94 @@ -35,7 +31,7 @@
95 static void efi_free_all_buff_pages(struct capsule_info *cap_info)
96 {
97 while (cap_info->index > 0)
98 - __free_page(phys_to_page(cap_info->pages[--cap_info->index]));
99 + __free_page(cap_info->pages[--cap_info->index]);
100
101 cap_info->index = NO_FURTHER_WRITE_ACTION;
102 }
103 @@ -71,6 +67,14 @@ int __efi_capsule_setup_info(struct caps
104
105 cap_info->pages = temp_page;
106
107 + temp_page = krealloc(cap_info->phys,
108 + pages_needed * sizeof(phys_addr_t *),
109 + GFP_KERNEL | __GFP_ZERO);
110 + if (!temp_page)
111 + return -ENOMEM;
112 +
113 + cap_info->phys = temp_page;
114 +
115 return 0;
116 }
117
118 @@ -105,9 +109,24 @@ int __weak efi_capsule_setup_info(struct
119 **/
120 static ssize_t efi_capsule_submit_update(struct capsule_info *cap_info)
121 {
122 + bool do_vunmap = false;
123 int ret;
124
125 - ret = efi_capsule_update(&cap_info->header, cap_info->pages);
126 + /*
127 + * cap_info->capsule may have been assigned already by a quirk
128 + * handler, so only overwrite it if it is NULL
129 + */
130 + if (!cap_info->capsule) {
131 + cap_info->capsule = vmap(cap_info->pages, cap_info->index,
132 + VM_MAP, PAGE_KERNEL);
133 + if (!cap_info->capsule)
134 + return -ENOMEM;
135 + do_vunmap = true;
136 + }
137 +
138 + ret = efi_capsule_update(cap_info->capsule, cap_info->phys);
139 + if (do_vunmap)
140 + vunmap(cap_info->capsule);
141 if (ret) {
142 pr_err("capsule update failed\n");
143 return ret;
144 @@ -165,10 +184,12 @@ static ssize_t efi_capsule_write(struct
145 goto failed;
146 }
147
148 - cap_info->pages[cap_info->index++] = page_to_phys(page);
149 + cap_info->pages[cap_info->index] = page;
150 + cap_info->phys[cap_info->index] = page_to_phys(page);
151 cap_info->page_bytes_remain = PAGE_SIZE;
152 + cap_info->index++;
153 } else {
154 - page = phys_to_page(cap_info->pages[cap_info->index - 1]);
155 + page = cap_info->pages[cap_info->index - 1];
156 }
157
158 kbuff = kmap(page);
159 @@ -252,6 +273,7 @@ static int efi_capsule_release(struct in
160 struct capsule_info *cap_info = file->private_data;
161
162 kfree(cap_info->pages);
163 + kfree(cap_info->phys);
164 kfree(file->private_data);
165 file->private_data = NULL;
166 return 0;
167 @@ -280,6 +302,13 @@ static int efi_capsule_open(struct inode
168 kfree(cap_info);
169 return -ENOMEM;
170 }
171 +
172 + cap_info->phys = kzalloc(sizeof(void *), GFP_KERNEL);
173 + if (!cap_info->phys) {
174 + kfree(cap_info->pages);
175 + kfree(cap_info);
176 + return -ENOMEM;
177 + }
178
179 file->private_data = cap_info;
180
181 --- a/include/linux/efi.h
182 +++ b/include/linux/efi.h
183 @@ -140,11 +140,13 @@ struct efi_boot_memmap {
184
185 struct capsule_info {
186 efi_capsule_header_t header;
187 + efi_capsule_header_t *capsule;
188 int reset_type;
189 long index;
190 size_t count;
191 size_t total_size;
192 - phys_addr_t *pages;
193 + struct page **pages;
194 + phys_addr_t *phys;
195 size_t page_bytes_remain;
196 };
197

  ViewVC Help
Powered by ViewVC 1.1.30