diff options
author | Salvatore Bonaccorso <carnil@debian.org> | 2021-05-27 14:21:44 +0200 |
---|---|---|
committer | Salvatore Bonaccorso <carnil@debian.org> | 2021-05-27 14:54:49 +0200 |
commit | 5e9ccfa114eb2a5aab018fc4e4f289bf0cfb1682 (patch) | |
tree | da3786bce56c1ef2ab857bf57d4b9b16096dc353 | |
parent | cb08b0f4f4078f64937aa50ddf864d6faecd0f38 (diff) | |
download | kernel_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
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 |