aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSalvatore Bonaccorso <carnil@debian.org>2021-05-27 14:21:44 +0200
committerSalvatore Bonaccorso <carnil@debian.org>2021-05-27 14:54:49 +0200
commit5e9ccfa114eb2a5aab018fc4e4f289bf0cfb1682 (patch)
treeda3786bce56c1ef2ab857bf57d4b9b16096dc353
parentcb08b0f4f4078f64937aa50ddf864d6faecd0f38 (diff)
downloadkernel_replicant_linux-5e9ccfa114eb2a5aab018fc4e4f289bf0cfb1682.tar.gz
kernel_replicant_linux-5e9ccfa114eb2a5aab018fc4e4f289bf0cfb1682.tar.bz2
kernel_replicant_linux-5e9ccfa114eb2a5aab018fc4e4f289bf0cfb1682.zip
Add patches to address CVE-2021-33200
bpf: Wrap aux data inside bpf_sanitize_info container bpf: Fix mask direction swap upon off reg sign change bpf: No need to simulate speculative domain for immediates
-rw-r--r--debian/changelog8
-rw-r--r--debian/patches/bugfix/all/bpf-fix-mask-direction-swap-upon-off-reg-sign-change.patch74
-rw-r--r--debian/patches/bugfix/all/bpf-no-need-to-simulate-speculative-domain-for-immediates.patch44
-rw-r--r--debian/patches/bugfix/all/bpf-wrap-aux-data-inside-bpf_sanitize_info-container.patch84
-rw-r--r--debian/patches/series3
5 files changed, 213 insertions, 0 deletions
diff --git a/debian/changelog b/debian/changelog
index 572b49fc1336..94eda8a3d66b 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
+linux (5.10.38-2) UNRELEASED; urgency=medium
+
+ * bpf: Wrap aux data inside bpf_sanitize_info container (CVE-2021-33200)
+ * bpf: Fix mask direction swap upon off reg sign change (CVE-2021-33200)
+ * bpf: No need to simulate speculative domain for immediates (CVE-2021-33200)
+
+ -- Salvatore Bonaccorso <carnil@debian.org> Thu, 27 May 2021 14:24:21 +0200
+
linux (5.10.38-1) unstable; urgency=medium
* New upstream stable update:
diff --git a/debian/patches/bugfix/all/bpf-fix-mask-direction-swap-upon-off-reg-sign-change.patch b/debian/patches/bugfix/all/bpf-fix-mask-direction-swap-upon-off-reg-sign-change.patch
new file mode 100644
index 000000000000..471f2fe85834
--- /dev/null
+++ b/debian/patches/bugfix/all/bpf-fix-mask-direction-swap-upon-off-reg-sign-change.patch
@@ -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/debian/patches/bugfix/all/bpf-no-need-to-simulate-speculative-domain-for-immediates.patch b/debian/patches/bugfix/all/bpf-no-need-to-simulate-speculative-domain-for-immediates.patch
new file mode 100644
index 000000000000..1f05d5ea4654
--- /dev/null
+++ b/debian/patches/bugfix/all/bpf-no-need-to-simulate-speculative-domain-for-immediates.patch
@@ -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/debian/patches/bugfix/all/bpf-wrap-aux-data-inside-bpf_sanitize_info-container.patch b/debian/patches/bugfix/all/bpf-wrap-aux-data-inside-bpf_sanitize_info-container.patch
new file mode 100644
index 000000000000..b775f7013c28
--- /dev/null
+++ b/debian/patches/bugfix/all/bpf-wrap-aux-data-inside-bpf_sanitize_info-container.patch
@@ -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);
+ }
diff --git a/debian/patches/series b/debian/patches/series
index 7fd9e47ce1c9..5e6ffa6b0856 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -110,6 +110,9 @@ features/all/db-mok-keyring/KEYS-Make-use-of-platform-keyring-for-module-signatu
debian/i386-686-pae-pci-set-pci-nobios-by-default.patch
debian/ntfs-mark-it-as-broken.patch
bugfix/all/vfs-move-cap_convert_nscap-call-into-vfs_setxattr.patch
+bugfix/all/bpf-wrap-aux-data-inside-bpf_sanitize_info-container.patch
+bugfix/all/bpf-fix-mask-direction-swap-upon-off-reg-sign-change.patch
+bugfix/all/bpf-no-need-to-simulate-speculative-domain-for-immediates.patch
# Fix exported symbol versions
bugfix/all/module-disable-matching-missing-version-crc.patch