diff mbox series

[SRU,Groovy,Focal/linux-oem-5.10/Hirsute,1/2] UBUNTU: SAUCE: Revert "UBUNTU: SAUCE: bpf: prevent writable memory-mapping of read-only ringbuf pages"

Message ID 20210527001150.38562-2-cascardo@canonical.com
State New
Headers show
Series CVE-2021-3489 fixups | expand

Commit Message

Thadeu Lima de Souza Cascardo May 27, 2021, 12:11 a.m. UTC
This reverts commit abcc616635230904054f511bf99ec5b4bc819239.

Though the else is aligned to the first if, as there are no braces being
used, it refers to the second if.

There is no harm in the cases where !(vma->vm_flags & VM_WRITE), because
kernel/bpf/syscall.c:bpf_map_mmap will already do it before calling our
ringbuf mmap function.

However, for the case of mapping the consumer pointer page, it will have
its VM_MAYWRITE flag removed. This prevents mprotect(PROT_WRITE) from
working.

The following commit will apply the upstream version, which has this fixed,
hence reverting this one.

Reported-by: Kamal Mostafa <kamal@canonical.com>
CVE-2021-3489
Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
---
 kernel/bpf/ringbuf.c | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)
diff mbox series

Patch

diff --git a/kernel/bpf/ringbuf.c b/kernel/bpf/ringbuf.c
index debe27564924..1619afe00ded 100644
--- a/kernel/bpf/ringbuf.c
+++ b/kernel/bpf/ringbuf.c
@@ -247,20 +247,25 @@  static int ringbuf_map_get_next_key(struct bpf_map *map, void *key,
 	return -ENOTSUPP;
 }
 
+static size_t bpf_ringbuf_mmap_page_cnt(const struct bpf_ringbuf *rb)
+{
+	size_t data_pages = (rb->mask + 1) >> PAGE_SHIFT;
+
+	/* consumer page + producer page + 2 x data pages */
+	return RINGBUF_POS_PAGES + 2 * data_pages;
+}
+
 static int ringbuf_map_mmap(struct bpf_map *map, struct vm_area_struct *vma)
 {
 	struct bpf_ringbuf_map *rb_map;
+	size_t mmap_sz;
 
 	rb_map = container_of(map, struct bpf_ringbuf_map, map);
+	mmap_sz = bpf_ringbuf_mmap_page_cnt(rb_map->rb) << PAGE_SHIFT;
 
-	if (vma->vm_flags & VM_WRITE)
-		/* allow writable mapping for the consumer_pos only */
-		if (vma->vm_pgoff != 0 || vma->vm_end - vma->vm_start != PAGE_SIZE)
-			return -EPERM;
-	else
-		vma->vm_flags &= ~VM_MAYWRITE;
+	if (vma->vm_pgoff * PAGE_SIZE + (vma->vm_end - vma->vm_start) > mmap_sz)
+		return -EINVAL;
 
-		/* remap_vmalloc_range() checks size and offset constraints */
 	return remap_vmalloc_range(vma, rb_map->rb,
 				   vma->vm_pgoff + RINGBUF_PGOFF);
 }