All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Gustavo A. R. Silva" <gustavoars@kernel.org>
To: Kees Cook <keescook@chromium.org>
Cc: Dave Hansen <dave.hansen@linux.intel.com>,
	Andy Lutomirski <luto@kernel.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
	"H. Peter Anvin" <hpa@zytor.com>,
	x86@kernel.org, linux-kernel@vger.kernel.org,
	linux-hardening@vger.kernel.org
Subject: Re: [PATCH v2][next] x86/mm/pgtable: Fix -Wstringop-overflow warnings
Date: Tue, 10 May 2022 09:54:15 -0500	[thread overview]
Message-ID: <20220510145415.GA8111@embeddedor> (raw)
In-Reply-To: <20220510141202.GA6878@embeddedor>

On Tue, May 10, 2022 at 09:12:02AM -0500, Gustavo A. R. Silva wrote:
> > > > > --- a/arch/x86/mm/pgtable.c
> > > > > +++ b/arch/x86/mm/pgtable.c
> > > > > @@ -434,14 +434,18 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
> > > > >  
> > > > >  	mm->pgd = pgd;
> > > > >  
> > > > > -	if (preallocate_pmds(mm, pmds, PREALLOCATED_PMDS) != 0)
> > > > > -		goto out_free_pgd;
> > > > > +	if (MAX_PREALLOCATED_PMDS != 0 && MAX_PREALLOCATED_USER_PMDS != 0) {
> > > > > +		if (preallocate_pmds(mm, pmds, PREALLOCATED_PMDS) != 0)
> > > > > +			goto out_free_pgd;
> > > > >  
> > > > > -	if (preallocate_pmds(mm, u_pmds, PREALLOCATED_USER_PMDS) != 0)
> > > > > -		goto out_free_pmds;
> > > > > +		if (preallocate_pmds(mm, u_pmds, PREALLOCATED_USER_PMDS) != 0)
> > > > > +			goto out_free_pmds;
> > > > >  
> > > > > -	if (paravirt_pgd_alloc(mm) != 0)
> > > > > -		goto out_free_user_pmds;
> > > > > +		if (paravirt_pgd_alloc(mm) != 0)
> > > > > +			goto out_free_user_pmds;
> > > > > +	} else {
> > > > > +		goto out_free_pgd;
> > > > 
> > > > The "all 0" case shouldn't be a failure mode; it should just skip the
> > > > preallocate_pmds() calls.
> > > 
> > > Do you mean something like this:
> > > 
> > > diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
> > > index f16059e9a85e..4dae168408f1 100644
> > > --- a/arch/x86/mm/pgtable.c
> > > +++ b/arch/x86/mm/pgtable.c
> > > @@ -434,11 +434,13 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
> > > 
> > >         mm->pgd = pgd;
> > > 
> > > -       if (preallocate_pmds(mm, pmds, PREALLOCATED_PMDS) != 0)
> > > -               goto out_free_pgd;
> > > +       if (MAX_PREALLOCATED_PMDS != 0 && MAX_PREALLOCATED_USER_PMDS != 0) {
> > > +               if (preallocate_pmds(mm, pmds, PREALLOCATED_PMDS) != 0)
> > > +                       goto out_free_pgd;
> > > 
> > > -       if (preallocate_pmds(mm, u_pmds, PREALLOCATED_USER_PMDS) != 0)
> > > -               goto out_free_pmds;
> > > +               if (preallocate_pmds(mm, u_pmds, PREALLOCATED_USER_PMDS) != 0)
> > > +                       goto out_free_pmds;
> > > +       }
> > > 
> > >         if (paravirt_pgd_alloc(mm) != 0)
> > >                 goto out_free_user_pmds;
> > > 
> > > It seems that the above is not enough, because we have the same issue
> > > when calling pgd_prepopulate_pmd(), pgd_prepopulate_user_pmd() and
> > > free_pmds():
> > > 
> > >   CC      arch/x86/mm/pgtable.o
> > > arch/x86/mm/pgtable.c: In function 'pgd_alloc':
> > > arch/x86/mm/pgtable.c:464:9: warning: 'free_pmds' accessing 8 bytes in a region of size 0 [-Wstringop-overflow=]
> > >   464 |         free_pmds(mm, u_pmds, PREALLOCATED_USER_PMDS);
> > >       |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > 
> > Ugh. Perhaps just marking both preallocate_pmds() and free_pmds() as
> > inline is enough to let the compiler "see" everything correctly?
> 
> It doesn't seem to work... however, the following piece of code implies
> that pmds and u_pmds should be first preallocated through preallocate_pmds(),
> which cannot happen if (MAX_PREALLOCATED_PMDS != 0 && MAX_PREALLOCATED_USER_PMDS != 0)

I wanted to say: which cannot happen if MAX_PREALLOCATED_PMDS == 0 && MAX_PREALLOCATED_USER_PMDS == 0

> 
> 448         /*
> 449          * Make sure that pre-populating the pmds is atomic with
> 450          * respect to anything walking the pgd_list, so that they
> 451          * never see a partially populated pgd.
> 452          */
> 453         spin_lock(&pgd_lock);
> 454
> 455         pgd_ctor(mm, pgd);
> 456         pgd_prepopulate_pmd(mm, pgd, pmds);
> 457         pgd_prepopulate_user_pmd(mm, pgd, u_pmds);
> 458
> 459         spin_unlock(&pgd_lock);
> 460
> 461         return pgd;
> 
> So, my question here is why do you think the "all 0" case should only skip the
> preallocate_pmds() calls and not the pgd_prepopulate_pmd() calls too?
> 
> > 
> > Otherwise, they'll likely each need the same check that was added to
> > pgd_prepopulate_pmd() ages ago for a similar situation...
> 
> uhm... that doesn't seem to have an impact nowadays, or at least now
> Wstringop-overflow sees the problem first, because now the issue is
> detected at the moment of passing the arguments to the the function
> and not when actually executing the function?
> 
> otherwise, I think we wouldn't see this error:
> 
> arch/x86/mm/pgtable.c:454:9: warning: 'pgd_prepopulate_pmd' accessing 8 bytes in a region of size 0 [-Wstringop-overflow=]
>   454 |         pgd_prepopulate_pmd(mm, pgd, pmds);
>       |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> arch/x86/mm/pgtable.c:454:9: note: referencing argument 3 of type 'pmd_t *[0]'
> arch/x86/mm/pgtable.c:296:13: note: in a call to function 'pgd_prepopulate_pmd'
>   296 | static void pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmds[])
>       |             ^~~~~~~~~~~~~~~~~~~
> 

Thanks
--
Gustavo

  reply	other threads:[~2022-05-10 15:08 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-09 19:45 [PATCH v2][next] x86/mm/pgtable: Fix -Wstringop-overflow warnings Gustavo A. R. Silva
2022-05-09 19:59 ` Kees Cook
2022-05-09 20:50   ` Gustavo A. R. Silva
2022-05-09 20:54     ` Kees Cook
2022-05-10 14:12       ` Gustavo A. R. Silva
2022-05-10 14:54         ` Gustavo A. R. Silva [this message]
2022-05-11 18:41         ` Kees Cook

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=20220510145415.GA8111@embeddedor \
    --to=gustavoars@kernel.org \
    --cc=bp@alien8.de \
    --cc=dave.hansen@linux.intel.com \
    --cc=hpa@zytor.com \
    --cc=keescook@chromium.org \
    --cc=linux-hardening@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=tglx@linutronix.de \
    --cc=x86@kernel.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.