|
Gary Lin |
a8864c |
From: Daniel Borkmann <daniel@iogearbox.net>
|
|
Gary Lin |
a8864c |
Date: Fri, 21 May 2021 10:19:22 +0000
|
|
Gary Lin |
a8864c |
Subject: bpf: Fix mask direction swap upon off reg sign change
|
|
Gary Lin |
a8864c |
Patch-mainline: Queued in subsystem maintainer repository
|
|
Gary Lin |
a8864c |
Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
|
|
Gary Lin |
a8864c |
Git-commit: bb01a1bba579b4b1c5566af24d95f1767859771e
|
|
Gary Lin |
a8864c |
References: bsc#1186484,CVE-2021-33200
|
|
Gary Lin |
a8864c |
|
|
Gary Lin |
a8864c |
Masking direction as indicated via mask_to_left is considered to be
|
|
Gary Lin |
a8864c |
calculated once and then used to derive pointer limits. Thus, this
|
|
Gary Lin |
a8864c |
needs to be placed into bpf_sanitize_info instead so we can pass it
|
|
Gary Lin |
a8864c |
to sanitize_ptr_alu() call after the pointer move. Piotr noticed a
|
|
Gary Lin |
a8864c |
corner case where the off reg causes masking direction change which
|
|
Gary Lin |
a8864c |
then results in an incorrect final aux->alu_limit.
|
|
Gary Lin |
a8864c |
|
|
Gary Lin |
a8864c |
Fixes: 7fedb63a8307 ("bpf: Tighten speculative pointer arithmetic mask")
|
|
Gary Lin |
a8864c |
Reported-by: Piotr Krysiuk <piotras@gmail.com>
|
|
Gary Lin |
a8864c |
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
|
|
Gary Lin |
a8864c |
Reviewed-by: Piotr Krysiuk <piotras@gmail.com>
|
|
Gary Lin |
a8864c |
Acked-by: Alexei Starovoitov <ast@kernel.org>
|
|
Gary Lin |
a8864c |
Acked-by: Gary Lin <glin@suse.com>
|
|
Gary Lin |
a8864c |
---
|
|
Gary Lin |
a8864c |
kernel/bpf/verifier.c | 22 ++++++++++++----------
|
|
Gary Lin |
a8864c |
1 file changed, 12 insertions(+), 10 deletions(-)
|
|
Gary Lin |
a8864c |
|
|
Gary Lin |
a8864c |
--- a/kernel/bpf/verifier.c
|
|
Gary Lin |
a8864c |
+++ b/kernel/bpf/verifier.c
|
|
Gary Lin |
a8864c |
@@ -4451,18 +4451,10 @@ enum {
|
|
Gary Lin |
a8864c |
};
|
|
Gary Lin |
a8864c |
|
|
Gary Lin |
a8864c |
static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg,
|
|
Gary Lin |
a8864c |
- const struct bpf_reg_state *off_reg,
|
|
Gary Lin |
a8864c |
- u32 *alu_limit, u8 opcode)
|
|
Gary Lin |
a8864c |
+ u32 *alu_limit, bool mask_to_left)
|
|
Gary Lin |
a8864c |
{
|
|
Gary Lin |
a8864c |
- bool off_is_neg = off_reg->smin_value < 0;
|
|
Gary Lin |
a8864c |
- bool mask_to_left = (opcode == BPF_ADD && off_is_neg) ||
|
|
Gary Lin |
a8864c |
- (opcode == BPF_SUB && !off_is_neg);
|
|
Gary Lin |
a8864c |
u32 max = 0, ptr_limit = 0;
|
|
Gary Lin |
a8864c |
|
|
Gary Lin |
a8864c |
- if (!tnum_is_const(off_reg->var_off) &&
|
|
Gary Lin |
a8864c |
- (off_reg->smin_value < 0) != (off_reg->smax_value < 0))
|
|
Gary Lin |
a8864c |
- return REASON_BOUNDS;
|
|
Gary Lin |
a8864c |
-
|
|
Gary Lin |
a8864c |
switch (ptr_reg->type) {
|
|
Gary Lin |
a8864c |
case PTR_TO_STACK:
|
|
Gary Lin |
a8864c |
/* Offset 0 is out-of-bounds, but acceptable start for the
|
|
Gary Lin |
a8864c |
@@ -4530,6 +4522,7 @@ static bool sanitize_needed(u8 opcode)
|
|
Gary Lin |
a8864c |
|
|
Gary Lin |
a8864c |
struct bpf_sanitize_info {
|
|
Gary Lin |
a8864c |
struct bpf_insn_aux_data aux;
|
|
Gary Lin |
a8864c |
+ bool mask_to_left;
|
|
Gary Lin |
a8864c |
};
|
|
Gary Lin |
a8864c |
|
|
Gary Lin |
a8864c |
static int sanitize_ptr_alu(struct bpf_verifier_env *env,
|
|
Gary Lin |
a8864c |
@@ -4561,7 +4554,16 @@ static int sanitize_ptr_alu(struct bpf_v
|
|
Gary Lin |
a8864c |
if (vstate->speculative)
|
|
Gary Lin |
a8864c |
goto do_sim;
|
|
Gary Lin |
a8864c |
|
|
Gary Lin |
a8864c |
- err = retrieve_ptr_limit(ptr_reg, off_reg, &alu_limit, opcode);
|
|
Gary Lin |
a8864c |
+ if (!commit_window) {
|
|
Gary Lin |
a8864c |
+ if (!tnum_is_const(off_reg->var_off) &&
|
|
Gary Lin |
a8864c |
+ (off_reg->smin_value < 0) != (off_reg->smax_value < 0))
|
|
Gary Lin |
a8864c |
+ return REASON_BOUNDS;
|
|
Gary Lin |
a8864c |
+
|
|
Gary Lin |
a8864c |
+ info->mask_to_left = (opcode == BPF_ADD && off_is_neg) ||
|
|
Gary Lin |
a8864c |
+ (opcode == BPF_SUB && !off_is_neg);
|
|
Gary Lin |
a8864c |
+ }
|
|
Gary Lin |
a8864c |
+
|
|
Gary Lin |
a8864c |
+ err = retrieve_ptr_limit(ptr_reg, &alu_limit, info->mask_to_left);
|
|
Gary Lin |
a8864c |
if (err < 0)
|
|
Gary Lin |
a8864c |
return err;
|
|
Gary Lin |
a8864c |
|