From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9EE7CC43603 for ; Wed, 11 Dec 2019 15:24:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 71B2024671 for ; Wed, 11 Dec 2019 15:24:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1576077896; bh=ff0QTGzeYj8UTsK1lZeu7l1UwpxXfyO2RNO2yWWQ4W8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=Drkw0mCr0zbE4NFMtBi1/iol2PLQe7rjlvvmApTiVILfV+PKUwMs0K/l3lgj3pYry fdqsMcNHQG0zL4Aq2qyTzLSWGd5wN5cfFvRq8SoR6K+2wIZSOJrMFGwiaHTm5wIIkc ut8kPOL50XxTIdfS6Eon1U++L1o6KYBmHwquUzDA= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732920AbfLKPYz (ORCPT ); Wed, 11 Dec 2019 10:24:55 -0500 Received: from mail.kernel.org ([198.145.29.99]:56334 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732906AbfLKPYw (ORCPT ); Wed, 11 Dec 2019 10:24:52 -0500 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 40892208C3; Wed, 11 Dec 2019 15:24:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1576077891; bh=ff0QTGzeYj8UTsK1lZeu7l1UwpxXfyO2RNO2yWWQ4W8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=2OwYYKsY+ulFoCYYv5yi6rPl4KetTKUWb6tJVqXcKAWX0qcwUYchhBgXvtCUm5Cwv fBNGufbyCGl3T+88g453oUsuiasy97+yPbfJdv0hBpGNaKcqTsX3p72sPYHM2xyn02 d7jc+u5ANTorVInVVklaXuvypQjiZE0in9cKYLuQ= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Borislav Petkov , Joerg Roedel , Andy Lutomirski , Borislav Petkov , Dave Hansen , Joerg Roedel , Linus Torvalds , Peter Zijlstra , Thomas Gleixner , hpa@zytor.com, Ingo Molnar Subject: [PATCH 4.19 210/243] x86/mm/32: Sync only to VMALLOC_END in vmalloc_sync_all() Date: Wed, 11 Dec 2019 16:06:12 +0100 Message-Id: <20191211150353.514527388@linuxfoundation.org> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20191211150339.185439726@linuxfoundation.org> References: <20191211150339.185439726@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: Joerg Roedel commit 9a62d20027da3164a22244d9f022c0c987261687 upstream. The job of vmalloc_sync_all() is to help the lazy freeing of vmalloc() ranges: before such vmap ranges are reused we make sure that they are unmapped from every task's page tables. This is really easy on pagetable setups where the kernel page tables are shared between all tasks - this is the case on 32-bit kernels with SHARED_KERNEL_PMD = 1. But on !SHARED_KERNEL_PMD 32-bit kernels this involves iterating over the pgd_list and clearing all pmd entries in the pgds that are cleared in the init_mm.pgd, which is the reference pagetable that the vmalloc() code uses. In that context the current practice of vmalloc_sync_all() iterating until FIX_ADDR_TOP is buggy: for (address = VMALLOC_START & PMD_MASK; address >= TASK_SIZE_MAX && address < FIXADDR_TOP; address += PMD_SIZE) { struct page *page; Because iterating up to FIXADDR_TOP will involve a lot of non-vmalloc address ranges: VMALLOC -> PKMAP -> LDT -> CPU_ENTRY_AREA -> FIX_ADDR This is mostly harmless for the FIX_ADDR and CPU_ENTRY_AREA ranges that don't clear their pmds, but it's lethal for the LDT range, which relies on having different mappings in different processes, and 'synchronizing' them in the vmalloc sense corrupts those pagetable entries (clearing them). This got particularly prominent with PTI, which turns SHARED_KERNEL_PMD off and makes this the dominant mapping mode on 32-bit. To make LDT working again vmalloc_sync_all() must only iterate over the volatile parts of the kernel address range that are identical between all processes. So the correct check in vmalloc_sync_all() is "address < VMALLOC_END" to make sure the VMALLOC areas are synchronized and the LDT mapping is not falsely overwritten. The CPU_ENTRY_AREA and the FIXMAP area are no longer synced either, but this is not really a proplem since their PMDs get established during bootup and never change. This change fixes the ldt_gdt selftest in my setup. [ mingo: Fixed up the changelog to explain the logic and modified the copying to only happen up until VMALLOC_END. ] Reported-by: Borislav Petkov Tested-by: Borislav Petkov Signed-off-by: Joerg Roedel Cc: Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Dave Hansen Cc: Joerg Roedel Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: hpa@zytor.com Fixes: 7757d607c6b3: ("x86/pti: Allow CONFIG_PAGE_TABLE_ISOLATION for x86_32") Link: https://lkml.kernel.org/r/20191126111119.GA110513@gmail.com Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/mm/fault.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -281,7 +281,7 @@ void vmalloc_sync_all(void) return; for (address = VMALLOC_START & PMD_MASK; - address >= TASK_SIZE_MAX && address < FIXADDR_TOP; + address >= TASK_SIZE_MAX && address < VMALLOC_END; address += PMD_SIZE) { struct page *page;