Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp276465pxb; Thu, 25 Feb 2021 02:07:35 -0800 (PST) X-Google-Smtp-Source: ABdhPJzEhTX6NA4W4Szw/FDZHigjT1aLUIg+HPfgxBeLbZgkFVM9SNEB9ixfq1ha79J+WuJbEnX8 X-Received: by 2002:a17:906:750:: with SMTP id z16mr1929222ejb.53.1614247655226; Thu, 25 Feb 2021 02:07:35 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1614247655; cv=none; d=google.com; s=arc-20160816; b=ACDpK2oMxd5GBb58F71vLh4/FUFDikmmyR4eWMpyKhZez4Ss8e17FYiq1hxi2NpxpZ QjufPgkjk4wqsbCM0aGfl3t3mqRNXweDegJTu/0YV523Uj+gKUCfIXaBggmUnnW2J4UE 6/Aq0JH15ECXIb446rUvks1cfCZ1TdSJV3ZUESzJewUKsZe2s+dMaf/VJV79MggWxdsL WDEC+KaWcc4hgauSEJHWer9FCwZDZ2wzNlQR7IUP1lrqJmmGXpyeoP2+kXKiR98Pe25k GZ5L93zw3QTSR1G2yA98CF0E5ziZ+cW5ZxBNq2ZrBwvbsOixpk4MQ5rjYtK96YmUrZTj L0Hw== 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=G2mxB0qjIQci+aP8gZsejH6GsNaWDpL5r3ddGo9u1gg=; b=rBLfEQR9rmslslWUKnO2TyFTPWf9RLFXfx3SO42QAiqmEbhbZjs6QaMyDgW90UkeO3 yNY38TBmbAVZ0Mla2TE/PbT4B3alge8lsHAbLSrEYb3CXZBjDBJVCHJT/b4OYeW64ImK YcFfbO9JDAfy6w0qh5uLt2zYUpdVMvPs45jI0sur4ytrWgO6H+sWEDx8njVMlc+Ko2Fy Zu/FFT23pG+hPhLRAu7WuDn+dmAnSe/XXAftZXBfLkFcXiQUZmK832mU4gABKgntvSh/ fl8uzdo1HAF5QeYGjZl/7cRgnQL0xEsyfyxUAQnvTdxZRS2v4joFyjspnXTGrDEkrvH3 KsTQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=X2kglI4W; 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 m6si3736182ejl.144.2021.02.25.02.07.13; Thu, 25 Feb 2021 02:07:35 -0800 (PST) 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=X2kglI4W; 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 S235669AbhBYKDt (ORCPT + 99 others); Thu, 25 Feb 2021 05:03:49 -0500 Received: from mail.kernel.org ([198.145.29.99]:34282 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235610AbhBYJ4v (ORCPT ); Thu, 25 Feb 2021 04:56:51 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id A243C64F0E; Thu, 25 Feb 2021 09:54:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1614246870; bh=2wo8AbEXmn9+tACyGxCQgrWKlUDMAjztRuZqvG+JXG4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=X2kglI4Wvwr25ornEIAE8NLbiwPf8gLLdsPgCMqqezNV4eL+btQLua1Kqg3ipDGOj XT5ZW+p7ALbBKVZQ1jU010egXM82M/ImFs2GkfET87ljN/6b1CY9Wp2nUksm8TE7cB qdnWiR7UKgetOdfWCMjsn4okb2reOJtnL6vHh96Y= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Daniel Borkmann , John Fastabend , Alexei Starovoitov Subject: [PATCH 5.10 01/23] bpf: Fix truncation handling for mod32 dst reg wrt zero Date: Thu, 25 Feb 2021 10:53:32 +0100 Message-Id: <20210225092516.605892798@linuxfoundation.org> X-Mailer: git-send-email 2.30.1 In-Reply-To: <20210225092516.531932232@linuxfoundation.org> References: <20210225092516.531932232@linuxfoundation.org> User-Agent: quilt/0.66 X-stable: review X-Patchwork-Hint: ignore 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 9b00f1b78809309163dda2d044d9e94a3c0248a3 upstream. Recently noticed that when mod32 with a known src reg of 0 is performed, then the dst register is 32-bit truncated in verifier: 0: R1=ctx(id=0,off=0,imm=0) R10=fp0 0: (b7) r0 = 0 1: R0_w=inv0 R1=ctx(id=0,off=0,imm=0) R10=fp0 1: (b7) r1 = -1 2: R0_w=inv0 R1_w=inv-1 R10=fp0 2: (b4) w2 = -1 3: R0_w=inv0 R1_w=inv-1 R2_w=inv4294967295 R10=fp0 3: (9c) w1 %= w0 4: R0_w=inv0 R1_w=inv(id=0,umax_value=4294967295,var_off=(0x0; 0xffffffff)) R2_w=inv4294967295 R10=fp0 4: (b7) r0 = 1 5: R0_w=inv1 R1_w=inv(id=0,umax_value=4294967295,var_off=(0x0; 0xffffffff)) R2_w=inv4294967295 R10=fp0 5: (1d) if r1 == r2 goto pc+1 R0_w=inv1 R1_w=inv(id=0,umax_value=4294967295,var_off=(0x0; 0xffffffff)) R2_w=inv4294967295 R10=fp0 6: R0_w=inv1 R1_w=inv(id=0,umax_value=4294967295,var_off=(0x0; 0xffffffff)) R2_w=inv4294967295 R10=fp0 6: (b7) r0 = 2 7: R0_w=inv2 R1_w=inv(id=0,umax_value=4294967295,var_off=(0x0; 0xffffffff)) R2_w=inv4294967295 R10=fp0 7: (95) exit 7: R0=inv1 R1=inv(id=0,umin_value=4294967295,umax_value=4294967295,var_off=(0x0; 0xffffffff)) R2=inv4294967295 R10=fp0 7: (95) exit However, as a runtime result, we get 2 instead of 1, meaning the dst register does not contain (u32)-1 in this case. The reason is fairly straight forward given the 0 test leaves the dst register as-is: # ./bpftool p d x i 23 0: (b7) r0 = 0 1: (b7) r1 = -1 2: (b4) w2 = -1 3: (16) if w0 == 0x0 goto pc+1 4: (9c) w1 %= w0 5: (b7) r0 = 1 6: (1d) if r1 == r2 goto pc+1 7: (b7) r0 = 2 8: (95) exit This was originally not an issue given the dst register was marked as completely unknown (aka 64 bit unknown). However, after 468f6eafa6c4 ("bpf: fix 32-bit ALU op verification") the verifier casts the register output to 32 bit, and hence it becomes 32 bit unknown. Note that for the case where the src register is unknown, the dst register is marked 64 bit unknown. After the fix, the register is truncated by the runtime and the test passes: # ./bpftool p d x i 23 0: (b7) r0 = 0 1: (b7) r1 = -1 2: (b4) w2 = -1 3: (16) if w0 == 0x0 goto pc+2 4: (9c) w1 %= w0 5: (05) goto pc+1 6: (bc) w1 = w1 7: (b7) r0 = 1 8: (1d) if r1 == r2 goto pc+1 9: (b7) r0 = 2 10: (95) exit Semantics also match with {R,W}x mod{64,32} 0 -> {R,W}x. Invalid div has always been {R,W}x div{64,32} 0 -> 0. Rewrites are as follows: mod32: mod64: (16) if w0 == 0x0 goto pc+2 (15) if r0 == 0x0 goto pc+1 (9c) w1 %= w0 (9f) r1 %= r0 (05) goto pc+1 (bc) w1 = w1 Fixes: 468f6eafa6c4 ("bpf: fix 32-bit ALU op verification") Signed-off-by: Daniel Borkmann Reviewed-by: John Fastabend Acked-by: Alexei Starovoitov Signed-off-by: Greg Kroah-Hartman --- kernel/bpf/verifier.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -10869,7 +10869,7 @@ static int fixup_bpf_calls(struct bpf_ve bool isdiv = BPF_OP(insn->code) == BPF_DIV; struct bpf_insn *patchlet; struct bpf_insn chk_and_div[] = { - /* Rx div 0 -> 0 */ + /* [R,W]x div 0 -> 0 */ BPF_RAW_INSN((is64 ? BPF_JMP : BPF_JMP32) | BPF_JNE | BPF_K, insn->src_reg, 0, 2, 0), @@ -10878,16 +10878,18 @@ static int fixup_bpf_calls(struct bpf_ve *insn, }; struct bpf_insn chk_and_mod[] = { - /* Rx mod 0 -> Rx */ + /* [R,W]x mod 0 -> [R,W]x */ BPF_RAW_INSN((is64 ? BPF_JMP : BPF_JMP32) | BPF_JEQ | BPF_K, insn->src_reg, - 0, 1, 0), + 0, 1 + (is64 ? 0 : 1), 0), *insn, + BPF_JMP_IMM(BPF_JA, 0, 0, 1), + BPF_MOV32_REG(insn->dst_reg, insn->dst_reg), }; patchlet = isdiv ? chk_and_div : chk_and_mod; cnt = isdiv ? ARRAY_SIZE(chk_and_div) : - ARRAY_SIZE(chk_and_mod); + ARRAY_SIZE(chk_and_mod) - (is64 ? 2 : 0); new_prog = bpf_patch_insn_data(env, i + delta, patchlet, cnt); if (!new_prog)