[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20251106125255.1969938-4-hao.sun@inf.ethz.ch>
Date: Thu, 6 Nov 2025 13:52:41 +0100
From: Hao Sun <sunhao.th@...il.com>
To: bpf@...r.kernel.org
Cc: ast@...nel.org,
daniel@...earbox.net,
andrii@...nel.org,
eddyz87@...il.com,
john.fastabend@...il.com,
martin.lau@...ux.dev,
song@...nel.org,
yonghong.song@...ux.dev,
linux-kernel@...r.kernel.org,
sunhao.th@...il.com,
Hao Sun <hao.sun@....ethz.ch>
Subject: [PATCH RFC 03/17] bpf: Add UAPI fields for BCF proof interaction
Extend union bpf_attr for BPF_PROG_LOAD to support proof-based verifier
refinement. The new fields let the verifier export the refinement
condition to userspace, preserve its state behind an anon-fd, and later
accept a proof and resume analysis.
- bcf_buf, bcf_buf_size, bcf_buf_true_size: shared buffer used first to
export expressions+condition to userspace and later to receive a proof.
true_size refers to the condition size and proof size accordingly.
- bcf_fd: anon-fd that owns the preserved verifier_env. Set by the kernel on
request; userspace passes it back when submitting a proof.
Tools uapi is also updated.
Signed-off-by: Hao Sun <hao.sun@....ethz.ch>
---
include/uapi/linux/bpf.h | 21 +++++++++++++++++++++
kernel/bpf/syscall.c | 23 ++++++++++++++++++++++-
tools/include/uapi/linux/bpf.h | 21 +++++++++++++++++++++
3 files changed, 64 insertions(+), 1 deletion(-)
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 1d73f165394d..fbe99fbc39ab 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -1484,6 +1484,15 @@ enum {
BPF_STREAM_STDERR = 2,
};
+/* bcf_flags used in BPF_PROG_LOAD command to indicate if the verifier
+ * requests or the user provides proofs.
+ */
+enum {
+ BCF_F_PROOF_REQUESTED = (1U << 0),
+ BCF_F_PROOF_PROVIDED = (1U << 1),
+ BCF_F_PROOF_PATH_UNREACHABLE = (1U << 2),
+};
+
union bpf_attr {
struct { /* anonymous struct used by BPF_MAP_CREATE command */
__u32 map_type; /* one of enum bpf_map_type */
@@ -1624,6 +1633,18 @@ union bpf_attr {
* verification.
*/
__s32 keyring_id;
+ /* BCF buffer for both the condition to be proved required by
+ * the verifier and the proof provided from user space.
+ */
+ __aligned_u64 bcf_buf;
+ __u32 bcf_buf_size;
+ __u32 bcf_buf_true_size;
+ /* output: BCF fd for loading proof, set by the verifier when
+ * proof is requested.
+ */
+ __u32 bcf_fd;
+ /* input/output: proof requested or provided. */
+ __u32 bcf_flags;
};
struct { /* anonymous struct used by BPF_OBJ_* commands */
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 8a129746bd6c..5968b74ed7b2 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -2854,7 +2854,7 @@ static int bpf_prog_verify_signature(struct bpf_prog *prog, union bpf_attr *attr
}
/* last field in 'union bpf_attr' used by this command */
-#define BPF_PROG_LOAD_LAST_FIELD keyring_id
+#define BPF_PROG_LOAD_LAST_FIELD bcf_flags
static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size)
{
@@ -2869,6 +2869,24 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size)
if (CHECK_ATTR(BPF_PROG_LOAD))
return -EINVAL;
+ if (!!attr->bcf_buf != !!attr->bcf_buf_size ||
+ (attr->bcf_flags & ~(BCF_F_PROOF_PROVIDED |
+ BCF_F_PROOF_PATH_UNREACHABLE)))
+ return -EINVAL;
+
+ /* Check proof and resume the last analysis. */
+ if (attr->bcf_flags & BCF_F_PROOF_PROVIDED) {
+ if (attr->bcf_buf_true_size > attr->bcf_buf_size ||
+ !attr->bcf_buf_size)
+ return -EINVAL;
+ /* The resumed analysis must only uses the old, first attr. */
+ memset(attr, 0, offsetof(union bpf_attr, bcf_buf));
+ return -ENOTSUPP;
+ }
+
+ if (attr->bcf_fd || attr->bcf_buf_true_size || attr->bcf_flags)
+ return -EINVAL;
+
if (attr->prog_flags & ~(BPF_F_STRICT_ALIGNMENT |
BPF_F_ANY_ALIGNMENT |
BPF_F_TEST_STATE_FREQ |
@@ -2901,6 +2919,9 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size)
bpf_cap = bpf_token_capable(token, CAP_BPF);
err = -EPERM;
+ if (attr->bcf_buf && !bpf_cap)
+ goto put_token;
+
if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) &&
(attr->prog_flags & BPF_F_ANY_ALIGNMENT) &&
!bpf_cap)
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 1d73f165394d..fbe99fbc39ab 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -1484,6 +1484,15 @@ enum {
BPF_STREAM_STDERR = 2,
};
+/* bcf_flags used in BPF_PROG_LOAD command to indicate if the verifier
+ * requests or the user provides proofs.
+ */
+enum {
+ BCF_F_PROOF_REQUESTED = (1U << 0),
+ BCF_F_PROOF_PROVIDED = (1U << 1),
+ BCF_F_PROOF_PATH_UNREACHABLE = (1U << 2),
+};
+
union bpf_attr {
struct { /* anonymous struct used by BPF_MAP_CREATE command */
__u32 map_type; /* one of enum bpf_map_type */
@@ -1624,6 +1633,18 @@ union bpf_attr {
* verification.
*/
__s32 keyring_id;
+ /* BCF buffer for both the condition to be proved required by
+ * the verifier and the proof provided from user space.
+ */
+ __aligned_u64 bcf_buf;
+ __u32 bcf_buf_size;
+ __u32 bcf_buf_true_size;
+ /* output: BCF fd for loading proof, set by the verifier when
+ * proof is requested.
+ */
+ __u32 bcf_fd;
+ /* input/output: proof requested or provided. */
+ __u32 bcf_flags;
};
struct { /* anonymous struct used by BPF_OBJ_* commands */
--
2.34.1
Powered by blists - more mailing lists