All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 1/1] mm: fix use-after-free when anon vma name is used after vma is freed
@ 2022-02-10  4:32 Suren Baghdasaryan
  2022-02-10 12:40 ` Michal Hocko
  2022-02-10 13:27 ` Matthew Wilcox
  0 siblings, 2 replies; 10+ messages in thread
From: Suren Baghdasaryan @ 2022-02-10  4:32 UTC (permalink / raw)
  To: akpm
  Cc: ccross, sumit.semwal, mhocko, dave.hansen, keescook, willy,
	kirill.shutemov, vbabka, hannes, ebiederm, brauner, legion,
	ran.xiaokai, sashal, chris.hyser, dave, pcc, caoxiaofeng, david,
	gorcunov, linux-mm, linux-kernel, kernel-team, surenb,
	syzbot+aa7b3d4b35f9dc46a366

When adjacent vmas are being merged it can result in the vma that was
originally passed to madvise_update_vma being destroyed. In the current
implementation, the name parameter passed to madvise_update_vma points
directly to vma->anon_name->name and it is used after the call to
vma_merge. In the cases when vma_merge merges the original vma and
destroys it, this will result in use-after-free bug as shown below:

madvise_vma_behavior << passes vma->anon_name->name as name param
  madvise_update_vma(name)
    vma_merge
      __vma_adjust
        vm_area_free <-- frees the vma
    replace_vma_anon_name(name) <-- UAF

Fix this by raising the name refcount and stabilizing it. Introduce
vma_anon_name_{get/put} API for this purpose.

Fixes: 9a10064f5625 ("mm: add a field to store names for private anonymous memory")
Reported-by: syzbot+aa7b3d4b35f9dc46a366@syzkaller.appspotmail.com
Signed-off-by: Suren Baghdasaryan <surenb@google.com>
---
changes in v2:
- Replaces name copying with refcounting and added vma_anon_name_{get/put} API,
per Andrew Morton

 include/linux/mm_inline.h | 13 +++++++++++++
 mm/madvise.c              | 28 ++++++++++++++++++++++++++--
 2 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h
