Received: by 2002:a05:6a10:206:0:0:0:0 with SMTP id 6csp4753057pxj; Wed, 12 May 2021 12:26:31 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyvmmTib3o4ZcYG81WFrKqVeEQnh87sBgboyO1owFrZTY7jTND+wVI4j9nMPGWq9T3y8vUl X-Received: by 2002:a17:906:9bc2:: with SMTP id de2mr8484132ejc.340.1620847591139; Wed, 12 May 2021 12:26:31 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1620847591; cv=none; d=google.com; s=arc-20160816; b=PDOy7GSL0Kt5EY7Obify/CdF52VfVYCwEH07CWgmdVpABt3qZmzIw+SDhxSY3P6QP+ 58jo+TiTUPRB3RurrlnlETL17AIwOE3rgZ+vsmsbNwclYSK5Z0cyI5Fe+WWYD5yVjg6W kTdls4RGic45XvAuqHGzL2LGRC5y+Imr2h01Y6lKQNEQYMKJacUrNQyz5UGmgHghJ8So eGBC4N54g2JcJ7JbZNBOxLeyOCf7XemvCPvIOyANXeX2oEeqR6AHsNcZWZfqNmSMqFqw aIk3Tim1OGoKVTtRakorYNhRWGStoBU0l3g34w8h72MeGAapgb2tDTfJ1vcEGbfhH119 pWGw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=OFy6UdqnIC9wovC54gbP9urni0cDG5u/NYFB7K1LJrs=; b=heQ8nj+W6mtLmkcDsWjW9f3zHCuzucDP7M0Igh8pZDR0rY50zOhDg6bchHGGdFrZjg 0RLbLwSI0ZBVIW3xia0ormOD+upNUgrRl2lpRjGXa9XRbbTRwjuWZZI06CjIvZLkHPdA m/en9wynlcDtaWG0b8F+XPwRJ9kbAoL3hExPLTBPM12bi+zr7m3wM/L0NUs5hjCxg5XP OauChcLZq2xBlUUVFwZGcyfYcWe7gn8aXVA8Xs+rwlyHBxB6MIujGSMdj/Z93cY04laS QEJJRhNzXncxUDs88BylWHEm3IKcMxC41o+4ksxEHxMehL5DfILNV36Y4tw9hOHodx9F G89A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=Wpu1m7wm; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id u8si485617edq.102.2021.05.12.12.26.07; Wed, 12 May 2021 12:26:31 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=Wpu1m7wm; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1379628AbhELTUE (ORCPT + 99 others); Wed, 12 May 2021 15:20:04 -0400 Received: from mail.kernel.org ([198.145.29.99]:48156 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244727AbhELQvH (ORCPT ); Wed, 12 May 2021 12:51:07 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 00B58619A1; Wed, 12 May 2021 16:17:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1620836253; bh=nDsvaUtR5+NM1aQtWBoHsaWfrQrabDxdC0niWjTWqc4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Wpu1m7wmeB7fJUdxBPznelkY/kUBy/+BhfiwKKRUqnOvX9rasoVLlaFLBaNQj+vs0 Zjocq004KVaYtRlJzjoZM9zvhpIqFwPzv/bLK8M4jCS6iP2IQuvDJj5xDlTLYm5xHh bY4Lu+GBd9QHteUqdxzWXCJ7gzK9HJXPczEbKzW4= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Thadeu Lima de Souza Cascardo , Daniel Borkmann , John Fastabend , Alexei Starovoitov Subject: [PATCH 5.12 671/677] bpf: Fix alu32 const subreg bound tracking on bitwise operations Date: Wed, 12 May 2021 16:51:57 +0200 Message-Id: <20210512144859.652746828@linuxfoundation.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210512144837.204217980@linuxfoundation.org> References: <20210512144837.204217980@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Daniel Borkmann commit 049c4e13714ecbca567b4d5f6d563f05d431c80e upstream. Fix a bug in the verifier's scalar32_min_max_*() functions which leads to incorrect tracking of 32 bit bounds for the simulation of and/or/xor bitops. When both the src & dst subreg is a known constant, then the assumption is that scalar_min_max_*() will take care to update bounds correctly. However, this is not the case, for example, consider a register R2 which has a tnum of 0xffffffff00000000, meaning, lower 32 bits are known constant and in this case of value 0x00000001. R2 is then and'ed with a register R3 which is a 64 bit known constant, here, 0x100000002. What can be seen in line '10:' is that 32 bit bounds reach an invalid state where {u,s}32_min_value > {u,s}32_max_value. The reason is scalar32_min_max_*() delegates 32 bit bounds updates to scalar_min_max_*(), however, that really only takes place when both the 64 bit src & dst register is a known constant. Given scalar32_min_max_*() is intended to be designed as closely as possible to scalar_min_max_*(), update the 32 bit bounds in this situation through __mark_reg32_known() which will set all {u,s}32_{min,max}_value to the correct constant, which is 0x00000000 after the fix (given 0x00000001 & 0x00000002 in 32 bit space). This is possible given var32_off already holds the final value as dst_reg->var_off is updated before calling scalar32_min_max_*(). Before fix, invalid tracking of R2: [...] 9: R0_w=inv1337 R1=ctx(id=0,off=0,imm=0) R2_w=inv(id=0,smin_value=-9223372036854775807 (0x8000000000000001),smax_value=9223372032559808513 (0x7fffffff00000001),umin_value=1,umax_value=0xffffffff00000001,var_off=(0x1; 0xffffffff00000000),s32_min_value=1,s32_max_value=1,u32_min_value=1,u32_max_value=1) R3_w=inv4294967298 R10=fp0 9: (5f) r2 &= r3 10: R0_w=inv1337 R1=ctx(id=0,off=0,imm=0) R2_w=inv(id=0,smin_value=0,smax_value=4294967296 (0x100000000),umin_value=0,umax_value=0x100000000,var_off=(0x0; 0x100000000),s32_min_value=1,s32_max_value=0,u32_min_value=1,u32_max_value=0) R3_w=inv4294967298 R10=fp0 [...] After fix, correct tracking of R2: [...] 9: R0_w=inv1337 R1=ctx(id=0,off=0,imm=0) R2_w=inv(id=0,smin_value=-9223372036854775807 (0x8000000000000001),smax_value=9223372032559808513 (0x7fffffff00000001),umin_value=1,umax_value=0xffffffff00000001,var_off=(0x1; 0xffffffff00000000),s32_min_value=1,s32_max_value=1,u32_min_value=1,u32_max_value=1) R3_w=inv4294967298 R10=fp0 9: (5f) r2 &= r3 10: R0_w=inv1337 R1=ctx(id=0,off=0,imm=0) R2_w=inv(id=0,smin_value=0,smax_value=4294967296 (0x100000000),umin_value=0,umax_value=0x100000000,var_off=(0x0; 0x100000000),s32_min_value=0,s32_max_value=0,u32_min_value=0,u32_max_value=0) R3_w=inv4294967298 R10=fp0 [...] Fixes: 3f50f132d840 ("bpf: Verifier, do explicit ALU32 bounds tracking") Fixes: 2921c90d4718 ("bpf: Fix a verifier failure with xor") Reported-by: Manfred Paul (@_manfp) Reported-by: Thadeu Lima de Souza Cascardo Signed-off-by: Daniel Borkmann Reviewed-by: John Fastabend Acked-by: Alexei Starovoitov Signed-off-by: Greg Kroah-Hartman --- kernel/bpf/verifier.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -6538,11 +6538,10 @@ static void scalar32_min_max_and(struct 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) + if (src_known && dst_known) { + __mark_reg32_known(dst_reg, var32_off.value); return; + } /* We get our minimum from the var_off, since that's inherently * bitwise. Our maximum is the minimum of the operands' maxima. @@ -6562,7 +6561,6 @@ static void scalar32_min_max_and(struct dst_reg->s32_min_value = dst_reg->u32_min_value; dst_reg->s32_max_value = dst_reg->u32_max_value; } - } static void scalar_min_max_and(struct bpf_reg_state *dst_reg, @@ -6609,11 +6607,10 @@ static void scalar32_min_max_or(struct b 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) + if (src_known && dst_known) { + __mark_reg32_known(dst_reg, var32_off.value); return; + } /* We get our maximum from the var_off, and our minimum is the * maximum of the operands' minima @@ -6678,11 +6675,10 @@ static void scalar32_min_max_xor(struct 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) + if (src_known && dst_known) { + __mark_reg32_known(dst_reg, var32_off.value); return; + } /* We get both minimum and maximum from the var32_off. */ dst_reg->u32_min_value = var32_off.value;