Received: by 2002:a05:7412:d8a:b0:e2:908c:2ebd with SMTP id b10csp539484rdg; Tue, 10 Oct 2023 19:42:56 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGM/JDZ6cbVbt0fkvWLpFX/LDvzh8fjzkDWhQ7sinchES0jhw0JlPQLmu3FRRXJDwU8EesM X-Received: by 2002:a9d:6a50:0:b0:6bc:c9e6:30b7 with SMTP id h16-20020a9d6a50000000b006bcc9e630b7mr20563949otn.26.1696992176092; Tue, 10 Oct 2023 19:42:56 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1696992176; cv=none; d=google.com; s=arc-20160816; b=ml9iw+23CM8jFaSGlwAbR+pWOH4+gluXDrDUJPl2L19z/j8e2X3QHz4SLPs0YrMWyH zB816dJBHAnGes3MLlYGX4OUJJW4QMdryBmruCXlm6+3wgu0AWHzFTu3moBCTFkZ2FIw r+tsrkST7VU7gh4GyZXVdQIMhZaPBzSUDFWn6CaUCVLMavbfcoBHuzIo1iuSLxMlF8vO XYPFqLj+z5HOdvdLrdjaw3VoxNDTHcNg239zjUYzHDUH/UQch0C/tIYiMOdShbk6ymC/ jQmu29FPbKh9wcj1mx48qFFHPiaCMGRHCFClWfhinHI+0JW2+0gaVgFLb6N5o164WQgh +RyQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:cc:to:subject :message-id:date:from:in-reply-to:references:mime-version :dkim-signature; bh=id44sh06sB+VzUBOjFeGvj0/2qgnTKDwavEKyMyAfT8=; fh=jtRgjCjVAJCBCcwoF9UOb45iZUbSDPueeMUgDAb6Rvw=; b=stcYQvh+Rsu2hO+HtwHvWxLsbmHKZVwtqpLcEYzWx88eKS1x8zhzQg8XZsuSs1qF5X XAXZNjBqqJoMOJo0fWXHwpuQVeiV79yRQcYNXF/zLyzLcO00MNGnX7O0Iz4/fVfgBnEh yBLlUvM2jc7rOQzjmwc8kulI/ANvApK3F/apVk9XvuIYVvBPt/rOztIKQpHYXDw7Fh4H URBllyAUrnp0rrwLIGpuui9a6iIaMMOVvtZvx7z/6csEg/AqK5SvKUd2cFiu6sIJUPCx VNi7PNjMM7j23fXrGxC+shPnZSe6ua7Lvu6gmjonu6Ldg6wQuH5W0N8iPwz/a/xrk0hm UMBQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20230601 header.b=BCwdqKcy; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.37 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from snail.vger.email (snail.vger.email. [23.128.96.37]) by mx.google.com with ESMTPS id be3-20020a656e43000000b0056da0ae25a0si2589036pgb.441.2023.10.10.19.42.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 10 Oct 2023 19:42:56 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.37 as permitted sender) client-ip=23.128.96.37; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20230601 header.b=BCwdqKcy; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.37 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by snail.vger.email (Postfix) with ESMTP id 4BAD9812DBED; Tue, 10 Oct 2023 19:42:55 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at snail.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344850AbjJKCmv (ORCPT + 99 others); Tue, 10 Oct 2023 22:42:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60412 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344791AbjJKCmu (ORCPT ); Tue, 10 Oct 2023 22:42:50 -0400 Received: from mail-ed1-x52c.google.com (mail-ed1-x52c.google.com [IPv6:2a00:1450:4864:20::52c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4AEF49D; Tue, 10 Oct 2023 19:42:48 -0700 (PDT) Received: by mail-ed1-x52c.google.com with SMTP id 4fb4d7f45d1cf-53d9b94731aso2096154a12.1; Tue, 10 Oct 2023 19:42:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1696992167; x=1697596967; darn=vger.kernel.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=id44sh06sB+VzUBOjFeGvj0/2qgnTKDwavEKyMyAfT8=; b=BCwdqKcyDt0sXI1J+5NqANmhZer7jYfnxy2jW2bL/5T75TUoRuBpZKwc3YwnNF6ryV vFqyWSuCodt04lgNeezExMwt0BnxiZ9M/MIK1lDVyAMykBZOyFm5EJK+6PTrp9pcx937 7SNNvCJMU1Ud7jmlUXkfHlEl/1zashQ459GulCIoZOrnt3p56uBSwFGUGUWkHoc0Rc4S KHcufuk6H7oTrg+nvdW6IleD5g7hAjEVQPO93mwArRp9BUEHcI76j8rq+RAVi6Rei3PQ sBEEyh4O0S+OTDTfSkqRpbQ+2Y9hECkL2yVt1o0kJwvTSf8apU+2F4w/08U14yqMN+/a 6SEQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1696992167; x=1697596967; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=id44sh06sB+VzUBOjFeGvj0/2qgnTKDwavEKyMyAfT8=; b=hIh86MIJ3nf6CEiI5zW6Kg4RIF/+PSrD+d6iLL/9+dQgyEx4hCQpCVNhZKtQpoYkpw 4SBRZhfEW06mfHBb7JxfJYqT2Dk8lYEO/P7H1qisktAY0ZnVjgCD0UoNQPIA5ZNN5hvg AzmQ2x9JD2ydCUpp2XUkxqhUB4/nc0J3HHWK0nVwF+PlX9pV/5Fee6iJHhYHOM7Iwd4f Scd6z2zH1M3g442UhgrBbjhKLtv3507t35AZ8f3W2RgPpeyq1lF4Mi+ei5LhGTuPQgza H9/hZAA7KvVVmWVq3AxCZ5BJJ5PTyEM7BHO37RamgP96yS1LnY/XNwvrLZygRwXUQAcm lzMw== X-Gm-Message-State: AOJu0YwHDGCiP6ji+yPIlHCEjtcBYltOIWhdm4vm6IjrBScT3lsDByIs i3iaRNu7AGRLp71lszLjkMTz2LyNjP9k8HgtnT0= X-Received: by 2002:aa7:c904:0:b0:525:7f37:e87a with SMTP id b4-20020aa7c904000000b005257f37e87amr18005344edt.16.1696992166517; Tue, 10 Oct 2023 19:42:46 -0700 (PDT) MIME-Version: 1.0 References: <20231009-jmp-into-reserved-fields-v1-1-d8006e2ac1f6@gmail.com> <6524f6f77b896_66abc2084d@john.notmuch> <92f824ec-9538-501c-e63e-8483ffe14bad@iogearbox.net> In-Reply-To: <92f824ec-9538-501c-e63e-8483ffe14bad@iogearbox.net> From: Andrii Nakryiko Date: Tue, 10 Oct 2023 19:42:35 -0700 Message-ID: Subject: Re: [PATCH bpf-next] Detect jumping to reserved code during check_cfg() To: Daniel Borkmann Cc: John Fastabend , Hao Sun , Alexei Starovoitov , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , bpf@vger.kernel.org, linux-kernel@vger.kernel.org Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_BLOCKED,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (snail.vger.email [0.0.0.0]); Tue, 10 Oct 2023 19:42:55 -0700 (PDT) On Tue, Oct 10, 2023 at 1:33=E2=80=AFAM Daniel Borkmann wrote: > > On 10/10/23 9:02 AM, John Fastabend wrote: > > Hao Sun wrote: > >> Currently, we don't check if the branch-taken of a jump is reserved co= de of > >> ld_imm64. Instead, such a issue is captured in check_ld_imm(). The ver= ifier > >> gives the following log in such case: > >> > >> func#0 @0 > >> 0: R1=3Dctx(off=3D0,imm=3D0) R10=3Dfp0 > >> 0: (18) r4 =3D 0xffff888103436000 ; R4_w=3Dmap_ptr(off=3D0,ks=3D= 4,vs=3D128,imm=3D0) > >> 2: (18) r1 =3D 0x1d ; R1_w=3D29 > >> 4: (55) if r4 !=3D 0x0 goto pc+4 ; R4_w=3Dmap_ptr(off=3D0,ks=3D= 4,vs=3D128,imm=3D0) > >> 5: (1c) w1 -=3D w1 ; R1_w=3D0 > >> 6: (18) r5 =3D 0x32 ; R5_w=3D50 > >> 8: (56) if w5 !=3D 0xfffffff4 goto pc-2 > >> mark_precise: frame0: last_idx 8 first_idx 0 subseq_idx -1 > >> mark_precise: frame0: regs=3Dr5 stack=3D before 6: (18) r5 =3D 0x32 > >> 7: R5_w=3D50 > >> 7: BUG_ld_00 > >> invalid BPF_LD_IMM insn > >> > >> Here the verifier rejects the program because it thinks insn at 7 is a= n > >> invalid BPF_LD_IMM, but such a error log is not accurate since the iss= ue > >> is jumping to reserved code not because the program contains invalid i= nsn. > >> Therefore, make the verifier check the jump target during check_cfg().= For > >> the same program, the verifier reports the following log: > > > > I think we at least would want a test case for this. Also how did you c= reate > > this case? Is it just something you did manually and noticed a strange = error? > > Curious as well. > > We do have test cases which try to jump into the middle of a double insn = as can > be seen that this patch breaks BPF CI with regards to log mismatch below = (which > still needs to be adapted, too). Either way, it probably doesn't hurt to = also add > the above snippet as a test. > > Hao, as I understand, the patch here is an usability improvement (not a f= ix per se) > where we reject such cases earlier during cfg check rather than at a late= r point > where we validate ld_imm instruction. Or are there cases you found which = were not > yet captured via current check_ld_imm()? > > test_verifier failure log : > > #458/u test1 ld_imm64 FAIL > Unexpected verifier log! > EXP: R1 pointer comparison > RES: > FAIL > Unexpected error message! > EXP: R1 pointer comparison > RES: jump to reserved code from insn 0 to 2 > verification time 22 usec > stack depth 0 > processed 0 insns (limit 1000000) max_states_per_insn 0 total_states 0= peak_states 0 mark_read 0 > > jump to reserved code from insn 0 to 2 > verification time 22 usec > stack depth 0 > processed 0 insns (limit 1000000) max_states_per_insn 0 total_states 0= peak_states 0 mark_read 0 > #458/p test1 ld_imm64 FAIL > Unexpected verifier log! > EXP: invalid BPF_LD_IMM insn > RES: > FAIL > Unexpected error message! > EXP: invalid BPF_LD_IMM insn > RES: jump to reserved code from insn 0 to 2 > verification time 9 usec > stack depth 0 > processed 0 insns (limit 1000000) max_states_per_insn 0 total_states 0= peak_states 0 mark_read 0 > > jump to reserved code from insn 0 to 2 > verification time 9 usec > stack depth 0 > processed 0 insns (limit 1000000) max_states_per_insn 0 total_states 0= peak_states 0 mark_read 0 > #459/u test2 ld_imm64 FAIL > Unexpected verifier log! > EXP: R1 pointer comparison > RES: > FAIL > Unexpected error message! > EXP: R1 pointer comparison > RES: jump to reserved code from insn 0 to 2 > verification time 11 usec > stack depth 0 > processed 0 insns (limit 1000000) max_states_per_insn 0 total_states 0= peak_states 0 mark_read 0 > > jump to reserved code from insn 0 to 2 > verification time 11 usec > stack depth 0 > processed 0 insns (limit 1000000) max_states_per_insn 0 total_states 0= peak_states 0 mark_read 0 > #459/p test2 ld_imm64 FAIL > Unexpected verifier log! > EXP: invalid BPF_LD_IMM insn > RES: > FAIL > Unexpected error message! > EXP: invalid BPF_LD_IMM insn > RES: jump to reserved code from insn 0 to 2 > verification time 8 usec > stack depth 0 > processed 0 insns (limit 1000000) max_states_per_insn 0 total_states 0= peak_states 0 mark_read 0 > > jump to reserved code from insn 0 to 2 > verification time 8 usec > stack depth 0 > processed 0 insns (limit 1000000) max_states_per_insn 0 total_states 0= peak_states 0 mark_read 0 > #460/u test3 ld_imm64 OK > > >> func#0 @0 > >> jump to reserved code from insn 8 to 7 > >> > >> --- > >> > >> > >> Signed-off-by: Hao Sun > > nit: This needs to be before the "---" line. > > >> --- > >> kernel/bpf/verifier.c | 7 +++++++ > >> 1 file changed, 7 insertions(+) > >> > >> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c > >> index eed7350e15f4..725ac0b464cf 100644 > >> --- a/kernel/bpf/verifier.c > >> +++ b/kernel/bpf/verifier.c > >> @@ -14980,6 +14980,7 @@ static int push_insn(int t, int w, int e, stru= ct bpf_verifier_env *env, > >> { > >> int *insn_stack =3D env->cfg.insn_stack; > >> int *insn_state =3D env->cfg.insn_state; > >> + struct bpf_insn *insns =3D env->prog->insnsi; > >> > >> if (e =3D=3D FALLTHROUGH && insn_state[t] >=3D (DISCOVERED | FALL= THROUGH)) > >> return DONE_EXPLORING; > >> @@ -14993,6 +14994,12 @@ static int push_insn(int t, int w, int e, str= uct bpf_verifier_env *env, > >> return -EINVAL; > >> } > >> > >> + if (e =3D=3D BRANCH && insns[w].code =3D=3D 0) { > >> + verbose_linfo(env, t, "%d", t); > >> + verbose(env, "jump to reserved code from insn %d to %d\n"= , t, w); > >> + return -EINVAL; > >> + } > > Other than that, lgtm. We do rely quite a lot on verifier not complaining eagerly about some potentially invalid instructions if it's provable that some portion of the code won't ever be reached (think using .rodata variables for feature gating, poisoning intructions due to failed CO-RE relocation, which libbpf does actively, except it's using a call to non-existing helper). As such, check_cfg() is a wrong place to do such validity checks because some of the branches might never be run and validated in practice. This seems like a pretty obscure case of fuzzer generated test with random jumps into the middle of ldimm64 instruction. I think the tool should be able to avoid this or handle verifier log just fine in such situations. On the other hand, valid code generated by compilers will never have such jumps. So perhaps we can improve existing "invalid BPF_LD_IMM insn" message, but let's not teach check_cfg() more checks than necessary? > > >> if (e =3D=3D BRANCH) { > >> /* mark branch target for state pruning */ > >> mark_prune_point(env, w); > >> >