Received: by 2002:a05:6a10:af89:0:0:0:0 with SMTP id iu9csp1191662pxb; Fri, 21 Jan 2022 11:54:53 -0800 (PST) X-Google-Smtp-Source: ABdhPJx2gOsnXnEkTXRVDLEOAuVLdKKZvGBGQyfeW9o7WecxX6kGJZYPJ1hZjUOI05lAwIBD+f4C X-Received: by 2002:a17:902:dac7:b0:14a:8d4a:78c5 with SMTP id q7-20020a170902dac700b0014a8d4a78c5mr5539462plx.78.1642794892869; Fri, 21 Jan 2022 11:54:52 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1642794892; cv=none; d=google.com; s=arc-20160816; b=CQULtEK0bFfdfYiXXUbGvBNPuktpA9rGJQ+IYlazSe1sUNQyWZzdMoRJnwlOe0Rd9f tH42yXeWbWPp5LccVkGsn6tTsQln/FQ1a6lwAkYZLnqhUHJN6QMcDHFlpHgSp0F3gUd9 4SOXej94xWoTBWWMhsOVyfvBN4FrQthsMJhxm7X6gd2t0RlGDUnsaB/lq7dSYEE9mbDY RkiTxfJ5anIDCfOIZth9DNF/xpRdmU7zkU5NeSHCBM+6qb0j4XYZU/vzfMvF3yanYiCD YJstk8zDbZ1sepF0JQs1NDrv0xkEk0JjmnEzbCUVgSTNqwiiaxwtgJrTGtCBQlH5R3Np A55A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:in-reply-to:content-disposition:mime-version :references:message-id:subject:cc:to:from:date; bh=bVNkwx8RBoB3BpP/Vikfru9jnVV8eZHIzFHAb3bMC1g=; b=waat95Pnq4PWLqaoOSpJQL0UJJW/hEFW6+GRQQfjzLzyVGoJ+RM9aPO4PQUUWBfqWA 0snAn6oU1e0QeY3OQpUPGgahx8I5MUXCKZ+4n/JckwVUjzXei/W74SH+7L1YLbweRZRo KgtPn9YVlXkI1cQGzxRPUmd11DzqnOlZbhzWr6jjONNHkgt3d1yQOIWQbleKObYdq8H2 iAl9gwJRbLxx+gKHtrzTn9PGAsX2yDzS+UmsGVcA1lXI2aI3Kb/XNJEyYO8AKaOqn1wI kpnTBgeOvfjHxuGXvC86vqKA3neZa7DHNJzT8Iqyc7fKEydEFyJclWMQp8yk2/3H5CTa /Ubw== ARC-Authentication-Results: i=1; mx.google.com; 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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id z19si7558079pgl.6.2022.01.21.11.54.40; Fri, 21 Jan 2022 11:54:52 -0800 (PST) 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; 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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239619AbiASSGV (ORCPT + 99 others); Wed, 19 Jan 2022 13:06:21 -0500 Received: from foss.arm.com ([217.140.110.172]:34248 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234280AbiASSGV (ORCPT ); Wed, 19 Jan 2022 13:06:21 -0500 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 6CF5C1FB; Wed, 19 Jan 2022 10:06:20 -0800 (PST) Received: from C02TD0UTHF1T.local (unknown [10.57.36.53]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 4B5F53F73D; Wed, 19 Jan 2022 10:06:18 -0800 (PST) Date: Wed, 19 Jan 2022 18:06:14 +0000 From: Mark Rutland To: Yury Norov Cc: Catalin Marinas , Will Deacon , Andrew Morton , Nicholas Piggin , Ding Tianhong , Anshuman Khandual , Matthew Wilcox , Alexey Klimov , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org Subject: Re: [PATCH] vmap(): don't allow invalid pages Message-ID: <20220119180614.GB43919@C02TD0UTHF1T.local> References: <20220118235244.540103-1-yury.norov@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Wed, Jan 19, 2022 at 09:00:23AM -0800, Yury Norov wrote: > On Wed, Jan 19, 2022 at 3:17 AM Mark Rutland wrote: > > > > Hi, > > > > I replied ot the original RFC before spotting this; duplicating those comments > > here because I think they apply regardless of the mechanism used to work around > > this. > > > > On Tue, Jan 18, 2022 at 03:52:44PM -0800, Yury Norov wrote: > > > vmap() takes struct page *pages as one of arguments, and user may provide > > > an invalid pointer which would lead to DABT at address translation later. > > > > > > Currently, kernel checks the pages against NULL. In my case, however, the > > > address was not NULL, and was big enough so that the hardware generated > > > Address Size Abort on arm64. > > > > Can you give an example of when this might happen? It sounds like you're > > actually hitting this, so a backtrace would be nice. > > > > I'm a bit confused as to when why we'd try to vmap() pages that we > > didn't have a legitimate struct page for -- where did these addresses > > come from? > > > > It sounds like this is going wrong at a higher level, and we're passing > > entirely bogus struct page pointers around. This seems like the sort of > > thing DEBUG_VIRTUAL or similar should check when we initially generate > > the struct page pointer. > > Hi Mark, > > This is an out-of-tree code that does: > > vaddr1 = dma_alloc_coherent() > page = virt_to_page() // Wrong here > ... > vaddr2 = vmap(page) > memset(vaddr2) // Fault 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. Ah, ok. FWIW, that case should be caught by DEBUG_VIRTUAL when that's enabled. It would be nice to put that within the commit message, since that clearly indicates this is about catching a mistake in buggy code, and indicates where to go looking next. > > > Interestingly, this abort happens even if copy_from_kernel_nofault() is > > > used, which is quite inconvenient for debugging purposes. > > > > I can go take a look at this, but TBH we never expect to take an address size > > fault to begin with, so this is arguably correct -- it's an internal > > consistency problem. > > > > > This patch adds a pfn_valid() check into vmap() path, so that invalid > > > mapping will not be created. > > > > > > RFC: https://lkml.org/lkml/2022/1/18/815 > > > v1: use pfn_valid() instead of adding an arch-specific > > > arch_vmap_page_valid(). Thanks to Matthew Wilcox for the hint. > > > > > > Signed-off-by: Yury Norov > > > --- > > > mm/vmalloc.c | 2 ++ > > > 1 file changed, 2 insertions(+) > > > > > > diff --git a/mm/vmalloc.c b/mm/vmalloc.c > > > index d2a00ad4e1dd..a4134ee56b10 100644 > > > --- a/mm/vmalloc.c > > > +++ b/mm/vmalloc.c > > > @@ -477,6 +477,8 @@ 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; > > > > My fear here is that for this to fire, we've already passed a bogus struct page > > pointer around the intermediate infrastructure, and any of that might try to > > use it in unsafe ways (in future even if we don't use it today). > > > > I think the fundamental issue here is that we generate a bogus struct page > > pointer at all, and knowing where that came from would help to fix that. > > You're right. That's why WARN_ON() is used for the page == null in the code > above, I believe, - to let client code know that something goes wrong, and it's > not a regular ENOMEM situation. Sure; with all the above in mind I think it's fine for this to be best-effort (e.g. as Robin noted page_to_pfn() might consume parts of the struct page before this), since either way that will indicate roughly where the problem is. As above, it would just be nice for the commit message to be a little more explicit as to that. Thanks, Mark.