[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <lhe2mky6ahlk2jzvvfjyongqiseelyx2uy7sbyuso6jcy3b2dq@7ju6cea62jgk>
Date: Wed, 7 Aug 2024 19:20:23 -0400
From: "Liam R. Howlett" <Liam.Howlett@...cle.com>
To: Jeff Xu <jeffxu@...gle.com>
Cc: Michael Ellerman <mpe@...erman.id.au>, linux-mm@...ck.org,
linuxppc-dev@...ts.ozlabs.org, torvalds@...ux-foundation.org,
akpm@...ux-foundation.org, christophe.leroy@...roup.eu,
jeffxu@...omium.org, linux-kernel@...r.kernel.org, npiggin@...il.com,
oliver.sang@...el.com, pedro.falcato@...il.com,
Kees Cook <keescook@...omium.org>
Subject: Re: [PATCH 2/4] powerpc/mm: Handle VDSO unmapping via close() rather
than arch_unmap()
* Jeff Xu <jeffxu@...gle.com> [240807 16:12]:
> On Wed, Aug 7, 2024 at 10:11 AM Liam R. Howlett <Liam.Howlett@...cle.com> wrote:
> >
> > * Jeff Xu <jeffxu@...gle.com> [240807 12:37]:
> > > On Wed, Aug 7, 2024 at 8:56 AM Liam R. Howlett <Liam.Howlett@...cle.com> wrote:
> > > >
> > > > * Jeff Xu <jeffxu@...gle.com> [240807 11:44]:
> > > > > On Wed, Aug 7, 2024 at 5:41 AM Michael Ellerman <mpe@...erman.id.au> wrote:
> > > > > >
> > > > > > Add a close() callback to the VDSO special mapping to handle unmapping
> > > > > > of the VDSO. That will make it possible to remove the arch_unmap() hook
> > > > > > entirely in a subsequent patch.
> > > > > >
> > > > > > Suggested-by: Linus Torvalds <torvalds@...ux-foundation.org>
> > > > > > Signed-off-by: Michael Ellerman <mpe@...erman.id.au>
> > > > > > ---
> > > > > > arch/powerpc/include/asm/mmu_context.h | 4 ----
> > > > > > arch/powerpc/kernel/vdso.c | 17 +++++++++++++++++
> > > > > > 2 files changed, 17 insertions(+), 4 deletions(-)
> > > > > >
> > > > > > diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h
> > > > > > index 37bffa0f7918..9b8c1555744e 100644
> > > > > > --- a/arch/powerpc/include/asm/mmu_context.h
> > > > > > +++ b/arch/powerpc/include/asm/mmu_context.h
> > > > > > @@ -263,10 +263,6 @@ extern void arch_exit_mmap(struct mm_struct *mm);
> > > > > > static inline void arch_unmap(struct mm_struct *mm,
> > > > > > unsigned long start, unsigned long end)
> > > > > > {
> > > > > > - unsigned long vdso_base = (unsigned long)mm->context.vdso;
> > > > > > -
> > > > > > - if (start <= vdso_base && vdso_base < end)
> > > > > > - mm->context.vdso = NULL;
> > > > > > }
> > > > > >
> > > > > > #ifdef CONFIG_PPC_MEM_KEYS
> > > > > > diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
> > > > > > index 7a2ff9010f17..220a76cae7c1 100644
> > > > > > --- a/arch/powerpc/kernel/vdso.c
> > > > > > +++ b/arch/powerpc/kernel/vdso.c
> > > > > > @@ -81,6 +81,21 @@ static int vdso64_mremap(const struct vm_special_mapping *sm, struct vm_area_str
> > > > > > return vdso_mremap(sm, new_vma, &vdso64_end - &vdso64_start);
> > > > > > }
> > > > > >
> > > > > > +static void vdso_close(const struct vm_special_mapping *sm, struct vm_area_struct *vma)
> > > > > > +{
> > > > > > + struct mm_struct *mm = vma->vm_mm;
> > > > > > +
> > > > > > + /*
> > > > > > + * close() is called for munmap() but also for mremap(). In the mremap()
> > > > > > + * case the vdso pointer has already been updated by the mremap() hook
> > > > > > + * above, so it must not be set to NULL here.
> > > > > > + */
> > > > > > + if (vma->vm_start != (unsigned long)mm->context.vdso)
> > > > > > + return;
> > > > > > +
> > > > > > + mm->context.vdso = NULL;
> > > > > > +}
> > > > > > +
> > > > > > static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
> > > > > > struct vm_area_struct *vma, struct vm_fault *vmf);
> > > > > >
> > > > > > @@ -92,11 +107,13 @@ static struct vm_special_mapping vvar_spec __ro_after_init = {
> > > > > > static struct vm_special_mapping vdso32_spec __ro_after_init = {
> > > > > > .name = "[vdso]",
> > > > > > .mremap = vdso32_mremap,
> > > > > > + .close = vdso_close,
> > > > > IIUC, only CHECKPOINT_RESTORE requires this, and
> > > > > CHECKPOINT_RESTORE is in init/Kconfig, with default N
> > > > >
> > > > > Can we add #ifdef CONFIG_CHECKPOINT_RESTORE here ?
> > > > >
> > > >
> > > > No, these can be unmapped and it needs to be cleaned up. Valgrind is
> > > > one application that is known to unmap the vdso and runs into issues on
> > > > platforms that do not handle the removal correctly.
> > > >
> > > Maybe Valgrind needs that exactly for checkpoint restore ? [1]
> >
> > Maybe, and maybe there are 100 other applications unmapping the vdso for
> > some other reason?
> >
> When PPC added arch_munamp, it was for CRIU, wasn't it ? That was the original
> intention.
>
> Maybe there are more apps that have started unmapping vdso, it might
> be interesting
> to know those use cases before widely opening this without kernel config.
>
> > >
> > > "CRIU fails to restore applications that have unmapped the vDSO
> > > segment. One such
> > > application is Valgrind."
> > >
> > > Usually when the kernel accepts new functionality, the patch needs to
> > > state the user case.
> >
...
> > > The only user case I found for .mremap and .close so far is the CRIU case.
> > >
> >
> > In fact, this is broken on other archs for valgrind since they unmap the
> > vdso and then crash [2]. There has been a fix in the works for a while,
> > which I stepped in during the patch set [1], which can be seen here
> > [3]. In the discussion, the issue with Valgrind is raised and a generic
> > solution to solve for more than just ppc is discussed. The solution
> > avoids crashing if vdso is unmapped and that seems like the sane
> > direction of this work.
> >
> > We also have users unmapping vdsos here [4] too.
> This is a strange code. If the use case about clock_gettime is legit, then
> kerne can provide an option to not unload vdso during elf loading.
Yes, I would not want to do this - but there are people doing strange
(to put it politely) things that we did not intend.
>
> >
> > Why would we leave a dangling pointer in the mm struct based on a
> > compile flag?
Okay, I'm going to try one more time here. You are suggesting to have a
conf flag to leave the vdso pointer unchanged when it is unmapped.
Having the close behind the conf option will not prevent it from being
unmapped or mapped over, so what you are suggesting is have a
configuration option that leaves a pointer, mm->context.vdso, to be
unsafe if it is unmapped if you disable checkpoint restore.
This is also not what userspace sees today, so you are changing user
visible behaviour based on a configuration option because you think, but
are not sure, that checkpoint restore is the only user.
Or did I miss something?
Thanks,
Liam
> >
> > [1] https://lore.kernel.org/linux-mm/20240717200709.1552558-18-Liam.Howlett@oracle.com/
> > [2] https://lore.kernel.org/lkml/87imd5h5kb.fsf@mpe.ellerman.id.au/
> > [3] https://lore.kernel.org/all/20210611180242.711399-17-dima@arista.com/
> > [4] https://github.com/insanitybit/void-ship
> >
Powered by blists - more mailing lists