From owner-svn-src-head@freebsd.org Wed Sep 2 15:55:17 2020 Return-Path: Delivered-To: svn-src-head@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 29ADE3DB01E; Wed, 2 Sep 2020 15:55:17 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4BhT6Y0Ngpz4v1f; Wed, 2 Sep 2020 15:55:17 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id C6DC4CA72; Wed, 2 Sep 2020 15:55:16 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 082FtGQX018237; Wed, 2 Sep 2020 15:55:16 GMT (envelope-from kib@FreeBSD.org) Received: (from kib@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 082FtGNT018236; Wed, 2 Sep 2020 15:55:16 GMT (envelope-from kib@FreeBSD.org) Message-Id: <202009021555.082FtGNT018236@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kib set sender to kib@FreeBSD.org using -f From: Konstantin Belousov Date: Wed, 2 Sep 2020 15:55:16 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r365251 - head/sys/amd64/amd64 X-SVN-Group: head X-SVN-Commit-Author: kib X-SVN-Commit-Paths: head/sys/amd64/amd64 X-SVN-Commit-Revision: 365251 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 02 Sep 2020 15:55:17 -0000 Author: kib Date: Wed Sep 2 15:55:16 2020 New Revision: 365251 URL: https://svnweb.freebsd.org/changeset/base/365251 Log: Fix a page table pages leak after LA57. If the call to _pmap_allocpte() is not sleepable, it is possible that allocation of PML4 or PDP page is successful but either PDP or PD page is not. Restructured code in _pmap_allocpte() leaves zero-referenced page in the paging structure. Handle it by checking refcount of the page one level above failed alloc and free that page if its reference count is zero. Reported and tested by: pho Reviewed by: markj Sponsored by: The FreeBSD Foundation Differential revision: https://reviews.freebsd.org/D26293 Modified: head/sys/amd64/amd64/pmap.c Modified: head/sys/amd64/amd64/pmap.c ============================================================================== --- head/sys/amd64/amd64/pmap.c Wed Sep 2 15:20:10 2020 (r365250) +++ head/sys/amd64/amd64/pmap.c Wed Sep 2 15:55:16 2020 (r365251) @@ -4101,6 +4101,21 @@ pmap_pinit(pmap_t pmap) return (pmap_pinit_type(pmap, PT_X86, pmap_flags)); } +static void +pmap_allocpte_free_unref(pmap_t pmap, vm_offset_t va, pt_entry_t *pte) +{ + vm_page_t mpg; + struct spglist free; + + mpg = PHYS_TO_VM_PAGE(*pte & PG_FRAME); + if (mpg->ref_count != 0) + return; + SLIST_INIT(&free); + _pmap_unwire_ptp(pmap, va, mpg, &free); + pmap_invalidate_page(pmap, va); + vm_page_free_pages_toq(&free, true); +} + static pml4_entry_t * pmap_allocpte_getpml4(pmap_t pmap, struct rwlock **lockp, vm_offset_t va, bool addref) @@ -4157,8 +4172,12 @@ pmap_allocpte_getpdp(pmap_t pmap, struct rwlock **lock if ((*pml4 & PG_V) == 0) { /* Have to allocate a new pdp, recurse */ if (_pmap_allocpte(pmap, pmap_pml4e_pindex(va), lockp, va) == - NULL) + NULL) { + if (pmap_is_la57(pmap)) + pmap_allocpte_free_unref(pmap, va, + pmap_pml5e(pmap, va)); return (NULL); + } allocated = true; } else { allocated = false; @@ -4332,6 +4351,8 @@ _pmap_allocpte(pmap_t pmap, vm_pindex_t ptepindex, str /* Have to allocate a new pd, recurse */ if (_pmap_allocpte(pmap, pmap_pdpe_pindex(va), lockp, va) == NULL) { + pmap_allocpte_free_unref(pmap, va, + pmap_pml4e(pmap, va)); vm_page_unwire_noq(m); vm_page_free_zero(m); return (NULL);