]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
UBUNTU: SAUCE: Revert "UBUNTU: SAUCE: bpf: verifier: fix ALU32 bounds tracking with...
authorThadeu Lima de Souza Cascardo <cascardo@canonical.com>
Thu, 27 May 2021 00:12:00 +0000 (02:12 +0200)
committerKleber Sacilotto de Souza <kleber.souza@canonical.com>
Fri, 28 May 2021 10:39:10 +0000 (12:39 +0200)
This reverts commit bd1e67cf571b8f750ce2fc0edeb9c09c9d637fe9.

The following commit was applied upstream, which allows better tracking of
bounds for the situations that have motivated this fix.

That is, instead of marking the entire register as unknown, the lower
32 bits will be kept as known.

CVE-2021-3490
Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
Acked-by: Tim Gardner <tim.gardner@canonical.com>
Acked-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
kernel/bpf/verifier.c

index 8a5f88a19024788829a5a9647536dfe0f526733e..3dd297203ab5cfda8493ddb9b4a06dd66aa74460 100644 (file)
@@ -6390,10 +6390,18 @@ static void scalar_min_max_mul(struct bpf_reg_state *dst_reg,
 static void scalar32_min_max_and(struct bpf_reg_state *dst_reg,
                                 struct bpf_reg_state *src_reg)
 {
+       bool src_known = tnum_subreg_is_const(src_reg->var_off);
+       bool dst_known = tnum_subreg_is_const(dst_reg->var_off);
        struct tnum var32_off = tnum_subreg(dst_reg->var_off);
        s32 smin_val = src_reg->s32_min_value;
        u32 umax_val = src_reg->u32_max_value;
 
+       /* Assuming scalar64_min_max_and will be called so its safe
+        * to skip updating register for known 32-bit case.
+        */
+       if (src_known && dst_known)
+               return;
+
        /* We get our minimum from the var_off, since that's inherently
         * bitwise.  Our maximum is the minimum of the operands' maxima.
         */
@@ -6453,10 +6461,18 @@ static void scalar_min_max_and(struct bpf_reg_state *dst_reg,
 static void scalar32_min_max_or(struct bpf_reg_state *dst_reg,
                                struct bpf_reg_state *src_reg)
 {
+       bool src_known = tnum_subreg_is_const(src_reg->var_off);
+       bool dst_known = tnum_subreg_is_const(dst_reg->var_off);
        struct tnum var32_off = tnum_subreg(dst_reg->var_off);
        s32 smin_val = src_reg->s32_min_value;
        u32 umin_val = src_reg->u32_min_value;
 
+       /* Assuming scalar64_min_max_or will be called so it is safe
+        * to skip updating register for known case.
+        */
+       if (src_known && dst_known)
+               return;
+
        /* We get our maximum from the var_off, and our minimum is the
         * maximum of the operands' minima
         */
@@ -6515,9 +6531,17 @@ static void scalar_min_max_or(struct bpf_reg_state *dst_reg,
 static void scalar32_min_max_xor(struct bpf_reg_state *dst_reg,
                                 struct bpf_reg_state *src_reg)
 {
+       bool src_known = tnum_subreg_is_const(src_reg->var_off);
+       bool dst_known = tnum_subreg_is_const(dst_reg->var_off);
        struct tnum var32_off = tnum_subreg(dst_reg->var_off);
        s32 smin_val = src_reg->s32_min_value;
 
+       /* Assuming scalar64_min_max_xor will be called so it is safe
+        * to skip updating register for known case.
+        */
+       if (src_known && dst_known)
+               return;
+
        /* We get both minimum and maximum from the var32_off. */
        dst_reg->u32_min_value = var32_off.value;
        dst_reg->u32_max_value = var32_off.value | var32_off.mask;