Skip to content

Commit 831e1c9

Browse files
KAGA-KOKOgregkh
authored andcommitted
perf/core: Handle buffer mapping fail correctly in perf_mmap()
commit f74b9f4 upstream. After successful allocation of a buffer or a successful attachment to an existing buffer perf_mmap() tries to map the buffer read only into the page table. If that fails, the already set up page table entries are zapped, but the other perf specific side effects of that failure are not handled. The calling code just cleans up the VMA and does not invoke perf_mmap_close(). This leaks reference counts, corrupts user->vm accounting and also results in an unbalanced invocation of event::event_mapped(). Cure this by moving the event::event_mapped() invocation before the map_range() call so that on map_range() failure perf_mmap_close() can be invoked without causing an unbalanced event::event_unmapped() call. perf_mmap_close() undoes the reference counts and eventually frees buffers. Fixes: b709eb8 ("perf/core: map pages in advance") Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 163b0d1 commit 831e1c9

1 file changed

Lines changed: 11 additions & 3 deletions

File tree

kernel/events/core.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7085,11 +7085,19 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)
70857085
vm_flags_set(vma, VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP);
70867086
vma->vm_ops = &perf_mmap_vmops;
70877087

7088-
ret = map_range(rb, vma);
7089-
7090-
if (!ret && event->pmu->event_mapped)
7088+
if (event->pmu->event_mapped)
70917089
event->pmu->event_mapped(event, vma->vm_mm);
70927090

7091+
/*
7092+
* Try to map it into the page table. On fail, invoke
7093+
* perf_mmap_close() to undo the above, as the callsite expects
7094+
* full cleanup in this case and therefore does not invoke
7095+
* vmops::close().
7096+
*/
7097+
ret = map_range(rb, vma);
7098+
if (ret)
7099+
perf_mmap_close(vma);
7100+
70937101
return ret;
70947102
}
70957103

0 commit comments

Comments
 (0)