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]);
>
> ^^^^^^^^^
> ---------------------------------------------------------------------
>
>
next prev parent 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.