From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pg1-f174.google.com (mail-pg1-f174.google.com [209.85.215.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5FB4330D40C for ; Wed, 19 Aug 2026 05:05:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.174 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787115937; cv=none; b=F2tIIF0XEBSuaHUEGh7r0xcNJ3IyFYD458j1kl5Uxs9ye0cw+euCZgvHVVyLWkxkTQMZ+zUMyeHNCiXpsa4gac/C16VoHheskmeDh3y2oikAn6WpFeYsjVyQhAnRwzvzNaY/PJJYfn6cOlVUwsB2NxtKfYaBRIkMzoVZBbgE02s= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787115937; c=relaxed/simple; bh=ESVl2l+jCjGfwzTUm5kjJLy66cWwvSgAKIr9oR5taao=; h=Message-ID:Subject:From:To:Cc:Date:In-Reply-To:References: Content-Type:MIME-Version; b=OD5MyXQxNDvMs6yp7TKWXJxmchSK3mvo+ea1gjTJGGdjeXQpNIIZZp/XsfuGbSWYTSvBgNz0vpWuaEqFgsn2WBCpMduiKX0hZOEUBja9TEEqYCHalvltuSq+ciVxw1WDIDLD+iPSAZXjgUDkZTKQ8zrFknUa05JITaIqst4775w= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=LeCg+rlF; arc=none smtp.client-ip=209.85.215.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="LeCg+rlF" Received: by mail-pg1-f174.google.com with SMTP id 41be03b00d2f7-cbb8b54fcf8so492490a12.0 for ; Tue, 18 Aug 2026 22:05:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787115936; x=1787720736; darn=vger.kernel.org; h=mime-version:user-agent:content-transfer-encoding:content-type :references:in-reply-to:date:cc:to:from:subject:message-id:from:to :cc:subject:date:message-id:reply-to:content-type; bh=UNb9D6xoKPP/4uKuy81gSrLLYpF2N2DZ3ii3QwO65zM=; b=LeCg+rlFkaKuA7ez3c/YNMT/DkmdKaLXr3GwNXHeYDAN8uZRaqIayGpN9HsuLMvAli 8zvqPB4geM8CuI4fKVccWPmNk+LJ2bH9cLx+sPFHRAnisaedCfs6mb51zf03Uk/D08Vb aYW18vWiCvlsYEnUS7uPIZZ/0WEq57kbzA+QfT8/HTkeRdaJ/qmnmgaszqsy81wD+pR+ q9xVQyHskJ+DcNAbJ8hst6Zzh1qAaBdIXxsALfFrit+wGhyYOdUiTSuM8JaK7h9Q5UTO Fhj2sYOsr3qCRtEtlu2kIBNnfi3UmrfYS37iekpOtTY4KeJeGOQdiJPi6rhgjGrKyse9 lQ1A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787115936; x=1787720736; h=mime-version:user-agent:content-transfer-encoding:content-type :references:in-reply-to:date:cc:to:from:subject:message-id:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=UNb9D6xoKPP/4uKuy81gSrLLYpF2N2DZ3ii3QwO65zM=; b=b/XKlJnkvABRyPu0JY8Ip5zA52GEIQHCci15UUdEZJg4Eu/sjO/P0jShJi1oayZYcn vmJcGwWAPLtyktZ7VGokdnx0T6c57zRA7xcQsLeNIAWgifv+XYgSuJEKVHRC2dQvEKVI uMFNS4TM57MqA9lvC5nCZOWWEgUu+3RZ93+HcJDK+4jZk7/JyrWaG4rBbb4Fbmrv3zcg 76Bp/aKDvjnsy67MHk6mg7J1TQgt5JVf6Jfwuq4ptwNE3O5qQNaGUhFQREH7DOOe+KvW 83QrgAJOqjRQlvWYR2Ue5TTIImYiEtikPkCanwG2R2XxOifnSwhYHacOF24XMtdlwYqM fZiQ== X-Forwarded-Encrypted: i=1; AHgh+RqrI7SJP7+4xMjHYniNXcmYlCGR8LBMJHY6gjxDP1Zya75vWd0vqfClnRrdT5N0wStUBPFhM+fhKc7antM=@vger.kernel.org X-Gm-Message-State: AOJu0Yx61kBpxOiEP4ddFMUX0fYlJ7kDMkuUvQDDqK0efYwpeymtM9IP rpvqiWFnABI3Yo410M6OFLuF0rfbDhxDszQAZ23F++1U/ZY/X+Qxxsja X-Gm-Gg: AR+sD13sjTIUXsygos/jRv0mvHm/oOP08nrbv+3DDbNxb5OQVHYtxu+fpnOl2Z9lCDm JannhnLo43QmJwGRYxrM+ZPxk+p5sNDiT7g/pYZTMihMNQV84ufZzOnras1Ic7prB5s2YLJu8pd XddRUbgC7hqTg3rurT17gY0W4ZNbO0M2es6irwdCknzbTeMxmVHgKjNeAtw3lLW9rrOsvH6n4X5 JuauiKLemEoNIRq9RSPWwmCSuMv4QzaH4vBp0exl382fBJnK+EB38ESVEqLYRoSCRiVTBBdObFP yh5XD1dMW+1J8Y0R2TAfupDIjzngYOWpKlt8zS3nemQjiWhFmxU6NZT9zhcJbkNuxj8bTuIEb04 1EDxXszzcOR8VHh6bROWY4eOO/eRWym5rUUqaweve0vWxr0w7N9Dg8vMSzRnB1LWH+EkA8uVP61 iP/JQExjRXmfXdEcouwcSnWcejIfkkzuvIYdkds67CNh33L6Fb2LcpIW88Wc4U99xhxF5Cj4azl /tExKE0QMxV9zpr X-Received: by 2002:a17:90b:4d83:b0:38d:dfd1:7c1 with SMTP id 98e67ed59e1d1-39580a91ad5mr3710120a91.2.1787115935585; Tue, 18 Aug 2026 22:05:35 -0700 (PDT) Received: from [192.168.0.13] ([38.34.87.7]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-3957fc82965sm390147a91.4.2026.08.18.22.05.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Aug 2026 22:05:35 -0700 (PDT) Message-ID: <54bed44859f9de519c56ed0fb9366160f625fce7.camel@gmail.com> Subject: Re: [RFC bpf-next 4/6] selftests/bpf: cover low-32 subreg-equal link for zero-extending movs From: Eduard Zingerman To: Vineet Gupta , ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, memxor@gmail.com Cc: martin.lau@linux.dev, song@kernel.org, yonghong.song@linux.dev, jolsa@kernel.org, emil@etsalapatis.com, ihor.solodrai@linux.dev, john.fastabend@gmail.com, shuah@kernel.org, bpf@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Date: Tue, 18 Aug 2026 22:05:32 -0700 In-Reply-To: <20260814231945.3884596-5-vineet.gupta@linux.dev> References: <20260814231945.3884596-1-vineet.gupta@linux.dev> <20260814231945.3884596-5-vineet.gupta@linux.dev> Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable User-Agent: Evolution 3.56.2-10 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 On Fri, 2026-08-14 at 16:19 -0700, Vineet Gupta wrote: Nit: let's keep all tests for this feature under verifier_linked_scalars.c. ... > diff --git a/tools/testing/selftests/bpf/progs/verifier_bounds.c b/tools/= testing/selftests/bpf/progs/verifier_bounds.c > index 1a273e416fed..6169a61269b2 100644 > --- a/tools/testing/selftests/bpf/progs/verifier_bounds.c > +++ b/tools/testing/selftests/bpf/progs/verifier_bounds.c > @@ -1516,7 +1516,15 @@ __naked void sub32_full_overflow(void) > =C2=A0SEC("socket") > =C2=A0__description("32-bit subtraction, partial overflow, result in unbo= unded u32 bounds") > =C2=A0__success __log_level(2) > -__msg("3: (1c) w3 -=3D w2 {{.*}} R3=3Dscalar(smin=3D0,smax=3Dumax=3D0xff= ffffff,var_off=3D(0x0; 0xffffffff))") > +/* > + * w3 =3D w0 forms a low-32 BPF_FLAG_SUBREG_ZEXT link, so R3 carries an = id here > + * where it did not before; the bounds are unchanged. The id is determin= istic > + * (raw asm, same bytecode in every flavour) so require it rather than m= aking > + * it optional -- otherwise the assertion would still pass if the link w= ere > + * dropped again. The delta suffix is left general: log.c prints ->delta > + * directly after the id with no separator when BPF_FLAG_ADD_CONST is se= t. > + */ Please cleanup LLM generated comments. All that changed here is 'id' for R3= . Is it important for this specific test to match the exact regex? Given the intended purpose of the test I think that the above comment is no= t warranted. > +__msg("3: (1c) w3 -=3D w2 {{.*}} R3=3Dscalar(id=3D{{[0-9]+([+-][0-9]+)?}= },smin=3D0,smax=3Dumax=3D0xffffffff,var_off=3D(0x0; 0xffffffff))") > =C2=A0__retval(0) > =C2=A0__naked void sub32_partial_overflow(void) > =C2=A0{ > diff --git a/tools/testing/selftests/bpf/progs/verifier_linked_scalars.c = b/tools/testing/selftests/bpf/progs/verifier_linked_scalars.c > index c80747c16bcf..2cc6f9e45aff 100644 > --- a/tools/testing/selftests/bpf/progs/verifier_linked_scalars.c > +++ b/tools/testing/selftests/bpf/progs/verifier_linked_scalars.c > @@ -711,4 +711,119 @@ l_exit_%=3D: \ > =C2=A0 : __clobber_all); > =C2=A0} > > +/* > + * A 32-bit zero-extending mov (w7 =3D w6) from a source with unknown hi= gh bits > + * shares only the low 32 bits (w7.lo =3D=3D w6.lo, w7.hi =3D=3D 0). A l= ater narrowing of > + * the source's low 32 bits must propagate to the destination via the > + * BPF_FLAG_SUBREG_ZEXT (low-32-only) link. This is the pattern bpf-gcc = emits when it > + * reuses "w0 =3D idx" for "return 0" on the idx=3D=3D0 path of a callba= ck. > + */ > +SEC("socket") > +__success > +__naked void subreg_eq_zext_mov_narrow(void) > +{ > + asm volatile (" \ > + call %[bpf_get_prandom_u32]; \ > + r6 =3D r0; /* r6 =3D 64-bit unknown (helper ret is unbounded) */ \ > + call %[bpf_get_prandom_u32]; \ > + r0 <<=3D 32; /* r0 =3D unknown high bits */ \ > + r6 |=3D r0; /* still 64-bit unknown; makes it explicit */ \ Why the second bpf_get_prandom_u32() call is necessary? LLM got confused by the _u32() in the function name? > + w7 =3D w6; /* 32-bit zero-extend mov, wide src */ \ > + if w6 !=3D 0 goto l_out_%=3D; /* w6 low =3D=3D 0 on fall-through */ \ > + /* w7 =3D zext32(w6 low) must be 0 here */ \ All three comments above can be dropped. What should be commented on is that `w7 =3D w6' forms a link and `w6 !=3D 0` propagates ranges through this link. > + if w7 =3D=3D 0 goto l_out_%=3D; /* provably 0 iff linked */ \ > + r0 /=3D 0; /* reached only if w7 not deduced 0 */ \ > +l_out_%=3D: \ Nit: please prefer `2: goto 1f; 1: goto 2b;' style labels. > + r0 =3D 0; \ > + exit; \ > +" : > + : __imm(bpf_get_prandom_u32) > + : __clobber_all); > +} > + > +/* > + * A 32-bit zero-extending mov (w7 =3D w5) whose SOURCE is a wide ADD_CO= NST-linked > + * register (r5 =3D base + K) must NOT disturb that source. Forming the = low-32 > + * BPF_FLAG_SUBREG_ZEXT link on the destination would need assign_scalar= _id_before_mov() > + * on the source, which clears its base+delta link -- and a combined > + * subreg+delta link isn't modeled anyway (sync_linked_regs() skips it).= So for a > + * wide ADD_CONST src the mov leaves the source's link intact and just c= lears the > + * destination. > + * > + * Here r5 =3D r6 + 3 (ADD_CONST, wide). After the mov, narrowing the ba= se r6 must > + * still reach r5 through the preserved link: r6 in [0, 10] =3D> r5 in [= 3, 13], so > + * the guarded div-by-zero is unreachable. Had the mov cleared r5's link= (calling > + * assign_scalar_id_before_mov() unconditionally), r5 would stay unbound= ed and the > + * div would be reachable (rejected). > + * > + * Note this is a no-regression guard rather than coverage of the new li= nk: > + * before this feature the wide-source path also left the source untouch= ed, so > + * the test passes either way. What it pins is the choice not to call > + * assign_scalar_id_before_mov() unconditionally. > + * > + * Written in asm so the bytecode is identical regardless of the host BP= F compiler. Please try to make the comments less verbose. > + */ > +SEC("socket") > +__success > +__naked void zext_mov_keeps_add_const_src(void) > +{ > + asm volatile (" \ > + call %[bpf_get_prandom_u32]; \ > + r6 =3D r0; /* r6 low =3D unknown u32 */ \ > + call %[bpf_get_prandom_u32]; \ > + r0 <<=3D 32; \ > + r6 |=3D r0; /* r6 =3D full 64-bit unknown (base) */ \ > + r5 =3D r6; /* r5, r6 linked (shared id) */ \ > + r5 +=3D 3; /* r5 =3D base + 3: ADD_CONST, still wide */ \ > + w7 =3D w5; /* 32-bit zext mov, wide ADD_CONST src */ \ > + if r6 > 10 goto l_out_%=3D;/* r6 in [0, 10] */ \ > + /* r5 =3D r6 + 3 must be in [3, 13] here (needs the kept link) */ \ > + if r5 > 13 goto l_err_%=3D;/* taken only if r5 not narrowed */ \ > + goto l_out_%=3D; \ > +l_err_%=3D: \ > + r0 /=3D 0; /* reachable iff r5's link was cleared */ \ > +l_out_%=3D: \ > + r0 =3D 0; \ > + exit; \ > +" : > + : __imm(bpf_get_prandom_u32) > + : __clobber_all); > +} ... Given the changes in regsafe/check_alu_op/sync_linked_regs, I think the following cases are not covered: - regsafe: a state whose register carries BPF_FLAG_SUBREG_ZEXT must not be deemed safe against one without it. - check_alu_op: a provably-u32 source takes the full-equality path and must not be flagged ZEXT. - check_alu_op: a self-mov w6 =3D w6 must not generate a self-link and should clear dst's id. - check_alu_op: a ZEXT-linked source must survive assign_scalar_id_before_mov(), so a chain of 32-bit assignments should preserve the id and the flag. - sync_linked_regs: no propagation when reg has ZEXT and known_reg has ADD_= CONST. - sync_linked_regs: no propagation when known_reg has ZEXT and reg has ADD_= CONST. - sync_linked_regs: low-32 reconstruction must still propagate when both reg and known_reg have ZEXT.