From nobody Mon Jun 8 19:47:06 2026 Received: from mail-pl1-f175.google.com (mail-pl1-f175.google.com [209.85.214.175]) (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 EFEC02F7F1B for ; Wed, 27 May 2026 05:26:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779859591; cv=none; b=LqamXHqJ+H88ect1FLKL8Gw+kDOz1CM8hHoffGCMa5Lg0AIWBJKTLt8pr/YvIG28rjvFus4SSAmADjzMdmj2sZK6sanZ1WyTOITcJCDjgXCOrtlJtEych8mZWqg49QSapC/UTqPDfhCfndWWZLwgehchImW6Kp4+iTMz8mOOyRQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779859591; c=relaxed/simple; bh=0PEmYmUKjjy+UjaIZHA18BYu7wgf2SlU3T4ccIn/5tM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PkNGQUj+bOxlpUk7KkM+WG/89HKdFVkttaySCzNw4MX4mICMT2mtZh5qGhWSsoYNrviGrhbb4JI6Wn/5cbQSon3HeZxIO3ka+AEMd50YKtsrmN9SIGfEQzx4LwwQ4iW0Omoy+VosnAXK1z+dfp4fobuZpb7U+dndhlEucYD11hM= 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=JXfxSldS; arc=none smtp.client-ip=209.85.214.175 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="JXfxSldS" Received: by mail-pl1-f175.google.com with SMTP id d9443c01a7336-2ba17c8cfacso118922395ad.2 for ; Tue, 26 May 2026 22:26:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1779859589; x=1780464389; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=fBBzQO9B+rRmoWSlMXPb0NICXzc+ZzEXtJVCUCazNEY=; b=JXfxSldSe+XRZ+/FxugXDjGuKun1YPRuizDBClEyd5DO5OppHFm/CFs+Dyj9n1niXt 2OdnEDH9eRKx6t7Sbmql0wRpL/1Df218S4NSRo3F7Xb28pTjNrla/8agXLkOBdR66P8D fiT/iA+dKUw0YFCa9d9Ee4ninG8hiRYZlzsPUbFkreo7vEmZ7EIG0hLOZdAMOm8nzvM3 WXVeWT1fJIISzuQg5oHzP+arXwarspJTZM7UbV6BdtomGcT+gdoGuxCqBnR1Q6SROBon mrWw9ga1fLOK7X7z91M8FNVgZFWMe+iHGLd693wyMZxCJ2LktMgGhyLfX1Tc4UPPCFVU shIw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779859589; x=1780464389; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=fBBzQO9B+rRmoWSlMXPb0NICXzc+ZzEXtJVCUCazNEY=; b=OtmeacCuks7ifoOHf8zVK51hijYXsZ07soteSc0Ge3Ory/xR0pnru0K5ES4abWkPc5 K/Ah0a3AVLV4Mn4a5/nFqtAuGs/Suow64dn5OVYmQxaFRJ2nIfzfjcSVY/IILQawlo1D ODi7pjMqsCx/EGvGK8QQ/9/NyYKembCjyHGZHzGVzkmCv/U1A2YVeUP1V0J1zcEqgZSW x8RhzcM0FzSPpoBtTRfVWNXuk6CN1F13AP+r870hJ1einZK3d7NQzPQLHKEK/pNmcu1c N3FxPs5RV82/OpkEfFHwt3REnu/cJBxe6WosZKdFBM2yY/ZuhbzR1qXTeTv+XrDGW2to kmWw== X-Forwarded-Encrypted: i=1; AFNElJ/iL+zFERq7ONefXTz6KYHnliDBF2qVUM/W8IHoM0K6+HVV0V5RRCjYSlX0GVQwLyfhBAYhdQTFm2x/QuE=@vger.kernel.org X-Gm-Message-State: AOJu0YwAXH/VcgnblEL0zIwyNa1E7R3/tuLXIm3N1J5WbswAn+KhG02h RxMX6mJIfxzIGwJgItBpAqR1xCSD01U6okj578XmXCUZBj5mB34PSN7x X-Gm-Gg: Acq92OGySRreNZe1Q7RfP39QJvDI4smSe4GSmy0gDxfejF9GW365jv/IPXhayMYfiRW aKWxXiFigHAAdVTEtoWrUWtZjXcLmTy7YhPd0dltSq39WKv2OuHnO54bOPrO66243M5v6HIyGEx j4aYM8xR9eUsAhM9n8EnpsZjfFx4+XapFwSCoFyCYwAJoa5c1G/xaOl4NzrcxHqHBGT0Y29nRS3 nRlV4fvH9sXz7padzXDJOI+R5bnsz9ck8vtT3f/mJF8/dtR5F3lhQyaqCOXpvbq+mMHBm+om+HQ UxaFkn2F/ZwZ0VhiiGoqO7qthrtQR/g19ASZ7OxS6G69dTzrjkMC98HqejyotAj3wWWfmkqrTtH VgndaO2a4fHvxSZ5FEqyQq5iWWIMLvs23chv/FnslZofmNl446lW9zUhcmGAeWE/vr/++Lm9RKG hj9r/TRH9OG79o0nCdwOirIln/far6jIRLflmB X-Received: by 2002:a17:903:1a2f:b0:2ba:7749:f89a with SMTP id d9443c01a7336-2beb035c500mr227120585ad.11.1779859589210; Tue, 26 May 2026 22:26:29 -0700 (PDT) Received: from localhost.localdomain ([220.83.29.221]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2beb58e4fcfsm144891465ad.71.2026.05.26.22.26.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 May 2026 22:26:27 -0700 (PDT) From: Taegu Ha To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko Cc: Eduard Zingerman , Kumar Kartikeya Dwivedi , Shuah Khan , bpf@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Taegu Ha Subject: [PATCH bpf 1/1] bpf: reject overlarge global subprog argument sizes Date: Wed, 27 May 2026 14:25:39 +0900 Message-ID: <20260527052539.3388700-2-hataegu0826@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260527052539.3388700-1-hataegu0826@gmail.com> References: <20260527052539.3388700-1-hataegu0826@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Global subprogram argument checking derives generic pointer sizes from BTF and passes the resolved size to check_mem_reg() as a u32. The access-size validation path then uses a signed int, and stack pointers negate the value before calling check_helper_mem_access(). A BTF type such as int[0x3fffffff] resolves to 0xfffffffc bytes. On a stack pointer, (int)mem_size becomes -4 and the negation validates only four bytes. A caller can therefore pass a four-byte stack slot while the callee is verified with a nearly 4GiB memory argument, allowing accesses outside the caller object. This was confirmed with a non-executing raw-BTF reproducer. On a vulnerable kernel, the verifier accepted a program where the caller passed a four-byte stack slot, while the callee argument was described by BTF as int[0x3fffffff]. The verifier log showed: R1=3Dmem_or_null(id=3D1,sz=3D0xfffffffc) r0 =3D *(u32 *)(r1 +4) The program was only loaded to prove verifier acceptance and was not attached or executed. Reject sizes that cannot be represented by the signed verifier access-size API before any conversion. Cast the non-stack case after the bound check to make the conversion explicit, and add a verifier regression test for the oversized BTF argument. Fixes: 2cb27158adb3 ("bpf: poison dead stack slots") Signed-off-by: Taegu Ha --- kernel/bpf/verifier.c | 7 ++++++- .../bpf/progs/verifier_global_subprogs.c | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 7fb88e1cd7c4..1007f204a1f5 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -7107,6 +7107,11 @@ static int check_mem_reg(struct bpf_verifier_env *en= v, struct bpf_reg_state *reg struct bpf_reg_state saved_reg; int err; =20 + if (mem_size > S32_MAX) { + verbose(env, "R%d memory size %u is too large\n", regno, mem_size); + return -EACCES; + } + if (bpf_register_is_null(reg)) return 0; =20 @@ -7119,7 +7124,7 @@ static int check_mem_reg(struct bpf_verifier_env *env= , struct bpf_reg_state *reg mark_ptr_not_null_reg(reg); } =20 - int size =3D base_type(reg->type) =3D=3D PTR_TO_STACK ? -(int)mem_size : = mem_size; + int size =3D base_type(reg->type) =3D=3D PTR_TO_STACK ? -(int)mem_size : = (int)mem_size; =20 err =3D check_helper_mem_access(env, regno, size, BPF_READ, true, NULL); err =3D err ?: check_helper_mem_access(env, regno, size, BPF_WRITE, true,= NULL); diff --git a/tools/testing/selftests/bpf/progs/verifier_global_subprogs.c b= /tools/testing/selftests/bpf/progs/verifier_global_subprogs.c index 1e08aff7532e..0ff8f85b4d46 100644 --- a/tools/testing/selftests/bpf/progs/verifier_global_subprogs.c +++ b/tools/testing/selftests/bpf/progs/verifier_global_subprogs.c @@ -151,6 +151,23 @@ int anon_user_mem_valid(void *ctx) return subprog_user_anon_mem(&t); } =20 +__noinline __weak int subprog_user_anon_mem_huge(int (*p)[0x3fffffff]) +{ + return p ? (*p)[1] : 0; +} + +SEC("?tracepoint") +__failure __log_level(2) +__msg("R1 memory size 4294967292 is too large") +int anon_user_mem_huge_size_invalid(void *ctx) +{ + int (*p)[0x3fffffff]; + int tiny =3D 42; + + p =3D (void *)&tiny; + return subprog_user_anon_mem_huge(p) + tiny; +} + __noinline __weak int subprog_nonnull_ptr_good(int *p1 __arg_nonnull, int = *p2 __arg_nonnull) { return (*p1) * (*p2); /* good, no need for NULL checks */ --=20 2.43.0