All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jan Beulich <jbeulich@suse.com>
To: Rustam Subkhankulov <subkhankulov@ispras.ru>
Cc: Stefano Stabellini <sstabellini@kernel.org>,
	Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>,
	xen-devel@lists.xenproject.org, linux-kernel@vger.kernel.org,
	Alexey Khoroshilov <khoroshilov@ispras.ru>,
	ldv-project@linuxtesting.org, Juergen Gross <jgross@suse.com>
Subject: Re: [POSSIBLE BUG] Dereferencing of NULL pointer
Date: Wed, 24 Aug 2022 15:59:44 +0200	[thread overview]
Message-ID: <0f5f26d2-2b22-2a0d-8bb2-ee2e729ada3f@suse.com> (raw)
In-Reply-To: <6228a437bb9d7f677f5e97973518bcd555bc2a07.camel@ispras.ru>

On 20.08.2022 19:30, Rustam Subkhankulov wrote:
> Version: 6.0-rc1
> 
> Description: 
> 
> In function 'privcmd_ioctl_dm_op' (drivers/xen/privcmd.c: 615)return
> value of 'kcalloc' with GFP_KERNEL flag is assigned to "pages"
> variable. GFP_KERNEL flag does not guarantee, that the return value
> will not be NULL. In that case, there is a jump to the "out" label. 

The problem is wider than that, because earlier errors would also
lead to "out" (e.g. after copy_from_user() failed). Plus I guess
unlock_pages() shouldn't be called at all (or with its 2nd arg set
to zero) before lock_pages() was actually called. But I agree with
the further analysis below. Would you mind sending a patch?

Jan

> ---------------------------------------------------------------------
> 667	pages = kcalloc(nr_pages, sizeof(*pages), GFP_KERNEL);
> 668	if (!pages) {
> 669		rc = -ENOMEM;
> 670		goto out;
> 671	}
> ---------------------------------------------------------------------
> 
> Variable 'pages' is passed to function 'unpin_user_pages_dirty_lock' as
> 1st parameter at [drivers/xen/privcmd.c: 695].
> 
> ---------------------------------------------------------------------
> 694	out:
> 695		unlock_pages(pages, nr_pages);
> ---------------------------------------------------------------------
> 
> Then, variable 'pages' is passed to function
> 'unpin_user_pages_dirty_lock' as 1st parameter at
> [drivers/xen/privcmd.c: 612].
> 
> ---------------------------------------------------------------------
> 610	static void unlock_pages(struct page *pages[], unsigned int
> nr_pages)
> 611	{
> 612		unpin_user_pages_dirty_lock(pages, nr_pages, true);
> 613	}
> ---------------------------------------------------------------------
> 
> 'pages' and 'npages' are passed as parameters to function
> 'sanity_check_pinned_pages' at [mm/gup.c: 311].
> 
> ---------------------------------------------------------------------
> 299	void unpin_user_pages_dirty_lock(struct page **pages, unsigned
> long npages,
> 300					 bool make_dirty)
> 301	{
> 302		unsigned long i;
> 303     struct folio *folio;
> 304     unsigned int nr;
> 305		
> 306		if (!make_dirty) {
> 307			unpin_user_pages(pages, npages);
> 308			return;
> 309		}
> 310
> 311		sanity_check_pinned_pages(pages, npages);
> ---------------------------------------------------------------------
> 
> In function 'sanity_check_pinned_pages', if
> (IS_ENABLED(CONFIG_DEBUG_VM)) and (npages > 0), NULL pointer 'pages' is
> dereferenced at [mm/gup.c: 51].
> 
> ---------------------------------------------------------------------
> 32	static inline void sanity_check_pinned_pages(struct page
> **pages,
> 33						     unsigned long
> npages)
> 34	{
> 35		if (!IS_ENABLED(CONFIG_DEBUG_VM))
> 36			return;
> ..
> 50		for (; npages; npages--, pages++) {
> 51			struct page *page = *pages;
> 								^^^^^^
> ^
> ---------------------------------------------------------------------
> 
> Else if (!IS_ENABLED(CONFIG_DEBUG_VM)) and (npages > 0) function
> 'gup_folio_next' is called with 'pages' and 'npages' as parameters at
> [mm/gup.c: 311].
> 
> ---------------------------------------------------------------------
> 312		for (i = 0; i < npages; i += nr) {
> 313			folio = gup_folio_next(pages, npages, i, &nr);
> ---------------------------------------------------------------------
> 
> In function 'gup_folio_next' NULL pointer 'list' is dereferenced at
> [mm/gup.c: 263].
> 
> ---------------------------------------------------------------------
> 262	static inline struct folio *gup_folio_next(struct page **list,
> 263			unsigned long npages, unsigned long i,
> unsigned int *ntails)
> 264	{
> 265		struct folio *folio = page_folio(list[i]);
> 								
> 		^^^^^^^^^
> ---------------------------------------------------------------------
> 
> 



  reply	other threads:[~2022-08-24 14:00 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-08-20 17:30 [POSSIBLE BUG] Dereferencing of NULL pointer Rustam Subkhankulov
2022-08-24 13:59 ` Jan Beulich [this message]
2022-08-24 14:00   ` Juergen Gross

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=0f5f26d2-2b22-2a0d-8bb2-ee2e729ada3f@suse.com \
    --to=jbeulich@suse.com \
    --cc=jgross@suse.com \
    --cc=khoroshilov@ispras.ru \
    --cc=ldv-project@linuxtesting.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=oleksandr_tyshchenko@epam.com \
    --cc=sstabellini@kernel.org \
    --cc=subkhankulov@ispras.ru \
    --cc=xen-devel@lists.xenproject.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.