All of lore.kernel.org
 help / color / mirror / Atom feed
From: Suren Baghdasaryan <surenb@google.com>
To: akpm@linux-foundation.org
Cc: ccross@google.com, sumit.semwal@linaro.org, mhocko@suse.com,
	dave.hansen@intel.com, keescook@chromium.org,
	willy@infradead.org, kirill.shutemov@linux.intel.com,
	vbabka@suse.cz, hannes@cmpxchg.org, ebiederm@xmission.com,
	brauner@kernel.org, legion@kernel.org, ran.xiaokai@zte.com.cn,
	sashal@kernel.org, chris.hyser@oracle.com, dave@stgolabs.net,
	pcc@google.com, caoxiaofeng@yulong.com, david@redhat.com,
	gorcunov@gmail.com, linux-mm@kvack.org,
	linux-kernel@vger.kernel.org, kernel-team@android.com,
	surenb@google.com,
	syzbot+aa7b3d4b35f9dc46a366@syzkaller.appspotmail.com
Subject: [PATCH v2 1/1] mm: fix use-after-free when anon vma name is used after vma is freed
Date: Wed,  9 Feb 2022 20:32:15 -0800	[thread overview]
Message-ID: <20220210043215.42794-1-surenb@google.com> (raw)

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


             reply	other threads:[~2022-02-10  4:32 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-02-10  4:32 Suren Baghdasaryan [this message]
2022-02-10 12:40 ` [PATCH v2 1/1] mm: fix use-after-free when anon vma name is used after vma is freed 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

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=20220210043215.42794-1-surenb@google.com \
    --to=surenb@google.com \
    --cc=akpm@linux-foundation.org \
    --cc=brauner@kernel.org \
    --cc=caoxiaofeng@yulong.com \
    --cc=ccross@google.com \
    --cc=chris.hyser@oracle.com \
    --cc=dave.hansen@intel.com \
    --cc=dave@stgolabs.net \
    --cc=david@redhat.com \
    --cc=ebiederm@xmission.com \
    --cc=gorcunov@gmail.com \
    --cc=hannes@cmpxchg.org \
    --cc=keescook@chromium.org \
    --cc=kernel-team@android.com \
    --cc=kirill.shutemov@linux.intel.com \
    --cc=legion@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=mhocko@suse.com \
    --cc=pcc@google.com \
    --cc=ran.xiaokai@zte.com.cn \
    --cc=sashal@kernel.org \
    --cc=sumit.semwal@linaro.org \
    --cc=syzbot+aa7b3d4b35f9dc46a366@syzkaller.appspotmail.com \
    --cc=vbabka@suse.cz \
    --cc=willy@infradead.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.