From a418c5b448d4ead25c4265db7803b238bc7cd1ee Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 19 Mar 2021 09:35:06 +0100 Subject: [PATCH] 4.14-stable patches added patches: bpf-add-sanity-check-for-upper-ptr_limit.patch bpf-fix-off-by-one-for-area-size-in-creating-mask-to-left.patch bpf-simplify-alu_limit-masking-for-pointer-arithmetic.patch --- ...add-sanity-check-for-upper-ptr_limit.patch | 58 +++++++++++++++++++ ...r-area-size-in-creating-mask-to-left.patch | 54 +++++++++++++++++ ...limit-masking-for-pointer-arithmetic.patch | 57 ++++++++++++++++++ queue-4.14/series | 3 + 4 files changed, 172 insertions(+) create mode 100644 queue-4.14/bpf-add-sanity-check-for-upper-ptr_limit.patch create mode 100644 queue-4.14/bpf-fix-off-by-one-for-area-size-in-creating-mask-to-left.patch create mode 100644 queue-4.14/bpf-simplify-alu_limit-masking-for-pointer-arithmetic.patch diff --git a/queue-4.14/bpf-add-sanity-check-for-upper-ptr_limit.patch b/queue-4.14/bpf-add-sanity-check-for-upper-ptr_limit.patch new file mode 100644 index 00000000000..50a6a0d984b --- /dev/null +++ b/queue-4.14/bpf-add-sanity-check-for-upper-ptr_limit.patch @@ -0,0 +1,58 @@ +From 1b1597e64e1a610c7a96710fc4717158e98a08b3 Mon Sep 17 00:00:00 2001 +From: Piotr Krysiuk +Date: Tue, 16 Mar 2021 09:47:02 +0100 +Subject: bpf: Add sanity check for upper ptr_limit + +From: Piotr Krysiuk + +commit 1b1597e64e1a610c7a96710fc4717158e98a08b3 upstream. + +Given we know the max possible value of ptr_limit at the time of retrieving +the latter, add basic assertions, so that the verifier can bail out if +anything looks odd and reject the program. Nothing triggered this so far, +but it also does not hurt to have these. + +Signed-off-by: Piotr Krysiuk +Co-developed-by: Daniel Borkmann +Signed-off-by: Daniel Borkmann +Acked-by: Alexei Starovoitov +Signed-off-by: Greg Kroah-Hartman +--- + kernel/bpf/verifier.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -2029,24 +2029,29 @@ static int retrieve_ptr_limit(const stru + { + bool mask_to_left = (opcode == BPF_ADD && off_is_neg) || + (opcode == BPF_SUB && !off_is_neg); +- u32 off; ++ u32 off, max; + + switch (ptr_reg->type) { + case PTR_TO_STACK: ++ /* Offset 0 is out-of-bounds, but acceptable start for the ++ * left direction, see BPF_REG_FP. ++ */ ++ max = MAX_BPF_STACK + mask_to_left; + off = ptr_reg->off + ptr_reg->var_off.value; + if (mask_to_left) + *ptr_limit = MAX_BPF_STACK + off; + else + *ptr_limit = -off - 1; +- return 0; ++ return *ptr_limit >= max ? -ERANGE : 0; + case PTR_TO_MAP_VALUE: ++ max = ptr_reg->map_ptr->value_size; + if (mask_to_left) { + *ptr_limit = ptr_reg->umax_value + ptr_reg->off; + } else { + off = ptr_reg->smin_value + ptr_reg->off; + *ptr_limit = ptr_reg->map_ptr->value_size - off - 1; + } +- return 0; ++ return *ptr_limit >= max ? -ERANGE : 0; + default: + return -EINVAL; + } diff --git a/queue-4.14/bpf-fix-off-by-one-for-area-size-in-creating-mask-to-left.patch b/queue-4.14/bpf-fix-off-by-one-for-area-size-in-creating-mask-to-left.patch new file mode 100644 index 00000000000..d51e17bd541 --- /dev/null +++ b/queue-4.14/bpf-fix-off-by-one-for-area-size-in-creating-mask-to-left.patch @@ -0,0 +1,54 @@ +From 10d2bb2e6b1d8c4576c56a748f697dbeb8388899 Mon Sep 17 00:00:00 2001 +From: Piotr Krysiuk +Date: Tue, 16 Mar 2021 08:20:16 +0100 +Subject: bpf: Fix off-by-one for area size in creating mask to left + +From: Piotr Krysiuk + +commit 10d2bb2e6b1d8c4576c56a748f697dbeb8388899 upstream. + +retrieve_ptr_limit() computes the ptr_limit for registers with stack and +map_value type. ptr_limit is the size of the memory area that is still +valid / in-bounds from the point of the current position and direction +of the operation (add / sub). This size will later be used for masking +the operation such that attempting out-of-bounds access in the speculative +domain is redirected to remain within the bounds of the current map value. + +When masking to the right the size is correct, however, when masking to +the left, the size is off-by-one which would lead to an incorrect mask +and thus incorrect arithmetic operation in the non-speculative domain. +Piotr found that if the resulting alu_limit value is zero, then the +BPF_MOV32_IMM() from the fixup_bpf_calls() rewrite will end up loading +0xffffffff into AX instead of sign-extending to the full 64 bit range, +and as a result, this allows abuse for executing speculatively out-of- +bounds loads against 4GB window of address space and thus extracting the +contents of kernel memory via side-channel. + +Fixes: 979d63d50c0c ("bpf: prevent out of bounds speculation on pointer arithmetic") +Signed-off-by: Piotr Krysiuk +Co-developed-by: Daniel Borkmann +Signed-off-by: Daniel Borkmann +Acked-by: Alexei Starovoitov +Signed-off-by: Greg Kroah-Hartman +--- + kernel/bpf/verifier.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -2035,13 +2035,13 @@ static int retrieve_ptr_limit(const stru + case PTR_TO_STACK: + off = ptr_reg->off + ptr_reg->var_off.value; + if (mask_to_left) +- *ptr_limit = MAX_BPF_STACK + off; ++ *ptr_limit = MAX_BPF_STACK + off + 1; + else + *ptr_limit = -off; + return 0; + case PTR_TO_MAP_VALUE: + if (mask_to_left) { +- *ptr_limit = ptr_reg->umax_value + ptr_reg->off; ++ *ptr_limit = ptr_reg->umax_value + ptr_reg->off + 1; + } else { + off = ptr_reg->smin_value + ptr_reg->off; + *ptr_limit = ptr_reg->map_ptr->value_size - off; diff --git a/queue-4.14/bpf-simplify-alu_limit-masking-for-pointer-arithmetic.patch b/queue-4.14/bpf-simplify-alu_limit-masking-for-pointer-arithmetic.patch new file mode 100644 index 00000000000..0db5ac3513f --- /dev/null +++ b/queue-4.14/bpf-simplify-alu_limit-masking-for-pointer-arithmetic.patch @@ -0,0 +1,57 @@ +From b5871dca250cd391885218b99cc015aca1a51aea Mon Sep 17 00:00:00 2001 +From: Piotr Krysiuk +Date: Tue, 16 Mar 2021 08:26:25 +0100 +Subject: bpf: Simplify alu_limit masking for pointer arithmetic + +From: Piotr Krysiuk + +commit b5871dca250cd391885218b99cc015aca1a51aea upstream. + +Instead of having the mov32 with aux->alu_limit - 1 immediate, move this +operation to retrieve_ptr_limit() instead to simplify the logic and to +allow for subsequent sanity boundary checks inside retrieve_ptr_limit(). +This avoids in future that at the time of the verifier masking rewrite +we'd run into an underflow which would not sign extend due to the nature +of mov32 instruction. + +Signed-off-by: Piotr Krysiuk +Co-developed-by: Daniel Borkmann +Signed-off-by: Daniel Borkmann +Acked-by: Alexei Starovoitov +Signed-off-by: Greg Kroah-Hartman +--- + kernel/bpf/verifier.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -2035,16 +2035,16 @@ static int retrieve_ptr_limit(const stru + case PTR_TO_STACK: + off = ptr_reg->off + ptr_reg->var_off.value; + if (mask_to_left) +- *ptr_limit = MAX_BPF_STACK + off + 1; ++ *ptr_limit = MAX_BPF_STACK + off; + else +- *ptr_limit = -off; ++ *ptr_limit = -off - 1; + return 0; + case PTR_TO_MAP_VALUE: + if (mask_to_left) { +- *ptr_limit = ptr_reg->umax_value + ptr_reg->off + 1; ++ *ptr_limit = ptr_reg->umax_value + ptr_reg->off; + } else { + off = ptr_reg->smin_value + ptr_reg->off; +- *ptr_limit = ptr_reg->map_ptr->value_size - off; ++ *ptr_limit = ptr_reg->map_ptr->value_size - off - 1; + } + return 0; + default: +@@ -4802,7 +4802,7 @@ static int fixup_bpf_calls(struct bpf_ve + off_reg = issrc ? insn->src_reg : insn->dst_reg; + if (isneg) + *patch++ = BPF_ALU64_IMM(BPF_MUL, off_reg, -1); +- *patch++ = BPF_MOV32_IMM(BPF_REG_AX, aux->alu_limit - 1); ++ *patch++ = BPF_MOV32_IMM(BPF_REG_AX, aux->alu_limit); + *patch++ = BPF_ALU64_REG(BPF_SUB, BPF_REG_AX, off_reg); + *patch++ = BPF_ALU64_REG(BPF_OR, BPF_REG_AX, off_reg); + *patch++ = BPF_ALU64_IMM(BPF_NEG, BPF_REG_AX, 0); diff --git a/queue-4.14/series b/queue-4.14/series index 09a51753b89..e466cc94f53 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -1,3 +1,6 @@ ext4-handle-error-of-ext4_setup_system_zone-on-remount.patch ext4-don-t-allow-overlapping-system-zones.patch ext4-check-journal-inode-extents-more-carefully.patch +bpf-fix-off-by-one-for-area-size-in-creating-mask-to-left.patch +bpf-simplify-alu_limit-masking-for-pointer-arithmetic.patch +bpf-add-sanity-check-for-upper-ptr_limit.patch -- 2.47.3