Skip to content

Commit 7d53be5

Browse files
committed
Merge tag 'x86_urgent_for_v5.10-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Borislav Petkov: - An IOMMU VT-d build fix when CONFIG_PCI_ATS=n along with a revert of same because the proper one is going through the IOMMU tree (Thomas Gleixner) - An Intel microcode loader fix to save the correct microcode patch to apply during resume (Chen Yu) - A fix to not access user memory of other processes when dumping opcode bytes (Thomas Gleixner) * tag 'x86_urgent_for_v5.10-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: Revert "iommu/vt-d: Take CONFIG_PCI_ATS into account" x86/dumpstack: Do not try to access user space code of other tasks x86/microcode/intel: Check patch signature before saving microcode for early loading iommu/vt-d: Take CONFIG_PCI_ATS into account
2 parents 4a51c60 + 01cf158 commit 7d53be5

File tree

2 files changed

+29
-57
lines changed

2 files changed

+29
-57
lines changed

arch/x86/kernel/cpu/microcode/intel.c

Lines changed: 10 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -100,53 +100,6 @@ static int has_newer_microcode(void *mc, unsigned int csig, int cpf, int new_rev
100100
return find_matching_signature(mc, csig, cpf);
101101
}
102102

103-
/*
104-
* Given CPU signature and a microcode patch, this function finds if the
105-
* microcode patch has matching family and model with the CPU.
106-
*
107-
* %true - if there's a match
108-
* %false - otherwise
109-
*/
110-
static bool microcode_matches(struct microcode_header_intel *mc_header,
111-
unsigned long sig)
112-
{
113-
unsigned long total_size = get_totalsize(mc_header);
114-
unsigned long data_size = get_datasize(mc_header);
115-
struct extended_sigtable *ext_header;
116-
unsigned int fam_ucode, model_ucode;
117-
struct extended_signature *ext_sig;
118-
unsigned int fam, model;
119-
int ext_sigcount, i;
120-
121-
fam = x86_family(sig);
122-
model = x86_model(sig);
123-
124-
fam_ucode = x86_family(mc_header->sig);
125-
model_ucode = x86_model(mc_header->sig);
126-
127-
if (fam == fam_ucode && model == model_ucode)
128-
return true;
129-
130-
/* Look for ext. headers: */
131-
if (total_size <= data_size + MC_HEADER_SIZE)
132-
return false;
133-
134-
ext_header = (void *) mc_header + data_size + MC_HEADER_SIZE;
135-
ext_sig = (void *)ext_header + EXT_HEADER_SIZE;
136-
ext_sigcount = ext_header->count;
137-
138-
for (i = 0; i < ext_sigcount; i++) {
139-
fam_ucode = x86_family(ext_sig->sig);
140-
model_ucode = x86_model(ext_sig->sig);
141-
142-
if (fam == fam_ucode && model == model_ucode)
143-
return true;
144-
145-
ext_sig++;
146-
}
147-
return false;
148-
}
149-
150103
static struct ucode_patch *memdup_patch(void *data, unsigned int size)
151104
{
152105
struct ucode_patch *p;
@@ -164,7 +117,7 @@ static struct ucode_patch *memdup_patch(void *data, unsigned int size)
164117
return p;
165118
}
166119

