From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pj1-f49.google.com (mail-pj1-f49.google.com [209.85.216.49]) (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 D0D133988E0 for ; Fri, 5 Jun 2026 02:22:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.49 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780626134; cv=none; b=q93Rtn35yNVVMHIltXxdbkdD66DJFpUzGW9Nz+4M6pmOCMccct4KXmKN9tSrQKIW1e1J6QIz9DxxP/IYXPgM7gK+6X6KtjGxF1Vb6NTHdnVcScK+76cdxUK2+aGO0FKijoueN2c+WDnE8QYLQF+/dtAUAHGhWqRAis1vhrXv19c= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780626134; c=relaxed/simple; bh=YTK2yn3+JfV92/yG4TiRuAONdxqlJXtMfBVC+8Pu3V4=; h=Message-ID:Subject:From:To:Cc:Date:In-Reply-To:References: Content-Type:MIME-Version; b=YMd781jU3uxbNBeqMt1DGnKbBHS8EbEch72nFVV6l87zMfs1A8uq6aXFDauNXSvf6mn7DQvTWHc3E4yjZhg90uf/VO7Lv2XiF2PIEfqEyZC6pi2HB9b6OGvWjOhrD1e3BRxUUlURffaDkQw2RBjwAp+EQjXjMCX17hzVJdSmTSc= 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=WF5B0MT4; arc=none smtp.client-ip=209.85.216.49 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="WF5B0MT4" Received: by mail-pj1-f49.google.com with SMTP id 98e67ed59e1d1-36baec934b6so1476725a91.0 for ; Thu, 04 Jun 2026 19:22:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1780626127; x=1781230927; darn=vger.kernel.org; h=mime-version:user-agent:content-transfer-encoding:references :in-reply-to:date:cc:to:from:subject:message-id:from:to:cc:subject :date:message-id:reply-to; bh=SbyefUHgNqxFdyMQYhLqgimeHunRN3uVdpFaTQjZxq4=; b=WF5B0MT4ovfXQLDM0uW2/ZZ6kVr2mh1Ei9Oyxeg645vgWc+3fYMqHd4a37urKh8kge 65g1RYTdyZKhvQXxx2qmp0arW20Ckk9VVriJgvptwfT7xHHoJb505o/YTfAJanGSwkOw Gs5gvoS62mV9XgtQPlH9e+kjGoqodDiVbfQgXzFvY5XhpRlfjzL529BuhvUToipTppqm mqv1XpEWCE3jBqjEwm6k4xW3lKkDD/mamGc2zo819yJYRZMVokwbaS6+t/no8s/I+jS8 aTlHdIk6WD/4irryC/kQITtYJxc9GppOVjdvKxGjjSMLVIfnhJOS5xsAySGmIioMZJQx OuJw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780626127; x=1781230927; h=mime-version:user-agent:content-transfer-encoding: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; bh=SbyefUHgNqxFdyMQYhLqgimeHunRN3uVdpFaTQjZxq4=; b=WXAgovcaXWhnv8REy3mkRpedm5M30PimEP7ycRr0rjQ2gtyHNd2XlSUbl1LlDsyjit dCIsXCUopwuIlSf7+pMa0TOnoM6gWOgrQKG9NplW2TGw1fuyH4HqdaPsAN4QfLvZgsRa w6Yko1XTD7E6lUq5mPJ+yiAwCJZKuZeUTlRVOIJErIMZMgOwBQfdCfbui3KBxbOQPaZ3 X+RJY51WnS/hgUWzQ7d5DaKhQgcCxTywW/caplG6gEzy8dADX6DNxn1eg3vcwevo9AYb kz3lBUm1flK3UMSIiLQthcc1dYDC/MntdAtgFpISQLXYg+yFXg2p4oW4ZbG1Ca3P8X9u jcjw== X-Forwarded-Encrypted: i=1; AFNElJ+R2z2hlh6cD5l0aFghpkxzyiAXLWVV1URwcRnXYGC/UW08zEzRa5RkrbVRwNSdKPYqJtDqXNDdJDEXAGQ=@vger.kernel.org X-Gm-Message-State: AOJu0YwXoHZIqGw07Bkrl1WnX4VmDDwoQpgVgjpImugZOxzCI0lO4stb OShTLfXsm2RBagCtRLM9dP4oj5Fpk5sEAGN4tS6RCY0/iMAAg6vIK1hC X-Gm-Gg: Acq92OEAxInLGo0NLQT98bMuoRokyJj1j9pHWXxb6TaAEStLjJVYdTsl82DusAnfCDI JBdtgGiPRm2VX/3uvlLVZXZDz/KEZkFtljY1I0QmbRt46Kj7FpkxO2BaokYVcgPbyfhiQQ6xtq/ yDARuW1DMjpLCiES5Ht7mrzfgtQlDZgPSLEgsubv/moYNzX2K8f/mM0geejIA/kGa6kadXKa46y 8OaSeyEsGyW38KMSEVep+kAkeGGkQwJv8gPizZHN6pmsYJzTx8zhyynp+ZvdPVT6FVD5pe7Zp/p ODkUknnef2+cs0pPIF8waY7tPdYErv8U8+Wef3rAeEhq4tvaBIk55kkEkTpzy5eQBGDa+isVZEx hoMC/hI/yYghiSon9h9MPIWfg53QyUWejW/dwYbxFVyoDT7+Be3NAL6MXgE9+j3Cz4DLKEohEBP Rqt5Gsp19duh4GoDtPRCu4N5gpp+ET+h/PYzVEsJeopvoA8RRxrlJR1xRdb3i/OA== X-Received: by 2002:a17:903:1b43:b0:2c1:88a1:9839 with SMTP id d9443c01a7336-2c1ec527f50mr5664095ad.11.1780626126715; Thu, 04 Jun 2026 19:22:06 -0700 (PDT) Received: from [192.168.0.13] ([38.34.87.7]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2c164f8679esm72210575ad.21.2026.06.04.19.22.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 04 Jun 2026 19:22:06 -0700 (PDT) Message-ID: Subject: Re: [PATCH bpf-next v2 1/2] bpf, verifier: fold reg->var_off into PTR_TO_FLOW_KEYS bounds check From: Eduard Zingerman To: Nuoqi Gui , ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org Cc: John Fastabend , Martin KaFai Lau , Kumar Kartikeya Dwivedi , Song Liu , Yonghong Song , Jiri Olsa , bpf@vger.kernel.org, linux-kernel@vger.kernel.org Date: Thu, 04 Jun 2026 19:22:03 -0700 In-Reply-To: <20260604180730.2518088-2-gnq25@mails.tsinghua.edu.cn> References: <20260604180730.2518088-1-gnq25@mails.tsinghua.edu.cn> <20260604180730.2518088-2-gnq25@mails.tsinghua.edu.cn> Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable User-Agent: Evolution 3.56.2-9 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 On Fri, 2026-06-05 at 02:07 +0800, Nuoqi Gui wrote: > Constant pointer arithmetic on a PTR_TO_FLOW_KEYS register lands the > constant in reg->var_off (e.g. flow_keys(imm=3D4096)), but the > PTR_TO_FLOW_KEYS path in check_mem_access() passes only insn->off to > check_flow_keys_access() and never folds reg->var_off.value.=C2=A0 The > verifier therefore accepts an access that, at runtime, dereferences past > struct bpf_flow_keys -- a verifier/runtime divergence that yields an > out-of-bounds read and write of kernel stack memory. >=20 > Commit 022ac0750883 ("bpf: use reg->var_off instead of reg->off for > pointers") removed the generic "off +=3D reg->off" that check_mem_access(= ) > applied before the per-type dispatch and replaced it with per-path > folding of reg->var_off.value (for example the ctx path now folds the > register offset via check_ctx_access()).=C2=A0 The PTR_TO_FLOW_KEYS path = was > not given the equivalent fold, so a constant offset that used to be > folded and rejected is now silently accepted: >=20 > =C2=A0 before 022ac0750883: the offset stays in reg->off and is folded > =C2=A0=C2=A0=C2=A0 generically, so the access is checked with off=3D4096 = and rejected. > =C2=A0 after=C2=A0 022ac0750883: the offset lands in reg->var_off, the fl= ow_keys > =C2=A0=C2=A0=C2=A0 path checks off=3D0 and accepts; at runtime the access= dereferences > =C2=A0=C2=A0=C2=A0 base + 0x1000. >=20 > For a BPF_PROG_TYPE_FLOW_DISSECTOR program the following is accepted: >=20 > =C2=A0 r2 =3D *(u64 *)(r1 + 144)=C2=A0=C2=A0 ; R2=3Dflow_keys (PTR_TO_FLO= W_KEYS) > =C2=A0 r2 +=3D 0x1000=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0 ; R2=3Dflow_keys(imm=3D4096), accepted > =C2=A0 r0 =3D *(u64 *)(r2 + 0)=C2=A0=C2=A0=C2=A0=C2=A0 ; accepted, var_of= f.value=3D0x1000 ignored >=20 > while the equivalent insn->off form >=20 > =C2=A0 r0 =3D *(u64 *)(r2 + 0x1000) >=20 > has the same effective offset but is correctly rejected with > "invalid access to flow keys off=3D4096 size=3D8", which isolates the def= ect > to the missing var_off fold.=C2=A0 Once attached as a flow dissector, the > accepted program reads kernel stack past struct bpf_flow_keys (a > kernel-stack / KASLR information leak) and can likewise write past it, > corrupting kernel memory. >=20 > Fix it by folding reg->var_off.value into the offset before the bounds > check and rejecting non-constant offsets, mirroring the other pointer > types (e.g. check_ctx_access()). >=20 > No released kernel is affected; the regression is confined to the 7.1 > development cycle (reproduced on v7.1-rc1..rc5), and v7.0.x rejects the > program above. >=20 > Fixes: 022ac0750883 ("bpf: use reg->var_off instead of reg->off for point= ers") > Signed-off-by: Nuoqi Gui > --- This fixes a real issue, thank you for finding it. > =C2=A0kernel/bpf/verifier.c | 19 ++++++++++++++++--- > =C2=A01 file changed, 16 insertions(+), 3 deletions(-) >=20 > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c > index 8ed484cb1a8a..c04941636ef4 100644 > --- a/kernel/bpf/verifier.c > +++ b/kernel/bpf/verifier.c > @@ -4728,9 +4728,22 @@ static int check_ctx_access(struct bpf_verifier_en= v *env, int insn_idx, struct b > =C2=A0 return err; > =C2=A0} > =C2=A0 > -static int check_flow_keys_access(struct bpf_verifier_env *env, int off, > - =C2=A0 int size) > +static int check_flow_keys_access(struct bpf_verifier_env *env, u32 regn= o, > + =C2=A0 int off, int size) > =C2=A0{ > + struct bpf_reg_state *reg =3D reg_state(env, regno); > + > + /* Only a constant offset is allowed here; fold it into off. */ > + if (!tnum_is_const(reg->var_off)) { > + char tn_buf[48]; > + > + tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off); > + verbose(env, "R%d invalid variable offset to flow keys: off=3D%d, var_= off=3D%s\n", > + regno, off, tn_buf); > + return -EACCES; > + } > + off +=3D reg->var_off.value; > + > =C2=A0 if (size < 0 || off < 0 || > =C2=A0 =C2=A0=C2=A0=C2=A0 (u64)off + size > sizeof(struct bpf_flow_keys))= { > =C2=A0 verbose(env, "invalid access to flow keys off=3D%d size=3D%d\n", > @@ -6239,7 +6252,7 @@ static int check_mem_access(struct bpf_verifier_env= *env, int insn_idx, struct b > =C2=A0 return -EACCES; > =C2=A0 } > =C2=A0 > - err =3D check_flow_keys_access(env, off, size); > + err =3D check_flow_keys_access(env, regno, off, size); ^^^^^ This variable is not defined, hence this patch leads to the compilation err= or. > =C2=A0 if (!err && t =3D=3D BPF_READ && value_regno >=3D 0) > =C2=A0 mark_reg_unknown(env, regs, value_regno); > =C2=A0 } else if (type_is_sk_pointer(reg->type)) {