]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.12-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 12 May 2021 12:05:20 +0000 (14:05 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 12 May 2021 12:05:20 +0000 (14:05 +0200)
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

queue-5.12/bpf-fix-alu32-const-subreg-bound-tracking-on-bitwise-operations.patch [new file with mode: 0644]
queue-5.12/bpf-prevent-writable-memory-mapping-of-read-only-ringbuf-pages.patch [new file with mode: 0644]
queue-5.12/bpf-ringbuf-deny-reserve-of-buffers-larger-than-ringbuf.patch [new file with mode: 0644]
queue-5.12/series

diff --git a/queue-5.12/bpf-fix-alu32-const-subreg-bound-tracking-on-bitwise-operations.patch b/queue-5.12/bpf-fix-alu32-const-subreg-bound-tracking-on-bitwise-operations.patch
new file mode 100644 (file)
index 0000000..d32f44d
--- /dev/null
@@ -0,0 +1,112 @@
+From 049c4e13714ecbca567b4d5f6d563f05d431c80e Mon Sep 17 00:00:00 2001
+From: Daniel Borkmann <daniel@iogearbox.net>
+Date: Mon, 10 May 2021 13:10:44 +0000
+Subject: bpf: Fix alu32 const subreg bound tracking on bitwise operations
+
+From: Daniel Borkmann <daniel@iogearbox.net>
+
+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 <cascardo@canonical.com>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Reviewed-by: John Fastabend <john.fastabend@gmail.com>
+Acked-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/bpf/verifier.c |   22 +++++++++-------------
+ 1 file changed, 9 insertions(+), 13 deletions(-)
+
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -6538,11 +6538,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.
+@@ -6562,7 +6561,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,
+@@ -6609,11 +6607,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
+@@ -6678,11 +6675,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.12/bpf-prevent-writable-memory-mapping-of-read-only-ringbuf-pages.patch b/queue-5.12/bpf-prevent-writable-memory-mapping-of-read-only-ringbuf-pages.patch
new file mode 100644 (file)
index 0000000..00751cb
--- /dev/null
@@ -0,0 +1,67 @@
+From 04ea3086c4d73da7009de1e84962a904139af219 Mon Sep 17 00:00:00 2001
+From: Andrii Nakryiko <andrii@kernel.org>
+Date: Tue, 4 May 2021 16:38:00 -0700
+Subject: bpf: Prevent writable memory-mapping of read-only ringbuf pages
+
+From: Andrii Nakryiko <andrii@kernel.org>
+
+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 <cascardo@canonical.com>
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Acked-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/bpf/ringbuf.c |   21 ++++++++-------------
+ 1 file changed, 8 insertions(+), 13 deletions(-)
+
+--- a/kernel/bpf/ringbuf.c
++++ b/kernel/bpf/ringbuf.c
+@@ -221,25 +221,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.12/bpf-ringbuf-deny-reserve-of-buffers-larger-than-ringbuf.patch b/queue-5.12/bpf-ringbuf-deny-reserve-of-buffers-larger-than-ringbuf.patch
new file mode 100644 (file)
index 0000000..9aabc15
--- /dev/null
@@ -0,0 +1,37 @@
+From 4b81ccebaeee885ab1aa1438133f2991e3a2b6ea Mon Sep 17 00:00:00 2001
+From: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
+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 <cascardo@canonical.com>
+
+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 <cascardo@canonical.com>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Acked-by: Andrii Nakryiko <andrii@kernel.org>
+Acked-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/bpf/ringbuf.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/kernel/bpf/ringbuf.c
++++ b/kernel/bpf/ringbuf.c
+@@ -315,6 +315,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()) {
index 0537f922c1c901c33d2aa8f7b33e97012a6d3437..6eeda0d1fd233c5a6f4a70570222d8b4656ce1e5 100644 (file)
@@ -668,3 +668,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