Commit 8a5f0605 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 fixes from Thomas Gleixner:
 "A set of fixes for x86:

   - Fix the swapped outb() parameters in the KASLR code

   - Fix the PKEY handling at fork which missed to preserve the pkey
     state for the child. Comes with a test case to validate that.

   - Fix the entry stack handling for XEN PV to respect that XEN PV
     systems enter the function already on the current thread stack and
     not on the trampoline.

   - Fix kexec load failure caused by using a stale value when the
     kexec_buf structure is reused for subsequent allocations.

   - Fix a bogus sizeof() in the memory encryption code

   - Enforce PCI dependency for the Intel Low Power Subsystem

   - Enforce PCI_LOCKLESS_CONFIG when PCI is enabled"

* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/Kconfig: Select PCI_LOCKLESS_CONFIG if PCI is enabled
  x86/entry/64/compat: Fix stack switching for XEN PV
  x86/kexec: Fix a kexec_file_load() failure
  x86/mm/mem_encrypt: Fix erroneous sizeof()
  x86/selftests/pkeys: Fork() to check for state being preserved
  x86/pkeys: Properly copy pkey state at fork()
  x86/kaslr: Fix incorrect i8254 outb() parameters
  x86/intel/lpss: Make PCI dependency explicit
parents 351e1aa6 625210cf
...@@ -198,7 +198,7 @@ config X86 ...@@ -198,7 +198,7 @@ config X86
select IRQ_FORCED_THREADING select IRQ_FORCED_THREADING
select NEED_SG_DMA_LENGTH select NEED_SG_DMA_LENGTH
select PCI_DOMAINS if PCI select PCI_DOMAINS if PCI
select PCI_LOCKLESS_CONFIG select PCI_LOCKLESS_CONFIG if PCI
select PERF_EVENTS select PERF_EVENTS
select RTC_LIB select RTC_LIB
select RTC_MC146818_LIB select RTC_MC146818_LIB
......
...@@ -361,7 +361,8 @@ ENTRY(entry_INT80_compat) ...@@ -361,7 +361,8 @@ ENTRY(entry_INT80_compat)
/* Need to switch before accessing the thread stack. */ /* Need to switch before accessing the thread stack. */
SWITCH_TO_KERNEL_CR3 scratch_reg=%rdi SWITCH_TO_KERNEL_CR3 scratch_reg=%rdi
movq %rsp, %rdi /* In the Xen PV case we already run on the thread stack. */
ALTERNATIVE "movq %rsp, %rdi", "jmp .Lint80_keep_stack", X86_FEATURE_XENPV
movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
pushq 6*8(%rdi) /* regs->ss */ pushq 6*8(%rdi) /* regs->ss */
...@@ -370,8 +371,9 @@ ENTRY(entry_INT80_compat) ...@@ -370,8 +371,9 @@ ENTRY(entry_INT80_compat)
pushq 3*8(%rdi) /* regs->cs */ pushq 3*8(%rdi) /* regs->cs */
pushq 2*8(%rdi) /* regs->ip */ pushq 2*8(%rdi) /* regs->ip */
pushq 1*8(%rdi) /* regs->orig_ax */ pushq 1*8(%rdi) /* regs->orig_ax */
pushq (%rdi) /* pt_regs->di */ pushq (%rdi) /* pt_regs->di */
.Lint80_keep_stack:
pushq %rsi /* pt_regs->si */ pushq %rsi /* pt_regs->si */
xorl %esi, %esi /* nospec si */ xorl %esi, %esi /* nospec si */
pushq %rdx /* pt_regs->dx */ pushq %rdx /* pt_regs->dx */
......
...@@ -178,6 +178,10 @@ static inline void switch_ldt(struct mm_struct *prev, struct mm_struct *next) ...@@ -178,6 +178,10 @@ static inline void switch_ldt(struct mm_struct *prev, struct mm_struct *next)
void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk); void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk);
/*
* Init a new mm. Used on mm copies, like at fork()
* and on mm's that are brand-new, like at execve().
*/
static inline int init_new_context(struct task_struct *tsk, static inline int init_new_context(struct task_struct *tsk,
struct mm_struct *mm) struct mm_struct *mm)
{ {
...@@ -228,8 +232,22 @@ do { \ ...@@ -228,8 +232,22 @@ do { \
} while (0) } while (0)
#endif #endif
static inline void arch_dup_pkeys(struct mm_struct *oldmm,
struct mm_struct *mm)
{
#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
if (!cpu_feature_enabled(X86_FEATURE_OSPKE))
return;
/* Duplicate the oldmm pkey state in mm: */
mm->context.pkey_allocation_map = oldmm->context.pkey_allocation_map;
mm->context.execute_only_pkey = oldmm->context.execute_only_pkey;
#endif
}
static inline int arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm) static inline int arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
{ {
arch_dup_pkeys(oldmm, mm);
paravirt_arch_dup_mmap(oldmm, mm); paravirt_arch_dup_mmap(oldmm, mm);
return ldt_dup_context(oldmm, mm); return ldt_dup_context(oldmm, mm);
} }
......
...@@ -470,6 +470,7 @@ int crash_load_segments(struct kimage *image) ...@@ -470,6 +470,7 @@ int crash_load_segments(struct kimage *image)
kbuf.memsz = kbuf.bufsz; kbuf.memsz = kbuf.bufsz;
kbuf.buf_align = ELF_CORE_HEADER_ALIGN; kbuf.buf_align = ELF_CORE_HEADER_ALIGN;
kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
ret = kexec_add_buffer(&kbuf); ret = kexec_add_buffer(&kbuf);
if (ret) { if (ret) {
vfree((void *)image->arch.elf_headers); vfree((void *)image->arch.elf_headers);
......
...@@ -434,6 +434,7 @@ static void *bzImage64_load(struct kimage *image, char *kernel, ...@@ -434,6 +434,7 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
kbuf.memsz = PAGE_ALIGN(header->init_size); kbuf.memsz = PAGE_ALIGN(header->init_size);
kbuf.buf_align = header->kernel_alignment; kbuf.buf_align = header->kernel_alignment;
kbuf.buf_min = MIN_KERNEL_LOAD_ADDR; kbuf.buf_min = MIN_KERNEL_LOAD_ADDR;
kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
ret = kexec_add_buffer(&kbuf); ret = kexec_add_buffer(&kbuf);
if (ret) if (ret)
goto out_free_params; goto out_free_params;
...@@ -448,6 +449,7 @@ static void *bzImage64_load(struct kimage *image, char *kernel, ...@@ -448,6 +449,7 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
kbuf.bufsz = kbuf.memsz = initrd_len; kbuf.bufsz = kbuf.memsz = initrd_len;
kbuf.buf_align = PAGE_SIZE; kbuf.buf_align = PAGE_SIZE;
kbuf.buf_min = MIN_INITRD_LOAD_ADDR; kbuf.buf_min = MIN_INITRD_LOAD_ADDR;
kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
ret = kexec_add_buffer(&kbuf); ret = kexec_add_buffer(&kbuf);
if (ret) if (ret)
goto out_free_params; goto out_free_params;
......
...@@ -36,8 +36,8 @@ static inline u16 i8254(void) ...@@ -36,8 +36,8 @@ static inline u16 i8254(void)
u16 status, timer; u16 status, timer;
do { do {
outb(I8254_PORT_CONTROL, outb(I8254_CMD_READBACK | I8254_SELECT_COUNTER0,
I8254_CMD_READBACK | I8254_SELECT_COUNTER0); I8254_PORT_CONTROL);
status = inb(I8254_PORT_COUNTER0); status = inb(I8254_PORT_COUNTER0);
timer = inb(I8254_PORT_COUNTER0); timer = inb(I8254_PORT_COUNTER0);
timer |= inb(I8254_PORT_COUNTER0) << 8; timer |= inb(I8254_PORT_COUNTER0) << 8;
......
...@@ -158,8 +158,8 @@ static void __init sme_populate_pgd(struct sme_populate_pgd_data *ppd) ...@@ -158,8 +158,8 @@ static void __init sme_populate_pgd(struct sme_populate_pgd_data *ppd)
pmd = pmd_offset(pud, ppd->vaddr); pmd = pmd_offset(pud, ppd->vaddr);
if (pmd_none(*pmd)) { if (pmd_none(*pmd)) {
pte = ppd->pgtable_area; pte = ppd->pgtable_area;
memset(pte, 0, sizeof(pte) * PTRS_PER_PTE); memset(pte, 0, sizeof(*pte) * PTRS_PER_PTE);
ppd->pgtable_area += sizeof(pte) * PTRS_PER_PTE; ppd->pgtable_area += sizeof(*pte) * PTRS_PER_PTE;
set_pmd(pmd, __pmd(PMD_FLAGS | __pa(pte))); set_pmd(pmd, __pmd(PMD_FLAGS | __pa(pte)));
} }
......
...@@ -1133,6 +1133,21 @@ void test_pkey_syscalls_bad_args(int *ptr, u16 pkey) ...@@ -1133,6 +1133,21 @@ void test_pkey_syscalls_bad_args(int *ptr, u16 pkey)
pkey_assert(err); pkey_assert(err);
} }
void become_child(void)
{
pid_t forkret;
forkret = fork();
pkey_assert(forkret >= 0);
dprintf3("[%d] fork() ret: %d\n", getpid(), forkret);
if (!forkret) {
/* in the child */
return;
}
exit(0);
}
/* Assumes that all pkeys other than 'pkey' are unallocated */ /* Assumes that all pkeys other than 'pkey' are unallocated */
void test_pkey_alloc_exhaust(int *ptr, u16 pkey) void test_pkey_alloc_exhaust(int *ptr, u16 pkey)
{ {
...@@ -1141,7 +1156,7 @@ void test_pkey_alloc_exhaust(int *ptr, u16 pkey) ...@@ -1141,7 +1156,7 @@ void test_pkey_alloc_exhaust(int *ptr, u16 pkey)
int nr_allocated_pkeys = 0; int nr_allocated_pkeys = 0;
int i; int i;
for (i = 0; i < NR_PKEYS*2; i++) { for (i = 0; i < NR_PKEYS*3; i++) {
int new_pkey; int new_pkey;
dprintf1("%s() alloc loop: %d\n", __func__, i); dprintf1("%s() alloc loop: %d\n", __func__, i);
new_pkey = alloc_pkey(); new_pkey = alloc_pkey();
...@@ -1152,19 +1167,25 @@ void test_pkey_alloc_exhaust(int *ptr, u16 pkey) ...@@ -1152,19 +1167,25 @@ void test_pkey_alloc_exhaust(int *ptr, u16 pkey)
if ((new_pkey == -1) && (errno == ENOSPC)) { if ((new_pkey == -1) && (errno == ENOSPC)) {
dprintf2("%s() failed to allocate pkey after %d tries\n", dprintf2("%s() failed to allocate pkey after %d tries\n",
__func__, nr_allocated_pkeys); __func__, nr_allocated_pkeys);
break; } else {
} /*
* Ensure the number of successes never
* exceeds the number of keys supported
* in the hardware.
*/
pkey_assert(nr_allocated_pkeys < NR_PKEYS); pkey_assert(nr_allocated_pkeys < NR_PKEYS);
allocated_pkeys[nr_allocated_pkeys++] = new_pkey; allocated_pkeys[nr_allocated_pkeys++] = new_pkey;
} }
dprintf3("%s()::%d\n", __func__, __LINE__);
/* /*
* ensure it did not reach the end of the loop without * Make sure that allocation state is properly
* failure: * preserved across fork().
*/ */
pkey_assert(i < NR_PKEYS*2); if (i == NR_PKEYS*2)
become_child();
}
dprintf3("%s()::%d\n", __func__, __LINE__);
/* /*
* There are 16 pkeys supported in hardware. Three are * There are 16 pkeys supported in hardware. Three are
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment