From patchwork Fri Apr 22 22:04:09 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yury Norov X-Patchwork-Id: 12824112 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 761A5C433F5 for ; Fri, 22 Apr 2022 22:05:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:Message-Id:Date:Subject:Cc :To:From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: List-Owner; bh=ojgyKLn8myrYvg6LUR78VrMAaXz/cyboYMsWG9kDxzg=; b=NF+8VMk0iSFKff tqQEwbgruToP8xbptaQH0F96jkpsKDsHuxGyIT9Ce5KAZTHOVdakQL673/KeRuZWjtazAx/vCiHpR cVz9IpmthLMpy+RNi+5C4BiANxkfqvO7dTUJXjJcTvgLUB1jXMI3bCJijBZT82LeO/OG6uCzrtHNj RbImK+YbfQgktmf8qUEaPc9nVihCO9AokBXDLabSwg4acNXJi41wgNMRqS0bhv6LcngRJQZRkrnWu ryy15fVFYa5o+toNR0v5YDjbmZxXvMHgAf8cCDw/aRK5uX3GxSBt5gAaS6U88DpI2yA6TPrRkzMwK CAYyCFLhy20hIVRDSZLQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1ni1Nz-002dsf-1V; Fri, 22 Apr 2022 22:04:19 +0000 Received: from mail-qt1-x82c.google.com ([2607:f8b0:4864:20::82c]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1ni1Nv-002drA-Ed for linux-arm-kernel@lists.infradead.org; Fri, 22 Apr 2022 22:04:17 +0000 Received: by mail-qt1-x82c.google.com with SMTP id fu34so6480033qtb.8 for ; Fri, 22 Apr 2022 15:04:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=yCHSC34arsQtBqUXmCj99wEfbz8l2mnQAFiJJnf/+tY=; b=qmfdiGivhoyIkipKSQ76fwohGQ0nvXqS1+nsk1poehqsmrff2+K/16UChzb38m3hQj gs1WQKtzgyTq2mMctaVd0Jt2zzr2zG2IqKNCLcM+nEG1TMLoqPiXqLQnEv2Kw/ioeAJK ZmU7plVLbatnN/8IoNWr7J+l5Wy6Zii8lL9NIw45KNmoFUNSf8s9KsWY5DStfUeCGP+f CI/b9EW51ScAA7B8x06oMrq5b/tsAEYP7ITb4x+lGfSbrvnafuwL1l1jIL13rQqu2E5u 71ghj+41o4siscitqftFUUVKGxB5KIUTREv6uiiQuexYnJRdpeQnRZcVNkEvG+bQ+Y3D kSjw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=yCHSC34arsQtBqUXmCj99wEfbz8l2mnQAFiJJnf/+tY=; b=5HsUg5Oy/O7iD9L1xkfY4nkPaRJhWj+SwY4IfKLe8EP7GDK+V1LjEi0BiokAss7ZER 8g7sM5WULKthb/H1v3jvCwdQLjqqxiGa+9kS1vcVbR/V8cVpujFMTVXjAUsEFOv+05GZ fKpz0pWBtnBNC6K7vZfHHxH4qObyyTj4x7ZA0GWcJebJ3g7NH3rz9w72pk6Do4cOPTrj reLNLx3K2xECkDZvP0sfVry6yIyht0eJeAP2i20/1imG7iy6A8+CxYIkALwjjyb2YJwt WNZ5Dn3UX2bZz39nUIWJYZ3yn2Wf7MzZm2I+uhOnfwmA6/YgeCn7E38WJBNge/AlOv0g ieAA== X-Gm-Message-State: AOAM530H2IaHwPsmCdTXEizh+pd7xEGTcBj+A6xNZfHgKymr1s1u6Go3 /ibTtUXmilqiTLKyVzzqWzM= X-Google-Smtp-Source: ABdhPJyz1y2RUabYBwdobyv5hbJm72+B1Hxi8qwHEg8tyJQ5dCwv2+SJtFNrZtoMkdp7DOqnRqQujg== X-Received: by 2002:a05:622a:1a86:b0:2f3:4be4:42dd with SMTP id s6-20020a05622a1a8600b002f34be442ddmr4886306qtc.55.1650665052201; Fri, 22 Apr 2022 15:04:12 -0700 (PDT) Received: from localhost ([2601:c4:c432:7d0:efbc:f1b5:7b2c:5d4c]) by smtp.gmail.com with ESMTPSA id h75-20020a379e4e000000b0069db8210ffbsm1440267qke.12.2022.04.22.15.04.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 22 Apr 2022 15:04:11 -0700 (PDT) From: Yury Norov To: Andrew Morton , Alexey Klimov , Anshuman Khandual , Catalin Marinas , Ding Tianhong , Mark Rutland , Matthew Wilcox , Nicholas Piggin , Robin Murphy , Russell King , Will Deacon , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org Cc: Yury Norov Subject: [PATCH v3] vmap(): don't allow invalid pages Date: Fri, 22 Apr 2022 15:04:09 -0700 Message-Id: <20220422220410.1308706-1-yury.norov@gmail.com> X-Mailer: git-send-email 2.32.0 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220422_150415_518792_913C16EC X-CRM114-Status: GOOD ( 16.97 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org vmap() takes struct page *pages as one of arguments, and user may provide an invalid pointer which may lead to corrupted translation table. An example of such behaviour is erroneous usage of virt_to_page(): vaddr1 = dma_alloc_coherent() page = virt_to_page() // Wrong here ... vaddr2 = vmap(page) memset(vaddr2) // Faulting here virt_to_page() returns a wrong pointer if vaddr1 is not a linear kernel address. The problem is that vmap() populates pte with bad pfn successfully, and it's much harder to debug at memory access time. This case should be caught by DEBUG_VIRTUAL being that enabled, but it's not enabled in popular distros. Kernel already checks the pages against NULL. In the case mentioned above, however, the address is not NULL, and it's big enough so that the hardware generated Address Size Abort on arm64: [ 665.484101] Unhandled fault at 0xffff8000252cd000 [ 665.488807] Mem abort info: [ 665.491617] ESR = 0x96000043 [ 665.494675] EC = 0x25: DABT (current EL), IL = 32 bits [ 665.499985] SET = 0, FnV = 0 [ 665.503039] EA = 0, S1PTW = 0 [ 665.506167] Data abort info: [ 665.509047] ISV = 0, ISS = 0x00000043 [ 665.512882] CM = 0, WnR = 1 [ 665.515851] swapper pgtable: 4k pages, 48-bit VAs, pgdp=00000000818cb000 [ 665.522550] [ffff8000252cd000] pgd=000000affcfff003, pud=000000affcffe003, pmd=0000008fad8c3003, pte=00688000a5217713 [ 665.533160] Internal error: level 3 address size fault: 96000043 [#1] SMP [ 665.539936] Modules linked in: [...] [ 665.616212] CPU: 178 PID: 13199 Comm: test Tainted: P OE 5.4.0-84-generic #94~18.04.1-Ubuntu [ 665.626806] Hardware name: HPE Apollo 70 /C01_APACHE_MB , BIOS L50_5.13_1.0.6 07/10/2018 [ 665.636618] pstate: 80400009 (Nzcv daif +PAN -UAO) [ 665.641407] pc : __memset+0x38/0x188 [ 665.645146] lr : test+0xcc/0x3f8 [ 665.650184] sp : ffff8000359bb840 [ 665.653486] x29: ffff8000359bb840 x28: 0000000000000000 [ 665.658785] x27: 0000000000000000 x26: 0000000000231000 [ 665.664083] x25: ffff00ae660f6110 x24: ffff00ae668cb800 [ 665.669382] x23: 0000000000000001 x22: ffff00af533e5000 [ 665.674680] x21: 0000000000001000 x20: 0000000000000000 [ 665.679978] x19: ffff00ae66950000 x18: ffffffffffffffff [ 665.685276] x17: 00000000588636a5 x16: 0000000000000013 [ 665.690574] x15: ffffffffffffffff x14: 000000000007ffff [ 665.695872] x13: 0000000080000000 x12: 0140000000000000 [ 665.701170] x11: 0000000000000041 x10: ffff8000652cd000 [ 665.706468] x9 : ffff8000252cf000 x8 : ffff8000252cd000 [ 665.711767] x7 : 0303030303030303 x6 : 0000000000001000 [ 665.717065] x5 : ffff8000252cd000 x4 : 0000000000000000 [ 665.722363] x3 : ffff8000252cdfff x2 : 0000000000000001 [ 665.727661] x1 : 0000000000000003 x0 : ffff8000252cd000 [ 665.732960] Call trace: [ 665.735395] __memset+0x38/0x188 [...] Interestingly, this abort happens even if copy_from_kernel_nofault() is used, which is quite inconvenient for debugging purposes. This patch adds a pfn_valid() check into vmap() path, so that invalid mapping will not be created; WARN_ON() is used to let client code know that something goes wrong, and it's not a regular EINVAL situation. Suggested-by: Matthew Wilcox (Oracle) Signed-off-by: Yury Norov (NVIDIA) --- RFC: https://lkml.org/lkml/2022/1/18/815 v1: https://lkml.org/lkml/2022/1/18/1026 v2: https://lore.kernel.org/linux-mm/20220118235244.540103-1-yury.norov@gmail.com/ v3: Add more details and example in commit message. mm/vmalloc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mm/vmalloc.c b/mm/vmalloc.c index e163372d3967..9b51a290d133 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -478,6 +478,9 @@ static int vmap_pages_pte_range(pmd_t *pmd, unsigned long addr, return -EBUSY; if (WARN_ON(!page)) return -ENOMEM; + if (WARN_ON(!pfn_valid(page_to_pfn(page)))) + return -EINVAL; + set_pte_at(&init_mm, addr, pte, mk_pte(page, prot)); (*nr)++; } while (pte++, addr += PAGE_SIZE, addr != end);