Skip to content

Commit bd40513

Browse files
gthelengregkh
authored andcommitted
perf/core: Avoid put_page() when GUP fails
commit 4716023 upstream. PEBS PERF_SAMPLE_PHYS_ADDR events use perf_virt_to_phys() to convert PMU sampled virtual addresses to physical using get_user_page_fast_only() and page_to_phys(). Some get_user_page_fast_only() error cases return false, indicating no page reference, but still initialize the output page pointer with an unreferenced page. In these error cases perf_virt_to_phys() calls put_page(). This causes page reference count underflow, which can lead to unintentional page sharing. Fix perf_virt_to_phys() to only put_page() if get_user_page_fast_only() returns a referenced page. Fixes: fc7ce9c ("perf/core, x86: Add PERF_SAMPLE_PHYS_ADDR") Signed-off-by: Greg Thelen <gthelen@google.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lkml.kernel.org/r/20211111021814.757086-1-gthelen@google.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent df58fb4 commit bd40513

1 file changed

Lines changed: 5 additions & 5 deletions

File tree

kernel/events/core.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7036,7 +7036,6 @@ void perf_output_sample(struct perf_output_handle *handle,
70367036
static u64 perf_virt_to_phys(u64 virt)
70377037
{
70387038
u64 phys_addr = 0;
7039-
struct page *p = NULL;
70407039

70417040
if (!virt)
70427041
return 0;
@@ -7055,14 +7054,15 @@ static u64 perf_virt_to_phys(u64 virt)
70557054
* If failed, leave phys_addr as 0.
70567055
*/
70577056
if (current->mm != NULL) {
7057+
struct page *p;
7058+
70587059
pagefault_disable();
7059-
if (get_user_page_fast_only(virt, 0, &p))
7060+
if (get_user_page_fast_only(virt, 0, &p)) {
70607061
phys_addr = page_to_phys(p) + virt % PAGE_SIZE;
7062+
put_page(p);
7063+
}
70617064
pagefault_enable();
70627065
}
7063-
7064-
if (p)
7065-
put_page(p);
70667066
}
70677067

70687068
return phys_addr;

0 commit comments

Comments
 (0)