diff mbox series

[SRU,OEM-5.10/HWE-5.11/Impish/OEM-5.14/Jammy,2/3] bpf: Don't promote bogus looking registers after null check.

Message ID 20220128180003.75186-3-cascardo@canonical.com
State New
Headers show
Series CVE-2022-23222 | expand

Commit Message

Thadeu Lima de Souza Cascardo Jan. 28, 2022, 6 p.m. UTC
From: Daniel Borkmann <daniel@iogearbox.net>

If we ever get to a point again where we convert a bogus looking <ptr>_or_null
typed register containing a non-zero fixed or variable offset, then lets not
reset these bounds to zero since they are not and also don't promote the register
to a <ptr> type, but instead leave it as <ptr>_or_null. Converting to a unknown
register could be an avenue as well, but then if we run into this case it would
allow to leak a kernel pointer this way.

Fixes: f1174f77b50c ("bpf/verifier: rework value tracking")
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
(cherry picked from commit e60b0d12a95dcf16a63225cead4541567f5cb517)
CVE-2022-23222
Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
---
 kernel/bpf/verifier.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

Comments

Andrea Righi Jan. 28, 2022, 6:15 p.m. UTC | #1
On Fri, Jan 28, 2022 at 03:00:02PM -0300, Thadeu Lima de Souza Cascardo wrote:
> From: Daniel Borkmann <daniel@iogearbox.net>
> 
> If we ever get to a point again where we convert a bogus looking <ptr>_or_null
> typed register containing a non-zero fixed or variable offset, then lets not
> reset these bounds to zero since they are not and also don't promote the register
> to a <ptr> type, but instead leave it as <ptr>_or_null. Converting to a unknown
> register could be an avenue as well, but then if we run into this case it would
> allow to leak a kernel pointer this way.
> 
> Fixes: f1174f77b50c ("bpf/verifier: rework value tracking")
> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
> (cherry picked from commit e60b0d12a95dcf16a63225cead4541567f5cb517)
> CVE-2022-23222
> Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>

Already applied to jammy/linux via stable updates.

-Andrea

> ---
>  kernel/bpf/verifier.c | 12 ++++++------
>  1 file changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 296144d71d32..797444bec1aa 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -7822,15 +7822,15 @@ static void mark_ptr_or_null_reg(struct bpf_func_state *state,
>  {
>  	if (reg_type_may_be_null(reg->type) && reg->id == id &&
>  	    !WARN_ON_ONCE(!reg->id)) {
> -		/* Old offset (both fixed and variable parts) should
> -		 * have been known-zero, because we don't allow pointer
> -		 * arithmetic on pointers that might be NULL.
> -		 */
>  		if (WARN_ON_ONCE(reg->smin_value || reg->smax_value ||
>  				 !tnum_equals_const(reg->var_off, 0) ||
>  				 reg->off)) {
> -			__mark_reg_known_zero(reg);
> -			reg->off = 0;
> +			/* Old offset (both fixed and variable parts) should
> +			 * have been known-zero, because we don't allow pointer
> +			 * arithmetic on pointers that might be NULL. If we
> +			 * see this happening, don't convert the register.
> +			 */
> +			return;
>  		}
>  		if (is_null) {
>  			reg->type = SCALAR_VALUE;
> -- 
> 2.32.0
> 
> 
> -- 
> kernel-team mailing list
> kernel-team@lists.ubuntu.com
> https://lists.ubuntu.com/mailman/listinfo/kernel-team
diff mbox series

Patch

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 296144d71d32..797444bec1aa 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -7822,15 +7822,15 @@  static void mark_ptr_or_null_reg(struct bpf_func_state *state,
 {
 	if (reg_type_may_be_null(reg->type) && reg->id == id &&
 	    !WARN_ON_ONCE(!reg->id)) {
-		/* Old offset (both fixed and variable parts) should
-		 * have been known-zero, because we don't allow pointer
-		 * arithmetic on pointers that might be NULL.
-		 */
 		if (WARN_ON_ONCE(reg->smin_value || reg->smax_value ||
 				 !tnum_equals_const(reg->var_off, 0) ||
 				 reg->off)) {
-			__mark_reg_known_zero(reg);
-			reg->off = 0;
+			/* Old offset (both fixed and variable parts) should
+			 * have been known-zero, because we don't allow pointer
+			 * arithmetic on pointers that might be NULL. If we
+			 * see this happening, don't convert the register.
+			 */
+			return;
 		}
 		if (is_null) {
 			reg->type = SCALAR_VALUE;