mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Sinclair Yeh <syeh@vmware.com>
To: Kees Cook <keescook@chromium.org>
Cc: Thomas Hellstrom <thellstrom@vmware.com>,
	Rik van Riel <riel@redhat.com>, Laura Abbott <labbott@redhat.com>,
	VMware Graphics <linux-graphics-maintainer@vmware.com>,
	Vinson Lee <vlee@freedesktop.org>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Vladimir Davydov <vdavydov.dev@gmail.com>,
	Johannes Weiner <hannes@cmpxchg.org>,
	"Andy Lutomirski" <luto@kernel.org>,
	<linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v2] usercopy: remove page-spanning test for now
Date: Wed, 7 Sep 2016 11:54:11 -0700	[thread overview]
Message-ID: <20160907185410.GA7170@promb-2n-dhcp38.eng.vmware.com> (raw)
In-Reply-To: <20160907180845.GA31134@www.outflux.net>

Reviewed-by: Sinclair Yeh <syeh@vmware.com>

On Wed, Sep 07, 2016 at 11:08:45AM -0700, Kees Cook wrote:
> A custom allocator without __GFP_COMP that copies to userspace has been
> found in vmw_execbuf_process[1], so this disables the page-span checker
> by placing it behind a CONFIG for future work where such things can be
> tracked down later.
> 
> [1] https://urldefense.proofpoint.com/v2/url?u=https-3A__bugzilla.redhat.com_show-5Fbug.cgi-3Fid-3D1373326&d=CwIBAg&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=w9Iu3o4zAy-3-s8MFvrNSQ&m=HmnBFNgZxprKMPy51P5NjJYN3A5FrdjyzaM817eexKU&s=Htqh5qkhK5mXIdzTCYiqCaZU1R98sOatRFgsoDbGOzw&e= 
> 
> Reported-by: Vinson Lee <vlee@freedesktop.org>
> Fixes: f5509cc18daa ("mm: Hardened usercopy")
> Signed-off-by: Kees Cook <keescook@chromium.org>
> ---
> v2:
> - split logic into separate function entirely, torvalds
> ---
>  mm/usercopy.c    | 61 ++++++++++++++++++++++++++++++++------------------------
>  security/Kconfig | 11 ++++++++++
>  2 files changed, 46 insertions(+), 26 deletions(-)
> 
> diff --git a/mm/usercopy.c b/mm/usercopy.c
> index a3cc3052f830..089328f2b920 100644
> --- a/mm/usercopy.c
> +++ b/mm/usercopy.c
> @@ -134,31 +134,16 @@ static inline const char *check_bogus_address(const void *ptr, unsigned long n)
>  	return NULL;
>  }
>  
> -static inline const char *check_heap_object(const void *ptr, unsigned long n,
> -					    bool to_user)
> +/* Checks for allocs that are marked in some way as spanning multiple pages. */
> +static inline const char *check_page_span(const void *ptr, unsigned long n,
> +					  struct page *page, bool to_user)
>  {
> -	struct page *page, *endpage;
> +#ifdef CONFIG_HARDENED_USERCOPY_PAGESPAN
>  	const void *end = ptr + n - 1;
> +	struct page *endpage;
>  	bool is_reserved, is_cma;
>  
>  	/*
> -	 * Some architectures (arm64) return true for virt_addr_valid() on
> -	 * vmalloced addresses. Work around this by checking for vmalloc
> -	 * first.
> -	 */
> -	if (is_vmalloc_addr(ptr))
> -		return NULL;
> -
> -	if (!virt_addr_valid(ptr))
> -		return NULL;
> -
> -	page = virt_to_head_page(ptr);
> -
> -	/* Check slab allocator for flags and size. */
> -	if (PageSlab(page))
> -		return __check_heap_object(ptr, n, page);
> -
> -	/*
>  	 * Sometimes the kernel data regions are not marked Reserved (see
>  	 * check below). And sometimes [_sdata,_edata) does not cover
>  	 * rodata and/or bss, so check each range explicitly.
> @@ -186,7 +171,7 @@ static inline const char *check_heap_object(const void *ptr, unsigned long n,
>  		   ((unsigned long)end & (unsigned long)PAGE_MASK)))
>  		return NULL;
>  
> -	/* Allow if start and end are inside the same compound page. */
> +	/* Allow if fully inside the same compound (__GFP_COMP) page. */
>  	endpage = virt_to_head_page(end);
>  	if (likely(endpage == page))
>  		return NULL;
> @@ -199,20 +184,44 @@ static inline const char *check_heap_object(const void *ptr, unsigned long n,
>  	is_reserved = PageReserved(page);
>  	is_cma = is_migrate_cma_page(page);
>  	if (!is_reserved && !is_cma)
> -		goto reject;
> +		return "<spans multiple pages>";
>  
>  	for (ptr += PAGE_SIZE; ptr <= end; ptr += PAGE_SIZE) {
>  		page = virt_to_head_page(ptr);
>  		if (is_reserved && !PageReserved(page))
> -			goto reject;
> +			return "<spans Reserved and non-Reserved pages>";
>  		if (is_cma && !is_migrate_cma_page(page))
> -			goto reject;
> +			return "<spans CMA and non-CMA pages>";
>  	}
> +#endif
>  
>  	return NULL;
> +}
> +
> +static inline const char *check_heap_object(const void *ptr, unsigned long n,
> +					    bool to_user)
> +{
> +	struct page *page;
> +
> +	/*
> +	 * Some architectures (arm64) return true for virt_addr_valid() on
> +	 * vmalloced addresses. Work around this by checking for vmalloc
> +	 * first.
> +	 */
> +	if (is_vmalloc_addr(ptr))
> +		return NULL;
> +
> +	if (!virt_addr_valid(ptr))
> +		return NULL;
> +
> +	page = virt_to_head_page(ptr);
> +
> +	/* Check slab allocator for flags and size. */
> +	if (PageSlab(page))
> +		return __check_heap_object(ptr, n, page);
>  
> -reject:
> -	return "<spans multiple pages>";
> +	/* Verify object does not incorrectly span multiple pages. */
> +	return check_page_span(ptr, n, page, to_user);
>  }
>  
>  /*
> diff --git a/security/Kconfig b/security/Kconfig
> index da10d9b573a4..2dfc0ce4083e 100644
> --- a/security/Kconfig
> +++ b/security/Kconfig
> @@ -147,6 +147,17 @@ config HARDENED_USERCOPY
>  	  or are part of the kernel text. This kills entire classes
>  	  of heap overflow exploits and similar kernel memory exposures.
>  
> +config HARDENED_USERCOPY_PAGESPAN
> +	bool "Refuse to copy allocations that span multiple pages"
> +	depends on HARDENED_USERCOPY
> +	depends on !COMPILE_TEST
> +	help
> +	  When a multi-page allocation is done without __GFP_COMP,
> +	  hardened usercopy will reject attempts to copy it. There are,
> +	  however, several cases of this in the kernel that have not all
> +	  been removed. This config is intended to be used only while
> +	  trying to find such users.
> +
>  source security/selinux/Kconfig
>  source security/smack/Kconfig
>  source security/tomoyo/Kconfig
> -- 
> 2.7.4
> 
> 
> -- 
> Kees Cook
> Nexus Security

      parent reply	other threads:[~2016-09-07 18:54 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-07 18:08 Kees Cook
2016-09-07 18:29 ` Rik van Riel
2016-09-07 18:31 ` Linus Torvalds
2016-09-07 18:33   ` Kees Cook
2016-09-07 18:54 ` Sinclair Yeh [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160907185410.GA7170@promb-2n-dhcp38.eng.vmware.com \
    --to=syeh@vmware.com \
    --cc=hannes@cmpxchg.org \
    --cc=keescook@chromium.org \
    --cc=labbott@redhat.com \
    --cc=linux-graphics-maintainer@vmware.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=riel@redhat.com \
    --cc=thellstrom@vmware.com \
    --cc=torvalds@linux-foundation.org \
    --cc=vdavydov.dev@gmail.com \
    --cc=vlee@freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®