Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+29 -57
+10 -53
arch/x86/kernel/cpu/microcode/intel.c
··· 100 100 return find_matching_signature(mc, csig, cpf); 101 101 } 102 102 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 - 150 103 static struct ucode_patch *memdup_patch(void *data, unsigned int size) 151 104 { 152 105 struct ucode_patch *p; ··· 117 164 return p; 118 165 } 119 166 120 - static void save_microcode_patch(void *data, unsigned int size) 167 + static void save_microcode_patch(struct ucode_cpu_info *uci, void *data, unsigned int size) 121 168 { 122 169 struct microcode_header_intel *mc_hdr, *mc_saved_hdr; 123 170 struct ucode_patch *iter, *tmp, *p = NULL; ··· 161 208 } 162 209 163 210 if (!p) 211 + return; 212 + 213 + if (!find_matching_signature(p->data, uci->cpu_sig.sig, uci->cpu_sig.pf)) 164 214 return; 165 215 166 216 /* ··· 300 344 301 345 size -= mc_size; 302 346 303 - if (!microcode_matches(mc_header, uci->cpu_sig.sig)) { 347 + if (!find_matching_signature(data, uci->cpu_sig.sig, 348 + uci->cpu_sig.pf)) { 304 349 data += mc_size; 305 350 continue; 306 351 } 307 352 308 353 if (save) { 309 - save_microcode_patch(data, mc_size); 354 + save_microcode_patch(uci, data, mc_size); 310 355 goto next; 311 356 } 312 357 ··· 440 483 * Save this microcode patch. It will be loaded early when a CPU is 441 484 * hot-added or resumes. 442 485 */ 443 - static void save_mc_for_early(u8 *mc, unsigned int size) 486 + static void save_mc_for_early(struct ucode_cpu_info *uci, u8 *mc, unsigned int size) 444 487 { 445 488 /* Synchronization during CPU hotplug. */ 446 489 static DEFINE_MUTEX(x86_cpu_microcode_mutex); 447 490 448 491 mutex_lock(&x86_cpu_microcode_mutex); 449 492 450 - save_microcode_patch(mc, size); 493 + save_microcode_patch(uci, mc, size); 451 494 show_saved_mc(); 452 495 453 496 mutex_unlock(&x86_cpu_microcode_mutex); ··· 892 935 * permanent memory. So it will be loaded early when a CPU is hot added 893 936 * or resumes. 894 937 */ 895 - save_mc_for_early(new_mc, new_mc_size); 938 + save_mc_for_early(uci, new_mc, new_mc_size); 896 939 897 940 pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n", 898 941 cpu, new_rev, uci->cpu_sig.rev);
+19 -4
arch/x86/kernel/dumpstack.c
··· 78 78 if (!user_mode(regs)) 79 79 return copy_from_kernel_nofault(buf, (u8 *)src, nbytes); 80 80 81 + /* The user space code from other tasks cannot be accessed. */ 82 + if (regs != task_pt_regs(current)) 83 + return -EPERM; 81 84 /* 82 85 * Make sure userspace isn't trying to trick us into dumping kernel 83 86 * memory by pointing the userspace instruction pointer at it. ··· 88 85 if (__chk_range_not_ok(src, nbytes, TASK_SIZE_MAX)) 89 86 return -EINVAL; 90 87 88 + /* 89 + * Even if named copy_from_user_nmi() this can be invoked from 90 + * other contexts and will not try to resolve a pagefault, which is 91 + * the correct thing to do here as this code can be called from any 92 + * context. 93 + */ 91 94 return copy_from_user_nmi(buf, (void __user *)src, nbytes); 92 95 } 93 96 ··· 124 115 u8 opcodes[OPCODE_BUFSIZE]; 125 116 unsigned long prologue = regs->ip - PROLOGUE_SIZE; 126 117 127 - if (copy_code(regs, opcodes, prologue, sizeof(opcodes))) { 128 - printk("%sCode: Unable to access opcode bytes at RIP 0x%lx.\n", 129 - loglvl, prologue); 130 - } else { 118 + switch (copy_code(regs, opcodes, prologue, sizeof(opcodes))) { 119 + case 0: 131 120 printk("%sCode: %" __stringify(PROLOGUE_SIZE) "ph <%02x> %" 132 121 __stringify(EPILOGUE_SIZE) "ph\n", loglvl, opcodes, 133 122 opcodes[PROLOGUE_SIZE], opcodes + PROLOGUE_SIZE + 1); 123 + break; 124 + case -EPERM: 125 + /* No access to the user space stack of other tasks. Ignore. */ 126 + break; 127 + default: 128 + printk("%sCode: Unable to access opcode bytes at RIP 0x%lx.\n", 129 + loglvl, prologue); 130 + break; 134 131 } 135 132 } 136 133