From nobody Tue Sep 9 17:14:40 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C6CD3C61DA4 for ; Fri, 24 Feb 2023 03:41:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229720AbjBXDlW (ORCPT ); Thu, 23 Feb 2023 22:41:22 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41280 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229625AbjBXDlF (ORCPT ); Thu, 23 Feb 2023 22:41:05 -0500 Received: from mail-pj1-x104a.google.com (mail-pj1-x104a.google.com [IPv6:2607:f8b0:4864:20::104a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BA11B60D52 for ; Thu, 23 Feb 2023 19:40:48 -0800 (PST) Received: by mail-pj1-x104a.google.com with SMTP id b18-20020a17090a489200b0023762d1ee58so655584pjh.4 for ; Thu, 23 Feb 2023 19:40:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=R3iBhiHTRJXOrBGrqzDxss6bg8LHug+SM3RBUwYxANE=; b=J6+YN9IGP6MwLPZckWbo5E/Xk82MfTw13Lhg5Ll7egHVE9N1Gz17NrAEoEi5jefz8h s5ZPFOX/8PJLvK8IZCoKa2hDIiAlP345R3P0/QmKYhzYHJiNlawUTL+V6gPo//gkOR/M mOuBhSmC9tdwpYZQpoGvgsscg2IxTOllCkHlB3kujyatWQlAuhKf1miS4RZdd2850qO4 +qtC2AkdlCtVdHThYkZIvoiVdrWWzeUE+eYrgb8yTUigK6VC6a9NjY0qTRfItPHTBl0v EtzRt4Z3mQqbuTjbxi5VNiZOEUoFEnKXp3uQgeDAlkBFgJmGLxIpVMkMBLKZI3M9gPxw Ie5A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=R3iBhiHTRJXOrBGrqzDxss6bg8LHug+SM3RBUwYxANE=; b=cP8yTwXEZPz9cabsc69Ej8rVawjaepnPOMeFidQXL2lqx/1AS0CA6I3eZXb8c7wRt7 MYQOe/UqM+0juI0KNYLqJW212wPKYud71RBFvRt/zUKvvYGWerkGoIvvkWs4/DLUN/wI CoaIqpuh5wMayS1cU3uJ/9eKvT+MDg9ZKKCduTPBws3PDEWAfw0HMyCJj7ernU3YNEyF WGpx2g9OMt9XT/9kJh5qplcLmvjK6rkboHTKeh3ls8qTcn1ValYL3RK8UuHdQ39nqbX3 dejmpMnnsvIBqYlGpN3jyBWpoeb9bVHoh9qsm+a28xxEvWHviQ5mJ0qFpS+tX9K2aoDk vKPw== X-Gm-Message-State: AO0yUKWRpBi9nXmJusjX40DdP2zy1TnAebdV+K8fjkssQQWCeizIDGHt tN63l5cGigb3dcQfCAqvcsCvo9WX77E= X-Google-Smtp-Source: AK7set8E3MEPhXV1/45uWmz2lxMH5cm58fZ0faRvczxB9TFOAlLdrNUle4su/XjXkfOaSWJtLZDQpa/gB4k= X-Received: from edliaw.c.googlers.com ([fda3:e722:ac3:cc00:24:72f4:c0a8:305d]) (user=edliaw job=sendgmr) by 2002:a17:90a:f82:b0:237:29b1:188f with SMTP id 2-20020a17090a0f8200b0023729b1188fmr1158374pjz.8.1677210048093; Thu, 23 Feb 2023 19:40:48 -0800 (PST) Date: Fri, 24 Feb 2023 03:40:19 +0000 In-Reply-To: <20230224034020.2080637-1-edliaw@google.com> Mime-Version: 1.0 References: <20230224034020.2080637-1-edliaw@google.com> X-Mailer: git-send-email 2.39.2.637.g21b0678d19-goog Message-ID: <20230224034020.2080637-5-edliaw@google.com> Subject: [PATCH 4.14 v3 4/4] bpf: Fix truncation handling for mod32 dst reg wrt zero From: Edward Liaw To: stable@vger.kernel.org, Alexei Starovoitov , Daniel Borkmann , "David S. Miller" Cc: bpf@vger.kernel.org, kernel-team@android.com, Edward Liaw , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, John Fastabend , Salvatore Bonaccorso , Thadeu Lima de Souza Cascardo Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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=3Dctx(id=3D0,off=3D0,imm=3D0) R10=3Dfp0 0: (b7) r0 =3D 0 1: R0_w=3Dinv0 R1=3Dctx(id=3D0,off=3D0,imm=3D0) R10=3Dfp0 1: (b7) r1 =3D -1 2: R0_w=3Dinv0 R1_w=3Dinv-1 R10=3Dfp0 2: (b4) w2 =3D -1 3: R0_w=3Dinv0 R1_w=3Dinv-1 R2_w=3Dinv4294967295 R10=3Dfp0 3: (9c) w1 %=3D w0 4: R0_w=3Dinv0 R1_w=3Dinv(id=3D0,umax_value=3D4294967295,var_off=3D(0x0; = 0xffffffff)) R2_w=3Dinv4294967295 R10=3Dfp0 4: (b7) r0 =3D 1 5: R0_w=3Dinv1 R1_w=3Dinv(id=3D0,umax_value=3D4294967295,var_off=3D(0x0; = 0xffffffff)) R2_w=3Dinv4294967295 R10=3Dfp0 5: (1d) if r1 =3D=3D r2 goto pc+1 R0_w=3Dinv1 R1_w=3Dinv(id=3D0,umax_value=3D4294967295,var_off=3D(0x0; 0x= ffffffff)) R2_w=3Dinv4294967295 R10=3Dfp0 6: R0_w=3Dinv1 R1_w=3Dinv(id=3D0,umax_value=3D4294967295,var_off=3D(0x0; = 0xffffffff)) R2_w=3Dinv4294967295 R10=3Dfp0 6: (b7) r0 =3D 2 7: R0_w=3Dinv2 R1_w=3Dinv(id=3D0,umax_value=3D4294967295,var_off=3D(0x0; = 0xffffffff)) R2_w=3Dinv4294967295 R10=3Dfp0 7: (95) exit 7: R0=3Dinv1 R1=3Dinv(id=3D0,umin_value=3D4294967295,umax_value=3D4294967= 295,var_off=3D(0x0; 0xffffffff)) R2=3Dinv4294967295 R10=3Dfp0 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 =3D 0 1: (b7) r1 =3D -1 2: (b4) w2 =3D -1 3: (16) if w0 =3D=3D 0x0 goto pc+1 4: (9c) w1 %=3D w0 5: (b7) r0 =3D 1 6: (1d) if r1 =3D=3D r2 goto pc+1 7: (b7) r0 =3D 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 =3D 0 1: (b7) r1 =3D -1 2: (b4) w2 =3D -1 3: (16) if w0 =3D=3D 0x0 goto pc+2 4: (9c) w1 %=3D w0 5: (05) goto pc+1 6: (bc) w1 =3D w1 7: (b7) r0 =3D 1 8: (1d) if r1 =3D=3D r2 goto pc+1 9: (b7) r0 =3D 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 =3D=3D 0x0 goto pc+2 (15) if r0 =3D=3D 0x0 goto pc+1 (9c) w1 %=3D w0 (9f) r1 %=3D r0 (05) goto pc+1 (bc) w1 =3D w1 [Salvatore Bonaccorso: This is an earlier version based on work by Daniel and John which does not rely on availability of the BPF_JMP32 instruction class. This means it is not even strictly a backport of the upstream commit mentioned but based on Daniel's and John's work to address the issue and was finalized by Thadeu Lima de Souza Cascardo.] Fixes: 468f6eafa6c4 ("bpf: fix 32-bit ALU op verification") Signed-off-by: Daniel Borkmann Reviewed-by: John Fastabend Tested-by: Salvatore Bonaccorso Signed-off-by: Thadeu Lima de Souza Cascardo Signed-off-by: Edward Liaw --- kernel/bpf/verifier.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 9f04d413df92..a55e264cdb54 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -4846,7 +4846,7 @@ static int fixup_bpf_calls(struct bpf_verifier_env *e= nv) bool is64 =3D BPF_CLASS(insn->code) =3D=3D BPF_ALU64; struct bpf_insn mask_and_div[] =3D { BPF_MOV_REG(BPF_CLASS(insn->code), BPF_REG_AX, insn->src_reg), - /* Rx div 0 -> 0 */ + /* [R,W]x div 0 -> 0 */ BPF_JMP_IMM(BPF_JEQ, BPF_REG_AX, 0, 2), BPF_RAW_REG(*insn, insn->dst_reg, BPF_REG_AX), BPF_JMP_IMM(BPF_JA, 0, 0, 1), @@ -4854,9 +4854,10 @@ static int fixup_bpf_calls(struct bpf_verifier_env *= env) }; struct bpf_insn mask_and_mod[] =3D { BPF_MOV_REG(BPF_CLASS(insn->code), BPF_REG_AX, insn->src_reg), - /* Rx mod 0 -> Rx */ - BPF_JMP_IMM(BPF_JEQ, BPF_REG_AX, 0, 1), + BPF_JMP_IMM(BPF_JEQ, BPF_REG_AX, 0, 1 + (is64 ? 0 : 1)), BPF_RAW_REG(*insn, insn->dst_reg, BPF_REG_AX), + BPF_JMP_IMM(BPF_JA, 0, 0, 1), + BPF_MOV32_REG(insn->dst_reg, insn->dst_reg), }; struct bpf_insn *patchlet; =20 @@ -4866,7 +4867,7 @@ static int fixup_bpf_calls(struct bpf_verifier_env *e= nv) cnt =3D ARRAY_SIZE(mask_and_div); } else { patchlet =3D mask_and_mod; - cnt =3D ARRAY_SIZE(mask_and_mod); + cnt =3D ARRAY_SIZE(mask_and_mod) - (is64 ? 2 : 0); } =20 new_prog =3D bpf_patch_insn_data(env, i + delta, patchlet, cnt); --=20 2.39.2.637.g21b0678d19-goog