Received: by 2002:a25:1985:0:0:0:0:0 with SMTP id 127csp4470994ybz; Tue, 28 Apr 2020 11:51:26 -0700 (PDT) X-Google-Smtp-Source: APiQypL6unCWWDsdwCkFhvINdJ/zCrXuER8Yvo1L8Yj8gv3PNM5Jkk4SLkfuNJCwELuXZqvNWOsw X-Received: by 2002:aa7:d344:: with SMTP id m4mr24493356edr.297.1588099886098; Tue, 28 Apr 2020 11:51:26 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1588099886; cv=none; d=google.com; s=arc-20160816; b=K1w1qOtVWaFKIsiz2i5uJqHO4nY9IpdO+CwvcKT6F6dchQ9uSFbkGSpcBO61exXZWS Y1r/5uQz5ZMo82N3fJ8465gNppfIqQKwlo/795zSptR6mNt9X61998sMMr/9n75CZ1pD Jmam2KSJPHxxbRNr04X3yQv1f5I/41RTGs4W0dKsYKHeU2fDPPk88sxg4OxOkIvKH9WB 7zcNeD3UL1VyWlP6dXNTyjCbiUbDoWeNwlfw6lwvPj26dAKzeOL427oWohL62QRiQqJv h2wSHhq+JkHy9IpLM6JogJvVEdCdA+z9T6aoZkJu4oWuLDXUAwf4YVaDsk7g3UW4y7YG h2pg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=VsViQP6J5XlsIYynWGrCNYQVsHnzYCKYmwEwtl7Ltg4=; b=Sl/m96WIWx77jNo0hIj9V23cRCb43Es2+BvaZP1WAnKwH30iPcMnOElr8YKBvGKZFr XPsXUW2yXJbR6LVQOH+9NOBbXd2gYg4wg6DvEk3N9ORNAHg2IhC6kJfXwfLKNPWhqjYV hqBfAkyaNorVy8qV8mdIAiQQ0FhZa3O4PqcL2do4S9iJZcg2NuNjnf5Rc3XZK5qGyspx +1hh9FDMPVTKNLcMnXaC/5KrSqBwgR0fiyOpX27rcUkmsWmsZ4SSIJPlg8ruFo6fteZn czwujA1u5ZFYMP9Yr+9U+GySyrS2+woDnyDrz2q9meu14tIHQ/ZQRG1cNzZy6cUuaBGN SijQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=VPOtuzL8; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id h2si2536802ejc.510.2020.04.28.11.51.02; Tue, 28 Apr 2020 11:51:26 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=VPOtuzL8; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730916AbgD1Stt (ORCPT + 99 others); Tue, 28 Apr 2020 14:49:49 -0400 Received: from mail.kernel.org ([198.145.29.99]:58712 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730862AbgD1Sjs (ORCPT ); Tue, 28 Apr 2020 14:39:48 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 4B8AF20730; Tue, 28 Apr 2020 18:39:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1588099187; bh=p1mEFL7GZrCu3Wlff4cQ8A8VxqTd/adu9gpNmAseRug=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VPOtuzL8w2VafAu7VR9JcFYjKChQuTizUFUD6O0u7SiEMi/Tjv2VPk+Cik9EjWX68 3/V2Sc86CVqQlaXVHLVHRB9QBILHy1b/DADhASz4Ye0wZ4oZVKAfUY95/ov8AiDVdr /AjqReed7M9RkDAq7CXHDrrNKWYLyPZAACqqcgFM= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Al Viro , Gerald Schaefer , Christian Borntraeger Subject: [PATCH 5.6 167/167] s390/mm: fix page table upgrade vs 2ndary address mode accesses Date: Tue, 28 Apr 2020 20:25:43 +0200 Message-Id: <20200428182246.762029529@linuxfoundation.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200428182225.451225420@linuxfoundation.org> References: <20200428182225.451225420@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Christian Borntraeger commit 316ec154810960052d4586b634156c54d0778f74 upstream. A page table upgrade in a kernel section that uses secondary address mode will mess up the kernel instructions as follows: Consider the following scenario: two threads are sharing memory. On CPU1 thread 1 does e.g. strnlen_user(). That gets to old_fs = enable_sacf_uaccess(); len = strnlen_user_srst(src, size); and " la %2,0(%1)\n" " la %3,0(%0,%1)\n" " slgr %0,%0\n" " sacf 256\n" "0: srst %3,%2\n" in strnlen_user_srst(). At that point we are in secondary space mode, control register 1 points to kernel page table and instruction fetching happens via c1, rather than usual c13. Interrupts are not disabled, for obvious reasons. On CPU2 thread 2 does MAP_FIXED mmap(), forcing the upgrade of page table from 3-level to e.g. 4-level one. We'd allocated new top-level table, set it up and now we hit this: notify = 1; spin_unlock_bh(&mm->page_table_lock); } if (notify) on_each_cpu(__crst_table_upgrade, mm, 0); OK, we need to actually change over to use of new page table and we need that to happen in all threads that are currently running. Which happens to include the thread 1. IPI is delivered and we have static void __crst_table_upgrade(void *arg) { struct mm_struct *mm = arg; if (current->active_mm == mm) set_user_asce(mm); __tlb_flush_local(); } run on CPU1. That does static inline void set_user_asce(struct mm_struct *mm) { S390_lowcore.user_asce = mm->context.asce; OK, user page table address updated... __ctl_load(S390_lowcore.user_asce, 1, 1); ... and control register 1 set to it. clear_cpu_flag(CIF_ASCE_PRIMARY); } IPI is run in home space mode, so it's fine - insns are fetched using c13, which always points to kernel page table. But as soon as we return from the interrupt, previous PSW is restored, putting CPU1 back into secondary space mode, at which point we no longer get the kernel instructions from the kernel mapping. The fix is to only fixup the control registers that are currently in use for user processes during the page table update. We must also disable interrupts in enable_sacf_uaccess to synchronize the cr and thread.mm_segment updates against the on_each-cpu. Fixes: 0aaba41b58bc ("s390: remove all code using the access register mode") Cc: stable@vger.kernel.org # 4.15+ Reported-by: Al Viro Reviewed-by: Gerald Schaefer Signed-off-by: Christian Borntraeger Signed-off-by: Greg Kroah-Hartman --- arch/s390/lib/uaccess.c | 4 ++++ arch/s390/mm/pgalloc.c | 16 ++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) --- a/arch/s390/lib/uaccess.c +++ b/arch/s390/lib/uaccess.c @@ -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); --- a/arch/s390/mm/pgalloc.c +++ b/arch/s390/mm/pgalloc.c @@ -70,8 +70,20 @@ static void __crst_table_upgrade(void *a { 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(); }