lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening PHC | |
Open Source and information security mailing list archives
| ||
|
Date: Tue, 10 May 2022 09:54:15 -0500 From: "Gustavo A. R. Silva" <gustavoars@...nel.org> To: Kees Cook <keescook@...omium.org> Cc: Dave Hansen <dave.hansen@...ux.intel.com>, Andy Lutomirski <luto@...nel.org>, Peter Zijlstra <peterz@...radead.org>, Thomas Gleixner <tglx@...utronix.de>, Ingo Molnar <mingo@...hat.com>, Borislav Petkov <bp@...en8.de>, "H. Peter Anvin" <hpa@...or.com>, x86@...nel.org, linux-kernel@...r.kernel.org, linux-hardening@...r.kernel.org Subject: Re: [PATCH v2][next] x86/mm/pgtable: Fix -Wstringop-overflow warnings 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
Powered by blists - more mailing lists