index b725839dfe71..2ad9b28499b1 100644
--- a/include/linux/mm_inline.h
+++ b/include/linux/mm_inline.h
@@ -145,6 +145,11 @@ static __always_inline void del_page_from_lru_list(struct page *page,
  */
 extern const char *vma_anon_name(struct vm_area_struct *vma);
 
+/* mmap_lock should be read-locked */
+extern struct anon_vma_name *vma_anon_name_get(struct vm_area_struct *vma);
+
+extern void vma_anon_name_put(struct anon_vma_name *anon_name);
+
 /*
  * mmap_lock should be read-locked for orig_vma->vm_mm.
  * mmap_lock should be write-locked for new_vma->vm_mm or new_vma should be
@@ -176,6 +181,14 @@ static inline const char *vma_anon_name(struct vm_area_struct *vma)
 {
 	return NULL;
 }
+
+static inline
+struct anon_vma_name *vma_anon_name_get(struct vm_area_struct *vma)
+{
+	return NULL;
+}
+
+static inline void vma_anon_name_put(struct anon_vma_name *anon_name) {}
 static inline void dup_vma_anon_name(struct vm_area_struct *orig_vma,
 			      struct vm_area_struct *new_vma) {}
 static inline void free_vma_anon_name(struct vm_area_struct *vma) {}
diff --git a/mm/madvise.c b/mm/madvise.c
index 5604064df464..9cf069e574c0 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -103,6 +103,22 @@ const char *vma_anon_name(struct vm_area_struct *vma)
 	return vma->anon_name->name;
 }
 
+struct anon_vma_name *vma_anon_name_get(struct vm_area_struct *vma)
+{
+	if (!has_vma_anon_name(vma))
+		return NULL;
+
+	mmap_assert_locked(vma->vm_mm);
+
+	kref_get(&vma->anon_name->kref);
+	return vma->anon_name;
+}
+
+void vma_anon_name_put(struct anon_vma_name *anon_name)
+{
+	kref_put(&anon_name->kref, vma_anon_name_free);
+}
+
 void dup_vma_anon_name(struct vm_area_struct *orig_vma,
 		       struct vm_area_struct *new_vma)
 {
@@ -976,6 +992,7 @@ static int madvise_vma_behavior(struct vm_area_struct *vma,
 {
 	int error;
 	unsigned long new_flags = vma->vm_flags;
+	struct anon_vma_name *anon_name;
 
 	switch (behavior) {
 	case MADV_REMOVE:
@@ -1040,8 +1057,15 @@ static int madvise_vma_behavior(struct vm_area_struct *vma,
 		break;
 	}
 
-	error = madvise_update_vma(vma, prev, start, end, new_flags,
-				   vma_anon_name(vma));
+	anon_name = vma_anon_name_get(vma);
+	if (anon_name) {
+		error = madvise_update_vma(vma, prev, start, end, new_flags,
+					   anon_name->name);
+		vma_anon_name_put(anon_name);
+	} else {
+		error = madvise_update_vma(vma, prev, start, end, new_flags,
+					   NULL);
+	}
 
 out:
 	/*
-- 
2.35.1.265.g69c8d7142f-goog


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 1/1] mm: fix use-after-free when anon vma name is used after vma is freed
  2022-02-10  4:32 [PATCH v2 1/1] mm: fix use-after-free when anon vma name is used after vma is freed Suren Baghdasaryan
@ 2022-02-10 12:40 ` Michal Hocko
  2022-02-10 15:18   ` Suren Baghdasaryan
  2022-02-10 13:27 ` Matthew Wilcox
  1 sibling, 1 reply; 10+ messages in thread
From: Michal Hocko @ 2022-02-10 12:40 UTC (permalink / raw)
  To: Suren Baghdasaryan
  Cc: akpm, ccross, sumit.semwal, dave.hansen, keescook, willy,
	kirill.shutemov, vbabka, hannes, ebiederm, brauner, legion,
	ran.xiaokai, sashal, chris.hyser, dave, pcc, caoxiaofeng, david,
	gorcunov, linux-mm, linux-kernel, kernel-team,
	syzbot+aa7b3d4b35f9dc46a366

On Wed 09-02-22 20:32:15, Suren Baghdasaryan wrote:
> When adjacent vmas are being merged it can result in the vma that was
> originally passed to madvise_update_vma being destroyed. In the current
> implementation, the name parameter passed to madvise_update_vma points
> directly to vma->anon_name->name and it is used after the call to
> vma_merge. In the cases when vma_merge merges the original vma and
> destroys it, this will result in use-after-free bug as shown below:
> 
> madvise_vma_behavior << passes vma->anon_name->name as name param
>   madvise_update_vma(name)
>     vma_merge
>       __vma_adjust
>         vm_area_free <-- frees the vma
>     replace_vma_anon_name(name) <-- UAF
> 
> Fix this by raising the name refcount and stabilizing it. Introduce
> vma_anon_name_{get/put} API for this purpose.

What is the reason that madvise_update_vma uses the naked name rather
than the encapsulated anon_vma_name? This really just begs for problems.
-- 
Michal Hocko
SUSE Labs

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 1/1] mm: fix use-after-free when anon vma name is used after vma is freed
  2022-02-10  4:32 [PATCH v2 1/1] mm: fix use-after-free when anon vma name is used after vma is freed Suren Baghdasaryan
  2022-02-10 12:40 ` Michal Hocko
@ 2022-02-10 13:27 ` Matthew Wilcox
  2022-02-10 15:21   ` Suren Baghdasaryan
  1 sibling, 1 reply; 10+ messages in thread
From: Matthew Wilcox @ 2022-02-10 13:27 UTC (permalink / raw)
  To: Suren Baghdasaryan
  Cc: akpm, ccross, sumit.semwal, mhocko, dave.hansen, keescook,
	kirill.shutemov, vbabka, hannes, ebiederm, brauner, legion,
	ran.xiaokai, sashal, chris.hyser, dave, pcc, caoxiaofeng, david,
	gorcunov, linux-mm, linux-kernel, kernel-team,
	syzbot+aa7b3d4b35f9dc46a366

On Wed, Feb 09, 2022 at 08:32:15PM -0800, Suren Baghdasaryan wrote:
> +void vma_anon_name_put(struct anon_vma_name *anon_name)
> +{
> +	kref_put(&anon_name->kref, vma_anon_name_free);
> +}

To agree with Michal, make this:

	if (anon_name)
		kref_put(&anon_name->kref, vma_anon_name_free);

>  
> -	error = madvise_update_vma(vma, prev, start, end, new_flags,
> -				   vma_anon_name(vma));
> +	anon_name = vma_anon_name_get(vma);
> +	if (anon_name) {
> +		error = madvise_update_vma(vma, prev, start, end, new_flags,
> +					   anon_name->name);
> +		vma_anon_name_put(anon_name);
> +	} else {
> +		error = madvise_update_vma(vma, prev, start, end, new_flags,
> +					   NULL);
> +	}

And then this becomes:

	anon_name = vma_anon_name_get(vma);
	error = madvise_update_vma(vma, prev, start, end, new_flags, anon_name);
	vma_anon_name_put(anon_name);

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 1/1] mm: fix use-after-free when anon vma name is used after vma is freed
  2022-02-10 12:40 ` Michal Hocko
@ 2022-02-10 15:18   ` Suren Baghdasaryan
  2022-02-10 15:27     ` Matthew Wilcox
  0 siblings, 1 reply; 10+ messages in thread
From: Suren Baghdasaryan @ 2022-02-10 15:18 UTC (permalink / raw)
  To: Michal Hocko
  Cc: Andrew Morton, Colin Cross, Sumit Semwal, Dave Hansen, Kees Cook,
	Matthew Wilcox, Kirill A . Shutemov, Vlastimil Babka,
	Johannes Weiner, Eric W. Biederman, brauner, legion, ran.xiaokai,
	sashal, Chris Hyser, Davidlohr Bueso, Peter Collingbourne,
	caoxiaofeng, David Hildenbrand, Cyrill Gorcunov, linux-mm, LKML,
	kernel-team, syzbot+aa7b3d4b35f9dc46a366

On Thu, Feb 10, 2022 at 4:40 AM 'Michal Hocko' via kernel-team
<kernel-team@android.com> wrote:
>
> On Wed 09-02-22 20:32:15, Suren Baghdasaryan wrote:
> > When adjacent vmas are being merged it can result in the vma that was
> > originally passed to madvise_update_vma being destroyed. In the current
> > implementation, the name parameter passed to madvise_update_vma points
> > directly to vma->anon_name->name and it is used after the call to
> > vma_merge. In the cases when vma_merge merges the original vma and
> > destroys it, this will result in use-after-free bug as shown below:
> >
> > madvise_vma_behavior << passes vma->anon_name->name as name param
> >   madvise_update_vma(name)
> >     vma_merge
> >       __vma_adjust
> >         vm_area_free <-- frees the vma
> >     replace_vma_anon_name(name) <-- UAF
> >
> > Fix this by raising the name refcount and stabilizing it. Introduce
> > vma_anon_name_{get/put} API for this purpose.
>
> What is the reason that madvise_update_vma uses the naked name rather
> than the encapsulated anon_vma_name? This really just begs for problems.

The reason for that is the second place it's being used from the prctl syscall:

prctl_set_vma
  madvise_set_anon_name
    madvise_vma_anon_name
      madvise_update_vma

In that case the name parameter is not part of any anon_vma_name
struct and therefore is stable. I can add a comment to
madvise_update_vma indicating that the name parameter has to be stable
if that helps.

> --
> Michal Hocko
> SUSE Labs
>
> --
> To unsubscribe from this group and stop receiving emails from it, send an email to kernel-team+unsubscribe@android.com.
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 1/1] mm: fix use-after-free when anon vma name is used after vma is freed
  2022-02-10 13:27 ` Matthew Wilcox
@ 2022-02-10 15:21   ` Suren Baghdasaryan
  0 siblings, 0 replies; 10+ messages in thread
From: Suren Baghdasaryan @ 2022-02-10 15:21 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: Andrew Morton, Colin Cross, Sumit Semwal, Michal Hocko,
	Dave Hansen, Kees Cook, Kirill A . Shutemov, Vlastimil Babka,
	Johannes Weiner, Eric W. Biederman, brauner, legion, ran.xiaokai,
	sashal, Chris Hyser, Davidlohr Bueso, Peter Collingbourne,
	caoxiaofeng, David Hildenbrand, Cyrill Gorcunov, linux-mm, LKML,
	kernel-team, syzbot+aa7b3d4b35f9dc46a366

On Thu, Feb 10, 2022 at 5:27 AM Matthew Wilcox <willy@infradead.org> wrote:
>
> On Wed, Feb 09, 2022 at 08:32:15PM -0800, Suren Baghdasaryan wrote:
> > +void vma_anon_name_put(struct anon_vma_name *anon_name)
> > +{
> > +     kref_put(&anon_name->kref, vma_anon_name_free);
> > +}
>
> To agree with Michal, make this:
>
>         if (anon_name)
>                 kref_put(&anon_name->kref, vma_anon_name_free);

Ack.

>
> >
> > -     error = madvise_update_vma(vma, prev, start, end, new_flags,
> > -                                vma_anon_name(vma));
> > +     anon_name = vma_anon_name_get(vma);
> > +     if (anon_name) {
> > +             error = madvise_update_vma(vma, prev, start, end, new_flags,
> > +                                        anon_name->name);
> > +             vma_anon_name_put(anon_name);
> > +     } else {
> > +             error = madvise_update_vma(vma, prev, start, end, new_flags,
> > +                                        NULL);
> > +     }
>
> And then this becomes:
>
>         anon_name = vma_anon_name_get(vma);
>         error = madvise_update_vma(vma, prev, start, end, new_flags, anon_name);
>         vma_anon_name_put(anon_name);

As I indicated in the other reply, there is another madvise_update_vma
user which has only the name string, not the anon_vma_name struct. So
this can become:

   anon_name = vma_anon_name_get(vma);
   error = madvise_update_vma(vma, prev, start, end, new_flags,
                                                   anon_name ?
anon_name->name : NULL);
   vma_anon_name_put(anon_name);

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 1/1] mm: fix use-after-free when anon vma name is used after vma is freed
  2022-02-10 15:18   ` Suren Baghdasaryan
@ 2022-02-10 15:27     ` Matthew Wilcox
  2022-02-10 16:00       ` Suren Baghdasaryan
  0 siblings, 1 reply; 10+ messages in thread
From: Matthew Wilcox @ 2022-02-10 15:27 UTC (permalink / raw)
  To: Suren Baghdasaryan
  Cc: Michal Hocko, Andrew Morton, Colin Cross, Sumit Semwal,
	Dave Hansen, Kees Cook, Kirill A . Shutemov, Vlastimil Babka,
	Johannes Weiner, Eric W. Biederman, brauner, legion, ran.xiaokai,
	sashal, Chris Hyser, Davidlohr Bueso, Peter Collingbourne,
	caoxiaofeng, David Hildenbrand, Cyrill Gorcunov, linux-mm, LKML,
	kernel-team, syzbot+aa7b3d4b35f9dc46a366

On Thu, Feb 10, 2022 at 07:18:24AM -0800, Suren Baghdasaryan wrote:
> On Thu, Feb 10, 2022 at 4:40 AM 'Michal Hocko' via kernel-team
> <kernel-team@android.com> wrote:
> >
> > On Wed 09-02-22 20:32:15, Suren Baghdasaryan wrote:
> > > When adjacent vmas are being merged it can result in the vma that was
> > > originally passed to madvise_update_vma being destroyed. In the current
> > > implementation, the name parameter passed to madvise_update_vma points
> > > directly to vma->anon_name->name and it is used after the call to
> > > vma_merge. In the cases when vma_merge merges the original vma and
> > > destroys it, this will result in use-after-free bug as shown below:
> > >
> > > madvise_vma_behavior << passes vma->anon_name->name as name param
> > >   madvise_update_vma(name)
> > >     vma_merge
> > >       __vma_adjust
> > >         vm_area_free <-- frees the vma
> > >     replace_vma_anon_name(name) <-- UAF
> > >
> > > Fix this by raising the name refcount and stabilizing it. Introduce
> > > vma_anon_name_{get/put} API for this purpose.
> >
> > What is the reason that madvise_update_vma uses the naked name rather
> > than the encapsulated anon_vma_name? This really just begs for problems.
> 
> The reason for that is the second place it's being used from the prctl syscall:
> 
> prctl_set_vma
>   madvise_set_anon_name
>     madvise_vma_anon_name
>       madvise_update_vma
> 
> In that case the name parameter is not part of any anon_vma_name
> struct and therefore is stable. I can add a comment to
> madvise_update_vma indicating that the name parameter has to be stable
> if that helps.

Seems to me it'd simplify things if replace_vma_anon_name() and
madvise_vma_anon_name() took a struct anon_vma_name instead of
a bare char *.  You could construct it in madvise_set_anon_name().

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 1/1] mm: fix use-after-free when anon vma name is used after vma is freed
  2022-02-10 15:27     ` Matthew Wilcox
@ 2022-02-10 16:00       ` Suren Baghdasaryan
  2022-02-10 19:35         ` Matthew Wilcox
  0 siblings, 1 reply; 10+ messages in thread
From: Suren Baghdasaryan @ 2022-02-10 16:00 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: Michal Hocko, Andrew Morton, Colin Cross, Sumit Semwal,
	Dave Hansen, Kees Cook, Kirill A . Shutemov, Vlastimil Babka,
	Johannes Weiner, Eric W. Biederman, brauner, legion, ran.xiaokai,
	sashal, Chris Hyser, Davidlohr Bueso, Peter Collingbourne,
	caoxiaofeng, David Hildenbrand, Cyrill Gorcunov, linux-mm, LKML,
	kernel-team, syzbot+aa7b3d4b35f9dc46a366

On Thu, Feb 10, 2022 at 7:27 AM Matthew Wilcox <willy@infradead.org> wrote:
>
> On Thu, Feb 10, 2022 at 07:18:24AM -0800, Suren Baghdasaryan wrote:
> > On Thu, Feb 10, 2022 at 4:40 AM 'Michal Hocko' via kernel-team
> > <kernel-team@android.com> wrote:
> > >
> > > On Wed 09-02-22 20:32:15, Suren Baghdasaryan wrote:
> > > > When adjacent vmas are being merged it can result in the vma that was
> > > > originally passed to madvise_update_vma being destroyed. In the current
> > > > implementation, the name parameter passed to madvise_update_vma points
> > > > directly to vma->anon_name->name and it is used after the call to
> > > > vma_merge. In the cases when vma_merge merges the original vma and
> > > > destroys it, this will result in use-after-free bug as shown below:
> > > >
> > > > madvise_vma_behavior << passes vma->anon_name->name as name param
> > > >   madvise_update_vma(name)
> > > >     vma_merge
> > > >       __vma_adjust
> > > >         vm_area_free <-- frees the vma
> > > >     replace_vma_anon_name(name) <-- UAF
> > > >
> > > > Fix this by raising the name refcount and stabilizing it. Introduce
> > > > vma_anon_name_{get/put} API for this purpose.
> > >
> > > What is the reason that madvise_update_vma uses the naked name rather
> > > than the encapsulated anon_vma_name? This really just begs for problems.
> >
> > The reason for that is the second place it's being used from the prctl syscall:
> >
> > prctl_set_vma
> >   madvise_set_anon_name
> >     madvise_vma_anon_name
> >       madvise_update_vma
> >
> > In that case the name parameter is not part of any anon_vma_name
> > struct and therefore is stable. I can add a comment to
> > madvise_update_vma indicating that the name parameter has to be stable
> > if that helps.
>
> Seems to me it'd simplify things if replace_vma_anon_name() and
> madvise_vma_anon_name() took a struct anon_vma_name instead of
> a bare char *.  You could construct it in madvise_set_anon_name().

Ok, this can be done. However I don't think changing
replace_vma_anon_name() to accept a struct anon_vma_name would be a
good idea. Reader might think that the object being passed will become
the vma->anon_name of the vma, while in reality that's not the case.
Keeping it a char* makes it obvious that the function will construct a
new anon_vma_name struct.
I'll post a v3 shortly implementing these suggestions.
Thanks for the review folks!

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 1/1] mm: fix use-after-free when anon vma name is used after vma is freed
  2022-02-10 16:00       ` Suren Baghdasaryan
@ 2022-02-10 19:35         ` Matthew Wilcox
  2022-02-10 19:52           ` Suren Baghdasaryan
  0 siblings, 1 reply; 10+ messages in thread
From: Matthew Wilcox @ 2022-02-10 19:35 UTC (permalink / raw)
  To: Suren Baghdasaryan
  Cc: Michal Hocko, Andrew Morton, Colin Cross, Sumit Semwal,
	Dave Hansen, Kees Cook, Kirill A . Shutemov, Vlastimil Babka,
	Johannes Weiner, Eric W. Biederman, brauner, legion, ran.xiaokai,
	sashal, Chris Hyser, Davidlohr Bueso, Peter Collingbourne,
	caoxiaofeng, David Hildenbrand, Cyrill Gorcunov, linux-mm, LKML,
	kernel-team, syzbot+aa7b3d4b35f9dc46a366

On Thu, Feb 10, 2022 at 08:00:15AM -0800, Suren Baghdasaryan wrote:
> On Thu, Feb 10, 2022 at 7:27 AM Matthew Wilcox <willy@infradead.org> wrote:
> >
> > On Thu, Feb 10, 2022 at 07:18:24AM -0800, Suren Baghdasaryan wrote:
> > > On Thu, Feb 10, 2022 at 4:40 AM 'Michal Hocko' via kernel-team
> > > <kernel-team@android.com> wrote:
> > > >
> > > > On Wed 09-02-22 20:32:15, Suren Baghdasaryan wrote:
> > > > > When adjacent vmas are being merged it can result in the vma that was
> > > > > originally passed to madvise_update_vma being destroyed. In the current
> > > > > implementation, the name parameter passed to madvise_update_vma points
> > > > > directly to vma->anon_name->name and it is used after the call to
> > > > > vma_merge. In the cases when vma_merge merges the original vma and
> > > > > destroys it, this will result in use-after-free bug as shown below:
> > > > >
> > > > > madvise_vma_behavior << passes vma->anon_name->name as name param
> > > > >   madvise_update_vma(name)
> > > > >     vma_merge
> > > > >       __vma_adjust
> > > > >         vm_area_free <-- frees the vma
> > > > >     replace_vma_anon_name(name) <-- UAF
> > > > >
> > > > > Fix this by raising the name refcount and stabilizing it. Introduce
> > > > > vma_anon_name_{get/put} API for this purpose.
> > > >
> > > > What is the reason that madvise_update_vma uses the naked name rather
> > > > than the encapsulated anon_vma_name? This really just begs for problems.
> > >
> > > The reason for that is the second place it's being used from the prctl syscall:
> > >
> > > prctl_set_vma
> > >   madvise_set_anon_name
> > >     madvise_vma_anon_name
> > >       madvise_update_vma
> > >
> > > In that case the name parameter is not part of any anon_vma_name
> > > struct and therefore is stable. I can add a comment to
> > > madvise_update_vma indicating that the name parameter has to be stable
> > > if that helps.
> >
> > Seems to me it'd simplify things if replace_vma_anon_name() and
> > madvise_vma_anon_name() took a struct anon_vma_name instead of
> > a bare char *.  You could construct it in madvise_set_anon_name().
> 
> Ok, this can be done. However I don't think changing
> replace_vma_anon_name() to accept a struct anon_vma_name would be a
> good idea. Reader might think that the object being passed will become
> the vma->anon_name of the vma, while in reality that's not the case.

Why woud we not want that to be the case?  It's a refcounted name.
I don't see why it shouldn't be shared between multiple VMAs that
have the same name?


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 1/1] mm: fix use-after-free when anon vma name is used after vma is freed
  2022-02-10 19:35         ` Matthew Wilcox
@ 2022-02-10 19:52           ` Suren Baghdasaryan
  2022-02-11  1:33             ` Suren Baghdasaryan
  0 siblings, 1 reply; 10+ messages in thread
From: Suren Baghdasaryan @ 2022-02-10 19:52 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: Michal Hocko, Andrew Morton, Colin Cross, Sumit Semwal,
	Dave Hansen, Kees Cook, Kirill A . Shutemov, Vlastimil Babka,
	Johannes Weiner, Eric W. Biederman, brauner, legion, ran.xiaokai,
	sashal, Chris Hyser, Davidlohr Bueso, Peter Collingbourne,
	caoxiaofeng, David Hildenbrand, Cyrill Gorcunov, linux-mm, LKML,
	kernel-team, syzbot+aa7b3d4b35f9dc46a366

On Thu, Feb 10, 2022 at 11:35 AM Matthew Wilcox <willy@infradead.org> wrote:
>
> On Thu, Feb 10, 2022 at 08:00:15AM -0800, Suren Baghdasaryan wrote:
> > On Thu, Feb 10, 2022 at 7:27 AM Matthew Wilcox <willy@infradead.org> wrote:
> > >
> > > On Thu, Feb 10, 2022 at 07:18:24AM -0800, Suren Baghdasaryan wrote:
> > > > On Thu, Feb 10, 2022 at 4:40 AM 'Michal Hocko' via kernel-team
> > > > <kernel-team@android.com> wrote:
> > > > >
> > > > > On Wed 09-02-22 20:32:15, Suren Baghdasaryan wrote:
> > > > > > When adjacent vmas are being merged it can result in the vma that was
> > > > > > originally passed to madvise_update_vma being destroyed. In the current
> > > > > > implementation, the name parameter passed to madvise_update_vma points
> > > > > > directly to vma->anon_name->name and it is used after the call to
> > > > > > vma_merge. In the cases when vma_merge merges the original vma and
> > > > > > destroys it, this will result in use-after-free bug as shown below:
> > > > > >
> > > > > > madvise_vma_behavior << passes vma->anon_name->name as name param
> > > > > >   madvise_update_vma(name)
> > > > > >     vma_merge
> > > > > >       __vma_adjust
> > > > > >         vm_area_free <-- frees the vma
> > > > > >     replace_vma_anon_name(name) <-- UAF
> > > > > >
> > > > > > Fix this by raising the name refcount and stabilizing it. Introduce
> > > > > > vma_anon_name_{get/put} API for this purpose.
> > > > >
> > > > > What is the reason that madvise_update_vma uses the naked name rather
> > > > > than the encapsulated anon_vma_name? This really just begs for problems.
> > > >
> > > > The reason for that is the second place it's being used from the prctl syscall:
> > > >
> > > > prctl_set_vma
> > > >   madvise_set_anon_name
> > > >     madvise_vma_anon_name
> > > >       madvise_update_vma
> > > >
> > > > In that case the name parameter is not part of any anon_vma_name
> > > > struct and therefore is stable. I can add a comment to
> > > > madvise_update_vma indicating that the name parameter has to be stable
> > > > if that helps.
> > >
> > > Seems to me it'd simplify things if replace_vma_anon_name() and
> > > madvise_vma_anon_name() took a struct anon_vma_name instead of
> > > a bare char *.  You could construct it in madvise_set_anon_name().
> >
> > Ok, this can be done. However I don't think changing
> > replace_vma_anon_name() to accept a struct anon_vma_name would be a
> > good idea. Reader might think that the object being passed will become
> > the vma->anon_name of the vma, while in reality that's not the case.
>
> Why woud we not want that to be the case?  It's a refcounted name.
> I don't see why it shouldn't be shared between multiple VMAs that
> have the same name?

You are right. After I reworked the code it became apparent that
replace_vma_anon_name() should use anon_vma_name. I have made that
change and am testing it now. Hopefully no new surprises pop up.
Thanks,
Suren.

>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 1/1] mm: fix use-after-free when anon vma name is used after vma is freed
  2022-02-10 19:52           ` Suren Baghdasaryan
@ 2022-02-11  1:33             ` Suren Baghdasaryan
  0 siblings, 0 replies; 10+ messages in thread
From: Suren Baghdasaryan @ 2022-02-11  1:33 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: Michal Hocko, Andrew Morton, Colin Cross, Sumit Semwal,
	Dave Hansen, Kees Cook, Kirill A . Shutemov, Vlastimil Babka,
	Johannes Weiner, Eric W. Biederman, brauner, legion, ran.xiaokai,
	sashal, Chris Hyser, Davidlohr Bueso, Peter Collingbourne,
	caoxiaofeng, David Hildenbrand, Cyrill Gorcunov, linux-mm, LKML,
	kernel-team, syzbot+aa7b3d4b35f9dc46a366

On Thu, Feb 10, 2022 at 11:52 AM Suren Baghdasaryan <surenb@google.com> wrote:
>
> On Thu, Feb 10, 2022 at 11:35 AM Matthew Wilcox <willy@infradead.org> wrote:
> >
> > On Thu, Feb 10, 2022 at 08:00:15AM -0800, Suren Baghdasaryan wrote:
> > > On Thu, Feb 10, 2022 at 7:27 AM Matthew Wilcox <willy@infradead.org> wrote:
> > > >
> > > > On Thu, Feb 10, 2022 at 07:18:24AM -0800, Suren Baghdasaryan wrote:
> > > > > On Thu, Feb 10, 2022 at 4:40 AM 'Michal Hocko' via kernel-team
> > > > > <kernel-team@android.com> wrote:
> > > > > >
> > > > > > On Wed 09-02-22 20:32:15, Suren Baghdasaryan wrote:
> > > > > > > When adjacent vmas are being merged it can result in the vma that was
> > > > > > > originally passed to madvise_update_vma being destroyed. In the current
> > > > > > > implementation, the name parameter passed to madvise_update_vma points
> > > > > > > directly to vma->anon_name->name and it is used after the call to
> > > > > > > vma_merge. In the cases when vma_merge merges the original vma and
> > > > > > > destroys it, this will result in use-after-free bug as shown below:
> > > > > > >
> > > > > > > madvise_vma_behavior << passes vma->anon_name->name as name param
> > > > > > >   madvise_update_vma(name)
> > > > > > >     vma_merge
> > > > > > >       __vma_adjust
> > > > > > >         vm_area_free <-- frees the vma
> > > > > > >     replace_vma_anon_name(name) <-- UAF
> > > > > > >
> > > > > > > Fix this by raising the name refcount and stabilizing it. Introduce
> > > > > > > vma_anon_name_{get/put} API for this purpose.
> > > > > >
> > > > > > What is the reason that madvise_update_vma uses the naked name rather
> > > > > > than the encapsulated anon_vma_name? This really just begs for problems.
> > > > >
> > > > > The reason for that is the second place it's being used from the prctl syscall:
> > > > >
> > > > > prctl_set_vma
> > > > >   madvise_set_anon_name
> > > > >     madvise_vma_anon_name
> > > > >       madvise_update_vma
> > > > >
> > > > > In that case the name parameter is not part of any anon_vma_name
> > > > > struct and therefore is stable. I can add a comment to
> > > > > madvise_update_vma indicating that the name parameter has to be stable
> > > > > if that helps.
> > > >
> > > > Seems to me it'd simplify things if replace_vma_anon_name() and
> > > > madvise_vma_anon_name() took a struct anon_vma_name instead of
> > > > a bare char *.  You could construct it in madvise_set_anon_name().
> > >
> > > Ok, this can be done. However I don't think changing
> > > replace_vma_anon_name() to accept a struct anon_vma_name would be a
> > > good idea. Reader might think that the object being passed will become
> > > the vma->anon_name of the vma, while in reality that's not the case.
> >
> > Why woud we not want that to be the case?  It's a refcounted name.
> > I don't see why it shouldn't be shared between multiple VMAs that
> > have the same name?
>
> You are right. After I reworked the code it became apparent that
> replace_vma_anon_name() should use anon_vma_name. I have made that
> change and am testing it now. Hopefully no new surprises pop up.

v3 is posted at
https://lore.kernel.org/all/20220211013032.623763-1-surenb@google.com/

> Thanks,
> Suren.
>
> >

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2022-02-11  1:33 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-10  4:32 [PATCH v2 1/1] mm: fix use-after-free when anon vma name is used after vma is freed Suren Baghdasaryan
2022-02-10 12:40 ` Michal Hocko
2022-02-10 15:18   ` Suren Baghdasaryan
2022-02-10 15:27     ` Matthew Wilcox
2022-02-10 16:00       ` Suren Baghdasaryan
2022-02-10 19:35         ` Matthew Wilcox
2022-02-10 19:52           ` Suren Baghdasaryan
2022-02-11  1:33             ` Suren Baghdasaryan
2022-02-10 13:27 ` Matthew Wilcox
2022-02-10 15:21   ` Suren Baghdasaryan

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.