[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"

Thadeu Lima de Souza Cascardo cascardo at canonical.com
Thu May 27 00:11:49 UTC 2021


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 at canonical.com>
CVE-2021-3489
Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo at canonical.com>
---
 kernel/bpf/ringbuf.c | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

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);
 }
-- 
2.30.2




More information about the kernel-team mailing list