]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 26 May 2021 15:16:15 +0000 (17:16 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 26 May 2021 15:16:15 +0000 (17:16 +0200)
added patches:
bpf-fix-mask-direction-swap-upon-off-reg-sign-change.patch
bpf-no-need-to-simulate-speculative-domain-for-immediates.patch
bpf-wrap-aux-data-inside-bpf_sanitize_info-container.patch

queue-5.10/bpf-fix-mask-direction-swap-upon-off-reg-sign-change.patch [new file with mode: 0644]
queue-5.10/bpf-no-need-to-simulate-speculative-domain-for-immediates.patch [new file with mode: 0644]
queue-5.10/bpf-wrap-aux-data-inside-bpf_sanitize_info-container.patch [new file with mode: 0644]

diff --git a/queue-5.10/bpf-fix-mask-direction-swap-upon-off-reg-sign-change.patch b/queue-5.10/bpf-fix-mask-direction-swap-upon-off-reg-sign-change.patch
new file mode 100644 (file)
index 0000000..471f2fe
--- /dev/null
@@ -0,0 +1,74 @@
+From bb01a1bba579b4b1c5566af24d95f1767859771e Mon Sep 17 00:00:00 2001
+From: Daniel Borkmann <daniel@iogearbox.net>
+Date: Fri, 21 May 2021 10:19:22 +0000
+Subject: bpf: Fix mask direction swap upon off reg sign change
+
+From: Daniel Borkmann <daniel@iogearbox.net>
+
+commit bb01a1bba579b4b1c5566af24d95f1767859771e upstream.
+
+Masking direction as indicated via mask_to_left is considered to be
+calculated once and then used to derive pointer limits. Thus, this
+needs to be placed into bpf_sanitize_info instead so we can pass it
+to sanitize_ptr_alu() call after the pointer move. Piotr noticed a
+corner case where the off reg causes masking direction change which
+then results in an incorrect final aux->alu_limit.
+
+Fixes: 7fedb63a8307 ("bpf: Tighten speculative pointer arithmetic mask")
+Reported-by: Piotr Krysiuk <piotras@gmail.com>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Reviewed-by: Piotr Krysiuk <piotras@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, 12 insertions(+), 10 deletions(-)
+
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -5666,18 +5666,10 @@ enum {
+ };
+ static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg,
+-                            const struct bpf_reg_state *off_reg,
+-                            u32 *alu_limit, u8 opcode)
++                            u32 *alu_limit, bool mask_to_left)
+ {
+-      bool off_is_neg = off_reg->smin_value < 0;
+-      bool mask_to_left = (opcode == BPF_ADD &&  off_is_neg) ||
+-                          (opcode == BPF_SUB && !off_is_neg);
+       u32 max = 0, ptr_limit = 0;
+-      if (!tnum_is_const(off_reg->var_off) &&
+-          (off_reg->smin_value < 0) != (off_reg->smax_value < 0))
+-              return REASON_BOUNDS;
+-
+       switch (ptr_reg->type) {
+       case PTR_TO_STACK:
+               /* Offset 0 is out-of-bounds, but acceptable start for the
+@@ -5745,6 +5737,7 @@ static bool sanitize_needed(u8 opcode)
+ struct bpf_sanitize_info {
+       struct bpf_insn_aux_data aux;
++      bool mask_to_left;
+ };
+ static int sanitize_ptr_alu(struct bpf_verifier_env *env,
+@@ -5776,7 +5769,16 @@ static int sanitize_ptr_alu(struct bpf_v
+       if (vstate->speculative)
+               goto do_sim;
+-      err = retrieve_ptr_limit(ptr_reg, off_reg, &alu_limit, opcode);
++      if (!commit_window) {
++              if (!tnum_is_const(off_reg->var_off) &&
++                  (off_reg->smin_value < 0) != (off_reg->smax_value < 0))
++                      return REASON_BOUNDS;
++
++              info->mask_to_left = (opcode == BPF_ADD &&  off_is_neg) ||
++                                   (opcode == BPF_SUB && !off_is_neg);
++      }
++
++      err = retrieve_ptr_limit(ptr_reg, &alu_limit, info->mask_to_left);
+       if (err < 0)
+               return err;
diff --git a/queue-5.10/bpf-no-need-to-simulate-speculative-domain-for-immediates.patch b/queue-5.10/bpf-no-need-to-simulate-speculative-domain-for-immediates.patch
new file mode 100644 (file)
index 0000000..1f05d5e
--- /dev/null
@@ -0,0 +1,44 @@
+From a7036191277f9fa68d92f2071ddc38c09b1e5ee5 Mon Sep 17 00:00:00 2001
+From: Daniel Borkmann <daniel@iogearbox.net>
+Date: Tue, 4 May 2021 08:58:25 +0000
+Subject: bpf: No need to simulate speculative domain for immediates
+
+From: Daniel Borkmann <daniel@iogearbox.net>
+
+commit a7036191277f9fa68d92f2071ddc38c09b1e5ee5 upstream.
+
+In 801c6058d14a ("bpf: Fix leakage of uninitialized bpf stack under
+speculation") we replaced masking logic with direct loads of immediates
+if the register is a known constant. Given in this case we do not apply
+any masking, there is also no reason for the operation to be truncated
+under the speculative domain.
+
+Therefore, there is also zero reason for the verifier to branch-off and
+simulate this case, it only needs to do it for unknown but bounded scalars.
+As a side-effect, this also enables few test cases that were previously
+rejected due to simulation under zero truncation.
+
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Reviewed-by: Piotr Krysiuk <piotras@gmail.com>
+Acked-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/bpf/verifier.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -5802,8 +5802,12 @@ do_sim:
+       /* If we're in commit phase, we're done here given we already
+        * pushed the truncated dst_reg into the speculative verification
+        * stack.
++       *
++       * Also, when register is a known constant, we rewrite register-based
++       * operation to immediate-based, and thus do not need masking (and as
++       * a consequence, do not need to simulate the zero-truncation either).
+        */
+-      if (commit_window)
++      if (commit_window || off_is_imm)
+               return 0;
+       /* Simulate and find potential out-of-bounds access under
diff --git a/queue-5.10/bpf-wrap-aux-data-inside-bpf_sanitize_info-container.patch b/queue-5.10/bpf-wrap-aux-data-inside-bpf_sanitize_info-container.patch
new file mode 100644 (file)
index 0000000..b775f70
--- /dev/null
@@ -0,0 +1,84 @@
+From 3d0220f6861d713213b015b582e9f21e5b28d2e0 Mon Sep 17 00:00:00 2001
+From: Daniel Borkmann <daniel@iogearbox.net>
+Date: Fri, 21 May 2021 10:17:36 +0000
+Subject: bpf: Wrap aux data inside bpf_sanitize_info container
+
+From: Daniel Borkmann <daniel@iogearbox.net>
+
+commit 3d0220f6861d713213b015b582e9f21e5b28d2e0 upstream.
+
+Add a container structure struct bpf_sanitize_info which holds
+the current aux info, and update call-sites to sanitize_ptr_alu()
+to pass it in. This is needed for passing in additional state
+later on.
+
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Reviewed-by: Piotr Krysiuk <piotras@gmail.com>
+Acked-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/bpf/verifier.c |   18 +++++++++++-------
+ 1 file changed, 11 insertions(+), 7 deletions(-)
+
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -5743,15 +5743,19 @@ static bool sanitize_needed(u8 opcode)
+       return opcode == BPF_ADD || opcode == BPF_SUB;
+ }
++struct bpf_sanitize_info {
++      struct bpf_insn_aux_data aux;
++};
++
+ static int sanitize_ptr_alu(struct bpf_verifier_env *env,
+                           struct bpf_insn *insn,
+                           const struct bpf_reg_state *ptr_reg,
+                           const struct bpf_reg_state *off_reg,
+                           struct bpf_reg_state *dst_reg,
+-                          struct bpf_insn_aux_data *tmp_aux,
++                          struct bpf_sanitize_info *info,
+                           const bool commit_window)
+ {
+-      struct bpf_insn_aux_data *aux = commit_window ? cur_aux(env) : tmp_aux;
++      struct bpf_insn_aux_data *aux = commit_window ? cur_aux(env) : &info->aux;
+       struct bpf_verifier_state *vstate = env->cur_state;
+       bool off_is_imm = tnum_is_const(off_reg->var_off);
+       bool off_is_neg = off_reg->smin_value < 0;
+@@ -5780,8 +5784,8 @@ static int sanitize_ptr_alu(struct bpf_v
+               /* In commit phase we narrow the masking window based on
+                * the observed pointer move after the simulated operation.
+                */
+-              alu_state = tmp_aux->alu_state;
+-              alu_limit = abs(tmp_aux->alu_limit - alu_limit);
++              alu_state = info->aux.alu_state;
++              alu_limit = abs(info->aux.alu_limit - alu_limit);
+       } else {
+               alu_state  = off_is_neg ? BPF_ALU_NEG_VALUE : 0;
+               alu_state |= off_is_imm ? BPF_ALU_IMMEDIATE : 0;
+@@ -5942,7 +5946,7 @@ static int adjust_ptr_min_max_vals(struc
+           smin_ptr = ptr_reg->smin_value, smax_ptr = ptr_reg->smax_value;
+       u64 umin_val = off_reg->umin_value, umax_val = off_reg->umax_value,
+           umin_ptr = ptr_reg->umin_value, umax_ptr = ptr_reg->umax_value;
+-      struct bpf_insn_aux_data tmp_aux = {};
++      struct bpf_sanitize_info info = {};
+       u8 opcode = BPF_OP(insn->code);
+       u32 dst = insn->dst_reg;
+       int ret;
+@@ -6011,7 +6015,7 @@ static int adjust_ptr_min_max_vals(struc
+       if (sanitize_needed(opcode)) {
+               ret = sanitize_ptr_alu(env, insn, ptr_reg, off_reg, dst_reg,
+-                                     &tmp_aux, false);
++                                     &info, false);
+               if (ret < 0)
+                       return sanitize_err(env, insn, ret, off_reg, dst_reg);
+       }
+@@ -6152,7 +6156,7 @@ static int adjust_ptr_min_max_vals(struc
+               return -EACCES;
+       if (sanitize_needed(opcode)) {
+               ret = sanitize_ptr_alu(env, insn, dst_reg, off_reg, dst_reg,
+-                                     &tmp_aux, true);
++                                     &info, true);
+               if (ret < 0)
+                       return sanitize_err(env, insn, ret, off_reg, dst_reg);
+       }