* [PATCH bpf-next v2 0/3] BPF signature hash chains
@ 2025-09-29 21:34 Blaise Boscaccy
2025-09-29 21:34 ` [PATCH bpf-next v2 1/3] bpf: Add hash chain signature support for arbitrary maps Blaise Boscaccy
` (3 more replies)
0 siblings, 4 replies; 24+ messages in thread
From: Blaise Boscaccy @ 2025-09-29 21:34 UTC (permalink / raw)
To: bpf, linux-security-module, kpsingh, bboscaccy, paul, kys, ast,
daniel, andrii, James.Bottomley, wufan, qmo
This patchset extends the currently proposed signature verification
patchset
https://lore.kernel.org/linux-security-module/20250813205526.2992911-1-kpsingh@kernel.org/
with hash-chain functionality to verify the contents of arbitrary
maps.
The currently proposed loader + map signature verification
scheme—requested by Alexei and KP—is simple to implement and
acceptable if users/admins are satisfied with it. However, verifying
both the loader and the maps offers additional benefits beyond just
verifying the loader:
1. Simplified Loader Logic: The lskel loader becomes simpler since it
doesn’t need to verify program maps—this is already handled by
bpf_check_signature().
2. Security and Audit Integrity: A key advantage is that the LSM
(Linux Security Module) hook for authorizing BPF program loads can
operate after signature verification. This ensures:
* Access control decisions can be based on verified signature
* status. Accurate system state measurement and logging. Log
* events claiming a verified signature are fully truthful, avoiding
* misleading entries that only the loader was verified while the
* actual BPF program verification happens later without logging.
This approach addresses concerns from users who require strict audit
trails and verification guarantees, especially in security-sensitive
environments.
A working tree with this patchset is being maintained at
https://github.com/blaiseboscaccy/linux/tree/bpf-hash-chains
bpf CI tests passed as well
https://github.com/kernel-patches/bpf/actions/runs/18110352925
v2 -> v1:
- Fix regression found by syzkaller
- Add bash auto-complete support for new command line switch
Blaise Boscaccy (3):
bpf: Add hash chain signature support for arbitrary maps
selftests/bpf: Enable map verification for some lskel tests
bpftool: Add support for signing program and map hash chains
include/uapi/linux/bpf.h | 6 ++
kernel/bpf/syscall.c | 73 ++++++++++++++++++-
.../bpf/bpftool/Documentation/bpftool-gen.rst | 7 +-
tools/bpf/bpftool/bash-completion/bpftool | 2 +-
tools/bpf/bpftool/gen.c | 27 ++++++-
tools/bpf/bpftool/main.c | 9 ++-
tools/bpf/bpftool/main.h | 1 +
tools/bpf/bpftool/sign.c | 16 +++-
tools/include/uapi/linux/bpf.h | 6 ++
tools/lib/bpf/libbpf.h | 3 +-
tools/lib/bpf/skel_internal.h | 6 +-
tools/testing/selftests/bpf/Makefile | 18 ++++-
12 files changed, 159 insertions(+), 15 deletions(-)
--
2.48.1
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH bpf-next v2 1/3] bpf: Add hash chain signature support for arbitrary maps
2025-09-29 21:34 [PATCH bpf-next v2 0/3] BPF signature hash chains Blaise Boscaccy
@ 2025-09-29 21:34 ` Blaise Boscaccy
2025-09-29 21:34 ` [PATCH bpf-next v2 2/3] selftests/bpf: Enable map verification for some lskel tests Blaise Boscaccy
` (2 subsequent siblings)
3 siblings, 0 replies; 24+ messages in thread
From: Blaise Boscaccy @ 2025-09-29 21:34 UTC (permalink / raw)
To: bpf, linux-security-module, kpsingh, bboscaccy, paul, kys, ast,
daniel, andrii, James.Bottomley, wufan, qmo
This patch introduces hash chain support for signature verification of
arbitrary bpf map objects which was described here:
https://lore.kernel.org/linux-security-module/20250721211958.1881379-1-kpsingh@kernel.org/
The UAPI is extended to allow for in-kernel checking of maps passed in
via the fd_array. A hash chain is constructed from the maps, in order
specified by the signature_maps field. The hash chain is terminated
with the hash of the program itself.
Tested-by: syzbot@syzkaller.appspotmail.com
Signed-off-by: Blaise Boscaccy <bboscaccy@linux.microsoft.com>
---
include/uapi/linux/bpf.h | 6 +++
kernel/bpf/syscall.c | 73 ++++++++++++++++++++++++++++++++--
tools/include/uapi/linux/bpf.h | 6 +++
3 files changed, 81 insertions(+), 4 deletions(-)
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index ae83d8649ef1c..a436a2ff49437 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -1621,6 +1621,12 @@ union bpf_attr {
* verification.
*/
__s32 keyring_id;
+ /* Pointer to a buffer containing the maps used in the signature
+ * hash chain of the BPF program.
+ */
+ __aligned_u64 signature_maps;
+ /* Size of the signature maps buffer. */
+ __u32 signature_maps_size;
};
struct { /* anonymous struct used by BPF_OBJ_* commands */
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index a48fa86f82a7f..f728f663765c4 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -2802,14 +2802,35 @@ static bool is_perfmon_prog_type(enum bpf_prog_type prog_type)
}
}
+static inline int bpf_map_get_hash(int map_fd, void *buffer)
+{
+ struct bpf_map *map;
+
+ CLASS(fd, f)(map_fd);
+ map = __bpf_map_get(f);
+ if (IS_ERR(map))
+ return PTR_ERR(map);
+
+ if (!map->ops->map_get_hash)
+ return -EINVAL;
+
+ return map->ops->map_get_hash(map, SHA256_DIGEST_SIZE, buffer);
+}
+
static int bpf_prog_verify_signature(struct bpf_prog *prog, union bpf_attr *attr,
bool is_kernel)
{
bpfptr_t usig = make_bpfptr(attr->signature, is_kernel);
- struct bpf_dynptr_kern sig_ptr, insns_ptr;
+ bpfptr_t umaps;
+ struct bpf_dynptr_kern sig_ptr, insns_ptr, hash_ptr;
struct bpf_key *key = NULL;
void *sig;
+ int *maps;
+ int map_fd;
int err = 0;
+ u64 buffer[SHA256_DIGEST_SIZE * 2 / sizeof(u64)];
+ u64 hash[SHA256_DIGEST_SIZE / sizeof(u64)];
+ int n;
if (system_keyring_id_check(attr->keyring_id) == 0)
key = bpf_lookup_system_key(attr->keyring_id);
@@ -2830,16 +2851,60 @@ static int bpf_prog_verify_signature(struct bpf_prog *prog, union bpf_attr *attr
bpf_dynptr_init(&insns_ptr, prog->insnsi, BPF_DYNPTR_TYPE_LOCAL, 0,
prog->len * sizeof(struct bpf_insn));
- err = bpf_verify_pkcs7_signature((struct bpf_dynptr *)&insns_ptr,
- (struct bpf_dynptr *)&sig_ptr, key);
+ if (!attr->signature_maps_size) {
+ err = bpf_verify_pkcs7_signature((struct bpf_dynptr *)&insns_ptr,
+ (struct bpf_dynptr *)&sig_ptr, key);
+ } else {
+ bpf_dynptr_init(&hash_ptr, hash, BPF_DYNPTR_TYPE_LOCAL, 0,
+ sizeof(hash));
+ umaps = make_bpfptr(attr->signature_maps, is_kernel);
+ maps = kvmemdup_bpfptr(umaps, attr->signature_maps_size * sizeof(*maps));
+ if (IS_ERR(maps)) {
+ err = PTR_ERR(maps);
+ goto out;
+ }
+ /* Process the map array in reverse order to generate a hash chain
+ * h(n) = sha256(h(n + 1), sha256(map(n)))
+ * h(n_len) = sha256(map(n_len))
+ */
+ for (n = attr->signature_maps_size - 1; n >= 0; n--) {
+ err = copy_from_bpfptr_offset(&map_fd,
+ make_bpfptr(attr->fd_array, is_kernel),
+ maps[n] * sizeof(map_fd),
+ sizeof(map_fd));
+ if (err)
+ goto free_maps;
+
+ if (n == attr->signature_maps_size - 1)
+ err = bpf_map_get_hash(map_fd, hash);
+ else {
+ memcpy(buffer, hash, sizeof(hash));
+ err = bpf_map_get_hash(map_fd, buffer + ARRAY_SIZE(hash));
+ sha256((u8 *)buffer, sizeof(buffer), (u8 *)&hash);
+ }
+ if (err)
+ goto free_maps;
+ }
+ /* Calculate final hash with program instructions
+ * f_hash = sha256(sha256(prog), h(0))
+ */
+ sha256((u8 *)prog->insnsi, prog->len * sizeof(struct bpf_insn), (u8 *)&buffer);
+ memcpy(buffer + ARRAY_SIZE(hash), hash, sizeof(hash));
+ sha256((u8 *)buffer, sizeof(buffer), (u8 *)&hash);
+ err = bpf_verify_pkcs7_signature((struct bpf_dynptr *)&hash_ptr,
+ (struct bpf_dynptr *)&sig_ptr, key);
+free_maps:
+ kvfree(maps);
+ }
+out:
bpf_key_put(key);
kvfree(sig);
return err;
}
/* last field in 'union bpf_attr' used by this command */
-#define BPF_PROG_LOAD_LAST_FIELD keyring_id
+#define BPF_PROG_LOAD_LAST_FIELD signature_maps_size
static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size)
{
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index ae83d8649ef1c..a436a2ff49437 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -1621,6 +1621,12 @@ union bpf_attr {
* verification.
*/
__s32 keyring_id;
+ /* Pointer to a buffer containing the maps used in the signature
+ * hash chain of the BPF program.
+ */
+ __aligned_u64 signature_maps;
+ /* Size of the signature maps buffer. */
+ __u32 signature_maps_size;
};
struct { /* anonymous struct used by BPF_OBJ_* commands */
--
2.48.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH bpf-next v2 2/3] selftests/bpf: Enable map verification for some lskel tests
2025-09-29 21:34 [PATCH bpf-next v2 0/3] BPF signature hash chains Blaise Boscaccy
2025-09-29 21:34 ` [PATCH bpf-next v2 1/3] bpf: Add hash chain signature support for arbitrary maps Blaise Boscaccy
@ 2025-09-29 21:34 ` Blaise Boscaccy
2025-09-29 21:34 ` [PATCH bpf-next v2 3/3] bpftool: Add support for signing program and map hash chains Blaise Boscaccy
2025-10-01 21:37 ` [PATCH bpf-next v2 0/3] BPF signature " Paul Moore
3 siblings, 0 replies; 24+ messages in thread
From: Blaise Boscaccy @ 2025-09-29 21:34 UTC (permalink / raw)
To: bpf, linux-security-module, kpsingh, bboscaccy, paul, kys, ast,
daniel, andrii, James.Bottomley, wufan, qmo
Convert an existing signed lskel test to use the newly introduced map
signature hash-chain support added to libbpf.
Signed-off-by: Blaise Boscaccy <bboscaccy@linux.microsoft.com>
---
tools/testing/selftests/bpf/Makefile | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index f00587d4ede68..ae03fa9001a61 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -500,12 +500,14 @@ LSKELS := fexit_sleep.c trace_printk.c trace_vprintk.c map_ptr_kern.c \
core_kern.c core_kern_overflow.c test_ringbuf.c \
test_ringbuf_n.c test_ringbuf_map_key.c test_ringbuf_write.c
-LSKELS_SIGNED := fentry_test.c fexit_test.c atomics.c
+LSKELS_SIGNED := fentry_test.c fexit_test.c
+
+LSKELS_SIGNED_MAPS := atomics.c
# Generate both light skeleton and libbpf skeleton for these
LSKELS_EXTRA := test_ksyms_module.c test_ksyms_weak.c kfunc_call_test.c \
kfunc_call_test_subprog.c
-SKEL_BLACKLIST += $$(LSKELS) $$(LSKELS_SIGNED)
+SKEL_BLACKLIST += $$(LSKELS) $$(LSKELS_SIGNED) $$(LSKELS_SIGNED_MAPS)
test_static_linked.skel.h-deps := test_static_linked1.bpf.o test_static_linked2.bpf.o
linked_funcs.skel.h-deps := linked_funcs1.bpf.o linked_funcs2.bpf.o
@@ -537,6 +539,7 @@ HEADERS_FOR_BPF_OBJS := $(wildcard $(BPFDIR)/*.bpf.h) \
define DEFINE_TEST_RUNNER
LSKEL_SIGN := -S -k $(PRIVATE_KEY) -i $(VERIFICATION_CERT)
+LSKEL_SIGN_MAPS := -S -M -k $(PRIVATE_KEY) -i $(VERIFICATION_CERT)
TRUNNER_OUTPUT := $(OUTPUT)$(if $2,/)$2
TRUNNER_BINARY := $1$(if $2,-)$2
TRUNNER_TEST_OBJS := $$(patsubst %.c,$$(TRUNNER_OUTPUT)/%.test.o, \
@@ -553,6 +556,7 @@ TRUNNER_BPF_SKELS := $$(patsubst %.c,$$(TRUNNER_OUTPUT)/%.skel.h, \
TRUNNER_BPF_LSKELS := $$(patsubst %.c,$$(TRUNNER_OUTPUT)/%.lskel.h, $$(LSKELS) $$(LSKELS_EXTRA))
TRUNNER_BPF_SKELS_LINKED := $$(addprefix $$(TRUNNER_OUTPUT)/,$(LINKED_SKELS))
TRUNNER_BPF_LSKELS_SIGNED := $$(patsubst %.c,$$(TRUNNER_OUTPUT)/%.lskel.h, $$(LSKELS_SIGNED))
+TRUNNER_BPF_LSKELS_SIGNED_MAPS := $$(patsubst %.c,$$(TRUNNER_OUTPUT)/%.lskel.h, $$(LSKELS_SIGNED_MAPS))
TEST_GEN_FILES += $$(TRUNNER_BPF_OBJS)
# Evaluate rules now with extra TRUNNER_XXX variables above already defined
@@ -616,6 +620,15 @@ $(TRUNNER_BPF_LSKELS_SIGNED): %.lskel.h: %.bpf.o $(BPFTOOL) | $(TRUNNER_OUTPUT)
$(Q)$$(BPFTOOL) gen skeleton $(LSKEL_SIGN) $$(<:.o=.llinked3.o) name $$(notdir $$(<:.bpf.o=_lskel)) > $$@
$(Q)rm -f $$(<:.o=.llinked1.o) $$(<:.o=.llinked2.o) $$(<:.o=.llinked3.o)
+$(TRUNNER_BPF_LSKELS_SIGNED_MAPS): %.lskel.h: %.bpf.o $(BPFTOOL) | $(TRUNNER_OUTPUT)
+ $$(call msg,GEN-SKEL,$(TRUNNER_BINARY) (signed),$$@)
+ $(Q)$$(BPFTOOL) gen object $$(<:.o=.llinked1.o) $$<
+ $(Q)$$(BPFTOOL) gen object $$(<:.o=.llinked2.o) $$(<:.o=.llinked1.o)
+ $(Q)$$(BPFTOOL) gen object $$(<:.o=.llinked3.o) $$(<:.o=.llinked2.o)
+ $(Q)diff $$(<:.o=.llinked2.o) $$(<:.o=.llinked3.o)
+ $(Q)$$(BPFTOOL) gen skeleton $(LSKEL_SIGN_MAPS) $$(<:.o=.llinked3.o) name $$(notdir $$(<:.bpf.o=_lskel)) > $$@
+ $(Q)rm -f $$(<:.o=.llinked1.o) $$(<:.o=.llinked2.o) $$(<:.o=.llinked3.o)
+
$(LINKED_BPF_OBJS): %: $(TRUNNER_OUTPUT)/%
# .SECONDEXPANSION here allows to correctly expand %-deps variables as prerequisites
@@ -666,6 +679,7 @@ $(TRUNNER_TEST_OBJS:.o=.d): $(TRUNNER_OUTPUT)/%.test.d: \
$(TRUNNER_BPF_SKELS) \
$(TRUNNER_BPF_LSKELS) \
$(TRUNNER_BPF_LSKELS_SIGNED) \
+ $(TRUNNER_BPF_LSKELS_SIGNED_MAPS) \
$(TRUNNER_BPF_SKELS_LINKED) \
$$(BPFOBJ) | $(TRUNNER_OUTPUT)
--
2.48.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH bpf-next v2 3/3] bpftool: Add support for signing program and map hash chains
2025-09-29 21:34 [PATCH bpf-next v2 0/3] BPF signature hash chains Blaise Boscaccy
2025-09-29 21:34 ` [PATCH bpf-next v2 1/3] bpf: Add hash chain signature support for arbitrary maps Blaise Boscaccy
2025-09-29 21:34 ` [PATCH bpf-next v2 2/3] selftests/bpf: Enable map verification for some lskel tests Blaise Boscaccy
@ 2025-09-29 21:34 ` Blaise Boscaccy
2025-10-01 21:37 ` [PATCH bpf-next v2 0/3] BPF signature " Paul Moore
3 siblings, 0 replies; 24+ messages in thread
From: Blaise Boscaccy @ 2025-09-29 21:34 UTC (permalink / raw)
To: bpf, linux-security-module, kpsingh, bboscaccy, paul, kys, ast,
daniel, andrii, James.Bottomley, wufan, qmo
Add a new mode of operation for program loading which supports the
generation of signed hash chains for light skeletons, using the new
signed map hash chain UAPI additions.
e.g bpftool prog load -S -M -k <private_key> -i <identity_cert> fentry_test.bpf.o
The -M or --sign-maps command line switch is introduced. It generates
a hash chain such that:
H(program, maps) = sha256(sha256(program), sha256(map[0]))
Signed-off-by: Blaise Boscaccy <bboscaccy@linux.microsoft.com>
---
.../bpf/bpftool/Documentation/bpftool-gen.rst | 7 ++++-
tools/bpf/bpftool/bash-completion/bpftool | 2 +-
tools/bpf/bpftool/gen.c | 27 ++++++++++++++++++-
tools/bpf/bpftool/main.c | 9 ++++++-
tools/bpf/bpftool/main.h | 1 +
tools/bpf/bpftool/sign.c | 16 ++++++++---
tools/lib/bpf/libbpf.h | 3 ++-
tools/lib/bpf/skel_internal.h | 6 ++++-
8 files changed, 62 insertions(+), 9 deletions(-)
diff --git a/tools/bpf/bpftool/Documentation/bpftool-gen.rst b/tools/bpf/bpftool/Documentation/bpftool-gen.rst
index d0a36f442db72..b632ab87adf20 100644
--- a/tools/bpf/bpftool/Documentation/bpftool-gen.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool-gen.rst
@@ -16,7 +16,7 @@ SYNOPSIS
**bpftool** [*OPTIONS*] **gen** *COMMAND*
-*OPTIONS* := { |COMMON_OPTIONS| | { **-L** | **--use-loader** } | [ { **-S** | **--sign** } {**-k** <private_key.pem>} **-i** <certificate.x509> ] }
+*OPTIONS* := { |COMMON_OPTIONS| | { **-L** | **--use-loader** } | [ { **-S** | **--sign** } { **-M** | **--sign-maps** } {**-k** <private_key.pem>} **-i** <certificate.x509> ] }
*COMMAND* := { **object** | **skeleton** | **help** }
@@ -190,6 +190,11 @@ OPTIONS
For skeletons, generate a signed skeleton. This option must be used with
**-k** and **-i**. Using this flag implicitly enables **--use-loader**.
+-M --sign-maps
+ For skeletons, generate a signed skeleton that includes a hash chain for the
+ skeletons maps. This option must be used with **-k** and **-i**. Using this
+ flag implicitly enables **--use-loader** and **--sign**.
+
-k <private_key.pem>
Path to the private key file in PEM format, required for signing.
diff --git a/tools/bpf/bpftool/bash-completion/bpftool b/tools/bpf/bpftool/bash-completion/bpftool
index 53bcfeb1a76e6..f8c217f09989c 100644
--- a/tools/bpf/bpftool/bash-completion/bpftool
+++ b/tools/bpf/bpftool/bash-completion/bpftool
@@ -262,7 +262,7 @@ _bpftool()
# Deal with options
if [[ ${words[cword]} == -* ]]; then
local c='--version --json --pretty --bpffs --mapcompat --debug \
- --use-loader --base-btf --sign -i -k'
+ --use-loader --base-btf --sign --sign-maps -i -k'
COMPREPLY=( $( compgen -W "$c" -- "$cur" ) )
return 0
fi
diff --git a/tools/bpf/bpftool/gen.c b/tools/bpf/bpftool/gen.c
index 993c7d9484a46..1c4278e2a662b 100644
--- a/tools/bpf/bpftool/gen.c
+++ b/tools/bpf/bpftool/gen.c
@@ -699,6 +699,9 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h
if (sign_progs)
opts.gen_hash = true;
+ if (sign_maps)
+ opts.sign_maps = true;
+
err = bpf_object__gen_loader(obj, &opts);
if (err)
return err;
@@ -793,6 +796,8 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h
if (sign_progs) {
sopts.insns = opts.insns;
sopts.insns_sz = opts.insns_sz;
+ sopts.data = opts.data;
+ sopts.data_sz = opts.data_sz;
sopts.excl_prog_hash = prog_sha;
sopts.excl_prog_hash_sz = sizeof(prog_sha);
sopts.signature = sig_buf;
@@ -822,6 +827,13 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h
\n\
\";\n");
+ if (sign_maps) {
+ codegen("\
+ \n\
+ static const int opts_signature_maps[1] __attribute__((__aligned__(8))) = {0}; \n\
+ ");
+ }
+
codegen("\
\n\
opts.signature = (void *)opts_sig; \n\
@@ -830,6 +842,19 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h
opts.excl_prog_hash_sz = sizeof(opts_excl_hash) - 1; \n\
opts.keyring_id = skel->keyring_id; \n\
");
+ if (sign_maps) {
+ codegen("\
+ \n\
+ opts.signature_maps = (void *)opts_signature_maps; \n\
+ opts.signature_maps_sz = 1; \n\
+ ");
+ } else {
+ codegen("\
+ \n\
+ opts.signature_maps = (void *)NULL; \n\
+ opts.signature_maps_sz = 0; \n\
+ ");
+ }
}
codegen("\
@@ -1990,7 +2015,7 @@ static int do_help(int argc, char **argv)
" %1$s %2$s help\n"
"\n"
" " HELP_SPEC_OPTIONS " |\n"
- " {-L|--use-loader} | [ {-S|--sign } {-k} <private_key.pem> {-i} <certificate.x509> ]}\n"
+ " {-L|--use-loader} | [ {-S|--sign } {-M|--sign-maps } {-k} <private_key.pem> {-i} <certificate.x509> ]}\n"
"",
bin_name, "gen");
diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c
index a829a6a49037a..47b14dcbae4ee 100644
--- a/tools/bpf/bpftool/main.c
+++ b/tools/bpf/bpftool/main.c
@@ -34,6 +34,7 @@ bool use_loader;
struct btf *base_btf;
struct hashmap *refs_table;
bool sign_progs;
+bool sign_maps;
const char *private_key_path;
const char *cert_path;
@@ -452,6 +453,7 @@ int main(int argc, char **argv)
{ "debug", no_argument, NULL, 'd' },
{ "use-loader", no_argument, NULL, 'L' },
{ "sign", no_argument, NULL, 'S' },
+ { "sign-maps", no_argument, NULL, 'M' },
{ "base-btf", required_argument, NULL, 'B' },
{ 0 }
};
@@ -478,7 +480,7 @@ int main(int argc, char **argv)
bin_name = "bpftool";
opterr = 0;
- while ((opt = getopt_long(argc, argv, "VhpjfLmndSi:k:B:l",
+ while ((opt = getopt_long(argc, argv, "VhpjfLmndSMi:k:B:l",
options, NULL)) >= 0) {
switch (opt) {
case 'V':
@@ -528,6 +530,11 @@ int main(int argc, char **argv)
sign_progs = true;
use_loader = true;
break;
+ case 'M':
+ sign_maps = true;
+ sign_progs = true;
+ use_loader = true;
+ break;
case 'k':
private_key_path = optarg;
break;
diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h
index 1130299cede0b..d4e8b39d97746 100644
--- a/tools/bpf/bpftool/main.h
+++ b/tools/bpf/bpftool/main.h
@@ -92,6 +92,7 @@ extern bool use_loader;
extern struct btf *base_btf;
extern struct hashmap *refs_table;
extern bool sign_progs;
+extern bool sign_maps;
extern const char *private_key_path;
extern const char *cert_path;
diff --git a/tools/bpf/bpftool/sign.c b/tools/bpf/bpftool/sign.c
index b34f74d210e9c..6338f0309cd91 100644
--- a/tools/bpf/bpftool/sign.c
+++ b/tools/bpf/bpftool/sign.c
@@ -23,6 +23,7 @@
#include <errno.h>
#include <bpf/skel_internal.h>
+#include <bpf/libbpf_internal.h>
#include "main.h"
@@ -130,8 +131,17 @@ int bpftool_prog_sign(struct bpf_load_and_run_opts *opts)
long actual_sig_len = 0;
X509 *x509 = NULL;
int err = 0;
-
- bd_in = BIO_new_mem_buf(opts->insns, opts->insns_sz);
+ unsigned char hash[SHA256_DIGEST_LENGTH * 2];
+ unsigned char term[SHA256_DIGEST_LENGTH];
+
+ if (sign_maps) {
+ libbpf_sha256(opts->insns, opts->insns_sz, hash);
+ libbpf_sha256(opts->data, opts->data_sz, hash + SHA256_DIGEST_LENGTH);
+ libbpf_sha256(hash, sizeof(hash), term);
+ bd_in = BIO_new_mem_buf(term, sizeof(term));
+ } else {
+ bd_in = BIO_new_mem_buf(opts->insns, opts->insns_sz);
+ }
if (!bd_in) {
err = -ENOMEM;
goto cleanup;
@@ -172,7 +182,7 @@ int bpftool_prog_sign(struct bpf_load_and_run_opts *opts)
EVP_Digest(opts->insns, opts->insns_sz, opts->excl_prog_hash,
&opts->excl_prog_hash_sz, EVP_sha256(), NULL);
- bd_out = BIO_new(BIO_s_mem());
+ bd_out = BIO_new(BIO_s_mem());
if (!bd_out) {
err = -ENOMEM;
goto cleanup;
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 5118d0a90e243..63946bdad41ad 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -1858,9 +1858,10 @@ struct gen_loader_opts {
__u32 data_sz;
__u32 insns_sz;
bool gen_hash;
+ bool sign_maps;
};
-#define gen_loader_opts__last_field gen_hash
+#define gen_loader_opts__last_field sign_maps
LIBBPF_API int bpf_object__gen_loader(struct bpf_object *obj,
struct gen_loader_opts *opts);
diff --git a/tools/lib/bpf/skel_internal.h b/tools/lib/bpf/skel_internal.h
index 6a8f5c7a02eb9..11c2c19a5b2a4 100644
--- a/tools/lib/bpf/skel_internal.h
+++ b/tools/lib/bpf/skel_internal.h
@@ -74,6 +74,8 @@ struct bpf_load_and_run_opts {
__s32 keyring_id;
void *excl_prog_hash;
__u32 excl_prog_hash_sz;
+ const int *signature_maps;
+ __u32 signature_maps_sz;
};
long kern_sys_bpf(__u32 cmd, void *attr, __u32 attr_size);
@@ -352,7 +354,7 @@ static inline int skel_map_freeze(int fd)
static inline int bpf_load_and_run(struct bpf_load_and_run_opts *opts)
{
- const size_t prog_load_attr_sz = offsetofend(union bpf_attr, keyring_id);
+ const size_t prog_load_attr_sz = offsetofend(union bpf_attr, signature_maps_size);
const size_t test_run_attr_sz = offsetofend(union bpf_attr, test);
int map_fd = -1, prog_fd = -1, key = 0, err;
union bpf_attr attr;
@@ -395,6 +397,8 @@ static inline int bpf_load_and_run(struct bpf_load_and_run_opts *opts)
#ifndef __KERNEL__
attr.signature = (long) opts->signature;
attr.signature_size = opts->signature_sz;
+ attr.signature_maps = (long) opts->signature_maps;
+ attr.signature_maps_size = opts->signature_maps_sz;
#else
if (opts->signature || opts->signature_sz)
pr_warn("signatures are not supported from bpf_preload\n");
--
2.48.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH bpf-next v2 0/3] BPF signature hash chains
2025-09-29 21:34 [PATCH bpf-next v2 0/3] BPF signature hash chains Blaise Boscaccy
` (2 preceding siblings ...)
2025-09-29 21:34 ` [PATCH bpf-next v2 3/3] bpftool: Add support for signing program and map hash chains Blaise Boscaccy
@ 2025-10-01 21:37 ` Paul Moore
2025-10-02 13:48 ` KP Singh
3 siblings, 1 reply; 24+ messages in thread
From: Paul Moore @ 2025-10-01 21:37 UTC (permalink / raw)
To: Linus Torvalds, Blaise Boscaccy, ast, kpsingh, james.bottomley
Cc: bpf, linux-security-module, kys, daniel, andrii, wufan, qmo
On Mon, Sep 29, 2025 at 5:35 PM Blaise Boscaccy
<bboscaccy@linux.microsoft.com> wrote:
>
> This patchset extends the currently proposed signature verification
> patchset
> https://lore.kernel.org/linux-security-module/20250813205526.2992911-1-kpsingh@kernel.org/
> with hash-chain functionality to verify the contents of arbitrary
> maps.
>
> The currently proposed loader + map signature verification
> scheme—requested by Alexei and KP—is simple to implement and
> acceptable if users/admins are satisfied with it. However, verifying
> both the loader and the maps offers additional benefits beyond just
> verifying the loader:
>
> 1. Simplified Loader Logic: The lskel loader becomes simpler since it
> doesn’t need to verify program maps—this is already handled by
> bpf_check_signature().
>
> 2. Security and Audit Integrity: A key advantage is that the LSM
> (Linux Security Module) hook for authorizing BPF program loads can
> operate after signature verification. This ensures:
>
> * Access control decisions can be based on verified signature
> * status. Accurate system state measurement and logging. Log
> * events claiming a verified signature are fully truthful, avoiding
> * misleading entries that only the loader was verified while the
> * actual BPF program verification happens later without logging.
>
> This approach addresses concerns from users who require strict audit
> trails and verification guarantees, especially in security-sensitive
> environments.
>
> A working tree with this patchset is being maintained at
> https://github.com/blaiseboscaccy/linux/tree/bpf-hash-chains
>
> bpf CI tests passed as well
> https://github.com/kernel-patches/bpf/actions/runs/18110352925
>
> v2 -> v1:
> - Fix regression found by syzkaller
> - Add bash auto-complete support for new command line switch
>
> Blaise Boscaccy (3):
> bpf: Add hash chain signature support for arbitrary maps
> selftests/bpf: Enable map verification for some lskel tests
> bpftool: Add support for signing program and map hash chains
>
> include/uapi/linux/bpf.h | 6 ++
> kernel/bpf/syscall.c | 73 ++++++++++++++++++-
> .../bpf/bpftool/Documentation/bpftool-gen.rst | 7 +-
> tools/bpf/bpftool/bash-completion/bpftool | 2 +-
> tools/bpf/bpftool/gen.c | 27 ++++++-
> tools/bpf/bpftool/main.c | 9 ++-
> tools/bpf/bpftool/main.h | 1 +
> tools/bpf/bpftool/sign.c | 16 +++-
> tools/include/uapi/linux/bpf.h | 6 ++
> tools/lib/bpf/libbpf.h | 3 +-
> tools/lib/bpf/skel_internal.h | 6 +-
> tools/testing/selftests/bpf/Makefile | 18 ++++-
> 12 files changed, 159 insertions(+), 15 deletions(-)
During a discussion of one of Blaise's earlier BPF signature
verification proposals Alexei mentioned that it sounded like I was
looking for Linus' opinion on our debate[1]. At the time I replied
that I was more interested in trying to find out what the BPF devs
wanted for a BPF program signing solution, and working towards making
sure we had something that worked for everyone[2]. That was almost
five months ago, and while Alexei and KP have provided an example of
their ideal solution, it can now be found in Linus' tree, they have
ignored the larger issues brought up by the LSM community and have
refused to review or comment on Blaise's many attempts[3][4][5][6] to
reconcile the needs of the two communities.
With the lack of engagement from the BPF devs, I'm now at the point
where I'm asking Linus to comment on the current situation around
Blaise's patchset. I recognize that Alexei and KP have a strong
affinity for the signature scheme implemented in KP's patchset, which
is fine, but if we are going to be serious about implementing BPF
signature verification that can be used by a number of different user
groups, we also need to support the signature scheme that Blaise is
proposing[6].
To make it clear at the start, Blaise's patchset does not change,
block, or otherwise prevent the BPF program signature scheme
implemented in KP's patchset. Blaise intentionally designed his
patches such that the two signature schemes can coexist together in
the same kernel, allowing users to select which scheme to use on each
BPF program load, enabling the kernel to support policy to selectively
enforce rules around which signature scheme is permitted for each BPF
program load.
Blaise's patch implements an alternate BPF program signature scheme,
using the same basic concepts as KP's design (light skeletons, hash
chaining, etc.), but does so in such a way that the kernel verifies
all relevant parts of the BPF program load prior to calling the
security_bpf_prog_load() LSM hook. KP's signature scheme only
verifies the light skeleton prior to calling the LSM hook and relies
on the BPF code in the light skeleton to verify the original BPF
program.
Relying on a light skeleton to verify the BPF program means that any
verification failures in the light skeleton will be "lost" as there is
no way to convey an error code back to the user who is attempting the
BPF program load. Blaise's approach to verifying the full signature
in the kernel, and not relying on the light skeleton for verification,
means that verification failures can be returned to the user; there
are no silent signature verification failures like one can experience
with KP's verification scheme.
KP's signature verification scheme is a two-part scheme with the
security_bpf_prog_load() LSM hook being called after the light
skeleton signature has been verified, but before the light skeleton
verifies the BPF program. Aside from breaking with typical
conventions around the placement of LSM hooks, this "halfway" approach
makes it difficult for LSMs to log anything about the signature status
of a BPF program being loaded, or use the signature status in any type
of access decision. This is important for a number of user groups
that use LSM based security policies as a way to help reason about the
security properties of a system, as KP's scheme would require the
users to analyze the signature verification code in every BPF light
skeleton they authorize as well as the LSM policy in order to reason
about the security mechanisms involved in BPF program loading.
Blaise's signature scheme also has the nice property that BPF ELF
objects created using his scheme are backwards compatible with
existing released kernels that do not support any BPF signature
verification schemes, of course without any signature verification.
Loading a BPF ELF object using KP's signature scheme will likely fail
when loaded on existing released kernels.
[1] https://lore.kernel.org/linux-security-module/CAADnVQ+C2KNR1ryRtBGOZTNk961pF+30FnU9n3dt3QjaQu_N6Q@mail.gmail.com/
[2] https://lore.kernel.org/linux-security-module/CAHC9VhRjKV4AbSgqb4J_-xhkWAp_VAcKDfLJ4GwhBNPOr+cvpg@mail.gmail.com/
[3] https://lore.kernel.org/linux-security-module/87sei58vy3.fsf@microsoft.com/
[4] https://lore.kernel.org/linux-security-module/20250909162345.569889-2-bboscaccy@linux.microsoft.com/
[5] https://lore.kernel.org/linux-security-module/20250926203111.1305999-1-bboscaccy@linux.microsoft.com/
[6] https://lore.kernel.org/linux-security-module/20250929213520.1821223-1-bboscaccy@linux.microsoft.com/
--
paul-moore.com
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf-next v2 0/3] BPF signature hash chains
2025-10-01 21:37 ` [PATCH bpf-next v2 0/3] BPF signature " Paul Moore
@ 2025-10-02 13:48 ` KP Singh
2025-10-02 20:01 ` Blaise Boscaccy
2025-10-03 2:35 ` Paul Moore
0 siblings, 2 replies; 24+ messages in thread
From: KP Singh @ 2025-10-02 13:48 UTC (permalink / raw)
To: Paul Moore
Cc: Linus Torvalds, Blaise Boscaccy, ast, james.bottomley, bpf,
linux-security-module, kys, daniel, andrii, wufan, qmo
On Wed, Oct 1, 2025 at 11:37 PM Paul Moore <paul@paul-moore.com> wrote:
>
[...]
> With the lack of engagement from the BPF devs, I'm now at the point
> where I'm asking Linus to comment on the current situation around
The lack of engagement is because Blaise has repeatedly sent patches
and ignored maintainer feedback and continued pushing a broken
approach. The community, in fact, prioritized the signing work to
unblock your use-case.
> Blaise's patchset. I recognize that Alexei and KP have a strong
> affinity for the signature scheme implemented in KP's patchset, which
> is fine, but if we are going to be serious about implementing BPF
> signature verification that can be used by a number of different user
> groups, we also need to support the signature scheme that Blaise is
> proposing[6].
>
Blaise's implementation fails on any modern BPF programs since
programs use more than one map, BTF information and kernel functions.
> To make it clear at the start, Blaise's patchset does not change,
> block, or otherwise prevent the BPF program signature scheme
> implemented in KP's patchset. Blaise intentionally designed his
> patches such that the two signature schemes can coexist together in
We cannot have multiple signature schemes, this is not the experience
we want for BPF users.
> the same kernel, allowing users to select which scheme to use on each
> BPF program load, enabling the kernel to support policy to selectively
> enforce rules around which signature scheme is permitted for each BPF
> program load.
>
> Blaise's patch implements an alternate BPF program signature scheme,
> using the same basic concepts as KP's design (light skeletons, hash
> chaining, etc.), but does so in such a way that the kernel verifies
> all relevant parts of the BPF program load prior to calling the
> security_bpf_prog_load() LSM hook. KP's signature scheme only
> verifies the light skeleton prior to calling the LSM hook and relies
You are confusing a light skeleton from a loader program. Loader
programs are independent of light skeletons.
> on the BPF code in the light skeleton to verify the original BPF
> program.
>
> Relying on a light skeleton to verify the BPF program means that any
> verification failures in the light skeleton will be "lost" as there is
> no way to convey an error code back to the user who is attempting the
This is not correct, the error is propagated back if the loader program fails.
> BPF program load. Blaise's approach to verifying the full signature
> in the kernel, and not relying on the light skeleton for verification,
> means that verification failures can be returned to the user; there
> are no silent signature verification failures like one can experience
> with KP's verification scheme.
>
> KP's signature verification scheme is a two-part scheme with the
> security_bpf_prog_load() LSM hook being called after the light
> skeleton signature has been verified, but before the light skeleton
> verifies the BPF program. Aside from breaking with typical
Again you mean, loader BPF program. Skeletons are just for
convenience. You don't have to use them. libbpf provides an
implementation to easily generate loader programs, but you don't have
to use that either.
> conventions around the placement of LSM hooks, this "halfway" approach
> makes it difficult for LSMs to log anything about the signature status
> of a BPF program being loaded, or use the signature status in any type
> of access decision. This is important for a number of user groups
> that use LSM based security policies as a way to help reason about the
> security properties of a system, as KP's scheme would require the
> users to analyze the signature verification code in every BPF light
> skeleton they authorize as well as the LSM policy in order to reason
> about the security mechanisms involved in BPF program loading.
>
> Blaise's signature scheme also has the nice property that BPF ELF
> objects created using his scheme are backwards compatible with
> existing released kernels that do not support any BPF signature
> verification schemes, of course without any signature verification.
> Loading a BPF ELF object using KP's signature scheme will likely fail
> when loaded on existing released kernels.
This does not make any sense. The ELF format and the way loaders like
libbpf interpret it, has nothing to do with the kernel or UAPI.
I had given detailed feedback to Blaise in
https://lore.kernel.org/bpf/CACYkzJ6yNjFOTzC04uOuCmFn=+51_ie2tB9_x-u2xbcO=yobTw@mail.gmail.com/
mentions also why we don't want any additional UAPI.
You keep mentioning having visibility in the LSM code and I again
ask, to implement what specific security policy and there is no clear
answer? On a system where you would like to only allow signed BPF
programs, you can purely deny any programs where the signature is not
provided and this can be implemented today.
Stable programs work as it is, programs that require runtime
relocation work with loader programs. We don't want to add more UAPI
as, in the future, it's quite possible that we can make the
instruction buffer stable.
- KP
>
> [1] https://lore.kernel.org/linux-security-module/CAADnVQ+C2KNR1ryRtBGOZTNk961pF+30FnU9n3dt3QjaQu_N6Q@mail.gmail.com/
> [2] https://lore.kernel.org/linux-security-module/CAHC9VhRjKV4AbSgqb4J_-xhkWAp_VAcKDfLJ4GwhBNPOr+cvpg@mail.gmail.com/
> [3] https://lore.kernel.org/linux-security-module/87sei58vy3.fsf@microsoft.com/
> [4] https://lore.kernel.org/linux-security-module/20250909162345.569889-2-bboscaccy@linux.microsoft.com/
> [5] https://lore.kernel.org/linux-security-module/20250926203111.1305999-1-bboscaccy@linux.microsoft.com/
> [6] https://lore.kernel.org/linux-security-module/20250929213520.1821223-1-bboscaccy@linux.microsoft.com/
>
> --
> paul-moore.com
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf-next v2 0/3] BPF signature hash chains
2025-10-02 13:48 ` KP Singh
@ 2025-10-02 20:01 ` Blaise Boscaccy
2025-10-03 16:59 ` KP Singh
2025-10-03 2:35 ` Paul Moore
1 sibling, 1 reply; 24+ messages in thread
From: Blaise Boscaccy @ 2025-10-02 20:01 UTC (permalink / raw)
To: KP Singh, Paul Moore
Cc: Linus Torvalds, ast, james.bottomley, bpf, linux-security-module,
kys, daniel, andrii, wufan, qmo
KP Singh <kpsingh@kernel.org> writes:
> On Wed, Oct 1, 2025 at 11:37 PM Paul Moore <paul@paul-moore.com> wrote:
>>
>
> [...]
>
[...]
I am confident that Paul will address your remaining points. However, I
would like to clarify a few factual inaccuracies outlined below.
>
> Blaise's implementation fails on any modern BPF programs since
> programs use more than one map, BTF information and kernel functions.
>
If you read the patch series you'd see that it supports verification of
any number of maps. If you've identified an issue with map verification,
please share the details and I’ll address it.
[...]
>> conventions around the placement of LSM hooks, this "halfway" approach
>> makes it difficult for LSMs to log anything about the signature status
>> of a BPF program being loaded, or use the signature status in any type
>> of access decision. This is important for a number of user groups
>> that use LSM based security policies as a way to help reason about the
>> security properties of a system, as KP's scheme would require the
>> users to analyze the signature verification code in every BPF light
>> skeleton they authorize as well as the LSM policy in order to reason
>> about the security mechanisms involved in BPF program loading.
>>
>> Blaise's signature scheme also has the nice property that BPF ELF
>> objects created using his scheme are backwards compatible with
>> existing released kernels that do not support any BPF signature
>> verification schemes, of course without any signature verification.
>> Loading a BPF ELF object using KP's signature scheme will likely fail
>> when loaded on existing released kernels.
>
> This does not make any sense. The ELF format and the way loaders like
> libbpf interpret it, has nothing to do with the kernel or UAPI.
>
We signed a program with your upstream tools and it failed to load on a
vanilla kernel 6.16. The loader in your patchset is intepreting the
first few fields of struct bpf_map as a byte array containing a sha256
digest on older kernels.
-blaise
> I had given detailed feedback to Blaise in
> https://lore.kernel.org/bpf/CACYkzJ6yNjFOTzC04uOuCmFn=+51_ie2tB9_x-u2xbcO=yobTw@mail.gmail.com/
> mentions also why we don't want any additional UAPI.
>
> You keep mentioning having visibility in the LSM code and I again
> ask, to implement what specific security policy and there is no clear
> answer? On a system where you would like to only allow signed BPF
> programs, you can purely deny any programs where the signature is not
> provided and this can be implemented today.
>
> Stable programs work as it is, programs that require runtime
> relocation work with loader programs. We don't want to add more UAPI
> as, in the future, it's quite possible that we can make the
> instruction buffer stable.
>
> - KP
>
>>
>> [1] https://lore.kernel.org/linux-security-module/CAADnVQ+C2KNR1ryRtBGOZTNk961pF+30FnU9n3dt3QjaQu_N6Q@mail.gmail.com/
>> [2] https://lore.kernel.org/linux-security-module/CAHC9VhRjKV4AbSgqb4J_-xhkWAp_VAcKDfLJ4GwhBNPOr+cvpg@mail.gmail.com/
>> [3] https://lore.kernel.org/linux-security-module/87sei58vy3.fsf@microsoft.com/
>> [4] https://lore.kernel.org/linux-security-module/20250909162345.569889-2-bboscaccy@linux.microsoft.com/
>> [5] https://lore.kernel.org/linux-security-module/20250926203111.1305999-1-bboscaccy@linux.microsoft.com/
>> [6] https://lore.kernel.org/linux-security-module/20250929213520.1821223-1-bboscaccy@linux.microsoft.com/
>>
>> --
>> paul-moore.com
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf-next v2 0/3] BPF signature hash chains
2025-10-02 13:48 ` KP Singh
2025-10-02 20:01 ` Blaise Boscaccy
@ 2025-10-03 2:35 ` Paul Moore
2025-10-03 16:24 ` KP Singh
1 sibling, 1 reply; 24+ messages in thread
From: Paul Moore @ 2025-10-03 2:35 UTC (permalink / raw)
To: KP Singh
Cc: Linus Torvalds, Blaise Boscaccy, ast, james.bottomley, bpf,
linux-security-module, kys, daniel, andrii, wufan, qmo
On Thu, Oct 2, 2025 at 9:48 AM KP Singh <kpsingh@kernel.org> wrote:
> On Wed, Oct 1, 2025 at 11:37 PM Paul Moore <paul@paul-moore.com> wrote:
> >
> > With the lack of engagement from the BPF devs, I'm now at the point
> > where I'm asking Linus to comment on the current situation around
>
> The lack of engagement is because Blaise has repeatedly sent patches
> and ignored maintainer feedback and continued pushing a broken
> approach.
I'm sorry you feel that way, but that simply does not appear to be the
case. Looking at the archives from this year I see that Blase has
proposed three different approaches[7][8][9] to verifying signed BPF
programs, with each new approach a result of the feedback received.
> The community, in fact, prioritized the signing work to unblock your use-case.
As mentioned previously, many times over, while your signature scheme
may satisfy your own
requirements, it does not provide a workable solution for use cases
that have more stringent security requirements. Blaise's latest
approach, a small patch on top of your patchset, is an attempt to
bridge that divide.
> Blaise's implementation ...
I think Blaise's response addressed your other comments rather well so
I'll just skip over those points.
> > To make it clear at the start, Blaise's patchset does not change,
> > block, or otherwise prevent the BPF program signature scheme
> > implemented in KP's patchset. Blaise intentionally designed his
> > patches such that the two signature schemes can coexist together in
>
> We cannot have multiple signature schemes, this is not the experience
> we want for BPF users.
In a perfect world there would be a singular BPF signature scheme
which would satisfy all the different use cases, but the sad reality
is that your signature scheme which Alexei sent to Linus during this
merge window falls short of that goal. Blaise's patch is an attempt
to provide a solution for the BPF use cases that are not sufficiently
addressed by your signature scheme.
> > Relying on a light skeleton to verify the BPF program means that any
> > verification failures in the light skeleton will be "lost" as there is
> > no way to convey an error code back to the user who is attempting the
>
> This is not correct, the error is propagated back if the loader program fails.
The loader BPF program which verifies the original BPF program, stored
as a map as part of the light skeleton, is not executed as part of the
original bpf() syscall issued from userspace. The loader BPF program,
and its verification code, is executed during a subsequent call. It
is possible for the PKCS7 signature on the loader to pass, with the
kernel reporting a successful program load, the LSM authorizing the
load based on a good signature, and audit recording a successful
signature verification yet the loader could still fail the integrity
check on the original BPF program, leaving the system with a false
positive on the BPF program load and a "questionable" audit trail.
> You keep mentioning having visibility in the LSM code and I again
> ask, to implement what specific security policy and there is no clear
> answer?
No one policy can satisfy the different security requirements of all
known users, simply look at all of the LSMs (including the BPF LSM)
which support different security policies as a real world example of
this. Even the presence of the LSM framework as an abstract layer is
an admission that no one policy, or model, solves all problems.
Instead, the goal is to ensure we have mechanisms in place which are
flexible enough to support a number of different policies and models.
[7] https://lore.kernel.org/all/20250109214617.485144-1-bboscaccy@linux.microsoft.com/
[8] https://lore.kernel.org/linux-security-module/20250321164537.16719-1-bboscaccy@linux.microsoft.com/
[9] https://lore.kernel.org/linux-security-module/87sei58vy3.fsf@microsoft.com/
--
paul-moore.com
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf-next v2 0/3] BPF signature hash chains
2025-10-03 2:35 ` Paul Moore
@ 2025-10-03 16:24 ` KP Singh
2025-10-06 3:08 ` Paul Moore
0 siblings, 1 reply; 24+ messages in thread
From: KP Singh @ 2025-10-03 16:24 UTC (permalink / raw)
To: Paul Moore
Cc: Linus Torvalds, Blaise Boscaccy, ast, james.bottomley, bpf,
linux-security-module, kys, daniel, andrii, wufan, qmo
On Fri, Oct 3, 2025 at 4:36 AM Paul Moore <paul@paul-moore.com> wrote:
>
> On Thu, Oct 2, 2025 at 9:48 AM KP Singh <kpsingh@kernel.org> wrote:
> > On Wed, Oct 1, 2025 at 11:37 PM Paul Moore <paul@paul-moore.com> wrote:
> > >
> > > With the lack of engagement from the BPF devs, I'm now at the point
> > > where I'm asking Linus to comment on the current situation around
> >
> > The lack of engagement is because Blaise has repeatedly sent patches
> > and ignored maintainer feedback and continued pushing a broken
> > approach.
>
> I'm sorry you feel that way, but that simply does not appear to be the
> case. Looking at the archives from this year I see that Blase has
> proposed three different approaches[7][8][9] to verifying signed BPF
> programs, with each new approach a result of the feedback received.
>
> > The community, in fact, prioritized the signing work to unblock your use-case.
>
> As mentioned previously, many times over, while your signature scheme
> may satisfy your own
> requirements, it does not provide a workable solution for use cases
> that have more stringent security requirements. Blaise's latest
> approach, a small patch on top of your patchset, is an attempt to
> bridge that divide.
>
> > Blaise's implementation ...
>
> I think Blaise's response addressed your other comments rather well so
> I'll just skip over those points.
>
> > > To make it clear at the start, Blaise's patchset does not change,
> > > block, or otherwise prevent the BPF program signature scheme
> > > implemented in KP's patchset. Blaise intentionally designed his
> > > patches such that the two signature schemes can coexist together in
> >
> > We cannot have multiple signature schemes, this is not the experience
> > we want for BPF users.
>
> In a perfect world there would be a singular BPF signature scheme
> which would satisfy all the different use cases, but the sad reality
> is that your signature scheme which Alexei sent to Linus during this
> merge window falls short of that goal. Blaise's patch is an attempt
> to provide a solution for the BPF use cases that are not sufficiently
> addressed by your signature scheme.
I am failing to understand your security requirements.
>
> > > Relying on a light skeleton to verify the BPF program means that any
> > > verification failures in the light skeleton will be "lost" as there is
> > > no way to convey an error code back to the user who is attempting the
> >
> > This is not correct, the error is propagated back if the loader program fails.
>
> The loader BPF program which verifies the original BPF program, stored
> as a map as part of the light skeleton, is not executed as part of the
> original bpf() syscall issued from userspace. The loader BPF program,
> and its verification code, is executed during a subsequent call. It
> is possible for the PKCS7 signature on the loader to pass, with the
> kernel reporting a successful program load, the LSM authorizing the
> load based on a good signature, and audit recording a successful
> signature verification yet the loader could still fail the integrity
> check on the original BPF program, leaving the system with a false
> positive on the BPF program load and a "questionable" audit trail.
>
> > You keep mentioning having visibility in the LSM code and I again
> > ask, to implement what specific security policy and there is no clear
> > answer?
>
> No one policy can satisfy the different security requirements of all
> known users, simply look at all of the LSMs (including the BPF LSM)
> which support different security policies as a real world example of
> this. Even the presence of the LSM framework as an abstract layer is
> an admission that no one policy, or model, solves all problems.
> Instead, the goal is to ensure we have mechanisms in place which are
> flexible enough to support a number of different policies and models.
Please share concrete policies you would like to implement, this is very vague.
- KP
>
> [7] https://lore.kernel.org/all/20250109214617.485144-1-bboscaccy@linux.microsoft.com/
> [8] https://lore.kernel.org/linux-security-module/20250321164537.16719-1-bboscaccy@linux.microsoft.com/
> [9] https://lore.kernel.org/linux-security-module/87sei58vy3.fsf@microsoft.com/
>
> --
> paul-moore.com
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf-next v2 0/3] BPF signature hash chains
2025-10-02 20:01 ` Blaise Boscaccy
@ 2025-10-03 16:59 ` KP Singh
2025-10-03 18:14 ` Blaise Boscaccy
0 siblings, 1 reply; 24+ messages in thread
From: KP Singh @ 2025-10-03 16:59 UTC (permalink / raw)
To: Blaise Boscaccy
Cc: Paul Moore, Linus Torvalds, ast, james.bottomley, bpf,
linux-security-module, kys, daniel, andrii, wufan, qmo
On Thu, Oct 2, 2025 at 10:01 PM Blaise Boscaccy
<bboscaccy@linux.microsoft.com> wrote:
>
> KP Singh <kpsingh@kernel.org> writes:
>
> > On Wed, Oct 1, 2025 at 11:37 PM Paul Moore <paul@paul-moore.com> wrote:
> >>
> >
> > [...]
> >
>
> [...]
>
> I am confident that Paul will address your remaining points. However, I
> would like to clarify a few factual inaccuracies outlined below.
>
> >
> > Blaise's implementation fails on any modern BPF programs since
> > programs use more than one map, BTF information and kernel functions.
> >
>
> If you read the patch series you'd see that it supports verification of
> any number of maps. If you've identified an issue with map verification,
> please share the details and I’ll address it.
>
I am sorry but this does not work, the UAPI here is
+ /* Pointer to a buffer containing the maps used in the signature
+ * hash chain of the BPF program.
+ */
+ __aligned_u64 signature_maps;
+ /* Size of the signature maps buffer. */
+ __u32 signature_maps_size;
This needs to be generically applicable and it's not, What happens if
the program is not a loader program / when the instruction buffer is
stable?
If you really want the property that all of the content is signed and
verified within the kernel, please explore approaches to make the
instruction buffer stable or feel free to deny any programs that do
relocations at load time for whatever "strict" security policy that
you want to implement.
Please stop pursuing this extension as it adds cruft to the UAPI
that's too specific, encodes the hash chain in the kernel and we won't
need in the future.
> [...]
>
> >> conventions around the placement of LSM hooks, this "halfway" approach
> >> makes it difficult for LSMs to log anything about the signature status
> >> of a BPF program being loaded, or use the signature status in any type
> >> of access decision. This is important for a number of user groups
> >> that use LSM based security policies as a way to help reason about the
> >> security properties of a system, as KP's scheme would require the
> >> users to analyze the signature verification code in every BPF light
> >> skeleton they authorize as well as the LSM policy in order to reason
> >> about the security mechanisms involved in BPF program loading.
> >>
> >> Blaise's signature scheme also has the nice property that BPF ELF
> >> objects created using his scheme are backwards compatible with
> >> existing released kernels that do not support any BPF signature
> >> verification schemes, of course without any signature verification.
> >> Loading a BPF ELF object using KP's signature scheme will likely fail
> >> when loaded on existing released kernels.
> >
> > This does not make any sense. The ELF format and the way loaders like
> > libbpf interpret it, has nothing to do with the kernel or UAPI.
> >
>
> We signed a program with your upstream tools and it failed to load on a
> vanilla kernel 6.16. The loader in your patchset is intepreting the
> first few fields of struct bpf_map as a byte array containing a sha256
> digest on older kernels.
We can convert BPF_OBJ_GET_INFO_BY_FD to be called from loader
programs to not rely on the struct field. and or libbbf can call
BPF_OBJ_GET_INFO_BY_FD to check if map_get_hash is supported before it
generates the hash check.
You should not expect bpftool -S -k -i to work on older kernels but it
should error out if the options are passed.
- KP
>
> -blaise
>
>
> > I had given detailed feedback to Blaise in
> > https://lore.kernel.org/bpf/CACYkzJ6yNjFOTzC04uOuCmFn=+51_ie2tB9_x-u2xbcO=yobTw@mail.gmail.com/
> > mentions also why we don't want any additional UAPI.
> >
> > You keep mentioning having visibility in the LSM code and I again
> > ask, to implement what specific security policy and there is no clear
> > answer? On a system where you would like to only allow signed BPF
> > programs, you can purely deny any programs where the signature is not
> > provided and this can be implemented today.
> >
> > Stable programs work as it is, programs that require runtime
> > relocation work with loader programs. We don't want to add more UAPI
> > as, in the future, it's quite possible that we can make the
> > instruction buffer stable.
> >
> > - KP
> >
> >>
> >> [1] https://lore.kernel.org/linux-security-module/CAADnVQ+C2KNR1ryRtBGOZTNk961pF+30FnU9n3dt3QjaQu_N6Q@mail.gmail.com/
> >> [2] https://lore.kernel.org/linux-security-module/CAHC9VhRjKV4AbSgqb4J_-xhkWAp_VAcKDfLJ4GwhBNPOr+cvpg@mail.gmail.com/
> >> [3] https://lore.kernel.org/linux-security-module/87sei58vy3.fsf@microsoft.com/
> >> [4] https://lore.kernel.org/linux-security-module/20250909162345.569889-2-bboscaccy@linux.microsoft.com/
> >> [5] https://lore.kernel.org/linux-security-module/20250926203111.1305999-1-bboscaccy@linux.microsoft.com/
> >> [6] https://lore.kernel.org/linux-security-module/20250929213520.1821223-1-bboscaccy@linux.microsoft.com/
> >>
> >> --
> >> paul-moore.com
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf-next v2 0/3] BPF signature hash chains
2025-10-03 16:59 ` KP Singh
@ 2025-10-03 18:14 ` Blaise Boscaccy
2025-10-03 19:02 ` KP Singh
0 siblings, 1 reply; 24+ messages in thread
From: Blaise Boscaccy @ 2025-10-03 18:14 UTC (permalink / raw)
To: KP Singh
Cc: Paul Moore, Linus Torvalds, ast, james.bottomley, bpf,
linux-security-module, kys, daniel, andrii, wufan, qmo
KP Singh <kpsingh@kernel.org> writes:
> On Thu, Oct 2, 2025 at 10:01 PM Blaise Boscaccy
> <bboscaccy@linux.microsoft.com> wrote:
>>
>> KP Singh <kpsingh@kernel.org> writes:
>>
>> > On Wed, Oct 1, 2025 at 11:37 PM Paul Moore <paul@paul-moore.com> wrote:
>> >>
>> >
>> > [...]
>> >
>>
>> [...]
>>
>> I am confident that Paul will address your remaining points. However, I
>> would like to clarify a few factual inaccuracies outlined below.
>>
>> >
>> > Blaise's implementation fails on any modern BPF programs since
>> > programs use more than one map, BTF information and kernel functions.
>> >
>>
>> If you read the patch series you'd see that it supports verification of
>> any number of maps. If you've identified an issue with map verification,
>> please share the details and I’ll address it.
>>
>
> I am sorry but this does not work, the UAPI here is
>
> + /* Pointer to a buffer containing the maps used in the signature
> + * hash chain of the BPF program.
> + */
> + __aligned_u64 signature_maps;
> + /* Size of the signature maps buffer. */
> + __u32 signature_maps_size;
>
> This needs to be generically applicable and it's not, What happens if
> the program is not a loader program / when the instruction buffer is
> stable?
>
The map array is fully configurable by the signer. Signing any or all
maps is optional. If the instruction buffer is stable, the signer can
generate the signature without maps and the caller passes zero in
those fields.
> If you really want the property that all of the content is signed and
> verified within the kernel,
That's what code signing is.
> please explore approaches to make the
> instruction buffer stable or feel free to deny any programs that do
> relocations at load time for whatever "strict" security policy that
> you want to implement.
>
> Please stop pursuing this extension as it adds cruft to the UAPI
> that's too specific, encodes the hash chain in the kernel and we won't
> need in the future.
>
If your primary complaint at this point is UAPI bloat, we'd be happy to
rework the configurable hash-chain patch to use the existing signature
buffer provided in your patchset.
>> [...]
>>
>> >> conventions around the placement of LSM hooks, this "halfway" approach
>> >> makes it difficult for LSMs to log anything about the signature status
>> >> of a BPF program being loaded, or use the signature status in any type
>> >> of access decision. This is important for a number of user groups
>> >> that use LSM based security policies as a way to help reason about the
>> >> security properties of a system, as KP's scheme would require the
>> >> users to analyze the signature verification code in every BPF light
>> >> skeleton they authorize as well as the LSM policy in order to reason
>> >> about the security mechanisms involved in BPF program loading.
>> >>
>> >> Blaise's signature scheme also has the nice property that BPF ELF
>> >> objects created using his scheme are backwards compatible with
>> >> existing released kernels that do not support any BPF signature
>> >> verification schemes, of course without any signature verification.
>> >> Loading a BPF ELF object using KP's signature scheme will likely fail
>> >> when loaded on existing released kernels.
>> >
>> > This does not make any sense. The ELF format and the way loaders like
>> > libbpf interpret it, has nothing to do with the kernel or UAPI.
>> >
>>
>> We signed a program with your upstream tools and it failed to load on a
>> vanilla kernel 6.16. The loader in your patchset is intepreting the
>> first few fields of struct bpf_map as a byte array containing a sha256
>> digest on older kernels.
>
> We can convert BPF_OBJ_GET_INFO_BY_FD to be called from loader
> programs to not rely on the struct field. and or libbbf can call
> BPF_OBJ_GET_INFO_BY_FD to check if map_get_hash is supported before it
> generates the hash check.
>
> You should not expect bpftool -S -k -i to work on older kernels but it
> should error out if the options are passed.
>
`bpftool gen` shouldn't have a priori knowledge of the target kernel
version.
-blaise
> - KP
>
>>
>> -blaise
>>
>>
>> > I had given detailed feedback to Blaise in
>> > https://lore.kernel.org/bpf/CACYkzJ6yNjFOTzC04uOuCmFn=+51_ie2tB9_x-u2xbcO=yobTw@mail.gmail.com/
>> > mentions also why we don't want any additional UAPI.
>> >
>> > You keep mentioning having visibility in the LSM code and I again
>> > ask, to implement what specific security policy and there is no clear
>> > answer? On a system where you would like to only allow signed BPF
>> > programs, you can purely deny any programs where the signature is not
>> > provided and this can be implemented today.
>> >
>> > Stable programs work as it is, programs that require runtime
>> > relocation work with loader programs. We don't want to add more UAPI
>> > as, in the future, it's quite possible that we can make the
>> > instruction buffer stable.
>> >
>> > - KP
>> >
>> >>
>> >> [1] https://lore.kernel.org/linux-security-module/CAADnVQ+C2KNR1ryRtBGOZTNk961pF+30FnU9n3dt3QjaQu_N6Q@mail.gmail.com/
>> >> [2] https://lore.kernel.org/linux-security-module/CAHC9VhRjKV4AbSgqb4J_-xhkWAp_VAcKDfLJ4GwhBNPOr+cvpg@mail.gmail.com/
>> >> [3] https://lore.kernel.org/linux-security-module/87sei58vy3.fsf@microsoft.com/
>> >> [4] https://lore.kernel.org/linux-security-module/20250909162345.569889-2-bboscaccy@linux.microsoft.com/
>> >> [5] https://lore.kernel.org/linux-security-module/20250926203111.1305999-1-bboscaccy@linux.microsoft.com/
>> >> [6] https://lore.kernel.org/linux-security-module/20250929213520.1821223-1-bboscaccy@linux.microsoft.com/
>> >>
>> >> --
>> >> paul-moore.com
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf-next v2 0/3] BPF signature hash chains
2025-10-03 18:14 ` Blaise Boscaccy
@ 2025-10-03 19:02 ` KP Singh
0 siblings, 0 replies; 24+ messages in thread
From: KP Singh @ 2025-10-03 19:02 UTC (permalink / raw)
To: Blaise Boscaccy
Cc: Paul Moore, Linus Torvalds, ast, james.bottomley, bpf,
linux-security-module, kys, daniel, andrii, wufan, qmo
On Fri, Oct 3, 2025 at 8:14 PM Blaise Boscaccy
<bboscaccy@linux.microsoft.com> wrote:
>
> KP Singh <kpsingh@kernel.org> writes:
>
> > On Thu, Oct 2, 2025 at 10:01 PM Blaise Boscaccy
> > <bboscaccy@linux.microsoft.com> wrote:
> >>
> >> KP Singh <kpsingh@kernel.org> writes:
[...]
> >
> > I am sorry but this does not work, the UAPI here is
> >
> > + /* Pointer to a buffer containing the maps used in the signature
> > + * hash chain of the BPF program.
> > + */
> > + __aligned_u64 signature_maps;
> > + /* Size of the signature maps buffer. */
> > + __u32 signature_maps_size;
> >
> > This needs to be generically applicable and it's not, What happens if
> > the program is not a loader program / when the instruction buffer is
> > stable?
> >
>
> The map array is fully configurable by the signer. Signing any or all
> maps is optional. If the instruction buffer is stable, the signer can
> generate the signature without maps and the caller passes zero in
> those fields.
>
> > If you really want the property that all of the content is signed and
> > verified within the kernel,
>
> That's what code signing is.
Sorry, this is wrong, allowing signed and trusted code to verify
subsequent executions is established in security.
Also you folks keep saying you want in-kernel verification, the loader
runs in the kernel, the same as any kernel code, so that requirement
is met. What you want is the logic to be hard coded in the kernel and
this goes against the BPF approach of flexibility.
>
> > please explore approaches to make the
> > instruction buffer stable or feel free to deny any programs that do
> > relocations at load time for whatever "strict" security policy that
> > you want to implement.
> >
> > Please stop pursuing this extension as it adds cruft to the UAPI
> > that's too specific, encodes the hash chain in the kernel and we won't
> > need in the future.
> >
>
> If your primary complaint at this point is UAPI bloat, we'd be happy to
> rework the configurable hash-chain patch to use the existing signature
> buffer provided in your patchset.
>
> >> [...]
> >>
> >> >> conventions around the placement of LSM hooks, this "halfway" approach
> >> >> makes it difficult for LSMs to log anything about the signature status
[...]
> >>
> >> We signed a program with your upstream tools and it failed to load on a
> >> vanilla kernel 6.16. The loader in your patchset is intepreting the
> >> first few fields of struct bpf_map as a byte array containing a sha256
> >> digest on older kernels.
> >
> > We can convert BPF_OBJ_GET_INFO_BY_FD to be called from loader
> > programs to not rely on the struct field. and or libbbf can call
> > BPF_OBJ_GET_INFO_BY_FD to check if map_get_hash is supported before it
> > generates the hash check.
> >
> > You should not expect bpftool -S -k -i to work on older kernels but it
> > should error out if the options are passed.
> >
>
> `bpftool gen` shouldn't have a priori knowledge of the target kernel
> version.
It can check whether the functionality is supported, it already does
it in many other places. I will follow-up with a fix for this.
- KP
>
> -blaise
>
>
> > - KP
> >
> >>
> >> -blaise
> >>
> >>
> >> > I had given detailed feedback to Blaise in
> >> > https://lore.kernel.org/bpf/CACYkzJ6yNjFOTzC04uOuCmFn=+51_ie2tB9_x-u2xbcO=yobTw@mail.gmail.com/
> >> > mentions also why we don't want any additional UAPI.
> >> >
> >> > You keep mentioning having visibility in the LSM code and I again
> >> > ask, to implement what specific security policy and there is no clear
> >> > answer? On a system where you would like to only allow signed BPF
> >> > programs, you can purely deny any programs where the signature is not
> >> > provided and this can be implemented today.
> >> >
> >> > Stable programs work as it is, programs that require runtime
> >> > relocation work with loader programs. We don't want to add more UAPI
> >> > as, in the future, it's quite possible that we can make the
> >> > instruction buffer stable.
> >> >
> >> > - KP
> >> >
> >> >>
[...]
> >> >> --
> >> >> paul-moore.com
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf-next v2 0/3] BPF signature hash chains
2025-10-03 16:24 ` KP Singh
@ 2025-10-06 3:08 ` Paul Moore
2025-10-07 13:53 ` KP Singh
0 siblings, 1 reply; 24+ messages in thread
From: Paul Moore @ 2025-10-06 3:08 UTC (permalink / raw)
To: KP Singh
Cc: Linus Torvalds, Blaise Boscaccy, ast, james.bottomley, bpf,
linux-security-module, kys, daniel, andrii, wufan, qmo
On Fri, Oct 3, 2025 at 12:25 PM KP Singh <kpsingh@kernel.org> wrote:
> On Fri, Oct 3, 2025 at 4:36 AM Paul Moore <paul@paul-moore.com> wrote:
> > On Thu, Oct 2, 2025 at 9:48 AM KP Singh <kpsingh@kernel.org> wrote:
> > > On Wed, Oct 1, 2025 at 11:37 PM Paul Moore <paul@paul-moore.com> wrote:
...
> > > > To make it clear at the start, Blaise's patchset does not change,
> > > > block, or otherwise prevent the BPF program signature scheme
> > > > implemented in KP's patchset. Blaise intentionally designed his
> > > > patches such that the two signature schemes can coexist together in
> > >
> > > We cannot have multiple signature schemes, this is not the experience
> > > we want for BPF users.
> >
> > In a perfect world there would be a singular BPF signature scheme
> > which would satisfy all the different use cases, but the sad reality
> > is that your signature scheme which Alexei sent to Linus during this
> > merge window falls short of that goal. Blaise's patch is an attempt
> > to provide a solution for the BPF use cases that are not sufficiently
> > addressed by your signature scheme.
>
> I am failing to understand your security requirements.
I'll be honest, given the months of discussion on this topic already,
I do worry that claiming a lack of understanding at this point is
simply a tactic to drag this discussion out or dismiss our arguments,
but if this is an honest admission let me try and better understand
the point where you are getting lost ...
* You've commented on Blaise's patch, so I'm assuming you have a
reasonable understanding of Blaise's patch, if not, please speak up.
* Similarly, are you comfortable in your understanding of the
differences between your BPF signature scheme and what Blaise has been
proposing in this patchset?
* Do you understand how Blaise's signature scheme verifies the
signature of both the loader BPF program and the original BPF program
before the security_bpf_prog_load() LSM hook?
* Do you understand how your signature scheme only verifies the loader
BPF program before the security_bpf_prog_load() LSM hook, meaning the
original BPF program has had no integrity or provenance verification
when security_bpf_prog_load() is called?
> > > You keep mentioning having visibility in the LSM code and I again
> > > ask, to implement what specific security policy and there is no clear
> > > answer?
> >
> > No one policy can satisfy the different security requirements of all
> > known users, simply look at all of the LSMs (including the BPF LSM)
> > which support different security policies as a real world example of
> > this. Even the presence of the LSM framework as an abstract layer is
> > an admission that no one policy, or model, solves all problems.
> > Instead, the goal is to ensure we have mechanisms in place which are
> > flexible enough to support a number of different policies and models.
>
> Please share concrete policies you would like to implement, this is very vague.
Please understand that this is the wrong question, for all the reasons
mentioned above. A better question would be to ask what primitives
are necessary to ensure that a LSM has the necessary visibility to
record the state of the BPF signature verification and make an access
control decision based on that state. Blaise's scheme verifies the
provenance and integrity of both the loader and original BPF program
prior to the LSM call, your scheme only verifies the loader before the
LSM call.
--
paul-moore.com
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf-next v2 0/3] BPF signature hash chains
2025-10-06 3:08 ` Paul Moore
@ 2025-10-07 13:53 ` KP Singh
2025-10-07 19:59 ` James Bottomley
2025-10-09 20:47 ` Paul Moore
0 siblings, 2 replies; 24+ messages in thread
From: KP Singh @ 2025-10-07 13:53 UTC (permalink / raw)
To: Paul Moore
Cc: Linus Torvalds, Blaise Boscaccy, ast, james.bottomley, bpf,
linux-security-module, kys, daniel, andrii, wufan, qmo
On Mon, Oct 6, 2025 at 5:08 AM Paul Moore <paul@paul-moore.com> wrote:
>
> On Fri, Oct 3, 2025 at 12:25 PM KP Singh <kpsingh@kernel.org> wrote:
> > On Fri, Oct 3, 2025 at 4:36 AM Paul Moore <paul@paul-moore.com> wrote:
> > > On Thu, Oct 2, 2025 at 9:48 AM KP Singh <kpsingh@kernel.org> wrote:
> > > > On Wed, Oct 1, 2025 at 11:37 PM Paul Moore <paul@paul-moore.com> wrote:
>
> ...
>
> > > > > To make it clear at the start, Blaise's patchset does not change,
> > > > > block, or otherwise prevent the BPF program signature scheme
> > > > > implemented in KP's patchset. Blaise intentionally designed his
> > > > > patches such that the two signature schemes can coexist together in
> > > >
> > > > We cannot have multiple signature schemes, this is not the experience
> > > > we want for BPF users.
> > >
> > > In a perfect world there would be a singular BPF signature scheme
> > > which would satisfy all the different use cases, but the sad reality
> > > is that your signature scheme which Alexei sent to Linus during this
> > > merge window falls short of that goal. Blaise's patch is an attempt
> > > to provide a solution for the BPF use cases that are not sufficiently
> > > addressed by your signature scheme.
> >
> > I am failing to understand your security requirements.
>
> I'll be honest, given the months of discussion on this topic already,
> I do worry that claiming a lack of understanding at this point is
> simply a tactic to drag this discussion out or dismiss our arguments,
> but if this is an honest admission let me try and better understand
> the point where you are getting lost ...
No, there is no clear security policy that you have proposed that you
want to implement and this prevents you from implementing the policy.
>
> * You've commented on Blaise's patch, so I'm assuming you have a
> reasonable understanding of Blaise's patch, if not, please speak up.
>
> * Similarly, are you comfortable in your understanding of the
> differences between your BPF signature scheme and what Blaise has been
> proposing in this patchset?
>
> * Do you understand how Blaise's signature scheme verifies the
> signature of both the loader BPF program and the original BPF program
> before the security_bpf_prog_load() LSM hook?
>
> * Do you understand how your signature scheme only verifies the loader
> BPF program before the security_bpf_prog_load() LSM hook, meaning the
> original BPF program has had no integrity or provenance verification
> when security_bpf_prog_load() is called?
Yeah, this loader is signed to load only specific trusted payload. You
are wrong about it not having integrity. The integrity checking
happens in the loader that the very entity that signed the payload of
the loader which contains:
* The hash of the loaded programs and metadata.
* An integrity check that verifies this hash before loading the programs.
I feel we will keep going in circles on this and I will leave it up to
the maintainers to resolve this.
>
> > > > You keep mentioning having visibility in the LSM code and I again
> > > > ask, to implement what specific security policy and there is no clear
> > > > answer?
> > >
> > > No one policy can satisfy the different security requirements of all
> > > known users, simply look at all of the LSMs (including the BPF LSM)
> > > which support different security policies as a real world example of
> > > this. Even the presence of the LSM framework as an abstract layer is
> > > an admission that no one policy, or model, solves all problems.
> > > Instead, the goal is to ensure we have mechanisms in place which are
> > > flexible enough to support a number of different policies and models.
> >
> > Please share concrete policies you would like to implement, this is very vague.
>
> Please understand that this is the wrong question, for all the reasons
> mentioned above. A better question would be to ask what primitives
> are necessary to ensure that a LSM has the necessary visibility to
> record the state of the BPF signature verification and make an access
> control decision based on that state. Blaise's scheme verifies the
> provenance and integrity of both the loader and original BPF program
> prior to the LSM call, your scheme only verifies the loader before the
> LSM call.
>
> --
> paul-moore.com
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf-next v2 0/3] BPF signature hash chains
2025-10-07 13:53 ` KP Singh
@ 2025-10-07 19:59 ` James Bottomley
2025-10-09 20:47 ` Paul Moore
1 sibling, 0 replies; 24+ messages in thread
From: James Bottomley @ 2025-10-07 19:59 UTC (permalink / raw)
To: KP Singh, Paul Moore
Cc: Linus Torvalds, Blaise Boscaccy, ast, bpf, linux-security-module,
kys, daniel, andrii, wufan, qmo
On Tue, 2025-10-07 at 15:53 +0200, KP Singh wrote:
> On Mon, Oct 6, 2025 at 5:08 AM Paul Moore <paul@paul-moore.com>
> wrote:
[...]
> > * Do you understand how your signature scheme only verifies the
> > loader BPF program before the security_bpf_prog_load() LSM hook,
> > meaning the original BPF program has had no integrity or provenance
> > verification when security_bpf_prog_load() is called?
>
> Yeah, this loader is signed to load only specific trusted payload.
> You are wrong about it not having integrity. The integrity checking
> happens in the loader that the very entity that signed the payload of
> the loader which contains:
>
> * The hash of the loaded programs and metadata.
> * An integrity check that verifies this hash before loading the
> programs.
>
I think this point is understood generally. However, the rub for LSM
is that the verification of the program map by the loader happens
*after* the security_bpf_prog_load() hook has been called. So there's
no way for the hook to a) know if the program will actually verify
because that final check occurs after it was called or b) leave an
audit trail of a program map verification failure which could be caused
by an attempt to tamper with the program and should be logged through
the security audit channels.
> I feel we will keep going in circles on this and I will leave it up
> to the maintainers to resolve this.
I think this is because what LSM is looking for isn't just signing,
it's full determination that all the integrity conditions it is
imposing are satisfied by the time the hook is called. From the flow I
describe above this isn't happening.
Regards,
James
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf-next v2 0/3] BPF signature hash chains
2025-10-07 13:53 ` KP Singh
2025-10-07 19:59 ` James Bottomley
@ 2025-10-09 20:47 ` Paul Moore
2025-10-10 1:00 ` Alexei Starovoitov
1 sibling, 1 reply; 24+ messages in thread
From: Paul Moore @ 2025-10-09 20:47 UTC (permalink / raw)
To: ast, KP Singh, Linus Torvalds
Cc: Blaise Boscaccy, james.bottomley, bpf, linux-security-module, kys,
daniel, andrii, wufan, qmo
On Tue, Oct 7, 2025 at 9:53 AM KP Singh <kpsingh@kernel.org> wrote:
> On Mon, Oct 6, 2025 at 5:08 AM Paul Moore <paul@paul-moore.com> wrote:
> > On Fri, Oct 3, 2025 at 12:25 PM KP Singh <kpsingh@kernel.org> wrote:
> > > On Fri, Oct 3, 2025 at 4:36 AM Paul Moore <paul@paul-moore.com> wrote:
> > > > On Thu, Oct 2, 2025 at 9:48 AM KP Singh <kpsingh@kernel.org> wrote:
> > > > > On Wed, Oct 1, 2025 at 11:37 PM Paul Moore <paul@paul-moore.com> wrote:
...
> I feel we will keep going in circles on this and I will leave it up to
> the maintainers to resolve this.
Yes, I think we can all agree that the discussion has reached a point
where both sides are simply repeating ourselves.
I believe we've outlined why the code merged into Linus' tree during
this merge window does not meet the BPF signature verification
requirements of a number of different user groups, with Blaise
proposing an addition to KP's code to satisfy those needs. Further, I
believe that either Blaise, James, or I have responded to all of KP's
concerns regarding Blaise's patchset, and while KP may not be happy
with those answers, no one has yet to offer an alternative solution to
Blaise's patchset.
With that in mind, I agree with KP that it's time for "the maintainers
to resolve this". Alexei, will you be merging Blaise's patchset and
sending it up to Linus?
--
paul-moore.com
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf-next v2 0/3] BPF signature hash chains
2025-10-09 20:47 ` Paul Moore
@ 2025-10-10 1:00 ` Alexei Starovoitov
2025-10-10 15:53 ` James Bottomley
0 siblings, 1 reply; 24+ messages in thread
From: Alexei Starovoitov @ 2025-10-10 1:00 UTC (permalink / raw)
To: Paul Moore
Cc: Alexei Starovoitov, KP Singh, Linus Torvalds, Blaise Boscaccy,
James Bottomley, bpf, LSM List, K. Y. Srinivasan, Daniel Borkmann,
Andrii Nakryiko, wufan, Quentin Monnet
On Thu, Oct 9, 2025 at 1:47 PM Paul Moore <paul@paul-moore.com> wrote:
>
> On Tue, Oct 7, 2025 at 9:53 AM KP Singh <kpsingh@kernel.org> wrote:
> > On Mon, Oct 6, 2025 at 5:08 AM Paul Moore <paul@paul-moore.com> wrote:
> > > On Fri, Oct 3, 2025 at 12:25 PM KP Singh <kpsingh@kernel.org> wrote:
> > > > On Fri, Oct 3, 2025 at 4:36 AM Paul Moore <paul@paul-moore.com> wrote:
> > > > > On Thu, Oct 2, 2025 at 9:48 AM KP Singh <kpsingh@kernel.org> wrote:
> > > > > > On Wed, Oct 1, 2025 at 11:37 PM Paul Moore <paul@paul-moore.com> wrote:
>
> ...
>
> > I feel we will keep going in circles on this and I will leave it up to
> > the maintainers to resolve this.
>
> Yes, I think we can all agree that the discussion has reached a point
> where both sides are simply repeating ourselves.
>
> I believe we've outlined why the code merged into Linus' tree during
> this merge window does not meet the BPF signature verification
> requirements of a number of different user groups, with Blaise
> proposing an addition to KP's code to satisfy those needs. Further, I
> believe that either Blaise, James, or I have responded to all of KP's
> concerns regarding Blaise's patchset, and while KP may not be happy
> with those answers, no one has yet to offer an alternative solution to
> Blaise's patchset.
>
> With that in mind, I agree with KP that it's time for "the maintainers
> to resolve this". Alexei, will you be merging Blaise's patchset and
> sending it up to Linus?
Nope. Both you and James did not understand what Blaise
patch set is actually doing, and that followed the whole set of
arguments and reasons that made no sense.
James's concern is valid though:
> However, the rub for LSM
> is that the verification of the program map by the loader happens
> *after* the security_bpf_prog_load() hook has been called.
I understand the discomfort, but that's what the kernel module loading
process is doing as well, so you should be concerned with both.
Since both are doing pretty much the same work.
Both allocate and populate kernel memory with data.
For kernel module it's bss, data, rodata.
For bpf it's BTF, maps.
Then the kernel applies relocations to .text against .data and against
the kernel.
bpf is doing the same. It applies relocation against maps, btf, kfuncs.
The only difference here is that ko loading is done by
kernel/module/main.c which is pretty complex on its own,
since it's parsing ELF, symbols, etc
While bpf loader is doing a fraction of that.
It doesn't need to parse ELF. It's a dumb sequence of commands:
load mapA, load mapB, apply relocation at off N to prog M.
If bpf loader has a bug it will still be caught by the verifier,
since it effectively runs multiple times. Once for loader prog,
and then for each prog that loader wants to load.
For kernel modules and for bpf we trust the build system to be correct.
gcc, clang, linker, objtool, pahole, various scripts/* need to do the
right thing for the kernel modules.
In bpf case it's only libbpf that is trusted to produce
valid loader bpf program for a set of bpf programs and maps.
I share the discomfort that tools/lib/bpf/gen_loader.c
is doing something that you don't understand,
but, really, do you understand what gcc, clang, objtool are doing?
You have to trust the build process otherwise it's all pointless.
Malicious "gcc" can inject special code into a signed kernel module.
Malicious "libbpf" can inject something into "loader prog",
but again the verifier is still there even if "loader prog" is busted.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf-next v2 0/3] BPF signature hash chains
2025-10-10 1:00 ` Alexei Starovoitov
@ 2025-10-10 15:53 ` James Bottomley
2025-10-10 19:39 ` Paul Moore
2025-10-10 23:06 ` Alexei Starovoitov
0 siblings, 2 replies; 24+ messages in thread
From: James Bottomley @ 2025-10-10 15:53 UTC (permalink / raw)
To: Alexei Starovoitov, Paul Moore
Cc: Alexei Starovoitov, KP Singh, Linus Torvalds, Blaise Boscaccy,
bpf, LSM List, K. Y. Srinivasan, Daniel Borkmann, Andrii Nakryiko,
wufan, Quentin Monnet
On Thu, 2025-10-09 at 18:00 -0700, Alexei Starovoitov wrote:
[...]
> James's concern is valid though:
>
> > However, the rub for LSM is that the verification of the program
> > map by the loader happens *after* the security_bpf_prog_load() hook
> > has been called.
>
> I understand the discomfort, but that's what the kernel module
> loading process is doing as well, so you should be concerned with
> both. Since both are doing pretty much the same work.
OK, so let me push on this one point because I don't agree with what
you say here. The way kernel modules and eBPF load is not equivalent.
The kernel module signatures go over a relocateable elf binary which is
subsequently relocated after signature verification in the kernel by
the ELF loader. You can regard the ELF loader as being equivalent to
the eBPF loader in terms of function, absolutely. However for security
purposes the ELF loader is a trusted part of the kernel security
envelope and its integrity is part of the kernel integrity and we have
a this single trusted loader for every module. In security terms
verification of the ELF object signature is sufficient to guarantee
integrity of the module because the integrity of the ELF loader is
already checked.
The eBPF loader, by contrast, because it contains all the relocations,
is different for every eBPF light skeleton. This means it's not a
trusted part of the kernel and has to be integrity checked as well.
Thus for eBPF, the integrity check must be over both the loader and the
program; integrity checking is not complete until the integrity of both
has been verified. If you sign only the loader and embed the hash of
the program into the loader that is a different way of doing things,
but the integrity check is not complete until the loader does the hash
verification which, as has been stated many times before, is *after*
the load LSM hook has run.
There are two potential solutions to this: complete the integrity check
before running the load hook (Blaise's patch) or add a LSM hook to
collect the integrity information from the run of the loader. Neither
of these is present in the scheme you put upstream.
Regards,
James
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf-next v2 0/3] BPF signature hash chains
2025-10-10 15:53 ` James Bottomley
@ 2025-10-10 19:39 ` Paul Moore
2025-10-10 23:06 ` Alexei Starovoitov
1 sibling, 0 replies; 24+ messages in thread
From: Paul Moore @ 2025-10-10 19:39 UTC (permalink / raw)
To: James Bottomley
Cc: Alexei Starovoitov, Alexei Starovoitov, KP Singh, Linus Torvalds,
Blaise Boscaccy, bpf, LSM List, K. Y. Srinivasan, Daniel Borkmann,
Andrii Nakryiko, wufan, Quentin Monnet
On Fri, Oct 10, 2025 at 11:53 AM James Bottomley
<James.Bottomley@hansenpartnership.com> wrote:
> On Thu, 2025-10-09 at 18:00 -0700, Alexei Starovoitov wrote:
> [...]
> > James's concern is valid though:
> >
> > > However, the rub for LSM is that the verification of the program
> > > map by the loader happens *after* the security_bpf_prog_load() hook
> > > has been called.
> >
> > I understand the discomfort, but that's what the kernel module
> > loading process is doing as well, so you should be concerned with
> > both. Since both are doing pretty much the same work.
>
> OK, so let me push on this one point because I don't agree with what
> you say here. The way kernel modules and eBPF load is not equivalent.
> The kernel module signatures go over a relocateable elf binary which is
> subsequently relocated after signature verification in the kernel by
> the ELF loader. You can regard the ELF loader as being equivalent to
> the eBPF loader in terms of function, absolutely. However for security
> purposes the ELF loader is a trusted part of the kernel security
> envelope and its integrity is part of the kernel integrity and we have
> a this single trusted loader for every module. In security terms
> verification of the ELF object signature is sufficient to guarantee
> integrity of the module because the integrity of the ELF loader is
> already checked.
>
> The eBPF loader, by contrast, because it contains all the relocations,
> is different for every eBPF light skeleton. This means it's not a
> trusted part of the kernel and has to be integrity checked as well.
> Thus for eBPF, the integrity check must be over both the loader and the
> program; integrity checking is not complete until the integrity of both
> has been verified. If you sign only the loader and embed the hash of
> the program into the loader that is a different way of doing things,
> but the integrity check is not complete until the loader does the hash
> verification which, as has been stated many times before, is *after*
> the load LSM hook has run.
>
> There are two potential solutions to this: complete the integrity check
> before running the load hook (Blaise's patch) or add a LSM hook to
> collect the integrity information from the run of the loader. Neither
> of these is present in the scheme you put upstream.
As a bit of background for those who weren't following the related
threads earlier this year, the idea of an additional hook was
discussed this spring and it was rejected by Alexei.
https://lore.kernel.org/linux-security-module/CAADnVQ+wE5cGhy6tgmWgUwkNutueEsrhh6UR8N2fzrZjt-vb4g@mail.gmail.com/
--
paul-moore.com
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf-next v2 0/3] BPF signature hash chains
2025-10-10 15:53 ` James Bottomley
2025-10-10 19:39 ` Paul Moore
@ 2025-10-10 23:06 ` Alexei Starovoitov
2025-10-11 14:52 ` James Bottomley
1 sibling, 1 reply; 24+ messages in thread
From: Alexei Starovoitov @ 2025-10-10 23:06 UTC (permalink / raw)
To: James Bottomley
Cc: Paul Moore, Alexei Starovoitov, KP Singh, Linus Torvalds,
Blaise Boscaccy, bpf, LSM List, K. Y. Srinivasan, Daniel Borkmann,
Andrii Nakryiko, wufan, Quentin Monnet
On Fri, Oct 10, 2025 at 8:53 AM James Bottomley
<James.Bottomley@hansenpartnership.com> wrote:
>
> On Thu, 2025-10-09 at 18:00 -0700, Alexei Starovoitov wrote:
> [...]
> > James's concern is valid though:
> >
> > > However, the rub for LSM is that the verification of the program
> > > map by the loader happens *after* the security_bpf_prog_load() hook
> > > has been called.
> >
> > I understand the discomfort, but that's what the kernel module
> > loading process is doing as well, so you should be concerned with
> > both. Since both are doing pretty much the same work.
>
> OK, so let me push on this one point because I don't agree with what
> you say here. The way kernel modules and eBPF load is not equivalent.
> The kernel module signatures go over a relocateable elf binary which is
> subsequently relocated after signature verification in the kernel by
> the ELF loader. You can regard the ELF loader as being equivalent to
> the eBPF loader in terms of function, absolutely. However for security
> purposes the ELF loader is a trusted part of the kernel security
> envelope and its integrity is part of the kernel integrity and we have
> a this single trusted loader for every module. In security terms
> verification of the ELF object signature is sufficient to guarantee
> integrity of the module because the integrity of the ELF loader is
> already checked.
"integrity of ELF loader" is _not_ checked. It's part of the kernel
and you trust that the kernel is valid, because you trust the
build tools that compiled that kernel.
The kmod signature only covers the contents of the kmod.
Now, kmods are typically targeted one specific kernel version
compiled with a specific config, but some folks do load the same
kmod on different kernels. So by checking integrity of kmod only
you're skipping on the loader. If symbols are not versioned
and crc checked bad things can happen (obviously no one should
be doing that), but signature doesn't protect against that.
Compare that with the bpf signature. The whole package is signed.
The loader and what it is loading with one signature.
I argue that this is a more secure approach than kmod signatures.
Think of it as a self-extracting zip archive.
The whole .zip is covered by one signature. Inside it has the code
to self extract plus all the files inside.
The extracting code is a loader prog. Which is a normal bpf
prog that is subject to the same verification rules.
The files are other bpf progs that are also subject to the verification.
> The eBPF loader, by contrast, because it contains all the relocations,
> is different for every eBPF light skeleton. This means it's not a
> trusted part of the kernel and has to be integrity checked as well.
...and the existing mechanism already does that.
> Thus for eBPF, the integrity check must be over both the loader and the
> program; integrity checking is not complete until the integrity of both
> has been verified.
The signature covers all components: loader, the map that assists
the loading and all progs and maps that are encoded inside that
loader/map tuple.
> If you sign only the loader and embed the hash of
> the program into the loader that is a different way of doing things,
That's simply not true.
Please read the current code more carefully. There is cover letter
that describes what's happening. There are no hashes of programs.
> There are two potential solutions to this: complete the integrity check
> before running the load hook (Blaise's patch)
That's not what it's doing! Read his patch. It's adding pointless
signature to the loader/map tuple. It does nothing to progs, maps,
relocations that will be created at the end when loader completes.
You need to realize that single loader plus single map is
an implementation choice of tools/lib/bpf/gen_loader.c.
It can do the same job with a single prog and no additional map.
Hence any kinda hard coded extra map signature makes no sense.
We're not going to burden the kernel with one specific implementation
detail of gen_loader.
Tomorrow we might change the gen_loader to use a triple:
prog+map+btf or any other form.
The existing approach allows all that extensibility and freedom
to change the gen_loader.
> or add a LSM hook to
> collect the integrity information from the run of the loader. Neither
> of these is present in the scheme you put upstream.
Neither is in cards as was explained countless times.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf-next v2 0/3] BPF signature hash chains
2025-10-10 23:06 ` Alexei Starovoitov
@ 2025-10-11 14:52 ` James Bottomley
2025-10-11 16:31 ` Alexei Starovoitov
0 siblings, 1 reply; 24+ messages in thread
From: James Bottomley @ 2025-10-11 14:52 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: Paul Moore, Alexei Starovoitov, KP Singh, Linus Torvalds,
Blaise Boscaccy, bpf, LSM List, K. Y. Srinivasan, Daniel Borkmann,
Andrii Nakryiko, wufan, Quentin Monnet
On Fri, 2025-10-10 at 16:06 -0700, Alexei Starovoitov wrote:
> On Fri, Oct 10, 2025 at 8:53 AM James Bottomley
> <James.Bottomley@hansenpartnership.com> wrote:
> >
> > On Thu, 2025-10-09 at 18:00 -0700, Alexei Starovoitov wrote:
> > [...]
> > > James's concern is valid though:
> > >
> > > > However, the rub for LSM is that the verification of the
> > > > program map by the loader happens *after* the
> > > > security_bpf_prog_load() hook has been called.
> > >
> > > I understand the discomfort, but that's what the kernel module
> > > loading process is doing as well, so you should be concerned with
> > > both. Since both are doing pretty much the same work.
> >
> > OK, so let me push on this one point because I don't agree with
> > what you say here. The way kernel modules and eBPF load is not
> > equivalent. The kernel module signatures go over a relocateable elf
> > binary which is subsequently relocated after signature verification
> > in the kernel by the ELF loader. You can regard the ELF loader as
> > being equivalent to the eBPF loader in terms of function,
> > absolutely. However for security purposes the ELF loader is a
> > trusted part of the kernel security envelope and its integrity is
> > part of the kernel integrity and we have a this single trusted
> > loader for every module. In security terms verification of the ELF
> > object signature is sufficient to guarantee integrity of the module
> > because the integrity of the ELF loader is already checked.
>
> "integrity of ELF loader" is _not_ checked. It's part of the kernel
> and you trust that the kernel is valid, because you trust the
> build tools that compiled that kernel.
No, I trust my kernel is valid because the bootloader checks its
signature on every boot (in case some tampering occurs after build).
There are a variety of integrity mechanisms for the kernel itself, but
they all essentially run a check on boot meaning the ELF loader *is*
integrity checked.
[...]
> > Thus for eBPF, the integrity check must be over both the loader and
> > the program; integrity checking is not complete until the integrity
> > of both has been verified.
>
> The signature covers all components: loader, the map that assists
> the loading and all progs and maps that are encoded inside that
> loader/map tuple.
The pkcs7 signature that is verified hashes over the loader only.
Other mechanisms cover the rest.
> > If you sign only the loader and embed the hash of the program into
> > the loader that is a different way of doing things,
>
> That's simply not true. Please read the current code more carefully.
> There is cover letter that describes what's happening. There are no
> hashes of programs.
Is this a semantic quibble over the meaning of the word "sign"? Fine,
I'll be more precise. Quoting from:
https://lore.kernel.org/bpf/20250921160120.9711-2-kpsingh@kernel.org/
> + bpf_dynptr_init(&insns_ptr, prog->insnsi,
> BPF_DYNPTR_TYPE_LOCAL, 0,
> + prog->len * sizeof(struct bpf_insn));
> +
> + err = bpf_verify_pkcs7_signature((struct bpf_dynptr
> *)&insns_ptr,
> + (struct bpf_dynptr
> *)&sig_ptr, key);
for a light skeleton prog->insnsi points to the loader and the second
statement is verifying the pkcs7 signature of the loader only.
> > There are two potential solutions to this: complete the integrity
> > check before running the load hook (Blaise's patch)
>
> That's not what it's doing! Read his patch. It's adding pointless
> signature to the loader/map tuple. It does nothing to progs, maps,
> relocations that will be created at the end when loader completes.
It doesn't need to, once we check both the loader and the map, the
integrity is verified and the loader can be trusted to run and relocate
the map into the bpf program (since you like the module parallel: we
have the integrity verification of the module object and the ELF
loader, so we can just let the relocation run: the output has integrity
because all inputs did).
> You need to realize that single loader plus single map is
> an implementation choice of tools/lib/bpf/gen_loader.c.
> It can do the same job with a single prog and no additional map.
Yes, and if the light skeleton scheme embedded the relocation and the
program itself into prog->insnsi then we wouldn't need the additional
map verification before the load hook because the pkcs7 signature check
would fully verify the integrity.
> Hence any kinda hard coded extra map signature makes no sense.
> We're not going to burden the kernel with one specific implementation
> detail of gen_loader.
> Tomorrow we might change the gen_loader to use a triple:
> prog+map+btf or any other form.
> The existing approach allows all that extensibility and freedom
> to change the gen_loader.
If we're whatiffing about the future: in the event that you need a
separate btf I assume it will come down as a map; bpftool gen -S -M
would compute a signature over the loader and both maps and the in-
kernel piece of Blaise's patch would just work.
Regards,
James
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf-next v2 0/3] BPF signature hash chains
2025-10-11 14:52 ` James Bottomley
@ 2025-10-11 16:31 ` Alexei Starovoitov
2025-10-11 17:09 ` James Bottomley
0 siblings, 1 reply; 24+ messages in thread
From: Alexei Starovoitov @ 2025-10-11 16:31 UTC (permalink / raw)
To: James Bottomley
Cc: Paul Moore, Alexei Starovoitov, KP Singh, Linus Torvalds,
Blaise Boscaccy, bpf, LSM List, K. Y. Srinivasan, Daniel Borkmann,
Andrii Nakryiko, wufan, Quentin Monnet
On Sat, Oct 11, 2025 at 7:52 AM James Bottomley
<James.Bottomley@hansenpartnership.com> wrote:
>
> It doesn't need to, once we check both the loader and the map, the
> integrity is verified and the loader can be trusted to run and relocate
> the map into the bpf program
You should read KP's cover letter again and then research trusted
hash chains. Here is a quote from the first googled link:
"A trusted hash chain is a cryptographic process used to verify the
integrity and authenticity of data by creating a sequence of hash
values, where each hash is linked to the next".
In addition KP's algorithm was vetted by various security teams.
There is nothing novel here. It's a classic algorithm used
to verify integrity and that's what was implemented.
> > You need to realize that single loader plus single map is
> > an implementation choice of tools/lib/bpf/gen_loader.c.
> > It can do the same job with a single prog and no additional map.
>
> Yes, and if the light skeleton scheme embedded the relocation and the
> program itself into prog->insnsi then we wouldn't need the additional
> map verification before the load hook because the pkcs7 signature check
> would fully verify the integrity.
I'm fine if you want to hack gen_loader.c to produce the loader prog
without a map, but we're not going to pollute the kernel with
pointless apis, because you don't understand hash chains.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf-next v2 0/3] BPF signature hash chains
2025-10-11 16:31 ` Alexei Starovoitov
@ 2025-10-11 17:09 ` James Bottomley
2025-10-13 2:12 ` Paul Moore
0 siblings, 1 reply; 24+ messages in thread
From: James Bottomley @ 2025-10-11 17:09 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: Paul Moore, Alexei Starovoitov, KP Singh, Linus Torvalds,
Blaise Boscaccy, bpf, LSM List, K. Y. Srinivasan, Daniel Borkmann,
Andrii Nakryiko, wufan, Quentin Monnet
On Sat, 2025-10-11 at 09:31 -0700, Alexei Starovoitov wrote:
> On Sat, Oct 11, 2025 at 7:52 AM James Bottomley
> <James.Bottomley@hansenpartnership.com> wrote:
> >
> > It doesn't need to, once we check both the loader and the map, the
> > integrity is verified and the loader can be trusted to run and
> > relocate the map into the bpf program
>
> You should read KP's cover letter again and then research trusted
> hash chains. Here is a quote from the first googled link:
>
> "A trusted hash chain is a cryptographic process used to verify the
> integrity and authenticity of data by creating a sequence of hash
> values, where each hash is linked to the next".
>
> In addition KP's algorithm was vetted by various security teams.
> There is nothing novel here. It's a classic algorithm used
> to verify integrity and that's what was implemented.
Both KP and Blaise's patch sets are implementations of trusted hash
chains. The security argument isn't about whether the hash chain
algorithm works, it's about where, in relation to the LSM hook, the
hash chain verification completes.
Regards,
James
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH bpf-next v2 0/3] BPF signature hash chains
2025-10-11 17:09 ` James Bottomley
@ 2025-10-13 2:12 ` Paul Moore
0 siblings, 0 replies; 24+ messages in thread
From: Paul Moore @ 2025-10-13 2:12 UTC (permalink / raw)
To: Alexei Starovoitov, KP Singh, James Bottomley, Linus Torvalds
Cc: Alexei Starovoitov, Blaise Boscaccy, bpf, LSM List,
K. Y. Srinivasan, Daniel Borkmann, Andrii Nakryiko, wufan,
Quentin Monnet
On Sat, Oct 11, 2025 at 1:09 PM James Bottomley
<James.Bottomley@hansenpartnership.com> wrote:
> On Sat, 2025-10-11 at 09:31 -0700, Alexei Starovoitov wrote:
> > On Sat, Oct 11, 2025 at 7:52 AM James Bottomley
> > <James.Bottomley@hansenpartnership.com> wrote:
> > >
> > > It doesn't need to, once we check both the loader and the map, the
> > > integrity is verified and the loader can be trusted to run and
> > > relocate the map into the bpf program
> >
> > You should read KP's cover letter again and then research trusted
> > hash chains. Here is a quote from the first googled link:
> >
> > "A trusted hash chain is a cryptographic process used to verify the
> > integrity and authenticity of data by creating a sequence of hash
> > values, where each hash is linked to the next".
> >
> > In addition KP's algorithm was vetted by various security teams.
> > There is nothing novel here. It's a classic algorithm used
> > to verify integrity and that's what was implemented.
>
> Both KP and Blaise's patch sets are implementations of trusted hash
> chains. The security argument isn't about whether the hash chain
> algorithm works, it's about where, in relation to the LSM hook, the
> hash chain verification completes.
Alexei, considering the discussion from the past few days, and the
responses to all of your objections, I'm not seeing a clear reason why
you are opposed to sending Blaise's patchset up to Linus. What is
preventing you from sending Blaise's patch up to Linus?
--
paul-moore.com
^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2025-10-13 2:12 UTC | newest]
Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-29 21:34 [PATCH bpf-next v2 0/3] BPF signature hash chains Blaise Boscaccy
2025-09-29 21:34 ` [PATCH bpf-next v2 1/3] bpf: Add hash chain signature support for arbitrary maps Blaise Boscaccy
2025-09-29 21:34 ` [PATCH bpf-next v2 2/3] selftests/bpf: Enable map verification for some lskel tests Blaise Boscaccy
2025-09-29 21:34 ` [PATCH bpf-next v2 3/3] bpftool: Add support for signing program and map hash chains Blaise Boscaccy
2025-10-01 21:37 ` [PATCH bpf-next v2 0/3] BPF signature " Paul Moore
2025-10-02 13:48 ` KP Singh
2025-10-02 20:01 ` Blaise Boscaccy
2025-10-03 16:59 ` KP Singh
2025-10-03 18:14 ` Blaise Boscaccy
2025-10-03 19:02 ` KP Singh
2025-10-03 2:35 ` Paul Moore
2025-10-03 16:24 ` KP Singh
2025-10-06 3:08 ` Paul Moore
2025-10-07 13:53 ` KP Singh
2025-10-07 19:59 ` James Bottomley
2025-10-09 20:47 ` Paul Moore
2025-10-10 1:00 ` Alexei Starovoitov
2025-10-10 15:53 ` James Bottomley
2025-10-10 19:39 ` Paul Moore
2025-10-10 23:06 ` Alexei Starovoitov
2025-10-11 14:52 ` James Bottomley
2025-10-11 16:31 ` Alexei Starovoitov
2025-10-11 17:09 ` James Bottomley
2025-10-13 2:12 ` Paul Moore
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).