From patchwork Wed Oct 6 12:42:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matthew Wilcox X-Patchwork-Id: 12539367 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3F7B3C433F5 for ; Wed, 6 Oct 2021 12:44:26 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id C487E61177 for ; Wed, 6 Oct 2021 12:44:21 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org C487E61177 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=infradead.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=kvack.org Received: by kanga.kvack.org (Postfix) id 4CFDB940007; Wed, 6 Oct 2021 08:44:21 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 47F456B0071; Wed, 6 Oct 2021 08:44:21 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 36EC8940007; Wed, 6 Oct 2021 08:44:21 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0228.hostedemail.com [216.40.44.228]) by kanga.kvack.org (Postfix) with ESMTP id 284906B006C for ; Wed, 6 Oct 2021 08:44:21 -0400 (EDT) Received: from smtpin30.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay05.hostedemail.com (Postfix) with ESMTP id E106C18037D50 for ; Wed, 6 Oct 2021 12:44:20 +0000 (UTC) X-FDA: 78665980680.30.0410819 Received: from casper.infradead.org (casper.infradead.org [90.155.50.34]) by imf09.hostedemail.com (Postfix) with ESMTP id 7FE6D30008C7 for ; Wed, 6 Oct 2021 12:44:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To: Content-Type:Content-ID:Content-Description; bh=o9WmfUO+Fo5cx+wqyijCOv0cN5Ciqh5Mu4Par0voGQ8=; b=OQTJPRMnP9iK1ylqcGNb8daffX wW1kQCHotKMvFuljVY60WLF20z6pWqxWio7aufpD3wrYtwEs0fQIFVbAW9DZiOJGyS+O6W8kzsZjJ qUX5KFNQlQCTKHu6YvRvmYinkOQpPRtq4wYZ30fAxbMH+HnC5m9zlQeK9/L8uGu7vscCXXwNeoQ1B s0iO2ZhYiB5OKJPbQ5QEKwgSgP1V7430jtWZTo0uJylJFXne+kuqYEh5YnJq0NyPH1uADo9dnOv2P Q2KYZc5LxVui8U9VkpTxAa/6I/xFD9BYjDpLQIJgo+2eBmUYt8OPPcX4MRc3UDCMMe2yZ7aVdnhSE AnQZnM4g==; Received: from willy by casper.infradead.org with local (Exim 4.94.2 #2 (Red Hat Linux)) id 1mY6GF-000sWe-S8; Wed, 06 Oct 2021 12:43:18 +0000 From: "Matthew Wilcox (Oracle)" To: Kees Cook Cc: "Matthew Wilcox (Oracle)" , linux-mm@kvack.org, Thomas Gleixner Subject: [PATCH v2 1/3] mm/usercopy: Check kmap addresses properly Date: Wed, 6 Oct 2021 13:42:24 +0100 Message-Id: <20211006124226.209484-2-willy@infradead.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211006124226.209484-1-willy@infradead.org> References: <20211006124226.209484-1-willy@infradead.org> MIME-Version: 1.0 Authentication-Results: imf09.hostedemail.com; dkim=pass header.d=infradead.org header.s=casper.20170209 header.b=OQTJPRMn; spf=none (imf09.hostedemail.com: domain of willy@infradead.org has no SPF policy when checking 90.155.50.34) smtp.mailfrom=willy@infradead.org; dmarc=none X-Rspamd-Server: rspam04 X-Rspamd-Queue-Id: 7FE6D30008C7 X-Stat-Signature: kubrmaixgwhaq79haex9zfa4hkwtzn95 X-HE-Tag: 1633524260-367977 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: If you are copying to an address in the kmap region, you may not copy across a page boundary, no matter what the size of the underlying allocation. You can't kmap() a slab page because slab pages always come from low memory. Signed-off-by: Matthew Wilcox (Oracle) Acked-by: Kees Cook --- arch/x86/include/asm/highmem.h | 1 + include/linux/highmem-internal.h | 10 ++++++++++ mm/usercopy.c | 16 ++++++++++------ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/highmem.h b/arch/x86/include/asm/highmem.h index 032e020853aa..731ee7cc40a5 100644 --- a/arch/x86/include/asm/highmem.h +++ b/arch/x86/include/asm/highmem.h @@ -26,6 +26,7 @@ #include #include #include +#include /* declarations for highmem.c */ extern unsigned long highstart_pfn, highend_pfn; diff --git a/include/linux/highmem-internal.h b/include/linux/highmem-internal.h index 4aa1031d3e4c..97d6dc836749 100644 --- a/include/linux/highmem-internal.h +++ b/include/linux/highmem-internal.h @@ -143,6 +143,11 @@ static inline void totalhigh_pages_add(long count) atomic_long_add(count, &_totalhigh_pages); } +static inline bool is_kmap_addr(const void *x) +{ + unsigned long addr = (unsigned long)x; + return addr >= PKMAP_ADDR(0) && addr < PKMAP_ADDR(LAST_PKMAP); +} #else /* CONFIG_HIGHMEM */ static inline struct page *kmap_to_page(void *addr) @@ -223,6 +228,11 @@ static inline void __kunmap_atomic(void *addr) static inline unsigned int nr_free_highpages(void) { return 0; } static inline unsigned long totalhigh_pages(void) { return 0UL; } +static inline bool is_kmap_addr(const void *x) +{ + return false; +} + #endif /* CONFIG_HIGHMEM */ /* diff --git a/mm/usercopy.c b/mm/usercopy.c index b3de3c4eefba..8c039302465f 100644 --- a/mm/usercopy.c +++ b/mm/usercopy.c @@ -228,12 +228,16 @@ static inline void check_heap_object(const void *ptr, unsigned long n, if (!virt_addr_valid(ptr)) return; - /* - * When CONFIG_HIGHMEM=y, kmap_to_page() will give either the - * highmem page or fallback to virt_to_page(). The following - * is effectively a highmem-aware virt_to_head_page(). - */ - page = compound_head(kmap_to_page((void *)ptr)); + if (is_kmap_addr(ptr)) { + unsigned long page_end = (unsigned long)ptr | (PAGE_SIZE - 1); + + if ((unsigned long)ptr + n - 1 > page_end) + usercopy_abort("kmap", NULL, to_user, + offset_in_page(ptr), n); + return; + } + + page = virt_to_head_page(ptr); if (PageSlab(page)) { /* Check slab allocator for flags and size. */ From patchwork Wed Oct 6 12:42:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matthew Wilcox X-Patchwork-Id: 12539369 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5D6FFC433F5 for ; Wed, 6 Oct 2021 12:45:17 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 0102161130 for ; Wed, 6 Oct 2021 12:45:16 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 0102161130 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=infradead.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=kvack.org Received: by kanga.kvack.org (Postfix) id 79121900002; Wed, 6 Oct 2021 08:45:16 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 716A66B0071; Wed, 6 Oct 2021 08:45:16 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 5DE42900002; Wed, 6 Oct 2021 08:45:16 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0004.hostedemail.com [216.40.44.4]) by kanga.kvack.org (Postfix) with ESMTP id 47A436B006C for ; Wed, 6 Oct 2021 08:45:16 -0400 (EDT) Received: from smtpin39.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay03.hostedemail.com (Postfix) with ESMTP id EEDCB8249980 for ; Wed, 6 Oct 2021 12:45:15 +0000 (UTC) X-FDA: 78665982990.39.B523442 Received: from casper.infradead.org (casper.infradead.org [90.155.50.34]) by imf07.hostedemail.com (Postfix) with ESMTP id AB0091001B22 for ; Wed, 6 Oct 2021 12:45:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To: Content-Type:Content-ID:Content-Description; bh=VDZiPZdOIoG2ugeSGOmR7uNCU45qsXkokayW5iVodM0=; b=kSxk8syTjJrPevoalbfUljbdqo rYuA+VprG9ZxF+pN0isiZ0a5ggNa8NruHbIqzic4EuqJegp+V8xP2UZhhatytHu1Dymhm9zQToOPl 9I6ETNMjdbQzdRf5ZOMRlgGnmWHaURnG+aXXAn6GW6l7CWrJE3u+3c3kWnlF4onXa0TTrQCLfP3Pw /0ORv1ai0o4ZHCAKkdDCkmeAg9/Pu2aAwMWDQWGoezISmoG7ZRJpmU4BKqpOO9MXc6l9r/c8YTVW4 LxKbG1dB3No5IIugGZCsgBBix4yk64mqup5h9p8tKX+PXkZlRtotZsRE7+6o7/yi1qEt/QQrklvej lStaadmA==; Received: from willy by casper.infradead.org with local (Exim 4.94.2 #2 (Red Hat Linux)) id 1mY6Gr-000sXu-N4; Wed, 06 Oct 2021 12:43:59 +0000 From: "Matthew Wilcox (Oracle)" To: Kees Cook Cc: "Matthew Wilcox (Oracle)" , linux-mm@kvack.org, Thomas Gleixner Subject: [PATCH v2 2/3] mm/usercopy: Detect vmalloc overruns Date: Wed, 6 Oct 2021 13:42:25 +0100 Message-Id: <20211006124226.209484-3-willy@infradead.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211006124226.209484-1-willy@infradead.org> References: <20211006124226.209484-1-willy@infradead.org> MIME-Version: 1.0 Authentication-Results: imf07.hostedemail.com; dkim=pass header.d=infradead.org header.s=casper.20170209 header.b=kSxk8syT; spf=none (imf07.hostedemail.com: domain of willy@infradead.org has no SPF policy when checking 90.155.50.34) smtp.mailfrom=willy@infradead.org; dmarc=none X-Rspamd-Server: rspam04 X-Rspamd-Queue-Id: AB0091001B22 X-Stat-Signature: oug4166xwrbqcsphqshu4s7w6zs9gih7 X-HE-Tag: 1633524315-504749 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: If you have a vmalloc() allocation, or an address from calling vmap(), you cannot overrun the vm_area which describes it, regardless of the size of the underlying allocation. This probably doesn't do much for security because vmalloc comes with guard pages these days, but it prevents usercopy aborts when copying to a vmap() of smaller pages. Signed-off-by: Matthew Wilcox (Oracle) Acked-by: Kees Cook --- mm/usercopy.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/mm/usercopy.c b/mm/usercopy.c index 8c039302465f..63476e1506e0 100644 --- a/mm/usercopy.c +++ b/mm/usercopy.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -237,6 +238,21 @@ static inline void check_heap_object(const void *ptr, unsigned long n, return; } + if (is_vmalloc_addr(ptr)) { + struct vm_struct *vm = find_vm_area(ptr); + unsigned long offset; + + if (!vm) { + usercopy_abort("vmalloc", "no area", to_user, 0, n); + return; + } + + offset = ptr - vm->addr; + if (offset + n > vm->size) + usercopy_abort("vmalloc", NULL, to_user, offset, n); + return; + } + page = virt_to_head_page(ptr); if (PageSlab(page)) { From patchwork Wed Oct 6 12:42:26 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matthew Wilcox X-Patchwork-Id: 12539371 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7B996C433EF for ; Wed, 6 Oct 2021 12:46:46 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 28F1460F59 for ; Wed, 6 Oct 2021 12:46:46 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 28F1460F59 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=infradead.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=kvack.org Received: by kanga.kvack.org (Postfix) id B35C86B006C; Wed, 6 Oct 2021 08:46:45 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id AE57E900002; Wed, 6 Oct 2021 08:46:45 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 9ADBA6B0073; Wed, 6 Oct 2021 08:46:45 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0096.hostedemail.com [216.40.44.96]) by kanga.kvack.org (Postfix) with ESMTP id 899746B006C for ; Wed, 6 Oct 2021 08:46:45 -0400 (EDT) Received: from smtpin35.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay02.hostedemail.com (Postfix) with ESMTP id 3BE8E2AEE4 for ; Wed, 6 Oct 2021 12:46:45 +0000 (UTC) X-FDA: 78665986770.35.955B899 Received: from casper.infradead.org (casper.infradead.org [90.155.50.34]) by imf29.hostedemail.com (Postfix) with ESMTP id E0E249013A4F for ; Wed, 6 Oct 2021 12:46:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To: Content-Type:Content-ID:Content-Description; bh=F9+gzjnmeCRoXMNmnYDpwpAyHVo53iZYHJVy+GWxplw=; b=rX49CiluVC1r7n+HoTRSFlD5/+ KZoQGTghfgS5JgEHFeTj+Y4k6Vn9xTNkEdRDkb61fBIPoOhCcY9fjCBQbnKFiJtq7XCDJ0RVblwJG FlNhMo+DHCeL2j6MkwfLXKwFhMrKAvJqhF0PI5ncofDcqI6V+rzwkX8bwQOoNM1bTZ5fuKO08mT6X v+hSfPvhIIJa5nDlFKWUgCMdXteOBj7f161vI47L9u/CjAV6+25SsgaSZgsIfiaofdhRP18Nvd4Eb k7XdUH+0H/x+axJeK1w26tcXMYnFaXPdJ7PPV8EYLZEd0eVgNxb+FxH/v1H4DSzSnstEpfH4eVMS7 BhHriixQ==; Received: from willy by casper.infradead.org with local (Exim 4.94.2 #2 (Red Hat Linux)) id 1mY6Ho-000sat-Lz; Wed, 06 Oct 2021 12:44:58 +0000 From: "Matthew Wilcox (Oracle)" To: Kees Cook Cc: "Matthew Wilcox (Oracle)" , linux-mm@kvack.org, Thomas Gleixner Subject: [PATCH v2 3/3] mm/usercopy: Detect compound page overruns Date: Wed, 6 Oct 2021 13:42:26 +0100 Message-Id: <20211006124226.209484-4-willy@infradead.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211006124226.209484-1-willy@infradead.org> References: <20211006124226.209484-1-willy@infradead.org> MIME-Version: 1.0 X-Rspamd-Queue-Id: E0E249013A4F X-Stat-Signature: jae9pufagjeqpk3w99w8ajjppdatt4ft Authentication-Results: imf29.hostedemail.com; dkim=pass header.d=infradead.org header.s=casper.20170209 header.b=rX49Cilu; spf=none (imf29.hostedemail.com: domain of willy@infradead.org has no SPF policy when checking 90.155.50.34) smtp.mailfrom=willy@infradead.org; dmarc=none X-Rspamd-Server: rspam06 X-HE-Tag: 1633524404-937031 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: Move the compound page overrun detection out of CONFIG_HARDENED_USERCOPY_PAGESPAN so it's enabled for more people. Signed-off-by: Matthew Wilcox (Oracle) Acked-by: Kees Cook --- mm/usercopy.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mm/usercopy.c b/mm/usercopy.c index 63476e1506e0..b825c4344917 100644 --- a/mm/usercopy.c +++ b/mm/usercopy.c @@ -194,11 +194,6 @@ static inline void check_page_span(const void *ptr, unsigned long n, ((unsigned long)end & (unsigned long)PAGE_MASK))) return; - /* Allow if fully inside the same compound (__GFP_COMP) page. */ - endpage = virt_to_head_page(end); - if (likely(endpage == page)) - return; - /* * Reject if range is entirely either Reserved (i.e. special or * device memory), or CMA. Otherwise, reject since the object spans @@ -258,6 +253,11 @@ static inline void check_heap_object(const void *ptr, unsigned long n, if (PageSlab(page)) { /* Check slab allocator for flags and size. */ __check_heap_object(ptr, n, page, to_user); + } else if (PageHead(page)) { + /* A compound allocation */ + unsigned long offset = ptr - page_address(page); + if (offset + n > page_size(page)) + usercopy_abort("page alloc", NULL, to_user, offset, n); } else { /* Verify object does not incorrectly span multiple pages. */ check_page_span(ptr, n, page, to_user);