57 lines
2.1 KiB
Diff
57 lines
2.1 KiB
Diff
|
From: Linus Torvalds <torvalds@linux-foundation.org>
|
||
|
Date: Thu, 11 Apr 2019 10:14:59 -0700
|
||
|
Subject: mm: add 'try_get_page()' helper function
|
||
|
Origin: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/commit?id=0612cae7ec6b79d2ff1b34562bab79d5bf96327a
|
||
|
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2019-11487
|
||
|
|
||
|
commit 88b1a17dfc3ed7728316478fae0f5ad508f50397 upstream.
|
||
|
|
||
|
This is the same as the traditional 'get_page()' function, but instead
|
||
|
of unconditionally incrementing the reference count of the page, it only
|
||
|
does so if the count was "safe". It returns whether the reference count
|
||
|
was incremented (and is marked __must_check, since the caller obviously
|
||
|
has to be aware of it).
|
||
|
|
||
|
Also like 'get_page()', you can't use this function unless you already
|
||
|
had a reference to the page. The intent is that you can use this
|
||
|
exactly like get_page(), but in situations where you want to limit the
|
||
|
maximum reference count.
|
||
|
|
||
|
The code currently does an unconditional WARN_ON_ONCE() if we ever hit
|
||
|
the reference count issues (either zero or negative), as a notification
|
||
|
that the conditional non-increment actually happened.
|
||
|
|
||
|
NOTE! The count access for the "safety" check is inherently racy, but
|
||
|
that doesn't matter since the buffer we use is basically half the range
|
||
|
of the reference count (ie we look at the sign of the count).
|
||
|
|
||
|
Acked-by: Matthew Wilcox <willy@infradead.org>
|
||
|
Cc: Jann Horn <jannh@google.com>
|
||
|
Cc: stable@kernel.org
|
||
|
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||
|
---
|
||
|
include/linux/mm.h | 9 +++++++++
|
||
|
1 file changed, 9 insertions(+)
|
||
|
|
||
|
diff --git a/include/linux/mm.h b/include/linux/mm.h
|
||
|
index 9965704813dc..bdec425c8e14 100644
|
||
|
--- a/include/linux/mm.h
|
||
|
+++ b/include/linux/mm.h
|
||
|
@@ -930,6 +930,15 @@ static inline void get_page(struct page *page)
|
||
|
page_ref_inc(page);
|
||
|
}
|
||
|
|
||
|
+static inline __must_check bool try_get_page(struct page *page)
|
||
|
+{
|
||
|
+ page = compound_head(page);
|
||
|
+ if (WARN_ON_ONCE(page_ref_count(page) <= 0))
|
||
|
+ return false;
|
||
|
+ page_ref_inc(page);
|
||
|
+ return true;
|
||
|
+}
|
||
|
+
|
||
|
static inline void put_page(struct page *page)
|
||
|
{
|
||
|
page = compound_head(page);
|