Commit 3f777e19 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'cve-2020-11884' from emailed bundle

Pull s390 fix from Christian Borntraeger:
 "Fix a race between page table upgrade and uaccess on s390.

  This fixes CVE-2020-11884 which allows for a local kernel crash or
  code execution"

* tag 'cve-2020-11884' from emailed bundle:
  s390/mm: fix page table upgrade vs 2ndary address mode accesses
parents 51184ae3 316ec154
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -64,10 +64,13 @@ mm_segment_t enable_sacf_uaccess(void)
{
	mm_segment_t old_fs;
	unsigned long asce, cr;
	unsigned long flags;

	old_fs = current->thread.mm_segment;
	if (old_fs & 1)
		return old_fs;
	/* protect against a concurrent page table upgrade */
	local_irq_save(flags);
	current->thread.mm_segment |= 1;
	asce = S390_lowcore.kernel_asce;
	if (likely(old_fs == USER_DS)) {
@@ -83,6 +86,7 @@ mm_segment_t enable_sacf_uaccess(void)
		__ctl_load(asce, 7, 7);
		set_cpu_flag(CIF_ASCE_SECONDARY);
	}
	local_irq_restore(flags);
	return old_fs;
}
EXPORT_SYMBOL(enable_sacf_uaccess);
+14 −2
Original line number Diff line number Diff line
@@ -70,8 +70,20 @@ static void __crst_table_upgrade(void *arg)
{
	struct mm_struct *mm = arg;

	if (current->active_mm == mm)
		set_user_asce(mm);
	/* we must change all active ASCEs to avoid the creation of new TLBs */
	if (current->active_mm == mm) {
		S390_lowcore.user_asce = mm->context.asce;
		if (current->thread.mm_segment == USER_DS) {
			__ctl_load(S390_lowcore.user_asce, 1, 1);
			/* Mark user-ASCE present in CR1 */
			clear_cpu_flag(CIF_ASCE_PRIMARY);
		}
		if (current->thread.mm_segment == USER_DS_SACF) {
			__ctl_load(S390_lowcore.user_asce, 7, 7);
			/* enable_sacf_uaccess does all or nothing */
			WARN_ON(!test_cpu_flag(CIF_ASCE_SECONDARY));
		}
	}
	__tlb_flush_local();
}