From: Greg Kroah-Hartman Date: Wed, 12 May 2021 12:04:39 +0000 (+0200) Subject: 5.10-stable patches X-Git-Tag: v5.4.119~22 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bc1e9ffc9c6ac83f96782dffde2971399c99a573;p=thirdparty%2Fkernel%2Fstable-queue.git 5.10-stable patches added patches: bpf-fix-alu32-const-subreg-bound-tracking-on-bitwise-operations.patch bpf-prevent-writable-memory-mapping-of-read-only-ringbuf-pages.patch bpf-ringbuf-deny-reserve-of-buffers-larger-than-ringbuf.patch --- diff --git a/queue-5.10/bpf-fix-alu32-const-subreg-bound-tracking-on-bitwise-operations.patch b/queue-5.10/bpf-fix-alu32-const-subreg-bound-tracking-on-bitwise-operations.patch new file mode 100644 index 00000000000..41827584d9f --- /dev/null +++ b/queue-5.10/bpf-fix-alu32-const-subreg-bound-tracking-on-bitwise-operations.patch @@ -0,0 +1,112 @@ +From 049c4e13714ecbca567b4d5f6d563f05d431c80e Mon Sep 17 00:00:00 2001 +From: Daniel Borkmann +Date: Mon, 10 May 2021 13:10:44 +0000 +Subject: bpf: Fix alu32 const subreg bound tracking on bitwise operations + +From: Daniel Borkmann + +commit 049c4e13714ecbca567b4d5f6d563f05d431c80e upstream. + +Fix a bug in the verifier's scalar32_min_max_*() functions which leads to +incorrect tracking of 32 bit bounds for the simulation of and/or/xor bitops. +When both the src & dst subreg is a known constant, then the assumption is +that scalar_min_max_*() will take care to update bounds correctly. However, +this is not the case, for example, consider a register R2 which has a tnum +of 0xffffffff00000000, meaning, lower 32 bits are known constant and in this +case of value 0x00000001. R2 is then and'ed with a register R3 which is a +64 bit known constant, here, 0x100000002. + +What can be seen in line '10:' is that 32 bit bounds reach an invalid state +where {u,s}32_min_value > {u,s}32_max_value. The reason is scalar32_min_max_*() +delegates 32 bit bounds updates to scalar_min_max_*(), however, that really +only takes place when both the 64 bit src & dst register is a known constant. +Given scalar32_min_max_*() is intended to be designed as closely as possible +to scalar_min_max_*(), update the 32 bit bounds in this situation through +__mark_reg32_known() which will set all {u,s}32_{min,max}_value to the correct +constant, which is 0x00000000 after the fix (given 0x00000001 & 0x00000002 in +32 bit space). This is possible given var32_off already holds the final value +as dst_reg->var_off is updated before calling scalar32_min_max_*(). + +Before fix, invalid tracking of R2: + + [...] + 9: R0_w=inv1337 R1=ctx(id=0,off=0,imm=0) R2_w=inv(id=0,smin_value=-9223372036854775807 (0x8000000000000001),smax_value=9223372032559808513 (0x7fffffff00000001),umin_value=1,umax_value=0xffffffff00000001,var_off=(0x1; 0xffffffff00000000),s32_min_value=1,s32_max_value=1,u32_min_value=1,u32_max_value=1) R3_w=inv4294967298 R10=fp0 + 9: (5f) r2 &= r3 + 10: R0_w=inv1337 R1=ctx(id=0,off=0,imm=0) R2_w=inv(id=0,smin_value=0,smax_value=4294967296 (0x100000000),umin_value=0,umax_value=0x100000000,var_off=(0x0; 0x100000000),s32_min_value=1,s32_max_value=0,u32_min_value=1,u32_max_value=0) R3_w=inv4294967298 R10=fp0 + [...] + +After fix, correct tracking of R2: + + [...] + 9: R0_w=inv1337 R1=ctx(id=0,off=0,imm=0) R2_w=inv(id=0,smin_value=-9223372036854775807 (0x8000000000000001),smax_value=9223372032559808513 (0x7fffffff00000001),umin_value=1,umax_value=0xffffffff00000001,var_off=(0x1; 0xffffffff00000000),s32_min_value=1,s32_max_value=1,u32_min_value=1,u32_max_value=1) R3_w=inv4294967298 R10=fp0 + 9: (5f) r2 &= r3 + 10: R0_w=inv1337 R1=ctx(id=0,off=0,imm=0) R2_w=inv(id=0,smin_value=0,smax_value=4294967296 (0x100000000),umin_value=0,umax_value=0x100000000,var_off=(0x0; 0x100000000),s32_min_value=0,s32_max_value=0,u32_min_value=0,u32_max_value=0) R3_w=inv4294967298 R10=fp0 + [...] + +Fixes: 3f50f132d840 ("bpf: Verifier, do explicit ALU32 bounds tracking") +Fixes: 2921c90d4718 ("bpf: Fix a verifier failure with xor") +Reported-by: Manfred Paul (@_manfp) +Reported-by: Thadeu Lima de Souza Cascardo +Signed-off-by: Daniel Borkmann +Reviewed-by: John Fastabend +Acked-by: Alexei Starovoitov +Signed-off-by: Greg Kroah-Hartman +--- + kernel/bpf/verifier.c | 22 +++++++++------------- + 1 file changed, 9 insertions(+), 13 deletions(-) + +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -6341,11 +6341,10 @@ static void scalar32_min_max_and(struct + s32 smin_val = src_reg->s32_min_value; + u32 umax_val = src_reg->u32_max_value; + +- /* Assuming scalar64_min_max_and will be called so its safe +- * to skip updating register for known 32-bit case. +- */ +- if (src_known && dst_known) ++ if (src_known && dst_known) { ++ __mark_reg32_known(dst_reg, var32_off.value); + return; ++ } + + /* We get our minimum from the var_off, since that's inherently + * bitwise. Our maximum is the minimum of the operands' maxima. +@@ -6365,7 +6364,6 @@ static void scalar32_min_max_and(struct + dst_reg->s32_min_value = dst_reg->u32_min_value; + dst_reg->s32_max_value = dst_reg->u32_max_value; + } +- + } + + static void scalar_min_max_and(struct bpf_reg_state *dst_reg, +@@ -6412,11 +6410,10 @@ static void scalar32_min_max_or(struct b + s32 smin_val = src_reg->s32_min_value; + u32 umin_val = src_reg->u32_min_value; + +- /* Assuming scalar64_min_max_or will be called so it is safe +- * to skip updating register for known case. +- */ +- if (src_known && dst_known) ++ if (src_known && dst_known) { ++ __mark_reg32_known(dst_reg, var32_off.value); + return; ++ } + + /* We get our maximum from the var_off, and our minimum is the + * maximum of the operands' minima +@@ -6481,11 +6478,10 @@ static void scalar32_min_max_xor(struct + struct tnum var32_off = tnum_subreg(dst_reg->var_off); + s32 smin_val = src_reg->s32_min_value; + +- /* Assuming scalar64_min_max_xor will be called so it is safe +- * to skip updating register for known case. +- */ +- if (src_known && dst_known) ++ if (src_known && dst_known) { ++ __mark_reg32_known(dst_reg, var32_off.value); + return; ++ } + + /* We get both minimum and maximum from the var32_off. */ + dst_reg->u32_min_value = var32_off.value; diff --git a/queue-5.10/bpf-prevent-writable-memory-mapping-of-read-only-ringbuf-pages.patch b/queue-5.10/bpf-prevent-writable-memory-mapping-of-read-only-ringbuf-pages.patch new file mode 100644 index 00000000000..6530c19e401 --- /dev/null +++ b/queue-5.10/bpf-prevent-writable-memory-mapping-of-read-only-ringbuf-pages.patch @@ -0,0 +1,67 @@ +From 04ea3086c4d73da7009de1e84962a904139af219 Mon Sep 17 00:00:00 2001 +From: Andrii Nakryiko +Date: Tue, 4 May 2021 16:38:00 -0700 +Subject: bpf: Prevent writable memory-mapping of read-only ringbuf pages + +From: Andrii Nakryiko + +commit 04ea3086c4d73da7009de1e84962a904139af219 upstream. + +Only the very first page of BPF ringbuf that contains consumer position +counter is supposed to be mapped as writeable by user-space. Producer +position is read-only and can be modified only by the kernel code. BPF ringbuf +data pages are read-only as well and are not meant to be modified by +user-code to maintain integrity of per-record headers. + +This patch allows to map only consumer position page as writeable and +everything else is restricted to be read-only. remap_vmalloc_range() +internally adds VM_DONTEXPAND, so all the established memory mappings can't be +extended, which prevents any future violations through mremap()'ing. + +Fixes: 457f44363a88 ("bpf: Implement BPF ring buffer and verifier support for it") +Reported-by: Ryota Shiga (Flatt Security) +Reported-by: Thadeu Lima de Souza Cascardo +Signed-off-by: Andrii Nakryiko +Signed-off-by: Daniel Borkmann +Acked-by: Alexei Starovoitov +Signed-off-by: Greg Kroah-Hartman +--- + kernel/bpf/ringbuf.c | 21 ++++++++------------- + 1 file changed, 8 insertions(+), 13 deletions(-) + +--- a/kernel/bpf/ringbuf.c ++++ b/kernel/bpf/ringbuf.c +@@ -240,25 +240,20 @@ static int ringbuf_map_get_next_key(stru + 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_pgoff * PAGE_SIZE + (vma->vm_end - vma->vm_start) > mmap_sz) +- return -EINVAL; + ++ 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; ++ } ++ /* remap_vmalloc_range() checks size and offset constraints */ + return remap_vmalloc_range(vma, rb_map->rb, + vma->vm_pgoff + RINGBUF_PGOFF); + } diff --git a/queue-5.10/bpf-ringbuf-deny-reserve-of-buffers-larger-than-ringbuf.patch b/queue-5.10/bpf-ringbuf-deny-reserve-of-buffers-larger-than-ringbuf.patch new file mode 100644 index 00000000000..e2d2c33e0c1 --- /dev/null +++ b/queue-5.10/bpf-ringbuf-deny-reserve-of-buffers-larger-than-ringbuf.patch @@ -0,0 +1,37 @@ +From 4b81ccebaeee885ab1aa1438133f2991e3a2b6ea Mon Sep 17 00:00:00 2001 +From: Thadeu Lima de Souza Cascardo +Date: Tue, 27 Apr 2021 10:12:12 -0300 +Subject: bpf, ringbuf: Deny reserve of buffers larger than ringbuf + +From: Thadeu Lima de Souza Cascardo + +commit 4b81ccebaeee885ab1aa1438133f2991e3a2b6ea upstream. + +A BPF program might try to reserve a buffer larger than the ringbuf size. +If the consumer pointer is way ahead of the producer, that would be +successfully reserved, allowing the BPF program to read or write out of +the ringbuf allocated area. + +Reported-by: Ryota Shiga (Flatt Security) +Fixes: 457f44363a88 ("bpf: Implement BPF ring buffer and verifier support for it") +Signed-off-by: Thadeu Lima de Souza Cascardo +Signed-off-by: Daniel Borkmann +Acked-by: Andrii Nakryiko +Acked-by: Alexei Starovoitov +Signed-off-by: Greg Kroah-Hartman +--- + kernel/bpf/ringbuf.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/kernel/bpf/ringbuf.c ++++ b/kernel/bpf/ringbuf.c +@@ -334,6 +334,9 @@ static void *__bpf_ringbuf_reserve(struc + return NULL; + + len = round_up(size + BPF_RINGBUF_HDR_SZ, 8); ++ if (len > rb->mask + 1) ++ return NULL; ++ + cons_pos = smp_load_acquire(&rb->consumer_pos); + + if (in_nmi()) { diff --git a/queue-5.10/series b/queue-5.10/series index 962481e32ee..8a7a4181b27 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -520,3 +520,6 @@ mm-memcontrol-slab-fix-obtain-a-reference-to-a-freei.patch mm-sparse-add-the-missing-sparse_buffer_fini-in-erro.patch mm-memory-failure-unnecessary-amount-of-unmapping.patch afs-fix-speculative-status-fetches.patch +bpf-fix-alu32-const-subreg-bound-tracking-on-bitwise-operations.patch +bpf-ringbuf-deny-reserve-of-buffers-larger-than-ringbuf.patch +bpf-prevent-writable-memory-mapping-of-read-only-ringbuf-pages.patch