167-
static void save_microcode_patch(void *data, unsigned int size)
120+
static void save_microcode_patch(struct ucode_cpu_info *uci, void *data, unsigned int size)
168121
{
169122
struct microcode_header_intel *mc_hdr, *mc_saved_hdr;
170123
struct ucode_patch *iter, *tmp, *p = NULL;
@@ -210,6 +163,9 @@ static void save_microcode_patch(void *data, unsigned int size)
210163
if (!p)
211164
return;
212165

166+
if (!find_matching_signature(p->data, uci->cpu_sig.sig, uci->cpu_sig.pf))
167+
return;
168+
213169
/*
214170
* Save for early loading. On 32-bit, that needs to be a physical
215171
* address as the APs are running from physical addresses, before
@@ -344,13 +300,14 @@ scan_microcode(void *data, size_t size, struct ucode_cpu_info *uci, bool save)
344300

345301
size -= mc_size;
346302

347-
if (!microcode_matches(mc_header, uci->cpu_sig.sig)) {
303+
if (!find_matching_signature(data, uci->cpu_sig.sig,
304+
uci->cpu_sig.pf)) {
348305
data += mc_size;
349306
continue;
350307
}
351308

352309
if (save) {
353-
save_microcode_patch(data, mc_size);
310+
save_microcode_patch(uci, data, mc_size);
354311
goto next;
355312
}
356313

@@ -483,14 +440,14 @@ static void show_saved_mc(void)
483440
* Save this microcode patch. It will be loaded early when a CPU is
484441
* hot-added or resumes.
485442
*/
486-
static void save_mc_for_early(u8 *mc, unsigned int size)
443+
static void save_mc_for_early(struct ucode_cpu_info *uci, u8 *mc, unsigned int size)
487444
{
488445
/* Synchronization during CPU hotplug. */
489446
static DEFINE_MUTEX(x86_cpu_microcode_mutex);
490447

491448
mutex_lock(&x86_cpu_microcode_mutex);
492449

493-
save_microcode_patch(mc, size);
450+
save_microcode_patch(uci, mc, size);
494451
show_saved_mc();
495452

496453
mutex_unlock(&x86_cpu_microcode_mutex);
@@ -935,7 +892,7 @@ static enum ucode_state generic_load_microcode(int cpu, struct iov_iter *iter)
935892
* permanent memory. So it will be loaded early when a CPU is hot added
936893
* or resumes.
937894
*/
938-
save_mc_for_early(new_mc, new_mc_size);
895+
save_mc_for_early(uci, new_mc, new_mc_size);
939896

940897
pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n",
941898
cpu, new_rev, uci->cpu_sig.rev);

arch/x86/kernel/dumpstack.c

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,22 @@ static int copy_code(struct pt_regs *regs, u8 *buf, unsigned long src,
7878
if (!user_mode(regs))
7979
return copy_from_kernel_nofault(buf, (u8 *)src, nbytes);
8080

81+
/* The user space code from other tasks cannot be accessed. */
82+
if (regs != task_pt_regs(current))
83+
return -EPERM;
8184
/*
8285
* Make sure userspace isn't trying to trick us into dumping kernel
8386
* memory by pointing the userspace instruction pointer at it.
8487
*/
8588
if (__chk_range_not_ok(src, nbytes, TASK_SIZE_MAX))
8689
return -EINVAL;
8790

91+
/*
92+
* Even if named copy_from_user_nmi() this can be invoked from
93+
* other contexts and will not try to resolve a pagefault, which is
94+
* the correct thing to do here as this code can be called from any
95+
* context.
96+
*/
8897
return copy_from_user_nmi(buf, (void __user *)src, nbytes);
8998
}
9099

@@ -115,13 +124,19 @@ void show_opcodes(struct pt_regs *regs, const char *loglvl)
115124
u8 opcodes[OPCODE_BUFSIZE];
116125
unsigned long prologue = regs->ip - PROLOGUE_SIZE;
117126

118-
if (copy_code(regs, opcodes, prologue, sizeof(opcodes))) {
119-
printk("%sCode: Unable to access opcode bytes at RIP 0x%lx.\n",
120-
loglvl, prologue);
121-
} else {
127+
switch (copy_code(regs, opcodes, prologue, sizeof(opcodes))) {
128+
case 0:
122129
printk("%sCode: %" __stringify(PROLOGUE_SIZE) "ph <%02x> %"
123130
__stringify(EPILOGUE_SIZE) "ph\n", loglvl, opcodes,
124131
opcodes[PROLOGUE_SIZE], opcodes + PROLOGUE_SIZE + 1);
132+
break;
133+
case -EPERM:
134+
/* No access to the user space stack of other tasks. Ignore. */
135+
break;
136+
default:
137+
printk("%sCode: Unable to access opcode bytes at RIP 0x%lx.\n",
138+
loglvl, prologue);
139+
break;
125140
}
126141
}
127142

0 commit comments

Comments
 (0)