* [PATCH v2 09/10] hornet: Add a light skeleton data extractor scripts
From: Blaise Boscaccy @ 2026-02-27 23:38 UTC (permalink / raw)
To: Blaise Boscaccy, Jonathan Corbet, Paul Moore, James Morris,
Serge E. Hallyn, Mickaël Salaün, Günther Noack,
Dr. David Alan Gilbert, Andrew Morton, James.Bottomley, dhowells,
Fan Wu, Ryan Foster, linux-security-module, linux-doc,
linux-kernel, bpf
In-Reply-To: <20260227233930.2418522-1-bboscaccy@linux.microsoft.com>
These script eases light skeleton development against Hornet by
generating a data payloads which can be used for signing a light
skeleton binary using gen_sig.
Signed-off-by: Blaise Boscaccy <bboscaccy@linux.microsoft.com>
---
| 27 +++++++++++++++++++++++++++
| 27 +++++++++++++++++++++++++++
| 27 +++++++++++++++++++++++++++
3 files changed, 81 insertions(+)
create mode 100755 scripts/hornet/extract-insn.sh
create mode 100755 scripts/hornet/extract-map.sh
create mode 100755 scripts/hornet/extract-skel.sh
--git a/scripts/hornet/extract-insn.sh b/scripts/hornet/extract-insn.sh
new file mode 100755
index 000000000000..52338f057ff6
--- /dev/null
+++ b/scripts/hornet/extract-insn.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (c) 2025 Microsoft Corporation
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of version 2 of the GNU General Public
+# License as published by the Free Software Foundation.
+
+function usage() {
+ echo "Sample script for extracting instructions"
+ echo "autogenerated eBPF lskel headers"
+ echo ""
+ echo "USAGE: header_file"
+ exit
+}
+
+ARGC=$#
+
+EXPECTED_ARGS=1
+
+if [ $ARGC -ne $EXPECTED_ARGS ] ; then
+ usage
+else
+ printf $(gcc -E $1 | grep "opts_insn" | \
+ awk -F"=" '{print $2}' | sed 's/;\+$//' | sed 's/\"//g')
+fi
--git a/scripts/hornet/extract-map.sh b/scripts/hornet/extract-map.sh
new file mode 100755
index 000000000000..c309f505c623
--- /dev/null
+++ b/scripts/hornet/extract-map.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (c) 2025 Microsoft Corporation
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of version 2 of the GNU General Public
+# License as published by the Free Software Foundation.
+
+function usage() {
+ echo "Sample script for extracting instructions"
+ echo "autogenerated eBPF lskel headers"
+ echo ""
+ echo "USAGE: header_file"
+ exit
+}
+
+ARGC=$#
+
+EXPECTED_ARGS=1
+
+if [ $ARGC -ne $EXPECTED_ARGS ] ; then
+ usage
+else
+ printf $(gcc -E $1 | grep "opts_data" | \
+ awk -F"=" '{print $2}' | sed 's/;\+$//' | sed 's/\"//g')
+fi
--git a/scripts/hornet/extract-skel.sh b/scripts/hornet/extract-skel.sh
new file mode 100755
index 000000000000..6550a86b8991
--- /dev/null
+++ b/scripts/hornet/extract-skel.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (c) 2025 Microsoft Corporation
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of version 2 of the GNU General Public
+# License as published by the Free Software Foundation.
+
+function usage() {
+ echo "Sample script for extracting instructions and map data out of"
+ echo "autogenerated eBPF lskel headers"
+ echo ""
+ echo "USAGE: header_file field"
+ exit
+}
+
+ARGC=$#
+
+EXPECTED_ARGS=2
+
+if [ $ARGC -ne $EXPECTED_ARGS ] ; then
+ usage
+else
+ printf $(gcc -E $1 | grep "static const char opts_$2" | \
+ awk -F"=" '{print $2}' | sed 's/;\+$//' | sed 's/\"//g')
+fi
--
2.52.0
^ permalink raw reply related
* [PATCH v2 08/10] hornet: Introduce gen_sig
From: Blaise Boscaccy @ 2026-02-27 23:38 UTC (permalink / raw)
To: Blaise Boscaccy, Jonathan Corbet, Paul Moore, James Morris,
Serge E. Hallyn, Mickaël Salaün, Günther Noack,
Dr. David Alan Gilbert, Andrew Morton, James.Bottomley, dhowells,
Fan Wu, Ryan Foster, linux-security-module, linux-doc,
linux-kernel, bpf
In-Reply-To: <20260227233930.2418522-1-bboscaccy@linux.microsoft.com>
This introduces the gen_sig tool. It creates a pkcs#7 signature of a
data payload. Additionally it appends a signed attribute containing a
set of hashes.
Typical usage is to provide a payload containing the light skeleton
ebpf syscall program binary and it's associated maps, which can be
extracted from the auto-generated skeleton header.
Signed-off-by: Blaise Boscaccy <bboscaccy@linux.microsoft.com>
---
scripts/Makefile | 1 +
scripts/hornet/Makefile | 5 +
scripts/hornet/gen_sig.c | 392 ++++++++++++++++++++++++++++++++++++
scripts/hornet/write-sig.sh | 27 +++
4 files changed, 425 insertions(+)
create mode 100644 scripts/hornet/Makefile
create mode 100644 scripts/hornet/gen_sig.c
create mode 100755 scripts/hornet/write-sig.sh
diff --git a/scripts/Makefile b/scripts/Makefile
index 0941e5ce7b57..dea8ab91bbe4 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -63,6 +63,7 @@ subdir-$(CONFIG_GENKSYMS) += genksyms
subdir-$(CONFIG_GENDWARFKSYMS) += gendwarfksyms
subdir-$(CONFIG_SECURITY_SELINUX) += selinux
subdir-$(CONFIG_SECURITY_IPE) += ipe
+subdir-$(CONFIG_SECURITY_HORNET) += hornet
# Let clean descend into subdirs
subdir- += basic dtc gdb kconfig mod
diff --git a/scripts/hornet/Makefile b/scripts/hornet/Makefile
new file mode 100644
index 000000000000..3ee41e5e9a9f
--- /dev/null
+++ b/scripts/hornet/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+hostprogs-always-y := gen_sig
+
+HOSTCFLAGS_gen_sig.o = $(shell $(HOSTPKG_CONFIG) --cflags libcrypto 2> /dev/null)
+HOSTLDLIBS_gen_sig = $(shell $(HOSTPKG_CONFIG) --libs libcrypto 2> /dev/null || echo -lcrypto)
diff --git a/scripts/hornet/gen_sig.c b/scripts/hornet/gen_sig.c
new file mode 100644
index 000000000000..f966516ebc99
--- /dev/null
+++ b/scripts/hornet/gen_sig.c
@@ -0,0 +1,392 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+ *
+ * Generate a signature for an eBPF program along with appending
+ * map hashes as signed attributes
+ *
+ * Copyright © 2025 Microsoft Corporation.
+ *
+ * Authors: Blaise Boscaccy <bboscaccy@linux.microsoft.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the licence, or (at your option) any later version.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <err.h>
+#include <getopt.h>
+
+#include <openssl/cms.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/pkcs7.h>
+#include <openssl/x509.h>
+#include <openssl/pem.h>
+#include <openssl/objects.h>
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/opensslv.h>
+#include <openssl/bio.h>
+#include <openssl/stack.h>
+
+#if OPENSSL_VERSION_MAJOR >= 3
+# define USE_PKCS11_PROVIDER
+# include <openssl/provider.h>
+# include <openssl/store.h>
+#else
+# if !defined(OPENSSL_NO_ENGINE) && !defined(OPENSSL_NO_DEPRECATED_3_0)
+# define USE_PKCS11_ENGINE
+# include <openssl/engine.h>
+# endif
+#endif
+#include "../ssl-common.h"
+
+#define SHA256_LEN 32
+#define BUF_SIZE (1 << 15) // 32 KiB
+#define MAX_HASHES 64
+
+struct hash_spec {
+ char *file;
+ int index;
+};
+
+typedef struct {
+ ASN1_INTEGER *index;
+ ASN1_OCTET_STRING *hash;
+
+} HORNET_MAP;
+
+DECLARE_ASN1_FUNCTIONS(HORNET_MAP)
+ASN1_SEQUENCE(HORNET_MAP) = {
+ ASN1_SIMPLE(HORNET_MAP, index, ASN1_INTEGER),
+ ASN1_SIMPLE(HORNET_MAP, hash, ASN1_OCTET_STRING)
+} ASN1_SEQUENCE_END(HORNET_MAP);
+
+IMPLEMENT_ASN1_FUNCTIONS(HORNET_MAP)
+
+DEFINE_STACK_OF(HORNET_MAP)
+
+typedef struct {
+ STACK_OF(HORNET_MAP) * maps;
+} MAP_SET;
+
+DECLARE_ASN1_FUNCTIONS(MAP_SET)
+ASN1_SEQUENCE(MAP_SET) = {
+ ASN1_SET_OF(MAP_SET, maps, HORNET_MAP)
+} ASN1_SEQUENCE_END(MAP_SET);
+
+IMPLEMENT_ASN1_FUNCTIONS(MAP_SET)
+
+#define DIE(...) do { fprintf(stderr, __VA_ARGS__); fputc('\n', stderr); \
+ exit(EXIT_FAILURE); } while (0)
+
+static BIO *bio_open_wr(const char *path)
+{
+ BIO *b = BIO_new_file(path, "wb");
+
+ if (!b) {
+ perror(path);
+ ERR_print_errors_fp(stderr);
+ exit(EXIT_FAILURE);
+ }
+ return b;
+}
+
+static void usage(const char *prog)
+{
+ fprintf(stderr,
+ "Usage:\n"
+ " %s --data content.bin --cert signer.crt --key signer.key [-pass pass]\n"
+ " --out newsig.p7b \n"
+ " --add FILE:index [--add FILE:index ...]\n",
+ prog);
+}
+
+static const char *key_pass;
+
+static int pem_pw_cb(char *buf, int len, int w, void *v)
+{
+ int pwlen;
+
+ if (!key_pass)
+ return -1;
+
+ pwlen = strlen(key_pass);
+ if (pwlen >= len)
+ return -1;
+
+ strcpy(buf, key_pass);
+
+ key_pass = NULL;
+
+ return pwlen;
+}
+
+static EVP_PKEY *read_private_key(const char *private_key_name)
+{
+ EVP_PKEY *private_key;
+ BIO *b;
+
+ b = BIO_new_file(private_key_name, "rb");
+ ERR(!b, "%s", private_key_name);
+ private_key = PEM_read_bio_PrivateKey(b, NULL, pem_pw_cb,
+ NULL);
+ ERR(!private_key, "%s", private_key_name);
+ BIO_free(b);
+
+ return private_key;
+}
+
+static X509 *read_x509(const char *x509_name)
+{
+ unsigned char buf[2];
+ X509 *x509;
+ BIO *b;
+ int n;
+
+ b = BIO_new_file(x509_name, "rb");
+ ERR(!b, "%s", x509_name);
+
+ /* Look at the first two bytes of the file to determine the encoding */
+ n = BIO_read(b, buf, 2);
+ if (n != 2) {
+ if (BIO_should_retry(b)) {
+ fprintf(stderr, "%s: Read wanted retry\n", x509_name);
+ exit(1);
+ }
+ if (n >= 0) {
+ fprintf(stderr, "%s: Short read\n", x509_name);
+ exit(1);
+ }
+ ERR(1, "%s", x509_name);
+ }
+
+ ERR(BIO_reset(b) != 0, "%s", x509_name);
+
+ if (buf[0] == 0x30 && buf[1] >= 0x81 && buf[1] <= 0x84)
+ /* Assume raw DER encoded X.509 */
+ x509 = d2i_X509_bio(b, NULL);
+ else
+ /* Assume PEM encoded X.509 */
+ x509 = PEM_read_bio_X509(b, NULL, NULL, NULL);
+
+ BIO_free(b);
+ ERR(!x509, "%s", x509_name);
+
+ return x509;
+}
+
+static int sha256(const char *path, unsigned char out[SHA256_LEN], unsigned int *out_len)
+{
+ FILE *f;
+ int rc;
+ EVP_MD_CTX *ctx;
+ unsigned char buf[BUF_SIZE];
+ size_t n;
+ unsigned int mdlen = 0;
+
+ if (!path || !out)
+ return -1;
+
+ f = fopen(path, "rb");
+ if (!f) {
+ perror("fopen");
+ return -2;
+ }
+
+ ERR_load_crypto_strings();
+
+ rc = -3;
+ ctx = EVP_MD_CTX_new();
+ if (!ctx) {
+ rc = -4;
+ goto done;
+ }
+
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ if (EVP_DigestInit_ex2(ctx, EVP_sha256(), NULL) != 1) {
+ rc = -5;
+ goto done;
+ }
+#else
+ if (EVP_DigestInit_ex(ctx, EVP_sha256(), NULL) != 1) {
+ rc = -5;
+ goto done;
+ }
+#endif
+ while ((n = fread(buf, 1, sizeof(buf), f)) > 0) {
+ if (EVP_DigestUpdate(ctx, buf, n) != 1) {
+ rc = -6;
+ goto done;
+ }
+ }
+ if (ferror(f)) {
+ rc = -7;
+ goto done;
+ }
+
+ if (EVP_DigestFinal_ex(ctx, out, &mdlen) != 1) {
+ rc = -8;
+ goto done;
+ }
+ if (mdlen != SHA256_LEN) {
+ rc = -9;
+ goto done;
+ }
+
+ if (out_len)
+ *out_len = mdlen;
+ rc = 0;
+
+done:
+ EVP_MD_CTX_free(ctx);
+ fclose(f);
+ ERR_free_strings();
+ return rc;
+}
+
+static void add_hash(MAP_SET *set, unsigned char *buffer, int buffer_len, int index)
+{
+ HORNET_MAP *map = NULL;
+
+ map = HORNET_MAP_new();
+ ASN1_INTEGER_set(map->index, index);
+ ASN1_OCTET_STRING_set(map->hash, buffer, buffer_len);
+ sk_HORNET_MAP_push(set->maps, map);
+}
+
+int main(int argc, char **argv)
+{
+ const char *cert_path = NULL;
+ const char *key_path = NULL;
+ const char *data_path = NULL;
+ const char *out_path = NULL;
+
+ X509 *signer;
+ EVP_PKEY *pkey;
+ BIO *data_in;
+ CMS_ContentInfo *cms_out;
+ struct hash_spec hashes[MAX_HASHES];
+ int hash_count = 0;
+ int flags;
+ CMS_SignerInfo *si;
+ MAP_SET *set;
+ unsigned char hash_buffer[SHA256_LEN];
+ unsigned int hash_len;
+ ASN1_OBJECT *oid;
+ unsigned char *der = NULL;
+ int der_len;
+ int err;
+ BIO *b_out;
+ int i;
+ char opt;
+
+ const char *short_opts = "C:K:P:O:A:Sh";
+
+ static const struct option long_opts[] = {
+ {"cert", required_argument, 0, 'C'},
+ {"key", required_argument, 0, 'K'},
+ {"pass", required_argument, 0, 'P'},
+ {"out", required_argument, 0, 'O'},
+ {"data", required_argument, 0, 'D'},
+ {"add", required_argument, 0, 'A'},
+ {"help", no_argument, 0, 'h'},
+ {0, 0, 0, 0}
+ };
+
+ while ((opt = getopt_long_only(argc, argv, short_opts, long_opts, NULL)) != -1) {
+ switch (opt) {
+ case 'C':
+ cert_path = optarg;
+ break;
+ case 'K':
+ key_path = optarg;
+ break;
+ case 'P':
+ key_pass = optarg;
+ break;
+ case 'O':
+ out_path = optarg;
+ break;
+ case 'D':
+ data_path = optarg;
+ break;
+ case 'A':
+ if (strchr(optarg, ':')) {
+ hashes[hash_count].file = strsep(&optarg, ":");
+ hashes[hash_count].index = atoi(optarg);
+ hash_count++;
+ } else {
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+ }
+ }
+
+ if (!cert_path || !key_path || !out_path || !data_path) {
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ OpenSSL_add_all_algorithms();
+ ERR_load_crypto_strings();
+
+ signer = read_x509(cert_path);
+ ERR(!signer, "Load cert failed");
+
+ pkey = read_private_key(key_path);
+ ERR(!pkey, "Load key failed");
+
+ data_in = BIO_new_file(data_path, "rb");
+ ERR(!data_in, "Load data failed");
+
+ cms_out = CMS_sign(NULL, NULL, NULL, NULL,
+ CMS_NOCERTS | CMS_PARTIAL | CMS_BINARY | CMS_DETACHED);
+ ERR(!cms_out, "create cms failed");
+
+ flags = CMS_NOCERTS | CMS_PARTIAL | CMS_BINARY | CMS_NOSMIMECAP | CMS_DETACHED;
+
+ si = CMS_add1_signer(cms_out, signer, pkey, EVP_sha256(), flags);
+ ERR(!si, "add signer failed");
+
+ set = MAP_SET_new();
+ set->maps = sk_HORNET_MAP_new_null();
+
+ for (i = 0; i < hash_count; i++) {
+ sha256(hashes[i].file, hash_buffer, &hash_len);
+ add_hash(set, hash_buffer, hash_len, hashes[i].index);
+ }
+
+ oid = OBJ_txt2obj("2.25.316487325684022475439036912669789383960", 1);
+ if (!oid) {
+ ERR_print_errors_fp(stderr);
+ DIE("create oid failed");
+ }
+
+ der_len = ASN1_item_i2d((ASN1_VALUE *)set, &der, ASN1_ITEM_rptr(MAP_SET));
+ CMS_signed_add1_attr_by_OBJ(si, oid, V_ASN1_SEQUENCE, der, der_len);
+
+ err = CMS_final(cms_out, data_in, NULL, CMS_NOCERTS | CMS_BINARY);
+ ERR(!err, "cms final failed");
+
+ OPENSSL_free(der);
+ MAP_SET_free(set);
+
+ b_out = bio_open_wr(out_path);
+ ERR(!b_out, "opening output path failed");
+
+ i2d_CMS_bio_stream(b_out, cms_out, NULL, 0);
+
+ BIO_free(data_in);
+ BIO_free(b_out);
+ EVP_cleanup();
+ ERR_free_strings();
+ return 0;
+}
diff --git a/scripts/hornet/write-sig.sh b/scripts/hornet/write-sig.sh
new file mode 100755
index 000000000000..7eaabe3bab9a
--- /dev/null
+++ b/scripts/hornet/write-sig.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (c) 2025 Microsoft Corporation
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of version 2 of the GNU General Public
+# License as published by the Free Software Foundation.
+
+function usage() {
+ echo "Sample for rewriting an autogenerated eBPF lskel headers"
+ echo "with a new signature"
+ echo ""
+ echo "USAGE: header_file sig"
+ exit
+}
+
+ARGC=$#
+
+EXPECTED_ARGS=2
+
+if [ $ARGC -ne $EXPECTED_ARGS ] ; then
+ usage
+else
+ SIG=$(xxd -p $2 | tr -d '\n' | sed 's/\(..\)/\\\\x\1/g')
+ sed '/const char opts_sig/,/;/c\\tstatic const char opts_sig[] __attribute__((__aligned__(8))) = "\\\n'"$(printf '%s\n' "$SIG")"'\";' $1
+fi
--
2.52.0
^ permalink raw reply related
* [PATCH v2 07/10] security: Hornet LSM
From: Blaise Boscaccy @ 2026-02-27 23:38 UTC (permalink / raw)
To: Blaise Boscaccy, Jonathan Corbet, Paul Moore, James Morris,
Serge E. Hallyn, Mickaël Salaün, Günther Noack,
Dr. David Alan Gilbert, Andrew Morton, James.Bottomley, dhowells,
Fan Wu, Ryan Foster, linux-security-module, linux-doc,
linux-kernel, bpf
In-Reply-To: <20260227233930.2418522-1-bboscaccy@linux.microsoft.com>
This adds the Hornet Linux Security Module which provides enhanced
signature verification and data validation for eBPF programs. This
allows users to continue to maintain an invariant that all code
running inside of the kernel has actually been signed and verified, by
the kernel.
This effort builds upon the currently excepted upstream solution. It
further hardens it by providing deterministic, in-kernel checking of
map hashes to solidify auditing along with preventing TOCTOU attacks
against lskel map hashes.
Target map hashes are passed in via PKCS#7 signed attributes. Hornet
determines the extent which the eBFP program is signed and defers to
other LSMs for policy decisions.
Signed-off-by: Blaise Boscaccy <bboscaccy@linux.microsoft.com>
Nacked-by: Alexei Starovoitov <alexei.starovoitov@gmail.com>
---
Documentation/admin-guide/LSM/Hornet.rst | 310 ++++++++++++++++++++++
Documentation/admin-guide/LSM/index.rst | 1 +
MAINTAINERS | 9 +
include/linux/oid_registry.h | 3 +
include/uapi/linux/lsm.h | 1 +
security/Kconfig | 3 +-
security/Makefile | 1 +
security/hornet/Kconfig | 11 +
security/hornet/Makefile | 7 +
security/hornet/hornet.asn1 | 13 +
security/hornet/hornet_lsm.c | 323 +++++++++++++++++++++++
11 files changed, 681 insertions(+), 1 deletion(-)
create mode 100644 Documentation/admin-guide/LSM/Hornet.rst
create mode 100644 security/hornet/Kconfig
create mode 100644 security/hornet/Makefile
create mode 100644 security/hornet/hornet.asn1
create mode 100644 security/hornet/hornet_lsm.c
diff --git a/Documentation/admin-guide/LSM/Hornet.rst b/Documentation/admin-guide/LSM/Hornet.rst
new file mode 100644
index 000000000000..0dd4c03b8a7e
--- /dev/null
+++ b/Documentation/admin-guide/LSM/Hornet.rst
@@ -0,0 +1,310 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+======
+Hornet
+======
+
+Hornet is a Linux Security Module that provides extensible signature
+verification for eBPF programs. This is selectable at build-time with
+``CONFIG_SECURITY_HORNET``.
+
+Overview
+========
+
+Hornet addresses concerns from users who require strict audit trails and
+verification guarantees for eBPF programs, especially in
+security-sensitive environments. Many production systems need assurance
+that only authorized, unmodified eBPF programs are loaded into the
+kernel. Hornet provides this assurance through cryptographic signature
+verification.
+
+When an eBPF program is loaded via the ``bpf()`` syscall, Hornet
+verifies a PKCS#7 signature attached to the program instructions. The
+signature is checked against the kernel's secondary keyring using the
+existing kernel cryptographic infrastructure. In addition to signing the
+program bytecode, Hornet supports signing SHA-256 hashes of associated
+BPF maps, enabling integrity verification of map contents at load time
+and at runtime.
+
+After verification, Hornet classifies the program into one of the
+following integrity states and passes the result to a downstream LSM hook
+(``bpf_prog_load_post_integrity``), allowing other security modules to
+make policy decisions based on the verification outcome:
+
+``LSM_INT_VERDICT_OK``
+ The program signature and all map hashes verified successfully.
+
+``LSM_INT_VERDICT_UNSIGNED``
+ No signature was provided with the program.
+
+``LSM_INT_VERDICT_PARTIALSIG``
+ The program signature verified, but the signing certificate is not
+ trusted in the secondary keyring, or the signature did not contain
+ hornet map hash data.
+
+``LSM_INT_VERDICT_BADSIG``
+ The signature or a map hash failed verification.
+
+Hornet itself does not enforce a policy on whether unsigned or partially
+signed programs should be rejected. It delegates that decision to
+downstream LSMs via the ``bpf_prog_load_post_integrity`` hook, making it
+a composable building block in a larger security architecture.
+
+Use Cases
+=========
+
+- **Locked-down production environments**: Ensure only eBPF programs
+ signed by a trusted authority can be loaded, preventing unauthorized
+ or tampered programs from running in the kernel.
+
+- **Audit and compliance**: Provide cryptographic evidence that loaded
+ eBPF programs match their expected build artifacts, supporting
+ compliance requirements in regulated industries.
+
+- **Supply chain integrity**: Verify that eBPF programs and their
+ associated map data have not been modified since they were built and
+ signed, protecting against supply chain attacks.
+
+Threat Model
+============
+
+Hornet protects against the following threats:
+
+- **Unauthorized eBPF program loading**: Programs that have not been
+ signed by a trusted key will be reported as unsigned or badly signed.
+
+- **Tampering with program instructions**: Any modification to the eBPF
+ bytecode after signing will cause signature verification to fail.
+
+- **Tampering with map data**: When map hashes are included in the
+ signature, Hornet verifies that frozen BPF maps match their expected
+ SHA-256 hashes at load time. Maps are also re-verified before program
+ execution via ``BPF_PROG_RUN``.
+
+Hornet does **not** protect against:
+
+- Compromise of the signing key itself.
+- Attacks that occur after a program has been loaded and verified.
+- Programs loaded by the kernel itself (kernel-internal loads bypass
+ the ``BPF_PROG_RUN`` map check).
+
+Known Limitations
+=================
+
+- Hornet requires programs to use :doc:`light skeletons
+ </bpf/libbpf/libbpf_naming_convention>` (lskels) for the signing
+ workflow, as the tooling operates on lskel-generated headers.
+
+- A maximum of 64 maps per program can be tracked for hash
+ verification.
+
+- Map hash verification requires the maps to be frozen before loading.
+ Maps that are not frozen at load time will cause verification to fail
+ when their hashes are included in the signature.
+
+- Hornet relies on the kernel's secondary keyring
+ (``VERIFY_USE_SECONDARY_KEYRING``) for certificate trust. Keys must
+ be provisioned into this keyring before programs can be verified.
+
+Configuration
+=============
+
+Build Configuration
+-------------------
+
+Enable Hornet by setting the following kernel configuration option::
+
+ CONFIG_SECURITY_HORNET=y
+
+This option is found under :menuselection:`Security options --> Hornet
+support` and depends on ``CONFIG_SECURITY``.
+
+When enabled, Hornet is included in the default LSM initialization order
+and will appear in ``/sys/kernel/security/lsm``.
+
+Architecture
+============
+
+Signature Verification Flow
+---------------------------
+
+The following describes what happens when a userspace program calls
+``bpf(BPF_PROG_LOAD, ...)`` with a signature attached:
+
+1. The ``bpf_prog_load_integrity`` LSM hook is invoked.
+
+2. Hornet reads the signature from the userspace buffer specified by
+ ``attr->signature`` (with length ``attr->signature_size``).
+
+3. The PKCS#7 signature is verified against the program instructions
+ using ``verify_pkcs7_signature()`` with the kernel's secondary
+ keyring.
+
+4. The PKCS#7 message is parsed and its trust chain is validated via
+ ``validate_pkcs7_trust()``.
+
+5. Hornet extracts the authenticated attribute identified by
+ ``OID_hornet_data`` (OID ``2.25.316487325684022475439036912669789383960``)
+ from the PKCS#7 message. This attribute contains an ASN.1-encoded set
+ of map index/hash pairs.
+
+6. For each map hash entry, Hornet retrieves the corresponding BPF map
+ via its file descriptor, confirms it is frozen, computes its SHA-256
+ hash, and compares it against the signed hash.
+
+7. The resulting integrity verdict is passed to the
+ ``bpf_prog_load_post_integrity`` hook so that downstream LSMs can
+ enforce policy.
+
+Runtime Map Verification
+------------------------
+
+When ``bpf(BPF_PROG_RUN, ...)`` is called from userspace, Hornet
+re-verifies the hashes of all maps associated with the program. This
+ensures that map contents have not been modified between program load
+and execution. If any map hash no longer matches, the ``BPF_PROG_RUN``
+command is denied.
+
+Userspace Interface
+-------------------
+
+Signatures are passed to the kernel through fields in ``union bpf_attr``
+when using the ``BPF_PROG_LOAD`` command:
+
+``signature``
+ A pointer to a userspace buffer containing the PKCS#7 signature.
+
+``signature_size``
+ The size of the signature buffer in bytes.
+
+ASN.1 Schema
+------------
+
+Map hashes are encoded as a signed attribute in the PKCS#7 message using
+the following ASN.1 schema::
+
+ HornetData ::= SET OF Map
+
+ Map ::= SEQUENCE {
+ index INTEGER,
+ sha OCTET STRING
+ }
+
+Each ``Map`` entry contains the index of the map in the program's
+``fd_array`` and its expected SHA-256 hash. A zero-length ``sha`` field
+indicates that the map at that index should be skipped during
+verification.
+
+Tooling
+=======
+
+Helper scripts and a signature generation tool are provided in
+``scripts/hornet/`` to support the development of signed eBPF light
+skeletons.
+
+gen_sig
+-------
+
+``gen_sig`` is a C program (using OpenSSL) that creates a PKCS#7
+signature over eBPF program instructions and optionally includes
+SHA-256 hashes of BPF maps as signed attributes.
+
+Usage::
+
+ gen_sig --data <instructions.bin> \
+ --cert <signer.crt> \
+ --key <signer.key> \
+ [--pass <passphrase>] \
+ --out <signature.p7b> \
+ [--add <mapfile.bin>:<index> ...]
+
+``--data``
+ Path to the binary file containing eBPF program instructions to sign.
+
+``--cert``
+ Path to the signing certificate (PEM or DER format).
+
+``--key``
+ Path to the private key (PEM or DER format).
+
+``--pass``
+ Optional passphrase for the private key.
+
+``--out``
+ Path to write the output PKCS#7 signature.
+
+``--add``
+ Attach a map hash as a signed attribute. The argument is a path to a
+ binary map file followed by a colon and the map's index in the
+ ``fd_array``. This option may be specified multiple times.
+
+extract-skel.sh
+---------------
+
+Extracts a named field from an autogenerated eBPF lskel header file.
+Used internally by other helper scripts.
+
+extract-insn.sh
+---------------
+
+Extracts the eBPF program instructions (``opts_insn``) from an lskel
+header into a binary file suitable for signing with ``gen_sig``.
+
+extract-map.sh
+--------------
+
+Extracts the map data (``opts_data``) from an lskel header into a
+binary file suitable for hashing with ``gen_sig``.
+
+write-sig.sh
+------------
+
+Replaces the signature data in an lskel header with a new signature
+from a binary file. This is used to embed a freshly generated signature
+back into the header after signing.
+
+Signing Workflow
+================
+
+A typical workflow for building and signing an eBPF light skeleton is:
+
+1. **Compile the eBPF program**::
+
+ clang -O2 -target bpf -c program.bpf.c -o program.bpf.o
+
+2. **Generate the light skeleton header** using ``bpftool``::
+
+ bpftool gen skeleton -S program.bpf.o > loader.h
+
+3. **Extract instructions and map data** from the generated header::
+
+ scripts/hornet/extract-insn.sh loader.h > insn.bin
+ scripts/hornet/extract-map.sh loader.h > map.bin
+
+4. **Generate the signature** with ``gen_sig``::
+
+ scripts/hornet/gen_sig \
+ --key signing_key.pem \
+ --cert signing_key.x509 \
+ --data insn.bin \
+ --add map.bin:0 \
+ --out sig.bin
+
+5. **Embed the signature** back into the header::
+
+ scripts/hornet/write-sig.sh loader.h sig.bin > signed_loader.h
+
+6. **Build the loader program** using the signed header::
+
+ cc -o loader loader.c -lbpf
+
+The resulting loader program will pass the embedded signature to the
+kernel when loading the eBPF program, enabling Hornet to verify it.
+
+Testing
+=======
+
+Self-tests are provided in ``tools/testing/selftests/hornet/``. The test
+suite builds a minimal eBPF program (``trivial.bpf.c``), signs it using
+the workflow described above, and verifies that the signed program loads
+successfully.
diff --git a/Documentation/admin-guide/LSM/index.rst b/Documentation/admin-guide/LSM/index.rst
index b44ef68f6e4d..57f6e9fbe5fd 100644
--- a/Documentation/admin-guide/LSM/index.rst
+++ b/Documentation/admin-guide/LSM/index.rst
@@ -49,3 +49,4 @@ subdirectories.
SafeSetID
ipe
landlock
+ Hornet
diff --git a/MAINTAINERS b/MAINTAINERS
index 55af015174a5..6e91234a9ba4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11682,6 +11682,15 @@ S: Maintained
F: Documentation/devicetree/bindings/iio/pressure/honeywell,mprls0025pa.yaml
F: drivers/iio/pressure/mprls0025pa*
+HORNET SECURITY MODULE
+M: Blaise Boscaccy <bboscaccy@linux.microsoft.com>
+L: linux-security-module@vger.kernel.org
+S: Supported
+T: git https://github.com/blaiseboscaccy/hornet.git
+F: Documentation/admin-guide/LSM/Hornet.rst
+F: scripts/hornet/
+F: security/hornet/
+
HP BIOSCFG DRIVER
M: Jorge Lopez <jorge.lopez2@hp.com>
L: platform-driver-x86@vger.kernel.org
diff --git a/include/linux/oid_registry.h b/include/linux/oid_registry.h
index ebce402854de..bf852715aaea 100644
--- a/include/linux/oid_registry.h
+++ b/include/linux/oid_registry.h
@@ -150,6 +150,9 @@ enum OID {
OID_id_ml_dsa_65, /* 2.16.840.1.101.3.4.3.18 */
OID_id_ml_dsa_87, /* 2.16.840.1.101.3.4.3.19 */
+ /* Hornet LSM */
+ OID_hornet_data, /* 2.25.316487325684022475439036912669789383960 */
+
OID__NR
};
diff --git a/include/uapi/linux/lsm.h b/include/uapi/linux/lsm.h
index 938593dfd5da..2ff9bcdd551e 100644
--- a/include/uapi/linux/lsm.h
+++ b/include/uapi/linux/lsm.h
@@ -65,6 +65,7 @@ struct lsm_ctx {
#define LSM_ID_IMA 111
#define LSM_ID_EVM 112
#define LSM_ID_IPE 113
+#define LSM_ID_HORNET 114
/*
* LSM_ATTR_XXX definitions identify different LSM attributes
diff --git a/security/Kconfig b/security/Kconfig
index 6a4393fce9a1..283c4a103209 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -230,6 +230,7 @@ source "security/safesetid/Kconfig"
source "security/lockdown/Kconfig"
source "security/landlock/Kconfig"
source "security/ipe/Kconfig"
+source "security/hornet/Kconfig"
source "security/integrity/Kconfig"
@@ -274,7 +275,7 @@ config LSM
default "landlock,lockdown,yama,loadpin,safesetid,apparmor,selinux,smack,tomoyo,ipe,bpf" if DEFAULT_SECURITY_APPARMOR
default "landlock,lockdown,yama,loadpin,safesetid,tomoyo,ipe,bpf" if DEFAULT_SECURITY_TOMOYO
default "landlock,lockdown,yama,loadpin,safesetid,ipe,bpf" if DEFAULT_SECURITY_DAC
- default "landlock,lockdown,yama,loadpin,safesetid,selinux,smack,tomoyo,apparmor,ipe,bpf"
+ default "landlock,lockdown,yama,loadpin,safesetid,selinux,smack,tomoyo,apparmor,ipe,hornet,bpf"
help
A comma-separated list of LSMs, in initialization order.
Any LSMs left off this list, except for those with order
diff --git a/security/Makefile b/security/Makefile
index 4601230ba442..b68cb56e419b 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_CGROUPS) += device_cgroup.o
obj-$(CONFIG_BPF_LSM) += bpf/
obj-$(CONFIG_SECURITY_LANDLOCK) += landlock/
obj-$(CONFIG_SECURITY_IPE) += ipe/
+obj-$(CONFIG_SECURITY_HORNET) += hornet/
# Object integrity file lists
obj-$(CONFIG_INTEGRITY) += integrity/
diff --git a/security/hornet/Kconfig b/security/hornet/Kconfig
new file mode 100644
index 000000000000..19406aa237ac
--- /dev/null
+++ b/security/hornet/Kconfig
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0-only
+config SECURITY_HORNET
+ bool "Hornet support"
+ depends on SECURITY
+ default n
+ help
+ This selects Hornet.
+ Further information can be found in
+ Documentation/admin-guide/LSM/Hornet.rst.
+
+ If you are unsure how to answer this question, answer N.
diff --git a/security/hornet/Makefile b/security/hornet/Makefile
new file mode 100644
index 000000000000..26b6f954f762
--- /dev/null
+++ b/security/hornet/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_SECURITY_HORNET) := hornet.o
+
+hornet-y := hornet.asn1.o \
+ hornet_lsm.o \
+
+$(obj)/hornet.asn1.o: $(obj)/hornet.asn1.c $(obj)/hornet.asn1.h
diff --git a/security/hornet/hornet.asn1 b/security/hornet/hornet.asn1
new file mode 100644
index 000000000000..c8d47b16b65d
--- /dev/null
+++ b/security/hornet/hornet.asn1
@@ -0,0 +1,13 @@
+-- SPDX-License-Identifier: BSD-3-Clause
+--
+-- Copyright (C) 2009 IETF Trust and the persons identified as authors
+-- of the code
+--
+-- https://www.rfc-editor.org/rfc/rfc5652#section-3
+
+HornetData ::= SET OF Map
+
+Map ::= SEQUENCE {
+ index INTEGER ({ hornet_map_index }),
+ sha OCTET STRING ({ hornet_map_hash })
+} ({ hornet_next_map })
diff --git a/security/hornet/hornet_lsm.c b/security/hornet/hornet_lsm.c
new file mode 100644
index 000000000000..6c821d6441fb
--- /dev/null
+++ b/security/hornet/hornet_lsm.c
@@ -0,0 +1,323 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Hornet Linux Security Module
+ *
+ * Author: Blaise Boscaccy <bboscaccy@linux.microsoft.com>
+ *
+ * Copyright (C) 2026 Microsoft Corporation
+ */
+
+#include <linux/lsm_hooks.h>
+#include <uapi/linux/lsm.h>
+#include <linux/bpf.h>
+#include <linux/verification.h>
+#include <crypto/public_key.h>
+#include <linux/module_signature.h>
+#include <crypto/pkcs7.h>
+#include <linux/sort.h>
+#include <linux/asn1_decoder.h>
+#include <linux/oid_registry.h>
+#include "hornet.asn1.h"
+
+#define MAX_USED_MAPS 64
+
+struct hornet_maps {
+ bpfptr_t fd_array;
+};
+
+struct hornet_parse_context {
+ int indexes[MAX_USED_MAPS];
+ bool skips[MAX_USED_MAPS];
+ unsigned char hashes[SHA256_DIGEST_SIZE * MAX_USED_MAPS];
+ int hash_count;
+};
+
+struct hornet_prog_security_struct {
+ bool checked[MAX_USED_MAPS];
+ unsigned char hashes[SHA256_DIGEST_SIZE * MAX_USED_MAPS];
+};
+
+struct hornet_map_security_struct {
+ bool checked;
+ int index;
+};
+
+struct lsm_blob_sizes hornet_blob_sizes __ro_after_init = {
+ .lbs_bpf_map = sizeof(struct hornet_map_security_struct),
+ .lbs_bpf_prog = sizeof(struct hornet_prog_security_struct),
+};
+
+static inline struct hornet_prog_security_struct *
+hornet_bpf_prog_security(struct bpf_prog *prog)
+{
+ return prog->aux->security + hornet_blob_sizes.lbs_bpf_prog;
+}
+
+static inline struct hornet_map_security_struct *
+hornet_bpf_map_security(struct bpf_map *map)
+{
+ return map->security + hornet_blob_sizes.lbs_bpf_map;
+}
+
+static int hornet_verify_hashes(struct hornet_maps *maps,
+ struct hornet_parse_context *ctx,
+ struct bpf_prog *prog)
+{
+ int map_fd;
+ u32 i;
+ struct bpf_map *map;
+ int err = 0;
+ unsigned char hash[SHA256_DIGEST_SIZE];
+ struct hornet_prog_security_struct *security = hornet_bpf_prog_security(prog);
+ struct hornet_map_security_struct *map_security;
+
+ for (i = 0; i < ctx->hash_count; i++) {
+ if (ctx->skips[i]) {
+ security->checked[i] = false;
+ continue;
+ }
+
+ err = copy_from_bpfptr_offset(&map_fd, maps->fd_array,
+ ctx->indexes[i] * sizeof(map_fd),
+ sizeof(map_fd));
+ if (err < 0)
+ return LSM_INT_VERDICT_BADSIG;
+
+ CLASS(fd, f)(map_fd);
+ if (fd_empty(f))
+ return LSM_INT_VERDICT_BADSIG;
+ if (unlikely(fd_file(f)->f_op != &bpf_map_fops))
+ return LSM_INT_VERDICT_BADSIG;
+
+ map = fd_file(f)->private_data;
+ if (!map->frozen)
+ return LSM_INT_VERDICT_BADSIG;
+
+ map->ops->map_get_hash(map, SHA256_DIGEST_SIZE, hash);
+
+ err = memcmp(hash, &ctx->hashes[i * SHA256_DIGEST_SIZE],
+ SHA256_DIGEST_SIZE);
+ if (err)
+ return LSM_INT_VERDICT_BADSIG;
+
+ security->checked[i] = true;
+ memcpy(&security->hashes[i * SHA256_DIGEST_SIZE], hash, SHA256_DIGEST_SIZE);
+ map_security = hornet_bpf_map_security(map);
+ map_security->checked = true;
+ map_security->index = i;
+ }
+ return LSM_INT_VERDICT_OK;
+}
+
+int hornet_next_map(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct hornet_parse_context *ctx = (struct hornet_parse_context *)context;
+
+ ctx->hash_count++;
+ return 0;
+}
+
+int hornet_map_index(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct hornet_parse_context *ctx = (struct hornet_parse_context *)context;
+
+ if (vlen > 1)
+ return -EINVAL;
+
+ ctx->indexes[ctx->hash_count] = *(u8 *)value;
+ return 0;
+}
+
+int hornet_map_hash(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+
+{
+ struct hornet_parse_context *ctx = (struct hornet_parse_context *)context;
+
+ if (vlen != SHA256_DIGEST_SIZE && vlen != 0)
+ return -EINVAL;
+
+ if (vlen) {
+ ctx->skips[ctx->hash_count] = false;
+ memcpy(&ctx->hashes[ctx->hash_count * SHA256_DIGEST_SIZE], value, vlen);
+ } else
+ ctx->skips[ctx->hash_count] = true;
+
+ return 0;
+}
+
+static int hornet_check_program(struct bpf_prog *prog, union bpf_attr *attr,
+ struct bpf_token *token, bool is_kernel)
+{
+ struct hornet_maps maps = {0};
+ bpfptr_t usig = make_bpfptr(attr->signature, is_kernel);
+ struct pkcs7_message *msg;
+ struct hornet_parse_context *ctx;
+ void *sig;
+ int err;
+ const void *authattrs;
+ size_t authattrs_len;
+
+ if (!attr->signature)
+ return LSM_INT_VERDICT_UNSIGNED;
+
+ ctx = kzalloc(sizeof(struct hornet_parse_context), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ maps.fd_array = make_bpfptr(attr->fd_array, is_kernel);
+ sig = kzalloc(attr->signature_size, GFP_KERNEL);
+ if (!sig) {
+ err = -ENOMEM;
+ goto out;
+ }
+ err = copy_from_bpfptr(sig, usig, attr->signature_size);
+ if (err != 0)
+ goto cleanup_sig;
+
+ err = verify_pkcs7_signature(prog->insnsi, prog->len * sizeof(struct bpf_insn),
+ sig, attr->signature_size, VERIFY_USE_SECONDARY_KEYRING,
+ VERIFYING_BPF_SIGNATURE, NULL, NULL);
+ if (err < 0) {
+ err = LSM_INT_VERDICT_BADSIG;
+ goto cleanup_sig;
+ }
+
+ msg = pkcs7_parse_message(sig, attr->signature_size);
+ if (IS_ERR(msg)) {
+ err = LSM_INT_VERDICT_BADSIG;
+ goto cleanup_sig;
+ }
+
+ if (validate_pkcs7_trust(msg, VERIFY_USE_SECONDARY_KEYRING)) {
+ err = LSM_INT_VERDICT_PARTIALSIG;
+ goto cleanup_msg;
+ }
+ if (pkcs7_get_authattr(msg, OID_hornet_data,
+ &authattrs, &authattrs_len) == -ENODATA) {
+ err = LSM_INT_VERDICT_PARTIALSIG;
+ goto cleanup_msg;
+ }
+
+ err = asn1_ber_decoder(&hornet_decoder, ctx, authattrs, authattrs_len);
+ if (err < 0 || authattrs == NULL) {
+ err = LSM_INT_VERDICT_PARTIALSIG;
+ goto cleanup_msg;
+ }
+ err = hornet_verify_hashes(&maps, ctx, prog);
+
+cleanup_msg:
+ pkcs7_free_message(msg);
+cleanup_sig:
+ kfree(sig);
+out:
+ kfree(ctx);
+ return err;
+}
+
+static const struct lsm_id hornet_lsmid = {
+ .name = "hornet",
+ .id = LSM_ID_HORNET,
+};
+
+static int hornet_bpf_prog_load_integrity(struct bpf_prog *prog, union bpf_attr *attr,
+ struct bpf_token *token, bool is_kernel)
+{
+ int result = hornet_check_program(prog, attr, token, is_kernel);
+
+ if (result < 0)
+ return result;
+
+ return security_bpf_prog_load_post_integrity(prog, attr, token, is_kernel,
+ &hornet_lsmid, result);
+}
+
+static int hornet_verify_map(struct bpf_prog *prog, int index)
+{
+ unsigned char hash[SHA256_DIGEST_SIZE];
+ int i;
+ struct bpf_map *map;
+ struct hornet_prog_security_struct *security = hornet_bpf_prog_security(prog);
+ struct hornet_map_security_struct *map_security;
+
+ if (!security->checked[index])
+ return 0;
+
+ for (i = 0; i < prog->aux->used_map_cnt; i++) {
+ map = prog->aux->used_maps[i];
+ map_security = hornet_bpf_map_security(map);
+ if (map_security->index != index)
+ continue;
+
+ if (!map->frozen)
+ return -EINVAL;
+
+ map->ops->map_get_hash(map, SHA256_DIGEST_SIZE, hash);
+ if (memcmp(hash, &security->hashes[index * SHA256_DIGEST_SIZE],
+ SHA256_DIGEST_SIZE) != 0)
+ return -EINVAL;
+ else
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static int hornet_check_prog_maps(u32 ufd)
+{
+ CLASS(fd, f)(ufd);
+ struct bpf_prog *prog;
+ int i, result = 0;
+
+ if (fd_empty(f))
+ return -EBADF;
+ if (fd_file(f)->f_op != &bpf_prog_fops)
+ return -EINVAL;
+
+ prog = fd_file(f)->private_data;
+
+ mutex_lock(&prog->aux->used_maps_mutex);
+ if (!prog->aux->used_map_cnt)
+ goto out;
+
+ for (i = 0; i < prog->aux->used_map_cnt; i++) {
+ result = hornet_verify_map(prog, i);
+ if (result)
+ goto out;
+ }
+out:
+ mutex_unlock(&prog->aux->used_maps_mutex);
+ return result;
+}
+
+static int hornet_bpf(int cmd, union bpf_attr *attr, unsigned int size, bool kernel)
+{
+ if (cmd != BPF_PROG_RUN)
+ return 0;
+ if (kernel)
+ return 0;
+
+ return hornet_check_prog_maps(attr->test.prog_fd);
+}
+
+static struct security_hook_list hornet_hooks[] __ro_after_init = {
+ LSM_HOOK_INIT(bpf_prog_load_integrity, hornet_bpf_prog_load_integrity),
+ LSM_HOOK_INIT(bpf, hornet_bpf),
+};
+
+static int __init hornet_init(void)
+{
+ pr_info("Hornet: eBPF signature verification enabled\n");
+ security_add_hooks(hornet_hooks, ARRAY_SIZE(hornet_hooks), &hornet_lsmid);
+ return 0;
+}
+
+DEFINE_LSM(hornet) = {
+ .id = &hornet_lsmid,
+ .blobs = &hornet_blob_sizes,
+ .init = hornet_init,
+};
--
2.52.0
^ permalink raw reply related
* [PATCH v2 06/10] lsm: framework for BPF integrity verification
From: Blaise Boscaccy @ 2026-02-27 23:38 UTC (permalink / raw)
To: Blaise Boscaccy, Jonathan Corbet, Paul Moore, James Morris,
Serge E. Hallyn, Mickaël Salaün, Günther Noack,
Dr. David Alan Gilbert, Andrew Morton, James.Bottomley, dhowells,
Fan Wu, Ryan Foster, linux-security-module, linux-doc,
linux-kernel, bpf
In-Reply-To: <20260227233930.2418522-1-bboscaccy@linux.microsoft.com>
From: Paul Moore <paul@paul-moore.com>
Add a new LSM hook and two new LSM hook callbacks to support LSMs that
perform integrity verification, e.g. digital signature verification,
of BPF programs.
While the BPF subsystem does implement a signature verification scheme,
it does not satisfy a number of existing requirements, adding support
for BPF program integrity verification to the LSM framework allows
administrators to select additional integrity verification mechanisms
to meet these needs while also providing a mechanism for future
expansion. Additional on why this is necessary can be found at the
lore archive link below:
https://lore.kernel.org/linux-security-module/CAHC9VhTQ_DR=ANzoDBjcCtrimV7XcCZVUsANPt=TjcvM4d-vjg@mail.gmail.com/
The LSM-based BPF integrity verification mechanism works within the
existing security_bpf_prog_load() hook called by the BPF subsystem.
It adds an additional dedicated integrity callback and a new LSM
hook/callback to be called from within LSMs implementing integrity
verification.
The first new callback, bpf_prog_load_integrity(), located within the
security_bpf_prog_load() hook, is necessary to ensure that the integrity
verification callbacks are executed before any of the existing LSMs
are executed via the bpf_prog_load() callback. Reusing the existing
bpf_prog_load() callback for integrity verification could result in LSMs
not having access to the integrity verification results when asked to
authorize the BPF program load in the bpf_prog_load() callback.
The new LSM hook, security_bpf_prog_load_post_integrity(), is intended
to be called from within LSMs performing BPF program integrity
verification. It is used to report the verdict of the integrity
verification to other LSMs enforcing access control policy on BPF
program loads. LSMs enforcing such access controls should register a
bpf_prog_load_post_integrity() callback to receive integrity verdicts.
More information on these new callbacks and hook can be found in the
code comments in this patch.
Signed-off-by: Paul Moore <paul@paul-moore.com>
---
include/linux/lsm_hook_defs.h | 5 +++
include/linux/security.h | 25 ++++++++++++
security/security.c | 75 +++++++++++++++++++++++++++++++++--
3 files changed, 102 insertions(+), 3 deletions(-)
diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
index 8c42b4bde09c..4971d3c36d5b 100644
--- a/include/linux/lsm_hook_defs.h
+++ b/include/linux/lsm_hook_defs.h
@@ -434,6 +434,11 @@ LSM_HOOK(int, 0, bpf_prog, struct bpf_prog *prog)
LSM_HOOK(int, 0, bpf_map_create, struct bpf_map *map, union bpf_attr *attr,
struct bpf_token *token, bool kernel)
LSM_HOOK(void, LSM_RET_VOID, bpf_map_free, struct bpf_map *map)
+LSM_HOOK(int, 0, bpf_prog_load_post_integrity, struct bpf_prog *prog,
+ union bpf_attr *attr, struct bpf_token *token, bool kernel,
+ const struct lsm_id *lsmid, enum lsm_integrity_verdict verdict)
+LSM_HOOK(int, 0, bpf_prog_load_integrity, struct bpf_prog *prog,
+ union bpf_attr *attr, struct bpf_token *token, bool kernel)
LSM_HOOK(int, 0, bpf_prog_load, struct bpf_prog *prog, union bpf_attr *attr,
struct bpf_token *token, bool kernel)
LSM_HOOK(void, LSM_RET_VOID, bpf_prog_free, struct bpf_prog *prog)
diff --git a/include/linux/security.h b/include/linux/security.h
index 83a646d72f6f..298a43b7744a 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -67,6 +67,7 @@ enum fs_value_type;
struct watch;
struct watch_notification;
struct lsm_ctx;
+struct lsm_id;
/* Default (no) options for the capable function */
#define CAP_OPT_NONE 0x0
@@ -100,6 +101,14 @@ enum lsm_integrity_type {
LSM_INT_FSVERITY_BUILTINSIG_VALID,
};
+enum lsm_integrity_verdict {
+ LSM_INT_VERDICT_NONE = 0,
+ LSM_INT_VERDICT_OK,
+ LSM_INT_VERDICT_UNSIGNED,
+ LSM_INT_VERDICT_PARTIALSIG,
+ LSM_INT_VERDICT_BADSIG,
+};
+
/*
* These are reasons that can be passed to the security_locked_down()
* LSM hook. Lockdown reasons that protect kernel integrity (ie, the
@@ -2269,6 +2278,12 @@ extern int security_bpf_prog(struct bpf_prog *prog);
extern int security_bpf_map_create(struct bpf_map *map, union bpf_attr *attr,
struct bpf_token *token, bool kernel);
extern void security_bpf_map_free(struct bpf_map *map);
+extern int security_bpf_prog_load_post_integrity(struct bpf_prog *prog,
+ union bpf_attr *attr,
+ struct bpf_token *token,
+ bool kernel,
+ const struct lsm_id *lsmid,
+ enum lsm_integrity_verdict verdict);
extern int security_bpf_prog_load(struct bpf_prog *prog, union bpf_attr *attr,
struct bpf_token *token, bool kernel);
extern void security_bpf_prog_free(struct bpf_prog *prog);
@@ -2303,6 +2318,16 @@ static inline int security_bpf_map_create(struct bpf_map *map, union bpf_attr *a
static inline void security_bpf_map_free(struct bpf_map *map)
{ }
+static inline int security_bpf_prog_load_post_integrity(struct bpf_prog *prog,
+ union bpf_attr *attr,
+ struct bpf_token *token,
+ bool kernel,
+ const struct lsm_id *lsmid,
+ enum lsm_integrity_verdict verdict)
+{
+ return 0;
+}
+
static inline int security_bpf_prog_load(struct bpf_prog *prog, union bpf_attr *attr,
struct bpf_token *token, bool kernel)
{
diff --git a/security/security.c b/security/security.c
index 67af9228c4e9..2d8279bd4aae 100644
--- a/security/security.c
+++ b/security/security.c
@@ -5232,6 +5232,50 @@ int security_bpf_map_create(struct bpf_map *map, union bpf_attr *attr,
return rc;
}
+/**
+ * security_bpf_prog_load_post_integrity() - Check if the BPF prog is allowed
+ * @prog: BPF program object
+ * @attr: BPF syscall attributes used to create BPF program
+ * @token: BPF token used to grant user access to BPF subsystem
+ * @kernel: whether or not call originated from kernel
+ * @lsmid: LSM ID of the LSM providing @verdict
+ * @verdict: result of the integrity verification
+ *
+ * See the comment block for the security_bpf_prog_load() LSM hook.
+ *
+ * This LSM hook is intended to be called from within the
+ * bpf_prog_load_integrity() callback that is part of the
+ * security_bpf_prog_load() hook; kernel subsystems outside the scope of the
+ * LSM framework should not call this hook directly.
+ *
+ * If the LSM calling into this hook receives a non-zero error code, it should
+ * return the same error code back to its caller. If this hook returns a zero,
+ * it does not necessarily mean that all of the enabled LSMs have authorized
+ * the BPF program load, as there may be other LSMs implementing BPF integrity
+ * checks which have yet to execute. However, if a zero is returned, the LSM
+ * calling into this hook should continue and return zero back to its caller.
+ *
+ * LSMs which implement the bpf_prog_load_post_integrity() callback and
+ * determine that a particular BPF program load is not authorized may choose to
+ * either return an error code for immediate rejection, or store their decision
+ * in their own LSM state attached to @prog, later returning an error code in
+ * the bpf_prog_load() callback. An immediate error code return is in keeping
+ * with the "fail fast" practice, but waiting until the bpf_prog_load()
+ * callback allows the LSM to consider multiple different integrity verdicts.
+ *
+ * Return: Returns 0 on success, error on failure.
+ */
+int security_bpf_prog_load_post_integrity(struct bpf_prog *prog,
+ union bpf_attr *attr,
+ struct bpf_token *token,
+ bool kernel,
+ const struct lsm_id *lsmid,
+ enum lsm_integrity_verdict verdict)
+{
+ return call_int_hook(bpf_prog_load_post_integrity, prog, attr, token,
+ kernel, lsmid, verdict);
+}
+
/**
* security_bpf_prog_load() - Check if loading of BPF program is allowed
* @prog: BPF program object
@@ -5240,8 +5284,24 @@ int security_bpf_map_create(struct bpf_map *map, union bpf_attr *attr,
* @kernel: whether or not call originated from kernel
*
* Perform an access control check when the kernel loads a BPF program and
- * allocates associated BPF program object. This hook is also responsible for
- * allocating any required LSM state for the BPF program.
+ * allocates the associated BPF program object. This hook is also responsible
+ * for allocating any required LSM state for the BPF program.
+ *
+ * This hook calls two LSM callbacks: bpf_prog_load_integrity() and
+ * bpf_prog_load(). The bpf_prog_load_integrity() callback is for those LSMs
+ * that wish to implement integrity verifications of BPF programs, e.g.
+ * signature verification, while the bpf_prog_load() callback is for general
+ * authorization of the BPF program load. Performing both verification and
+ * authorization in a single callback, with arbitrary LSM ordering, would be
+ * a challenge.
+ *
+ * LSMs which implement the bpf_prog_load_integrity() callback should call into
+ * the security_bpf_prog_load_post_integrity() hook with their integrity
+ * verdict. LSMs which implement BPF program integrity policy can register a
+ * callback for the security_bpf_prog_load_post_integrity() hook and
+ * either update their own internal state based on the verdict, or immediately
+ * reject the BPF program load with an error code. See the comment block for
+ * security_bpf_prog_load_post_integrity() for more information.
*
* Return: Returns 0 on success, error on failure.
*/
@@ -5254,9 +5314,18 @@ int security_bpf_prog_load(struct bpf_prog *prog, union bpf_attr *attr,
if (unlikely(rc))
return rc;
+ rc = call_int_hook(bpf_prog_load_integrity, prog, attr, token, kernel);
+ if (unlikely(rc))
+ goto err;
+
rc = call_int_hook(bpf_prog_load, prog, attr, token, kernel);
if (unlikely(rc))
- security_bpf_prog_free(prog);
+ goto err;
+
+ return rc;
+
+err:
+ security_bpf_prog_free(prog);
return rc;
}
--
2.52.0
^ permalink raw reply related
* [PATCH v2 05/10] crypto: pkcs7: add tests for pkcs7_get_authattr
From: Blaise Boscaccy @ 2026-02-27 23:38 UTC (permalink / raw)
To: Blaise Boscaccy, Jonathan Corbet, Paul Moore, James Morris,
Serge E. Hallyn, Mickaël Salaün, Günther Noack,
Dr. David Alan Gilbert, Andrew Morton, James.Bottomley, dhowells,
Fan Wu, Ryan Foster, linux-security-module, linux-doc,
linux-kernel, bpf
In-Reply-To: <20260227233930.2418522-1-bboscaccy@linux.microsoft.com>
From: James Bottomley <James.Bottomley@HansenPartnership.com>
Add example code to the test module pkcs7_key_type.c that verifies a
message and then pulls out a known authenticated attribute.
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Acked-by: David Howells <dhowells@redhat.com>
---
crypto/asymmetric_keys/pkcs7_key_type.c | 42 ++++++++++++++++++++++++-
1 file changed, 41 insertions(+), 1 deletion(-)
diff --git a/crypto/asymmetric_keys/pkcs7_key_type.c b/crypto/asymmetric_keys/pkcs7_key_type.c
index b930d3bbf1af..5a1ecb5501b2 100644
--- a/crypto/asymmetric_keys/pkcs7_key_type.c
+++ b/crypto/asymmetric_keys/pkcs7_key_type.c
@@ -12,6 +12,7 @@
#include <linux/verification.h>
#include <linux/key-type.h>
#include <keys/user-type.h>
+#include <crypto/pkcs7.h>
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("PKCS#7 testing key type");
@@ -51,16 +52,55 @@ static int pkcs7_view_content(void *ctx, const void *data, size_t len,
static int pkcs7_preparse(struct key_preparsed_payload *prep)
{
enum key_being_used_for usage = pkcs7_usage;
+ int ret;
+ struct pkcs7_message *pkcs7;
+ const void *data;
+ size_t len;
if (usage >= NR__KEY_BEING_USED_FOR) {
pr_err("Invalid usage type %d\n", usage);
return -EINVAL;
}
- return verify_pkcs7_signature(NULL, 0,
+ ret = verify_pkcs7_signature(NULL, 0,
prep->data, prep->datalen,
VERIFY_USE_SECONDARY_KEYRING, usage,
pkcs7_view_content, prep);
+ if (ret)
+ return ret;
+
+ pkcs7 = pkcs7_parse_message(prep->data, prep->datalen);
+ if (IS_ERR(pkcs7)) {
+ pr_err("pkcs7 parse error\n");
+ return PTR_ERR(pkcs7);
+ }
+
+ /*
+ * the parsed message has no trusted signer, so nothing should
+ * be returned here
+ */
+ ret = pkcs7_get_authattr(pkcs7, OID_messageDigest, &data, &len);
+ if (ret == 0) {
+ pr_err("OID returned when no trust in signer\n");
+ goto out;
+ }
+ /* add trust and check again */
+ ret = validate_pkcs7_trust(pkcs7, VERIFY_USE_SECONDARY_KEYRING);
+ if (ret) {
+ pr_err("validate_pkcs7_trust failed!!\n");
+ goto out;
+ }
+ /* now we should find the OID */
+ ret = pkcs7_get_authattr(pkcs7, OID_messageDigest, &data, &len);
+ if (ret) {
+ pr_err("Failed to get message digest\n");
+ goto out;
+ }
+ pr_info("Correctly Got message hash, size=%ld\n", len);
+
+ out:
+ pkcs7_free_message(pkcs7);
+ return 0;
}
/*
--
2.52.0
^ permalink raw reply related
* [PATCH v2 04/10] crypto: pkcs7: add ability to extract signed attributes by OID
From: Blaise Boscaccy @ 2026-02-27 23:38 UTC (permalink / raw)
To: Blaise Boscaccy, Jonathan Corbet, Paul Moore, James Morris,
Serge E. Hallyn, Mickaël Salaün, Günther Noack,
Dr. David Alan Gilbert, Andrew Morton, James.Bottomley, dhowells,
Fan Wu, Ryan Foster, linux-security-module, linux-doc,
linux-kernel, bpf
In-Reply-To: <20260227233930.2418522-1-bboscaccy@linux.microsoft.com>
From: James Bottomley <James.Bottomley@HansenPartnership.com>
Signers may add any information they like in signed attributes and
sometimes this information turns out to be relevant to specific
signing cases, so add an api pkcs7_get_authattr() to extract the value
of an authenticated attribute by specific OID. The current
implementation is designed for the single signer use case and simply
terminates the search when it finds the relevant OID.
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
---
crypto/asymmetric_keys/Makefile | 4 +-
crypto/asymmetric_keys/pkcs7_aa.asn1 | 18 ++++++
crypto/asymmetric_keys/pkcs7_parser.c | 81 +++++++++++++++++++++++++++
include/crypto/pkcs7.h | 4 ++
4 files changed, 106 insertions(+), 1 deletion(-)
create mode 100644 crypto/asymmetric_keys/pkcs7_aa.asn1
diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile
index bc65d3b98dcb..f99b7169ae7c 100644
--- a/crypto/asymmetric_keys/Makefile
+++ b/crypto/asymmetric_keys/Makefile
@@ -53,12 +53,14 @@ clean-files += pkcs8.asn1.c pkcs8.asn1.h
obj-$(CONFIG_PKCS7_MESSAGE_PARSER) += pkcs7_message.o
pkcs7_message-y := \
pkcs7.asn1.o \
+ pkcs7_aa.asn1.o \
pkcs7_parser.o \
pkcs7_trust.o \
pkcs7_verify.o
-$(obj)/pkcs7_parser.o: $(obj)/pkcs7.asn1.h
+$(obj)/pkcs7_parser.o: $(obj)/pkcs7.asn1.h $(obj)/pkcs7_aa.asn1.h
$(obj)/pkcs7.asn1.o: $(obj)/pkcs7.asn1.c $(obj)/pkcs7.asn1.h
+$(obj)/pkcs7_aa.asn1.o: $(obj)/pkcs7_aa.asn1.c $(obj)/pkcs7_aa.asn1.h
#
# PKCS#7 parser testing key
diff --git a/crypto/asymmetric_keys/pkcs7_aa.asn1 b/crypto/asymmetric_keys/pkcs7_aa.asn1
new file mode 100644
index 000000000000..7a8857bdf56e
--- /dev/null
+++ b/crypto/asymmetric_keys/pkcs7_aa.asn1
@@ -0,0 +1,18 @@
+-- SPDX-License-Identifier: BSD-3-Clause
+--
+-- Copyright (C) 2009 IETF Trust and the persons identified as authors
+-- of the code
+--
+-- https://www.rfc-editor.org/rfc/rfc5652#section-3
+
+AA ::= CHOICE {
+ aaSet [0] IMPLICIT AASet,
+ aaSequence [2] EXPLICIT SEQUENCE OF AuthenticatedAttribute
+}
+
+AASet ::= SET OF AuthenticatedAttribute
+
+AuthenticatedAttribute ::= SEQUENCE {
+ type OBJECT IDENTIFIER ({ pkcs7_aa_note_OID }),
+ values SET OF ANY ({ pkcs7_aa_note_attr })
+}
diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c
index 6e3ffdac83ac..d467866f7d93 100644
--- a/crypto/asymmetric_keys/pkcs7_parser.c
+++ b/crypto/asymmetric_keys/pkcs7_parser.c
@@ -15,6 +15,7 @@
#include <crypto/public_key.h>
#include "pkcs7_parser.h"
#include "pkcs7.asn1.h"
+#include "pkcs7_aa.asn1.h"
MODULE_DESCRIPTION("PKCS#7 parser");
MODULE_AUTHOR("Red Hat, Inc.");
@@ -211,6 +212,86 @@ int pkcs7_get_content_data(const struct pkcs7_message *pkcs7,
}
EXPORT_SYMBOL_GPL(pkcs7_get_content_data);
+struct pkcs7_aa_context {
+ bool found;
+ enum OID oid_to_find;
+ const void *data;
+ size_t len;
+};
+
+int pkcs7_aa_note_OID(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_aa_context *ctx = context;
+ enum OID oid = look_up_OID(value, vlen);
+
+ ctx->found = (oid == ctx->oid_to_find);
+
+ return 0;
+}
+
+int pkcs7_aa_note_attr(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_aa_context *ctx = context;
+
+ if (ctx->found) {
+ ctx->data = value;
+ ctx->len = vlen;
+ }
+
+ return 0;
+}
+
+/**
+ * pkcs7_get_authattr - get authenticated attribute by OID
+ * @pkcs7: The preparsed PKCS#7 message
+ * @oid: the enum value of the OID to find
+ * @_data: Place to return a pointer to the attribute value
+ * @_len: length of the attribute value
+ *
+ * Searches the authenticated attributes until one is found with a
+ * matching OID. Note that because the attributes are per signer
+ * there could be multiple signers with different values, but this
+ * routine will simply return the first one in parse order.
+ *
+ * Returns -ENODATA if the attribute can't be found
+ */
+int pkcs7_get_authattr(const struct pkcs7_message *pkcs7,
+ enum OID oid,
+ const void **_data, size_t *_len)
+{
+ struct pkcs7_signed_info *sinfo = pkcs7->signed_infos;
+ struct pkcs7_aa_context ctx;
+
+ ctx.data = NULL;
+ ctx.oid_to_find = oid;
+
+ for (; sinfo; sinfo = sinfo->next) {
+ int ret;
+
+ /* only extract OIDs from validated signers */
+ if (!sinfo->verified)
+ continue;
+
+ ret = asn1_ber_decoder(&pkcs7_aa_decoder, &ctx,
+ sinfo->authattrs, sinfo->authattrs_len);
+ if (ret < 0 || ctx.data != NULL)
+ break;
+ }
+
+ if (!ctx.data)
+ return -ENODATA;
+
+ *_data = ctx.data;
+ *_len = ctx.len;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pkcs7_get_authattr);
+
/*
* Note an OID when we find one for later processing when we know how
* to interpret it.
diff --git a/include/crypto/pkcs7.h b/include/crypto/pkcs7.h
index 38ec7f5f9041..bd83202cd805 100644
--- a/include/crypto/pkcs7.h
+++ b/include/crypto/pkcs7.h
@@ -25,6 +25,10 @@ extern void pkcs7_free_message(struct pkcs7_message *pkcs7);
extern int pkcs7_get_content_data(const struct pkcs7_message *pkcs7,
const void **_data, size_t *_datalen,
size_t *_headerlen);
+extern int pkcs7_get_authattr(const struct pkcs7_message *pkcs7,
+ enum OID oid,
+ const void **_data, size_t *_len);
+
/*
* pkcs7_trust.c
--
2.52.0
^ permalink raw reply related
* [PATCH v2 03/10] crypto: pkcs7: allow pkcs7_digest() to be called from pkcs7_trust
From: Blaise Boscaccy @ 2026-02-27 23:38 UTC (permalink / raw)
To: Blaise Boscaccy, Jonathan Corbet, Paul Moore, James Morris,
Serge E. Hallyn, Mickaël Salaün, Günther Noack,
Dr. David Alan Gilbert, Andrew Morton, James.Bottomley, dhowells,
Fan Wu, Ryan Foster, linux-security-module, linux-doc,
linux-kernel, bpf
In-Reply-To: <20260227233930.2418522-1-bboscaccy@linux.microsoft.com>
From: James Bottomley <James.Bottomley@HansenPartnership.com>
Trying to run pkcs7_validate_trust() on something that parsed
correctly but is not verified doesn't work because the signature
digest hasn't been calculated. Fix this by adding a digest calclation
in to pkcs7_validate_one(). This is almost a nop if the digest exists.
Additionally, the trust validation doesn't know the data payload, so
adjust the digest calculator to skip checking the data digest if
pkcs7->data is NULL. A check is added in pkcs7_verify() for
pkcs7->data being null (returning -EBADMSG) to guard against someone
forgetting to supply data and getting an invalid success return.
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
---
crypto/asymmetric_keys/pkcs7_parser.h | 3 +++
crypto/asymmetric_keys/pkcs7_trust.c | 8 ++++++++
crypto/asymmetric_keys/pkcs7_verify.c | 13 +++++++++----
3 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/crypto/asymmetric_keys/pkcs7_parser.h b/crypto/asymmetric_keys/pkcs7_parser.h
index 203062a33def..cbe823aeac06 100644
--- a/crypto/asymmetric_keys/pkcs7_parser.h
+++ b/crypto/asymmetric_keys/pkcs7_parser.h
@@ -66,3 +66,6 @@ struct pkcs7_message {
size_t data_hdrlen; /* Length of Data ASN.1 header */
const void *data; /* Content Data (or 0) */
};
+
+int pkcs7_digest(struct pkcs7_message *pkcs7,
+ struct pkcs7_signed_info *sinfo);
diff --git a/crypto/asymmetric_keys/pkcs7_trust.c b/crypto/asymmetric_keys/pkcs7_trust.c
index 78ebfb6373b6..7cb0a6bc7b32 100644
--- a/crypto/asymmetric_keys/pkcs7_trust.c
+++ b/crypto/asymmetric_keys/pkcs7_trust.c
@@ -30,6 +30,14 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7,
kenter(",%u,", sinfo->index);
+ /*
+ * if we're being called immediately after parse, the
+ * signature won't have a calculated digest yet, so calculate
+ * one. This function returns immediately if a digest has
+ * already been calculated
+ */
+ pkcs7_digest(pkcs7, sinfo);
+
if (sinfo->unsupported_crypto) {
kleave(" = -ENOPKG [cached]");
return -ENOPKG;
diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c
index 474e2c1ae21b..3080f0ec52e0 100644
--- a/crypto/asymmetric_keys/pkcs7_verify.c
+++ b/crypto/asymmetric_keys/pkcs7_verify.c
@@ -19,8 +19,8 @@
/*
* Digest the relevant parts of the PKCS#7 data
*/
-static int pkcs7_digest(struct pkcs7_message *pkcs7,
- struct pkcs7_signed_info *sinfo)
+int pkcs7_digest(struct pkcs7_message *pkcs7,
+ struct pkcs7_signed_info *sinfo)
{
struct public_key_signature *sig = sinfo->sig;
struct crypto_shash *tfm;
@@ -93,8 +93,8 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7,
goto error;
}
- if (memcmp(sig->m, sinfo->msgdigest,
- sinfo->msgdigest_len) != 0) {
+ if (pkcs7->data && memcmp(sig->m, sinfo->msgdigest,
+ sinfo->msgdigest_len) != 0) {
pr_warn("Sig %u: Message digest doesn't match\n",
sinfo->index);
ret = -EKEYREJECTED;
@@ -463,6 +463,11 @@ int pkcs7_verify(struct pkcs7_message *pkcs7,
return -EINVAL;
}
+ if (!pkcs7->data) {
+ pr_warn("Data not supplied to verify operation\n");
+ return -EBADMSG;
+ }
+
for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) {
ret = pkcs7_verify_one(pkcs7, sinfo);
if (sinfo->blacklisted) {
--
2.52.0
^ permalink raw reply related
* [PATCH v2 02/10] crypto: pkcs7: add flag for validated trust on a signed info block
From: Blaise Boscaccy @ 2026-02-27 23:38 UTC (permalink / raw)
To: Blaise Boscaccy, Jonathan Corbet, Paul Moore, James Morris,
Serge E. Hallyn, Mickaël Salaün, Günther Noack,
Dr. David Alan Gilbert, Andrew Morton, James.Bottomley, dhowells,
Fan Wu, Ryan Foster, linux-security-module, linux-doc,
linux-kernel, bpf
In-Reply-To: <20260227233930.2418522-1-bboscaccy@linux.microsoft.com>
From: James Bottomley <James.Bottomley@HansenPartnership.com>
Allow consumers of struct pkcs7_message to tell if any of the sinfo
fields has passed a trust validation. Note that this does not happen
in parsing, pkcs7_validate_trust() must be explicitly called or called
via validate_pkcs7_trust().
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
---
crypto/asymmetric_keys/pkcs7_parser.h | 1 +
crypto/asymmetric_keys/pkcs7_trust.c | 1 +
2 files changed, 2 insertions(+)
diff --git a/crypto/asymmetric_keys/pkcs7_parser.h b/crypto/asymmetric_keys/pkcs7_parser.h
index 6ef9f335bb17..203062a33def 100644
--- a/crypto/asymmetric_keys/pkcs7_parser.h
+++ b/crypto/asymmetric_keys/pkcs7_parser.h
@@ -20,6 +20,7 @@ struct pkcs7_signed_info {
unsigned index;
bool unsupported_crypto; /* T if not usable due to missing crypto */
bool blacklisted;
+ bool verified; /* T if this signer has validated trust */
/* Message digest - the digest of the Content Data (or NULL) */
const void *msgdigest;
diff --git a/crypto/asymmetric_keys/pkcs7_trust.c b/crypto/asymmetric_keys/pkcs7_trust.c
index 9a87c34ed173..78ebfb6373b6 100644
--- a/crypto/asymmetric_keys/pkcs7_trust.c
+++ b/crypto/asymmetric_keys/pkcs7_trust.c
@@ -127,6 +127,7 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7,
for (p = sinfo->signer; p != x509; p = p->signer)
p->verified = true;
}
+ sinfo->verified = true;
kleave(" = 0");
return 0;
}
--
2.52.0
^ permalink raw reply related
* [PATCH v2 01/10] certs: break out pkcs7 check into its own function
From: Blaise Boscaccy @ 2026-02-27 23:38 UTC (permalink / raw)
To: Blaise Boscaccy, Jonathan Corbet, Paul Moore, James Morris,
Serge E. Hallyn, Mickaël Salaün, Günther Noack,
Dr. David Alan Gilbert, Andrew Morton, James.Bottomley, dhowells,
Fan Wu, Ryan Foster, linux-security-module, linux-doc,
linux-kernel, bpf
In-Reply-To: <20260227233930.2418522-1-bboscaccy@linux.microsoft.com>
From: James Bottomley <James.Bottomley@HansenPartnership.com>
Add new validate_pkcs7_trust() function which can operate on the
system keyrings and is simply some of the innards of
verify_pkcs7_message_sig().
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
---
certs/system_keyring.c | 76 +++++++++++++++++++++---------------
include/linux/verification.h | 2 +
2 files changed, 47 insertions(+), 31 deletions(-)
diff --git a/certs/system_keyring.c b/certs/system_keyring.c
index e0761436ec7f..dcbefc2d3f6d 100644
--- a/certs/system_keyring.c
+++ b/certs/system_keyring.c
@@ -298,42 +298,19 @@ late_initcall(load_system_certificate_list);
#ifdef CONFIG_SYSTEM_DATA_VERIFICATION
/**
- * verify_pkcs7_message_sig - Verify a PKCS#7-based signature on system data.
- * @data: The data to be verified (NULL if expecting internal data).
- * @len: Size of @data.
+ * validate_pkcs7_trust - add trust markers based on keyring
* @pkcs7: The PKCS#7 message that is the signature.
* @trusted_keys: Trusted keys to use (NULL for builtin trusted keys only,
* (void *)1UL for all trusted keys).
- * @usage: The use to which the key is being put.
- * @view_content: Callback to gain access to content.
- * @ctx: Context for callback.
*/
-int verify_pkcs7_message_sig(const void *data, size_t len,
- struct pkcs7_message *pkcs7,
- struct key *trusted_keys,
- enum key_being_used_for usage,
- int (*view_content)(void *ctx,
- const void *data, size_t len,
- size_t asn1hdrlen),
- void *ctx)
+int validate_pkcs7_trust(struct pkcs7_message *pkcs7, struct key *trusted_keys)
{
int ret;
- /* The data should be detached - so we need to supply it. */
- if (data && pkcs7_supply_detached_data(pkcs7, data, len) < 0) {
- pr_err("PKCS#7 signature with non-detached data\n");
- ret = -EBADMSG;
- goto error;
- }
-
- ret = pkcs7_verify(pkcs7, usage);
- if (ret < 0)
- goto error;
-
ret = is_key_on_revocation_list(pkcs7);
if (ret != -ENOKEY) {
pr_devel("PKCS#7 key is on revocation list\n");
- goto error;
+ return ret;
}
if (!trusted_keys) {
@@ -351,18 +328,55 @@ int verify_pkcs7_message_sig(const void *data, size_t len,
trusted_keys = NULL;
#endif
if (!trusted_keys) {
- ret = -ENOKEY;
pr_devel("PKCS#7 platform keyring is not available\n");
- goto error;
+ return -ENOKEY;
}
}
ret = pkcs7_validate_trust(pkcs7, trusted_keys);
- if (ret < 0) {
- if (ret == -ENOKEY)
- pr_devel("PKCS#7 signature not signed with a trusted key\n");
+ if (ret == -ENOKEY)
+ pr_devel("PKCS#7 signature not signed with a trusted key\n");
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(validate_pkcs7_trust);
+
+/**
+ * verify_pkcs7_message_sig - Verify a PKCS#7-based signature on system data.
+ * @data: The data to be verified (NULL if expecting internal data).
+ * @len: Size of @data.
+ * @pkcs7: The PKCS#7 message that is the signature.
+ * @trusted_keys: Trusted keys to use (NULL for builtin trusted keys only,
+ * (void *)1UL for all trusted keys).
+ * @usage: The use to which the key is being put.
+ * @view_content: Callback to gain access to content.
+ * @ctx: Context for callback.
+ */
+int verify_pkcs7_message_sig(const void *data, size_t len,
+ struct pkcs7_message *pkcs7,
+ struct key *trusted_keys,
+ enum key_being_used_for usage,
+ int (*view_content)(void *ctx,
+ const void *data, size_t len,
+ size_t asn1hdrlen),
+ void *ctx)
+{
+ int ret;
+
+ /* The data should be detached - so we need to supply it. */
+ if (data && pkcs7_supply_detached_data(pkcs7, data, len) < 0) {
+ pr_err("PKCS#7 signature with non-detached data\n");
+ ret = -EBADMSG;
goto error;
}
+ ret = pkcs7_verify(pkcs7, usage);
+ if (ret < 0)
+ goto error;
+
+ ret = validate_pkcs7_trust(pkcs7, trusted_keys);
+ if (ret < 0)
+ goto error;
+
if (view_content) {
size_t asn1hdrlen;
diff --git a/include/linux/verification.h b/include/linux/verification.h
index dec7f2beabfd..57f1460d36f1 100644
--- a/include/linux/verification.h
+++ b/include/linux/verification.h
@@ -44,6 +44,8 @@ enum key_being_used_for {
struct key;
struct pkcs7_message;
+extern int validate_pkcs7_trust(struct pkcs7_message *pkcs7,
+ struct key *trusted_keys);
extern int verify_pkcs7_signature(const void *data, size_t len,
const void *raw_pkcs7, size_t pkcs7_len,
struct key *trusted_keys,
--
2.52.0
^ permalink raw reply related
* [PATCH v2 00/10] Reintrodce Hornet LSM
From: Blaise Boscaccy @ 2026-02-27 23:38 UTC (permalink / raw)
To: Blaise Boscaccy, Jonathan Corbet, Paul Moore, James Morris,
Serge E. Hallyn, Mickaël Salaün, Günther Noack,
Dr. David Alan Gilbert, Andrew Morton, James.Bottomley, dhowells,
Fan Wu, Ryan Foster, linux-security-module, linux-doc,
linux-kernel, bpf
This patch series introduces the next iteration of the Hornet LSM.
Hornet’s goal is to provide a secure and extensible in-kernel
signature verification mechanism for eBPF programs.
Hornet addresses concerns from users who require strict audit trails and
verification guarantees for eBPF programs, especially in
security-sensitive environments. Many production systems need assurance
that only authorized, unmodified eBPF programs are loaded into the
kernel. Hornet provides this assurance through cryptographic signature
verification.
The currently accepted loader-plus-map signature verification scheme,
mandated by Alexei and KP, is simple to implement and generally
acceptable if users and administrators are satisfied with it. However,
verifying both the loader and the maps offers additional benefits
beyond verifying the loader alone:
1. Security and Audit Integrity
A key advantage is that the LSM hook for authorizing BPF program loads
can operate after signature verification. This ensures:
* Access control decisions are based on verified signature status.
* Accurate system state measurement and logging.
* Log entries claiming a verified signature are truthful, avoiding
misleading records where only the loader was verified while the actual
BPF program verification occurs later without logging.
2. TOCTOU Attack Prevention
The current map hash implementation may be vulnerable to a TOCTOU
attack because it allows unfrozen maps to cache a previously
calculated hash. The accepted “trusted loader” scheme cannot detect
this and may permit loading altered maps.
3. Supply Chain Integrity
Verify that eBPF programs and their associated map data have not been
modified since they were built and signed, in the kernel proper, may
aid in protecting against supply chain attacks.
This approach addresses concerns from users who require strict audit
trails and verification guarantees, especially in security-sensitive
environments. Map hashes for extended verification are passed via the
existing PKCS#7 UAPI and verified by the crypto subsystem. Hornet then
calculates the program’s verification state. Hornet itself does not
enforce a policy on whether unsigned or partially signed programs
should be rejected. It delegates that decision to downstream LSMs
hook, making it a composable building block in a larger security
architecture.
Changes in V2:
- Addressed possible TocTou races in hash verification
- Improved documentation and tooling
- Added Alexie's nack
Link to RFC: https://lore.kernel.org/linux-security-module/20251211021257.1208712-1-bboscaccy@linux.microsoft.com/
Blaise Boscaccy (4):
security: Hornet LSM
hornet: Introduce gen_sig
hornet: Add a light skeleton data extractor scripts
selftests/hornet: Add a selftest for the Hornet LSM
James Bottomley (5):
certs: break out pkcs7 check into its own function
crypto: pkcs7: add flag for validated trust on a signed info block
crypto: pkcs7: allow pkcs7_digest() to be called from pkcs7_trust
crypto: pkcs7: add ability to extract signed attributes by OID
crypto: pkcs7: add tests for pkcs7_get_authattr
Paul Moore (1):
lsm: framework for BPF integrity verification
Documentation/admin-guide/LSM/Hornet.rst | 310 +++++++++++++++
Documentation/admin-guide/LSM/index.rst | 1 +
MAINTAINERS | 9 +
certs/system_keyring.c | 76 ++--
crypto/asymmetric_keys/Makefile | 4 +-
crypto/asymmetric_keys/pkcs7_aa.asn1 | 18 +
crypto/asymmetric_keys/pkcs7_key_type.c | 42 +-
crypto/asymmetric_keys/pkcs7_parser.c | 81 ++++
crypto/asymmetric_keys/pkcs7_parser.h | 4 +
crypto/asymmetric_keys/pkcs7_trust.c | 9 +
crypto/asymmetric_keys/pkcs7_verify.c | 13 +-
include/crypto/pkcs7.h | 4 +
include/linux/lsm_hook_defs.h | 5 +
include/linux/oid_registry.h | 3 +
include/linux/security.h | 25 ++
include/linux/verification.h | 2 +
include/uapi/linux/lsm.h | 1 +
scripts/Makefile | 1 +
scripts/hornet/Makefile | 5 +
scripts/hornet/extract-insn.sh | 27 ++
scripts/hornet/extract-map.sh | 27 ++
scripts/hornet/extract-skel.sh | 27 ++
scripts/hornet/gen_sig.c | 392 +++++++++++++++++++
scripts/hornet/write-sig.sh | 27 ++
security/Kconfig | 3 +-
security/Makefile | 1 +
security/hornet/Kconfig | 11 +
security/hornet/Makefile | 7 +
security/hornet/hornet.asn1 | 13 +
security/hornet/hornet_lsm.c | 323 +++++++++++++++
security/security.c | 75 +++-
tools/testing/selftests/Makefile | 1 +
tools/testing/selftests/hornet/Makefile | 63 +++
tools/testing/selftests/hornet/loader.c | 21 +
tools/testing/selftests/hornet/trivial.bpf.c | 33 ++
35 files changed, 1623 insertions(+), 41 deletions(-)
create mode 100644 Documentation/admin-guide/LSM/Hornet.rst
create mode 100644 crypto/asymmetric_keys/pkcs7_aa.asn1
create mode 100644 scripts/hornet/Makefile
create mode 100755 scripts/hornet/extract-insn.sh
create mode 100755 scripts/hornet/extract-map.sh
create mode 100755 scripts/hornet/extract-skel.sh
create mode 100644 scripts/hornet/gen_sig.c
create mode 100755 scripts/hornet/write-sig.sh
create mode 100644 security/hornet/Kconfig
create mode 100644 security/hornet/Makefile
create mode 100644 security/hornet/hornet.asn1
create mode 100644 security/hornet/hornet_lsm.c
create mode 100644 tools/testing/selftests/hornet/Makefile
create mode 100644 tools/testing/selftests/hornet/loader.c
create mode 100644 tools/testing/selftests/hornet/trivial.bpf.c
--
2.52.0
^ permalink raw reply
* Re: [PATCH 03/61] trace: update VFS-layer trace events for u64 i_ino
From: Jeff Layton @ 2026-02-27 21:05 UTC (permalink / raw)
To: Steven Rostedt
Cc: Alexander Viro, Christian Brauner, Jan Kara, Masami Hiramatsu,
Mathieu Desnoyers, Dan Williams, Matthew Wilcox, Eric Biggers,
Theodore Y. Ts'o, Muchun Song, Oscar Salvador,
David Hildenbrand, David Howells, Paulo Alcantara, Andreas Dilger,
Jan Kara, Jaegeuk Kim, Chao Yu, Trond Myklebust, Anna Schumaker,
Chuck Lever, NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
Steve French, Ronnie Sahlberg, Shyam Prasad N, Bharath SM,
Alexander Aring, Ryusuke Konishi, Viacheslav Dubeyko,
Eric Van Hensbergen, Latchesar Ionkov, Dominique Martinet,
Christian Schoenebeck, David Sterba, Marc Dionne, Ian Kent,
Luis de Bethencourt, Salah Triki, Tigran A. Aivazian,
Ilya Dryomov, Alex Markuze, Jan Harkes, coda, Nicolas Pitre,
Tyler Hicks, Amir Goldstein, Christoph Hellwig,
John Paul Adrian Glaubitz, Yangtao Li, Mikulas Patocka,
David Woodhouse, Richard Weinberger, Dave Kleikamp,
Konstantin Komarov, Mark Fasheh, Joel Becker, Joseph Qi,
Mike Marshall, Martin Brandenburg, Miklos Szeredi, Anders Larsen,
Zhihao Cheng, Damien Le Moal, Naohiro Aota, Johannes Thumshirn,
John Johansen, Paul Moore, James Morris, Serge E. Hallyn,
Mimi Zohar, Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Fan Wu,
Stephen Smalley, Ondrej Mosnacek, Casey Schaufler, Alex Deucher,
Christian König, David Airlie, Simona Vetter, Sumit Semwal,
Eric Dumazet, Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn,
David S. Miller, Jakub Kicinski, Simon Horman, Oleg Nesterov,
Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
Ian Rogers, Adrian Hunter, James Clark, Darrick J. Wong,
Martin Schiller, linux-fsdevel, linux-kernel, linux-trace-kernel,
nvdimm, fsverity, linux-mm, netfs, linux-ext4, linux-f2fs-devel,
linux-nfs, linux-cifs, samba-technical, linux-nilfs, v9fs,
linux-afs, autofs, ceph-devel, codalist, ecryptfs, linux-mtd,
jfs-discussion, ntfs3, ocfs2-devel, devel, linux-unionfs,
apparmor, linux-security-module, linux-integrity, selinux,
amd-gfx, dri-devel, linux-media, linaro-mm-sig, netdev,
linux-perf-users, linux-fscrypt, linux-xfs, linux-hams, linux-x25
In-Reply-To: <20260226124842.5593ed85@gandalf.local.home>
On Thu, 2026-02-26 at 12:48 -0500, Steven Rostedt wrote:
> On Thu, 26 Feb 2026 10:55:05 -0500
> Jeff Layton <jlayton@kernel.org> wrote:
>
> > Update trace event definitions in VFS-layer trace headers to use u64
> > instead of ino_t/unsigned long for inode number fields, and change
> > format strings from %lu/%lx to %llu/%llx to match.
> >
> > This is needed because i_ino is now u64. Changing trace event field
> > types changes the binary trace format, but the self-describing format
> > metadata handles this transparently for modern trace-cmd and perf.
> >
> > Files updated:
> > - cachefiles.h, filelock.h, filemap.h, fs_dax.h, fsverity.h,
> > hugetlbfs.h, netfs.h, readahead.h, timestamp.h, writeback.h
> >
>
> Hmm, on 32 bit systems, this will likely cause "holes" in a lot of these
> events.
>
> > Signed-off-by: Jeff Layton <jlayton@kernel.org>
> > ---
> > include/trace/events/cachefiles.h | 18 ++---
> > include/trace/events/filelock.h | 16 ++---
> > include/trace/events/filemap.h | 20 +++---
> > include/trace/events/fs_dax.h | 20 +++---
> > include/trace/events/fsverity.h | 30 ++++----
> > include/trace/events/hugetlbfs.h | 28 ++++----
> > include/trace/events/netfs.h | 4 +-
> > include/trace/events/readahead.h | 12 ++--
> > include/trace/events/timestamp.h | 12 ++--
> > include/trace/events/writeback.h | 148 +++++++++++++++++++-------------------
> > 10 files changed, 154 insertions(+), 154 deletions(-)
> >
> > diff --git a/include/trace/events/cachefiles.h b/include/trace/events/cachefiles.h
> > index a743b2a35ea7001447b3e05d41539cb88013bc7f..f967027711ee823f224abc1b8ab03f63da06ae6f 100644
> > --- a/include/trace/events/cachefiles.h
> > +++ b/include/trace/events/cachefiles.h
> > @@ -251,8 +251,8 @@ TRACE_EVENT(cachefiles_lookup,
> > TP_STRUCT__entry(
> > __field(unsigned int, obj)
> > __field(short, error)
>
> There was already a 2 byte hole here, but that's not a big deal.
>
> > - __field(unsigned long, dino)
> > - __field(unsigned long, ino)
> > + __field(u64, dino)
> > + __field(u64, ino)
> > ),
> >
> > TP_fast_assign(
> > @@ -263,7 +263,7 @@ TRACE_EVENT(cachefiles_lookup,
> > __entry->error = IS_ERR(de) ? PTR_ERR(de) : 0;
> > ),
> >
> > - TP_printk("o=%08x dB=%lx B=%lx e=%d",
> > + TP_printk("o=%08x dB=%llx B=%llx e=%d",
> > __entry->obj, __entry->dino, __entry->ino, __entry->error)
> > );
> >
> > @@ -579,7 +579,7 @@ TRACE_EVENT(cachefiles_mark_active,
> > /* Note that obj may be NULL */
> > TP_STRUCT__entry(
> > __field(unsigned int, obj)
> > - __field(ino_t, inode)
> > + __field(u64, inode)
>
> Might be better to reorder any of these that have int first.
>
> u64 inode;
> int obj;
>
> Will be packed tighter than:
>
> int obj
> u64 inode;
>
> Probably should have changed that before anyway.
>
Ok, I'll look at that. Given the number of places that need it though I
may do it in a separate patch.
> > ),
> >
> > TP_fast_assign(
> > @@ -587,7 +587,7 @@ TRACE_EVENT(cachefiles_mark_active,
> > __entry->inode = inode->i_ino;
> > ),
> >
> > - TP_printk("o=%08x B=%lx",
> > + TP_printk("o=%08x B=%llx",
> > __entry->obj, __entry->inode)
> > );
> >
> > @@ -600,7 +600,7 @@ TRACE_EVENT(cachefiles_mark_failed,
> > /* Note that obj may be NULL */
> > TP_STRUCT__entry(
> > __field(unsigned int, obj)
> > - __field(ino_t, inode)
> > + __field(u64, inode)
>
> Is ino_t being changed? Why the update here?
>
No, ino_t isn't. That's part of the ABI and has to remain unsigned
long. The point of this series is to make inode->i_ino a u64. Any event
holding an ino_t today is going to need a 64-bit field to fully
describe it.
And to be clear, this should make things better for 32-bit boxes in the
long run. Once this change is done, i_ino should be a reliable source
of info regardless of machine's word size.
For the tracepoints, I think it's best to just extend them to 64-bit
fields outright rather than using the new (temporary) kino_t typedef
that I'm adding.
> > ),
> >
> > TP_fast_assign(
> > @@ -608,7 +608,7 @@ TRACE_EVENT(cachefiles_mark_failed,
> > __entry->inode = inode->i_ino;
> > ),
> >
> > - TP_printk("o=%08x B=%lx",
> > + TP_printk("o=%08x B=%llx",
> > __entry->obj, __entry->inode)
> > );
> >
> > @@ -621,7 +621,7 @@ TRACE_EVENT(cachefiles_mark_inactive,
> > /* Note that obj may be NULL */
> > TP_STRUCT__entry(
> > __field(unsigned int, obj)
> > - __field(ino_t, inode)
> > + __field(u64, inode)
>
> Ditto.
>
> > ),
> >
> > TP_fast_assign(
> > @@ -629,7 +629,7 @@ TRACE_EVENT(cachefiles_mark_inactive,
> > __entry->inode = inode->i_ino;
> > ),
> >
> > - TP_printk("o=%08x B=%lx",
> > + TP_printk("o=%08x B=%llx",
> > __entry->obj, __entry->inode)
> > );
> >
> > diff --git a/include/trace/events/filelock.h b/include/trace/events/filelock.h
> > index 370016c38a5bbc07d5ba6c102030b49c9eb6424d..41bc752616b25d6cd7955203e2c604029d0b440c 100644
> > --- a/include/trace/events/filelock.h
> > +++ b/include/trace/events/filelock.h
> > @@ -42,7 +42,7 @@ TRACE_EVENT(locks_get_lock_context,
> > TP_ARGS(inode, type, ctx),
> >
> > TP_STRUCT__entry(
> > - __field(unsigned long, i_ino)
> > + __field(u64, i_ino)
> > __field(dev_t, s_dev)
> > __field(unsigned char, type)
> > __field(struct file_lock_context *, ctx)
> > @@ -55,7 +55,7 @@ TRACE_EVENT(locks_get_lock_context,
> > __entry->ctx = ctx;
> > ),
> >
> > - TP_printk("dev=0x%x:0x%x ino=0x%lx type=%s ctx=%p",
> > + TP_printk("dev=0x%x:0x%x ino=0x%llx type=%s ctx=%p",
> > MAJOR(__entry->s_dev), MINOR(__entry->s_dev),
> > __entry->i_ino, show_fl_type(__entry->type), __entry->ctx)
> > );
> > @@ -67,7 +67,7 @@ DECLARE_EVENT_CLASS(filelock_lock,
> >
> > TP_STRUCT__entry(
> > __field(struct file_lock *, fl)
> > - __field(unsigned long, i_ino)
> > + __field(u64, i_ino)
>
> Having u64 before a pointer would be tighter on 32 bit systems, and leaves
> out any holes in the trace.
>
> > __field(dev_t, s_dev)
> > __field(struct file_lock_core *, blocker)
> > __field(fl_owner_t, owner)
> > @@ -93,7 +93,7 @@ DECLARE_EVENT_CLASS(filelock_lock,
> > __entry->ret = ret;
> > ),
> >
> > - TP_printk("fl=%p dev=0x%x:0x%x ino=0x%lx fl_blocker=%p fl_owner=%p fl_pid=%u fl_flags=%s fl_type=%s fl_start=%lld fl_end=%lld ret=%d",
> > + TP_printk("fl=%p dev=0x%x:0x%x ino=0x%llx fl_blocker=%p fl_owner=%p fl_pid=%u fl_flags=%s fl_type=%s fl_start=%lld fl_end=%lld ret=%d",
> > __entry->fl, MAJOR(__entry->s_dev), MINOR(__entry->s_dev),
> > __entry->i_ino, __entry->blocker, __entry->owner,
> > __entry->pid, show_fl_flags(__entry->flags),
> > @@ -124,7 +124,7 @@ DECLARE_EVENT_CLASS(filelock_lease,
> >
> > TP_STRUCT__entry(
> > __field(struct file_lease *, fl)
> > - __field(unsigned long, i_ino)
> > + __field(u64, i_ino)
>
> Same here.
>
> > __field(dev_t, s_dev)
> > __field(struct file_lock_core *, blocker)
> > __field(fl_owner_t, owner)
> > @@ -146,7 +146,7 @@ DECLARE_EVENT_CLASS(filelock_lease,
> > __entry->downgrade_time = fl ? fl->fl_downgrade_time : 0;
> > ),
> >
> > - TP_printk("fl=%p dev=0x%x:0x%x ino=0x%lx fl_blocker=%p fl_owner=%p fl_flags=%s fl_type=%s fl_break_time=%lu fl_downgrade_time=%lu",
> > + TP_printk("fl=%p dev=0x%x:0x%x ino=0x%llx fl_blocker=%p fl_owner=%p fl_flags=%s fl_type=%s fl_break_time=%lu fl_downgrade_time=%lu",
> > __entry->fl, MAJOR(__entry->s_dev), MINOR(__entry->s_dev),
> > __entry->i_ino, __entry->blocker, __entry->owner,
> > show_fl_flags(__entry->flags),
> > @@ -175,7 +175,7 @@ TRACE_EVENT(generic_add_lease,
> > TP_ARGS(inode, fl),
> >
> > TP_STRUCT__entry(
> > - __field(unsigned long, i_ino)
> > + __field(u64, i_ino)
> > __field(int, wcount)
> > __field(int, rcount)
> > __field(int, icount)
> > @@ -196,7 +196,7 @@ TRACE_EVENT(generic_add_lease,
> > __entry->type = fl->c.flc_type;
> > ),
> >
> > - TP_printk("dev=0x%x:0x%x ino=0x%lx wcount=%d rcount=%d icount=%d fl_owner=%p fl_flags=%s fl_type=%s",
> > + TP_printk("dev=0x%x:0x%x ino=0x%llx wcount=%d rcount=%d icount=%d fl_owner=%p fl_flags=%s fl_type=%s",
> > MAJOR(__entry->s_dev), MINOR(__entry->s_dev),
> > __entry->i_ino, __entry->wcount, __entry->rcount,
> > __entry->icount, __entry->owner,
> > diff --git a/include/trace/events/filemap.h b/include/trace/events/filemap.h
> > index f48fe637bfd25885dc6daaf09336ab60626b4944..153491e57cce6df73e30ddee60a52ed7d8923c24 100644
> > --- a/include/trace/events/filemap.h
> > +++ b/include/trace/events/filemap.h
> > @@ -21,7 +21,7 @@ DECLARE_EVENT_CLASS(mm_filemap_op_page_cache,
> >
> > TP_STRUCT__entry(
> > __field(unsigned long, pfn)
> > - __field(unsigned long, i_ino)
> > + __field(u64, i_ino)
>
> Again, this would cause a 32 bit hole.
>
> > __field(unsigned long, index)
> > __field(dev_t, s_dev)
> > __field(unsigned char, order)
> > @@ -38,7 +38,7 @@ DECLARE_EVENT_CLASS(mm_filemap_op_page_cache,
> > __entry->order = folio_order(folio);
> > ),
> >
> > - TP_printk("dev %d:%d ino %lx pfn=0x%lx ofs=%lu order=%u",
> > + TP_printk("dev %d:%d ino %llx pfn=0x%lx ofs=%lu order=%u",
> > MAJOR(__entry->s_dev), MINOR(__entry->s_dev),
> > __entry->i_ino,
> > __entry->pfn,
> > @@ -67,7 +67,7 @@ DECLARE_EVENT_CLASS(mm_filemap_op_page_cache_range,
> > TP_ARGS(mapping, index, last_index),
> >
> > TP_STRUCT__entry(
> > - __field(unsigned long, i_ino)
> > + __field(u64, i_ino)
> > __field(dev_t, s_dev)
> > __field(unsigned long, index)
> > __field(unsigned long, last_index)
> > @@ -85,7 +85,7 @@ DECLARE_EVENT_CLASS(mm_filemap_op_page_cache_range,
> > ),
> >
> > TP_printk(
> > - "dev=%d:%d ino=%lx ofs=%lld-%lld",
> > + "dev=%d:%d ino=%llx ofs=%lld-%lld",
> > MAJOR(__entry->s_dev),
> > MINOR(__entry->s_dev), __entry->i_ino,
> > ((loff_t)__entry->index) << PAGE_SHIFT,
> > @@ -117,7 +117,7 @@ TRACE_EVENT(mm_filemap_fault,
> > TP_ARGS(mapping, index),
> >
> > TP_STRUCT__entry(
> > - __field(unsigned long, i_ino)
> > + __field(u64, i_ino)
> > __field(dev_t, s_dev)
> > __field(unsigned long, index)
> > ),
> > @@ -133,7 +133,7 @@ TRACE_EVENT(mm_filemap_fault,
> > ),
> >
> > TP_printk(
> > - "dev=%d:%d ino=%lx ofs=%lld",
> > + "dev=%d:%d ino=%llx ofs=%lld",
> > MAJOR(__entry->s_dev),
> > MINOR(__entry->s_dev), __entry->i_ino,
> > ((loff_t)__entry->index) << PAGE_SHIFT
> > @@ -146,7 +146,7 @@ TRACE_EVENT(filemap_set_wb_err,
> > TP_ARGS(mapping, eseq),
> >
> > TP_STRUCT__entry(
> > - __field(unsigned long, i_ino)
> > + __field(u64, i_ino)
> > __field(dev_t, s_dev)
> > __field(errseq_t, errseq)
> > ),
> > @@ -160,7 +160,7 @@ TRACE_EVENT(filemap_set_wb_err,
> > __entry->s_dev = mapping->host->i_rdev;
> > ),
> >
> > - TP_printk("dev=%d:%d ino=0x%lx errseq=0x%x",
> > + TP_printk("dev=%d:%d ino=0x%llx errseq=0x%x",
> > MAJOR(__entry->s_dev), MINOR(__entry->s_dev),
> > __entry->i_ino, __entry->errseq)
> > );
> > @@ -172,7 +172,7 @@ TRACE_EVENT(file_check_and_advance_wb_err,
> >
> > TP_STRUCT__entry(
> > __field(struct file *, file)
> > - __field(unsigned long, i_ino)
> > + __field(u64, i_ino)
>
> Having a pointer after the u64 is better.
>
> > __field(dev_t, s_dev)
> > __field(errseq_t, old)
> > __field(errseq_t, new)
> > @@ -191,7 +191,7 @@ TRACE_EVENT(file_check_and_advance_wb_err,
> > __entry->new = file->f_wb_err;
> > ),
> >
> > - TP_printk("file=%p dev=%d:%d ino=0x%lx old=0x%x new=0x%x",
> > + TP_printk("file=%p dev=%d:%d ino=0x%llx old=0x%x new=0x%x",
> > __entry->file, MAJOR(__entry->s_dev),
> > MINOR(__entry->s_dev), __entry->i_ino, __entry->old,
> > __entry->new)
> > diff --git a/include/trace/events/fs_dax.h b/include/trace/events/fs_dax.h
> > index 50ebc1290ab062a9c30ab00049fb96691f9a0f23..11121baa8ece7928c653b4f874fb10ffbdd02fd0 100644
> > --- a/include/trace/events/fs_dax.h
> > +++ b/include/trace/events/fs_dax.h
> > @@ -12,7 +12,7 @@ DECLARE_EVENT_CLASS(dax_pmd_fault_class,
> > pgoff_t max_pgoff, int result),
> > TP_ARGS(inode, vmf, max_pgoff, result),
> > TP_STRUCT__entry(
> > - __field(unsigned long, ino)
> > + __field(u64, ino)
> > __field(unsigned long, vm_start)
> > __field(unsigned long, vm_end)
> > __field(vm_flags_t, vm_flags)
> > @@ -35,7 +35,7 @@ DECLARE_EVENT_CLASS(dax_pmd_fault_class,
> > __entry->max_pgoff = max_pgoff;
> > __entry->result = result;
> > ),
> > - TP_printk("dev %d:%d ino %#lx %s %s address %#lx vm_start "
> > + TP_printk("dev %d:%d ino %#llx %s %s address %#lx vm_start "
> > "%#lx vm_end %#lx pgoff %#lx max_pgoff %#lx %s",
> > MAJOR(__entry->dev),
> > MINOR(__entry->dev),
> > @@ -66,7 +66,7 @@ DECLARE_EVENT_CLASS(dax_pmd_load_hole_class,
> > void *radix_entry),
> > TP_ARGS(inode, vmf, zero_folio, radix_entry),
> > TP_STRUCT__entry(
> > - __field(unsigned long, ino)
> > + __field(u64, ino)
> > __field(vm_flags_t, vm_flags)
> > __field(unsigned long, address)
> > __field(struct folio *, zero_folio)
> > @@ -81,7 +81,7 @@ DECLARE_EVENT_CLASS(dax_pmd_load_hole_class,
> > __entry->zero_folio = zero_folio;
> > __entry->radix_entry = radix_entry;
> > ),
> > - TP_printk("dev %d:%d ino %#lx %s address %#lx zero_folio %p "
> > + TP_printk("dev %d:%d ino %#llx %s address %#lx zero_folio %p "
> > "radix_entry %#lx",
> > MAJOR(__entry->dev),
> > MINOR(__entry->dev),
> > @@ -106,7 +106,7 @@ DECLARE_EVENT_CLASS(dax_pte_fault_class,
> > TP_PROTO(struct inode *inode, struct vm_fault *vmf, int result),
> > TP_ARGS(inode, vmf, result),
> > TP_STRUCT__entry(
> > - __field(unsigned long, ino)
> > + __field(u64, ino)
> > __field(vm_flags_t, vm_flags)
> > __field(unsigned long, address)
> > __field(pgoff_t, pgoff)
> > @@ -123,7 +123,7 @@ DECLARE_EVENT_CLASS(dax_pte_fault_class,
> > __entry->pgoff = vmf->pgoff;
> > __entry->result = result;
> > ),
> > - TP_printk("dev %d:%d ino %#lx %s %s address %#lx pgoff %#lx %s",
> > + TP_printk("dev %d:%d ino %#llx %s %s address %#lx pgoff %#lx %s",
> > MAJOR(__entry->dev),
> > MINOR(__entry->dev),
> > __entry->ino,
> > @@ -150,7 +150,7 @@ DECLARE_EVENT_CLASS(dax_writeback_range_class,
> > TP_PROTO(struct inode *inode, pgoff_t start_index, pgoff_t end_index),
> > TP_ARGS(inode, start_index, end_index),
> > TP_STRUCT__entry(
> > - __field(unsigned long, ino)
> > + __field(u64, ino)
> > __field(pgoff_t, start_index)
> > __field(pgoff_t, end_index)
> > __field(dev_t, dev)
> > @@ -161,7 +161,7 @@ DECLARE_EVENT_CLASS(dax_writeback_range_class,
> > __entry->start_index = start_index;
> > __entry->end_index = end_index;
> > ),
> > - TP_printk("dev %d:%d ino %#lx pgoff %#lx-%#lx",
> > + TP_printk("dev %d:%d ino %#llx pgoff %#lx-%#lx",
> > MAJOR(__entry->dev),
> > MINOR(__entry->dev),
> > __entry->ino,
> > @@ -182,7 +182,7 @@ TRACE_EVENT(dax_writeback_one,
> > TP_PROTO(struct inode *inode, pgoff_t pgoff, pgoff_t pglen),
> > TP_ARGS(inode, pgoff, pglen),
> > TP_STRUCT__entry(
> > - __field(unsigned long, ino)
> > + __field(u64, ino)
> > __field(pgoff_t, pgoff)
> > __field(pgoff_t, pglen)
> > __field(dev_t, dev)
> > @@ -193,7 +193,7 @@ TRACE_EVENT(dax_writeback_one,
> > __entry->pgoff = pgoff;
> > __entry->pglen = pglen;
> > ),
> > - TP_printk("dev %d:%d ino %#lx pgoff %#lx pglen %#lx",
> > + TP_printk("dev %d:%d ino %#llx pgoff %#lx pglen %#lx",
> > MAJOR(__entry->dev),
> > MINOR(__entry->dev),
> > __entry->ino,
> > diff --git a/include/trace/events/fsverity.h b/include/trace/events/fsverity.h
> > index a8c52f21cbd5eb010c7e7b2fdb8f9de49c8ea326..4477c17e05748360965c4e1840590efe96d6335e 100644
> > --- a/include/trace/events/fsverity.h
> > +++ b/include/trace/events/fsverity.h
> > @@ -16,7 +16,7 @@ TRACE_EVENT(fsverity_enable,
> > const struct merkle_tree_params *params),
> > TP_ARGS(inode, params),
> > TP_STRUCT__entry(
> > - __field(ino_t, ino)
> > + __field(u64, ino)
>
> Do you need to convert all these ino_t's?
>
> > __field(u64, data_size)
> > __field(u64, tree_size)
> > __field(unsigned int, merkle_block)
> > @@ -29,8 +29,8 @@ TRACE_EVENT(fsverity_enable,
> > __entry->merkle_block = params->block_size;
> > __entry->num_levels = params->num_levels;
> > ),
> > - TP_printk("ino %lu data_size %llu tree_size %llu merkle_block %u levels %u",
> > - (unsigned long) __entry->ino,
> > + TP_printk("ino %llu data_size %llu tree_size %llu merkle_block %u levels %u",
> > + __entry->ino,
> > __entry->data_size,
> > __entry->tree_size,
> > __entry->merkle_block,
> > @@ -42,7 +42,7 @@ TRACE_EVENT(fsverity_tree_done,
> > const struct merkle_tree_params *params),
> > TP_ARGS(inode, vi, params),
> > TP_STRUCT__entry(
> > - __field(ino_t, ino)
> > + __field(u64, ino)
> > __field(u64, data_size)
> > __field(u64, tree_size)
> > __field(unsigned int, merkle_block)
> > @@ -59,8 +59,8 @@ TRACE_EVENT(fsverity_tree_done,
> > memcpy(__get_dynamic_array(root_hash), vi->root_hash, __get_dynamic_array_len(root_hash));
> > memcpy(__get_dynamic_array(file_digest), vi->file_digest, __get_dynamic_array_len(file_digest));
> > ),
> > - TP_printk("ino %lu data_size %llu tree_size %lld merkle_block %u levels %u root_hash %s digest %s",
> > - (unsigned long) __entry->ino,
> > + TP_printk("ino %llu data_size %llu tree_size %lld merkle_block %u levels %u root_hash %s digest %s",
> > + __entry->ino,
> > __entry->data_size,
> > __entry->tree_size,
> > __entry->merkle_block,
> > @@ -75,7 +75,7 @@ TRACE_EVENT(fsverity_verify_data_block,
> > u64 data_pos),
> > TP_ARGS(inode, params, data_pos),
> > TP_STRUCT__entry(
> > - __field(ino_t, ino)
> > + __field(u64, ino)
> > __field(u64, data_pos)
> > __field(unsigned int, merkle_block)
> > ),
> > @@ -84,8 +84,8 @@ TRACE_EVENT(fsverity_verify_data_block,
> > __entry->data_pos = data_pos;
> > __entry->merkle_block = params->block_size;
> > ),
> > - TP_printk("ino %lu data_pos %llu merkle_block %u",
> > - (unsigned long) __entry->ino,
> > + TP_printk("ino %llu data_pos %llu merkle_block %u",
> > + __entry->ino,
> > __entry->data_pos,
> > __entry->merkle_block)
> > );
> > @@ -96,7 +96,7 @@ TRACE_EVENT(fsverity_merkle_hit,
> > unsigned int hidx),
> > TP_ARGS(inode, data_pos, hblock_idx, level, hidx),
> > TP_STRUCT__entry(
> > - __field(ino_t, ino)
> > + __field(u64, ino)
> > __field(u64, data_pos)
>
> Heh, this actually removed a hole, but again, why convert ino_t?
>
> Anyway, I stopped here. But you get the idea.
>
>
> > __field(unsigned long, hblock_idx)
> > __field(unsigned int, level)
Thanks for the review! I'll definitely look at reordering the
tracepoint fields for better packing since that has material
consequences.
--
Jeff Layton <jlayton@kernel.org>
^ permalink raw reply
* Re: [PATCH] cred: clarify usage of get_cred_rcu()
From: Paul Moore @ 2026-02-27 20:49 UTC (permalink / raw)
To: Alice Ryhl; +Cc: Serge Hallyn, linux-security-module, linux-kernel
In-Reply-To: <aaFsRbMZl2OIlSCg@google.com>
On Fri, Feb 27, 2026 at 5:04 AM Alice Ryhl <aliceryhl@google.com> wrote:
> On Thu, Feb 26, 2026 at 09:18:29PM -0500, Paul Moore wrote:
> > On Fri, Feb 20, 2026 at 4:19 AM Alice Ryhl <aliceryhl@google.com> wrote:
> > >
> > > After being confused by looking at get_cred() and get_cred_rcu(), I
> > > figured out what's going on. Thus, add some comments to clarify how
> > > get_cred_rcu() works for the benefit of others looking in the future.
> > >
> > > Note that in principle we could add an assertion that non_rcu is zero in
> > > the failure path of atomic_long_inc_not_zero().
> >
> > That would be interesting to add a WARN_ON() there and see what
> > happens. Hopefully nothing, but one never knows ;) Have you tried
> > this?
>
> I tried just now. I put it on an Android phone, and it did not seem to
> be triggered after a few minute of usage.
>
> I can send a patch adding it if you would like?
It would need much more testing than running it on Android for a few
minutes before I would consider merging it :) I suspect it's probably
not worth the effort, I just thought it would be mildly interesting to
see if anything tripped the assertion.
> > > Signed-off-by: Alice Ryhl <aliceryhl@google.com>
> > > ---
> > > include/linux/cred.h | 18 ++++++++++++++++++
> > > 1 file changed, 18 insertions(+)
> >
> > ...
> >
> > > +/*
> > > + * get_cred_rcu - Get a reference on a set of credentials under rcu
> >
> > I agree this is a bit pedantic, but it looks like the bulk of the file
> > capitalizes RCU and technically that is correct as it is an acronym.
>
> Will do.
>
> > > + * @cred: The credentials to reference
> > > + *
> > > + * Get a reference on the specified set of credentials, or %NULL if the last
> > > + * refcount has already been put.
> > > + *
> > > + * This is used to obtain a reference under an rcu read lock.
> >
> > I would suggest a different description:
> >
> > "Get a reference to the specified set of credentials and return a
> > pointer to the cred struct, or %NULL if it is not possible to obtain a
> > new reference. After successfully taking a new reference to the
> > specified credentials, the cred struct will be marked for free'ing via
> > RCU."
>
> I actually think it's confusing to include
>
> After successfully taking a new reference to the specified
> credentials, the cred struct will be marked for free'ing via
> RCU.
>
> in the documentation, because it makes it sounds like this method has
> the _rcu() suffix because it marks the struct for free'ing via RCU. But
> that is not the case. After all, get_cred() also marks it for free'ing
> via RCU.
>
> It has the _rcu() suffix because - if the cred struct is *already*
> marked for free'ing via RCU, then you are allowed to do this:
>
> rcu_read_lock();
> cred = get_cred_rcu(&foo->my_cred);
> rcu_read_unlock();
>
> even if another thread might put foo->my_cred in parallel with the above
> piece of code.
To be really nit picky, the code doesn't actually enforce these usage
guidelines, so both are "allowed" in that sense. The key difference
is that the rcu variant checks if the refcount is zero (the cred has
had its last ref dropped, but has not yet been free'd via rcu),
whereas the non-rcu variant always assumes the refcount is greater
than zero.
If you want to add a description/comment to the functions, I'd focus on that.
> > I suppose we could consider adding the zero check in the get_cred()
> > case, but even if we ignore the KCSAN barrier, it looks like the arch
> > support for the inc_not_zero() case isn't nearly as good, likely
> > resulting in more code to execute.
>
> I don't think that's necessary ...
I didn't say it was, in fact I was trying to dissuade anyone from
trying that because it will likely negatively impact performance for
minimal, if any, benefit.
--
paul-moore.com
^ permalink raw reply
* Re: [PATCH 00/61] vfs: change inode->i_ino from unsigned long to u64
From: Jeff Layton @ 2026-02-27 19:35 UTC (permalink / raw)
To: Mathieu Desnoyers, Matthew Wilcox
Cc: Alexander Viro, Christian Brauner, Jan Kara, Steven Rostedt,
Masami Hiramatsu, Dan Williams, Eric Biggers,
Theodore Y. Ts'o, Muchun Song, Oscar Salvador,
David Hildenbrand, David Howells, Paulo Alcantara, Andreas Dilger,
Jan Kara, Jaegeuk Kim, Chao Yu, Trond Myklebust, Anna Schumaker,
Chuck Lever, NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
Steve French, Ronnie Sahlberg, Shyam Prasad N, Bharath SM,
Alexander Aring, Ryusuke Konishi, Viacheslav Dubeyko,
Eric Van Hensbergen, Latchesar Ionkov, Dominique Martinet,
Christian Schoenebeck, David Sterba, Marc Dionne, Ian Kent,
Luis de Bethencourt, Salah Triki, Tigran A. Aivazian,
Ilya Dryomov, Alex Markuze, Jan Harkes, coda, Nicolas Pitre,
Tyler Hicks, Amir Goldstein, Christoph Hellwig,
John Paul Adrian Glaubitz, Yangtao Li, Mikulas Patocka,
David Woodhouse, Richard Weinberger, Dave Kleikamp,
Konstantin Komarov, Mark Fasheh, Joel Becker, Joseph Qi,
Mike Marshall, Martin Brandenburg, Miklos Szeredi, Anders Larsen,
Zhihao Cheng, Damien Le Moal, Naohiro Aota, Johannes Thumshirn,
John Johansen, Paul Moore, James Morris, Serge E. Hallyn,
Mimi Zohar, Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Fan Wu,
Stephen Smalley, Ondrej Mosnacek, Casey Schaufler, Alex Deucher,
Christian König, David Airlie, Simona Vetter, Sumit Semwal,
Eric Dumazet, Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn,
David S. Miller, Jakub Kicinski, Simon Horman, Oleg Nesterov,
Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
Ian Rogers, Adrian Hunter, James Clark, Darrick J. Wong,
Martin Schiller, linux-fsdevel, linux-kernel, linux-trace-kernel,
nvdimm, fsverity, linux-mm, netfs, linux-ext4, linux-f2fs-devel,
linux-nfs, linux-cifs, samba-technical, linux-nilfs, v9fs,
linux-afs, autofs, ceph-devel, codalist, ecryptfs, linux-mtd,
jfs-discussion, ntfs3, ocfs2-devel, devel, linux-unionfs,
apparmor, linux-security-module, linux-integrity, selinux,
amd-gfx, dri-devel, linux-media, linaro-mm-sig, netdev,
linux-perf-users, linux-fscrypt, linux-xfs, linux-hams, linux-x25
In-Reply-To: <b808e186-3eeb-46ed-9826-b0ae6cdcdb8b@efficios.com>
On Fri, 2026-02-27 at 14:01 -0500, Mathieu Desnoyers wrote:
> On 2026-02-27 12:19, Jeff Layton wrote:
> > On Thu, 2026-02-26 at 16:49 +0000, Matthew Wilcox wrote:
> > > On Thu, Feb 26, 2026 at 10:55:02AM -0500, Jeff Layton wrote:
> > > > The bulk of the changes are to format strings and tracepoints, since the
> > > > kernel itself doesn't care that much about the i_ino field. The first
> > > > patch changes some vfs function arguments, so check that one out
> > > > carefully.
> > >
> > > Why are the format strings all done as separate patches? Don't we get
> > > bisection hazards by splitting it apart this way?
> >
> > Circling back to this...
> >
> > I have a v2 series (~107 patches) that I'm testing now that does this
> > more bisectably with the typedef and macro scaffolding that Mathieu
> > suggested. I'll probably send it early next week.
> >
> > I had done it this way originally since I figured it was best to break
> > this up by subsystem. Should I continue with this series as a set of
> > patches broken up this way, or is it preferable to combine the pile of
> > format changes into fewer patches?
>
> Here is the approach I would recommend to maximize signal over noise
> for the follow up email thread discussions:
>
> Now that your series is bisectable, you could post a [RFC PATCH v2]
> series with the following:
>
> - Patch 00 introduces the series, points to your git branch implementing
> the whole series,
> - The first few patches introduce the new type (kino_t) and macro to
> do the format string transition. Initially kino_t would typedef to
> unsigned long (no changes).
> - Followed by patches implementing the type + format string changes for
> a few key subsystems.
> - The final patch would change kino_t and the format string macro to
> 64-bit integers.
>
That's pretty much the approach the set I have takes. The current set
is here:
https://git.kernel.org/pub/scm/linux/kernel/git/jlayton/linux.git/log/?h=iino-u64
My question was more about whether I should batch some of the changes
together. My inclination is that doing it in small, incremental patches
is a good thing, but I figured I'd ask before I spam everyone with a
100+ patch series.
> Once everyone agree on those core changes, you could proceed to post
> patches that change additional subsystems in a subsequent round.
>
> One more comment: have you tried using Coccinelle to do this kind of
> semantic code change ?
I've use coccinelle before for this sort of change, but my skills with
it are pretty primitive. The problem I saw with using it here is that
the main set of changes involved format strings, and that didn't look
straightforward to do with coccinelle. The LLM seems to have sorted it
out with no trouble though.
On a related note, has anyone has taught an LLM how to use Coccinelle.
I wonder if it might give it a better tool for its toolbox, since
Claude at least seems to mostly use bash, perl or python to make
changes across the tree.
--
Jeff Layton <jlayton@kernel.org>
^ permalink raw reply
* Re: [PATCH 00/61] vfs: change inode->i_ino from unsigned long to u64
From: Mathieu Desnoyers @ 2026-02-27 19:01 UTC (permalink / raw)
To: Jeff Layton, Matthew Wilcox
Cc: Alexander Viro, Christian Brauner, Jan Kara, Steven Rostedt,
Masami Hiramatsu, Dan Williams, Eric Biggers,
Theodore Y. Ts'o, Muchun Song, Oscar Salvador,
David Hildenbrand, David Howells, Paulo Alcantara, Andreas Dilger,
Jan Kara, Jaegeuk Kim, Chao Yu, Trond Myklebust, Anna Schumaker,
Chuck Lever, NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
Steve French, Ronnie Sahlberg, Shyam Prasad N, Bharath SM,
Alexander Aring, Ryusuke Konishi, Viacheslav Dubeyko,
Eric Van Hensbergen, Latchesar Ionkov, Dominique Martinet,
Christian Schoenebeck, David Sterba, Marc Dionne, Ian Kent,
Luis de Bethencourt, Salah Triki, Tigran A. Aivazian,
Ilya Dryomov, Alex Markuze, Jan Harkes, coda, Nicolas Pitre,
Tyler Hicks, Amir Goldstein, Christoph Hellwig,
John Paul Adrian Glaubitz, Yangtao Li, Mikulas Patocka,
David Woodhouse, Richard Weinberger, Dave Kleikamp,
Konstantin Komarov, Mark Fasheh, Joel Becker, Joseph Qi,
Mike Marshall, Martin Brandenburg, Miklos Szeredi, Anders Larsen,
Zhihao Cheng, Damien Le Moal, Naohiro Aota, Johannes Thumshirn,
John Johansen, Paul Moore, James Morris, Serge E. Hallyn,
Mimi Zohar, Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Fan Wu,
Stephen Smalley, Ondrej Mosnacek, Casey Schaufler, Alex Deucher,
Christian König, David Airlie, Simona Vetter, Sumit Semwal,
Eric Dumazet, Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn,
David S. Miller, Jakub Kicinski, Simon Horman, Oleg Nesterov,
Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
Ian Rogers, Adrian Hunter, James Clark, Darrick J. Wong,
Martin Schiller, linux-fsdevel, linux-kernel, linux-trace-kernel,
nvdimm, fsverity, linux-mm, netfs, linux-ext4, linux-f2fs-devel,
linux-nfs, linux-cifs, samba-technical, linux-nilfs, v9fs,
linux-afs, autofs, ceph-devel, codalist, ecryptfs, linux-mtd,
jfs-discussion, ntfs3, ocfs2-devel, devel, linux-unionfs,
apparmor, linux-security-module, linux-integrity, selinux,
amd-gfx, dri-devel, linux-media, linaro-mm-sig, netdev,
linux-perf-users, linux-fscrypt, linux-xfs, linux-hams, linux-x25
In-Reply-To: <4a462d40899698586c110add96ce3fab6ddac30b.camel@kernel.org>
On 2026-02-27 12:19, Jeff Layton wrote:
> On Thu, 2026-02-26 at 16:49 +0000, Matthew Wilcox wrote:
>> On Thu, Feb 26, 2026 at 10:55:02AM -0500, Jeff Layton wrote:
>>> The bulk of the changes are to format strings and tracepoints, since the
>>> kernel itself doesn't care that much about the i_ino field. The first
>>> patch changes some vfs function arguments, so check that one out
>>> carefully.
>>
>> Why are the format strings all done as separate patches? Don't we get
>> bisection hazards by splitting it apart this way?
>
> Circling back to this...
>
> I have a v2 series (~107 patches) that I'm testing now that does this
> more bisectably with the typedef and macro scaffolding that Mathieu
> suggested. I'll probably send it early next week.
>
> I had done it this way originally since I figured it was best to break
> this up by subsystem. Should I continue with this series as a set of
> patches broken up this way, or is it preferable to combine the pile of
> format changes into fewer patches?
Here is the approach I would recommend to maximize signal over noise
for the follow up email thread discussions:
Now that your series is bisectable, you could post a [RFC PATCH v2]
series with the following:
- Patch 00 introduces the series, points to your git branch implementing
the whole series,
- The first few patches introduce the new type (kino_t) and macro to
do the format string transition. Initially kino_t would typedef to
unsigned long (no changes).
- Followed by patches implementing the type + format string changes for
a few key subsystems.
- The final patch would change kino_t and the format string macro to
64-bit integers.
Once everyone agree on those core changes, you could proceed to post
patches that change additional subsystems in a subsequent round.
One more comment: have you tried using Coccinelle to do this kind of
semantic code change ?
Thanks,
Mathieu
--
Mathieu Desnoyers
EfficiOS Inc.
https://www.efficios.com
^ permalink raw reply
* Re: [PATCH v5] ima_fs: Avoid creating measurement lists for unsupported hash algos
From: Mimi Zohar @ 2026-02-27 18:46 UTC (permalink / raw)
To: Roberto Sassu, dima, Roberto Sassu, Dmitry Kasatkin,
Eric Snowberg, Paul Moore, James Morris, Serge E. Hallyn,
Silvia Sisinni, Enrico Bravi
Cc: Jonathan McDowell, linux-integrity, linux-security-module,
linux-kernel, stable, Dmitry Safonov
In-Reply-To: <0fde824faace320c6d3ef6137bf50cee0289c6c0.camel@huaweicloud.com>
> > > @@ -404,16 +398,24 @@ static int __init create_securityfs_measurement_lists(void)
> > > char file_name[NAME_MAX + 1];
> > > struct dentry *dentry;
> > >
> > > - sprintf(file_name, "ascii_runtime_measurements_%s",
> > > - hash_algo_name[algo]);
> > > + if (algo == HASH_ALGO__LAST)
> > > + sprintf(file_name, "ascii_runtime_measurements_tpm_alg_%x",
> > > + ima_tpm_chip->allocated_banks[i].alg_id);
> > > + else
> > > + sprintf(file_name, "ascii_runtime_measurements_%s",
> > > + hash_algo_name[algo]);
> > > dentry = securityfs_create_file(file_name, S_IRUSR | S_IRGRP,
> > > ima_dir, (void *)(uintptr_t)i,
> > > &ima_ascii_measurements_ops);
> > > if (IS_ERR(dentry))
> > > return PTR_ERR(dentry);
> > >
> > > - sprintf(file_name, "binary_runtime_measurements_%s",
> > > - hash_algo_name[algo]);
> > > + if (algo == HASH_ALGO__LAST)
> > > + sprintf(file_name, "binary_runtime_measurements_tpm_alg_%x",
> > > + ima_tpm_chip->allocated_banks[i].alg_id);
> >
> > There's no point in creating either of the securityfs files if the kernel
> > doesn't support the hash algorithm.
>
> It is not useful per se, but since it is an information that it is
> produced and maintained by IMA, we can print it. And second, it will
> expose the fact that there is an unsupported algorithm (in the case of
> SHA3-256, the fix is add to the TPM - crypto subsystem mapping in tpm2-
> cmd.c).
Yes, agreed.
Dmitry, the Subject line implies the measurement lists aren't being created, yet
you're actually creating them. Please update the patch description before re-
posting.
thanks,
Mimi
^ permalink raw reply
* Re: [PATCH 1/2] ima: efi: Drop unnecessary check for CONFIG_MODULE_SIG/CONFIG_KEXEC_SIG
From: Mimi Zohar @ 2026-02-27 18:21 UTC (permalink / raw)
To: Thomas Weißschuh, Roberto Sassu, Dmitry Kasatkin,
Eric Snowberg, Paul Moore, James Morris, Serge E. Hallyn,
Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
Christophe Leroy (CS GROUP)
Cc: linux-integrity, linux-security-module, linux-kernel,
linuxppc-dev, Aaron Tomlin, Nicolas Schier
In-Reply-To: <20260226-ima-ifdef-v1-1-8b9613edbbdb@weissschuh.net>
On Thu, 2026-02-26 at 08:20 +0100, Thomas Weißschuh wrote:
> When configuration settings are disabled the guarded functions are
> defined as empty stubs, so the check is unnecessary.
>
> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
> Reviewed-by: Aaron Tomlin <atomlin@atomlin.com>
> Reviewed-by: Nicolas Schier <nsc@kernel.org>
> ---
> security/integrity/ima/ima_efi.c | 6 ++----
> 1 file changed, 2 insertions(+), 4 deletions(-)
>
> diff --git a/security/integrity/ima/ima_efi.c b/security/integrity/ima/ima_efi.c
> index 138029bfcce1..a35dd166ad47 100644
> --- a/security/integrity/ima/ima_efi.c
> +++ b/security/integrity/ima/ima_efi.c
> @@ -68,10 +68,8 @@ static const char * const sb_arch_rules[] = {
> const char * const *arch_get_ima_policy(void)
> {
> if (IS_ENABLED(CONFIG_IMA_ARCH_POLICY) && arch_ima_get_secureboot()) {
> - if (IS_ENABLED(CONFIG_MODULE_SIG))
> - set_module_sig_enforced();
> - if (IS_ENABLED(CONFIG_KEXEC_SIG))
> - set_kexec_sig_enforced();
> + set_module_sig_enforced();
> + set_kexec_sig_enforced();
> return sb_arch_rules;
> }
> return NULL;
Thanks, Thomas.
With commit 63e8a44395a4 ("integrity: Make arch_ima_get_secureboot integrity-
wide"), there was a merge conflict. After fixing the merge conflict, your
patches are now queued in next-integrity.
Mimi
^ permalink raw reply
* Re: [PATCH 00/61] vfs: change inode->i_ino from unsigned long to u64
From: Jeff Layton @ 2026-02-27 17:19 UTC (permalink / raw)
To: Matthew Wilcox
Cc: Alexander Viro, Christian Brauner, Jan Kara, Steven Rostedt,
Masami Hiramatsu, Mathieu Desnoyers, Dan Williams, Eric Biggers,
Theodore Y. Ts'o, Muchun Song, Oscar Salvador,
David Hildenbrand, David Howells, Paulo Alcantara, Andreas Dilger,
Jan Kara, Jaegeuk Kim, Chao Yu, Trond Myklebust, Anna Schumaker,
Chuck Lever, NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
Steve French, Ronnie Sahlberg, Shyam Prasad N, Bharath SM,
Alexander Aring, Ryusuke Konishi, Viacheslav Dubeyko,
Eric Van Hensbergen, Latchesar Ionkov, Dominique Martinet,
Christian Schoenebeck, David Sterba, Marc Dionne, Ian Kent,
Luis de Bethencourt, Salah Triki, Tigran A. Aivazian,
Ilya Dryomov, Alex Markuze, Jan Harkes, coda, Nicolas Pitre,
Tyler Hicks, Amir Goldstein, Christoph Hellwig,
John Paul Adrian Glaubitz, Yangtao Li, Mikulas Patocka,
David Woodhouse, Richard Weinberger, Dave Kleikamp,
Konstantin Komarov, Mark Fasheh, Joel Becker, Joseph Qi,
Mike Marshall, Martin Brandenburg, Miklos Szeredi, Anders Larsen,
Zhihao Cheng, Damien Le Moal, Naohiro Aota, Johannes Thumshirn,
John Johansen, Paul Moore, James Morris, Serge E. Hallyn,
Mimi Zohar, Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Fan Wu,
Stephen Smalley, Ondrej Mosnacek, Casey Schaufler, Alex Deucher,
Christian König, David Airlie, Simona Vetter, Sumit Semwal,
Eric Dumazet, Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn,
David S. Miller, Jakub Kicinski, Simon Horman, Oleg Nesterov,
Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
Ian Rogers, Adrian Hunter, James Clark, Darrick J. Wong,
Martin Schiller, linux-fsdevel, linux-kernel, linux-trace-kernel,
nvdimm, fsverity, linux-mm, netfs, linux-ext4, linux-f2fs-devel,
linux-nfs, linux-cifs, samba-technical, linux-nilfs, v9fs,
linux-afs, autofs, ceph-devel, codalist, ecryptfs, linux-mtd,
jfs-discussion, ntfs3, ocfs2-devel, devel, linux-unionfs,
apparmor, linux-security-module, linux-integrity, selinux,
amd-gfx, dri-devel, linux-media, linaro-mm-sig, netdev,
linux-perf-users, linux-fscrypt, linux-xfs, linux-hams, linux-x25
In-Reply-To: <aaB5lgKd8FOIizPg@casper.infradead.org>
On Thu, 2026-02-26 at 16:49 +0000, Matthew Wilcox wrote:
> On Thu, Feb 26, 2026 at 10:55:02AM -0500, Jeff Layton wrote:
> > The bulk of the changes are to format strings and tracepoints, since the
> > kernel itself doesn't care that much about the i_ino field. The first
> > patch changes some vfs function arguments, so check that one out
> > carefully.
>
> Why are the format strings all done as separate patches? Don't we get
> bisection hazards by splitting it apart this way?
Circling back to this...
I have a v2 series (~107 patches) that I'm testing now that does this
more bisectably with the typedef and macro scaffolding that Mathieu
suggested. I'll probably send it early next week.
I had done it this way originally since I figured it was best to break
this up by subsystem. Should I continue with this series as a set of
patches broken up this way, or is it preferable to combine the pile of
format changes into fewer patches?
--
Jeff Layton <jlayton@kernel.org>
^ permalink raw reply
* Re: [PATCH 51/61] security: update audit format strings for u64 i_ino
From: Ryan Lee @ 2026-02-27 16:46 UTC (permalink / raw)
To: Jeff Layton
Cc: Alexander Viro, Christian Brauner, Jan Kara, Steven Rostedt,
Masami Hiramatsu, Mathieu Desnoyers, Dan Williams, Matthew Wilcox,
Eric Biggers, Theodore Y. Ts'o, Muchun Song, Oscar Salvador,
David Hildenbrand, David Howells, Paulo Alcantara, Andreas Dilger,
Jan Kara, Jaegeuk Kim, Chao Yu, Trond Myklebust, Anna Schumaker,
Chuck Lever, NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
Steve French, Ronnie Sahlberg, Shyam Prasad N, Bharath SM,
Alexander Aring, Ryusuke Konishi, Viacheslav Dubeyko,
Eric Van Hensbergen, Latchesar Ionkov, Dominique Martinet,
Christian Schoenebeck, David Sterba, Marc Dionne, Ian Kent,
Luis de Bethencourt, Salah Triki, Tigran A. Aivazian,
Ilya Dryomov, Alex Markuze, Jan Harkes, coda, Nicolas Pitre,
Tyler Hicks, Amir Goldstein, Christoph Hellwig,
John Paul Adrian Glaubitz, Yangtao Li, Mikulas Patocka,
David Woodhouse, Richard Weinberger, Dave Kleikamp,
Konstantin Komarov, Mark Fasheh, Joel Becker, Joseph Qi,
Mike Marshall, Martin Brandenburg, Miklos Szeredi, Anders Larsen,
Zhihao Cheng, Damien Le Moal, Naohiro Aota, Johannes Thumshirn,
John Johansen, Paul Moore, James Morris, Serge E. Hallyn,
Mimi Zohar, Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Fan Wu,
Stephen Smalley, Ondrej Mosnacek, Casey Schaufler, Alex Deucher,
Christian König, David Airlie, Simona Vetter, Sumit Semwal,
Eric Dumazet, Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn,
David S. Miller, Jakub Kicinski, Simon Horman, Oleg Nesterov,
Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
Ian Rogers, Adrian Hunter, James Clark, Darrick J. Wong,
Martin Schiller, linux-fsdevel, linux-kernel, linux-trace-kernel,
nvdimm, fsverity, linux-mm, netfs, linux-ext4, linux-f2fs-devel,
linux-nfs, linux-cifs, samba-technical, linux-nilfs, v9fs,
linux-afs, autofs, ceph-devel, codalist, ecryptfs, linux-mtd,
jfs-discussion, ntfs3, ocfs2-devel, devel, linux-unionfs,
apparmor, linux-security-module, linux-integrity, selinux,
amd-gfx, dri-devel, linux-media, linaro-mm-sig, netdev,
linux-perf-users, linux-fscrypt, linux-xfs, linux-hams, linux-x25
In-Reply-To: <20260226-iino-u64-v1-51-ccceff366db9@kernel.org>
On Thu, Feb 26, 2026 at 9:13 AM Jeff Layton <jlayton@kernel.org> wrote:
>
> Update %lu/%ld to %llu/%lld in security audit logging functions that
> print inode->i_ino, since i_ino is now u64.
>
> Files updated: apparmor/apparmorfs.c, integrity/integrity_audit.c,
> ipe/audit.c, lsm_audit.c.
>
> Signed-off-by: Jeff Layton <jlayton@kernel.org>
> ---
> security/apparmor/apparmorfs.c | 4 ++--
> security/integrity/integrity_audit.c | 2 +-
> security/ipe/audit.c | 2 +-
> security/lsm_audit.c | 10 +++++-----
> security/selinux/hooks.c | 4 ++--
> security/smack/smack_lsm.c | 12 ++++++------
> 6 files changed, 17 insertions(+), 17 deletions(-)
>
> diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
> index 2f84bd23edb69e7e69cb097e554091df0132816d..7b645f40e71c956f216fa6a7d69c3ecd4e2a5ff4 100644
> --- a/security/apparmor/apparmorfs.c
> +++ b/security/apparmor/apparmorfs.c
> @@ -149,7 +149,7 @@ static int aafs_count;
>
> static int aafs_show_path(struct seq_file *seq, struct dentry *dentry)
> {
> - seq_printf(seq, "%s:[%lu]", AAFS_NAME, d_inode(dentry)->i_ino);
> + seq_printf(seq, "%s:[%llu]", AAFS_NAME, d_inode(dentry)->i_ino);
> return 0;
> }
>
> @@ -2644,7 +2644,7 @@ static int policy_readlink(struct dentry *dentry, char __user *buffer,
> char name[32];
I have confirmed that the buffer is still big enough for a 64-bit inode number.
> int res;
>
> - res = snprintf(name, sizeof(name), "%s:[%lu]", AAFS_NAME,
> + res = snprintf(name, sizeof(name), "%s:[%llu]", AAFS_NAME,
> d_inode(dentry)->i_ino);
> if (res > 0 && res < sizeof(name))
> res = readlink_copy(buffer, buflen, name, strlen(name));
For the AppArmor portion:
Reviewed-By: Ryan Lee <ryan.lee@canonical.com>
> diff --git a/security/integrity/integrity_audit.c b/security/integrity/integrity_audit.c
> index 0ec5e4c22cb2a1066c2b897776ead6d3db72635c..d8d9e5ff1cd22b091f462d1e83d28d2d6bd983e9 100644
> --- a/security/integrity/integrity_audit.c
> +++ b/security/integrity/integrity_audit.c
> @@ -62,7 +62,7 @@ void integrity_audit_message(int audit_msgno, struct inode *inode,
> if (inode) {
> audit_log_format(ab, " dev=");
> audit_log_untrustedstring(ab, inode->i_sb->s_id);
> - audit_log_format(ab, " ino=%lu", inode->i_ino);
> + audit_log_format(ab, " ino=%llu", inode->i_ino);
> }
> audit_log_format(ab, " res=%d errno=%d", !result, errno);
> audit_log_end(ab);
> diff --git a/security/ipe/audit.c b/security/ipe/audit.c
> index 3f0deeb54912730d9acf5e021a4a0cb29a34e982..93fb59fbddd60b56c0b22be2a38b809ef9e18b76 100644
> --- a/security/ipe/audit.c
> +++ b/security/ipe/audit.c
> @@ -153,7 +153,7 @@ void ipe_audit_match(const struct ipe_eval_ctx *const ctx,
> if (inode) {
> audit_log_format(ab, " dev=");
> audit_log_untrustedstring(ab, inode->i_sb->s_id);
> - audit_log_format(ab, " ino=%lu", inode->i_ino);
> + audit_log_format(ab, " ino=%llu", inode->i_ino);
> } else {
> audit_log_format(ab, " dev=? ino=?");
> }
> diff --git a/security/lsm_audit.c b/security/lsm_audit.c
> index 7d623b00495c14b079e10e963c21a9f949c11f07..737f5a263a8f79416133315edf363ece3d79c722 100644
> --- a/security/lsm_audit.c
> +++ b/security/lsm_audit.c
> @@ -202,7 +202,7 @@ void audit_log_lsm_data(struct audit_buffer *ab,
> if (inode) {
> audit_log_format(ab, " dev=");
> audit_log_untrustedstring(ab, inode->i_sb->s_id);
> - audit_log_format(ab, " ino=%lu", inode->i_ino);
> + audit_log_format(ab, " ino=%llu", inode->i_ino);
> }
> break;
> }
> @@ -215,7 +215,7 @@ void audit_log_lsm_data(struct audit_buffer *ab,
> if (inode) {
> audit_log_format(ab, " dev=");
> audit_log_untrustedstring(ab, inode->i_sb->s_id);
> - audit_log_format(ab, " ino=%lu", inode->i_ino);
> + audit_log_format(ab, " ino=%llu", inode->i_ino);
> }
> break;
> }
> @@ -228,7 +228,7 @@ void audit_log_lsm_data(struct audit_buffer *ab,
> if (inode) {
> audit_log_format(ab, " dev=");
> audit_log_untrustedstring(ab, inode->i_sb->s_id);
> - audit_log_format(ab, " ino=%lu", inode->i_ino);
> + audit_log_format(ab, " ino=%llu", inode->i_ino);
> }
>
> audit_log_format(ab, " ioctlcmd=0x%hx", a->u.op->cmd);
> @@ -246,7 +246,7 @@ void audit_log_lsm_data(struct audit_buffer *ab,
> if (inode) {
> audit_log_format(ab, " dev=");
> audit_log_untrustedstring(ab, inode->i_sb->s_id);
> - audit_log_format(ab, " ino=%lu", inode->i_ino);
> + audit_log_format(ab, " ino=%llu", inode->i_ino);
> }
> break;
> }
> @@ -265,7 +265,7 @@ void audit_log_lsm_data(struct audit_buffer *ab,
> }
> audit_log_format(ab, " dev=");
> audit_log_untrustedstring(ab, inode->i_sb->s_id);
> - audit_log_format(ab, " ino=%lu", inode->i_ino);
> + audit_log_format(ab, " ino=%llu", inode->i_ino);
> rcu_read_unlock();
> break;
> }
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index d8224ea113d1ac273aac1fb52324f00b3301ae75..150ea86ebc1f7c7f8391af4109a3da82b12d00d2 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -1400,7 +1400,7 @@ static int inode_doinit_use_xattr(struct inode *inode, struct dentry *dentry,
> if (rc < 0) {
> kfree(context);
> if (rc != -ENODATA) {
> - pr_warn("SELinux: %s: getxattr returned %d for dev=%s ino=%ld\n",
> + pr_warn("SELinux: %s: getxattr returned %d for dev=%s ino=%lld\n",
> __func__, -rc, inode->i_sb->s_id, inode->i_ino);
> return rc;
> }
> @@ -3477,7 +3477,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
> &newsid);
> if (rc) {
> pr_err("SELinux: unable to map context to SID"
> - "for (%s, %lu), rc=%d\n",
> + "for (%s, %llu), rc=%d\n",
> inode->i_sb->s_id, inode->i_ino, -rc);
> return;
> }
> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> index 98af9d7b943469d0ddd344fc78c0b87ca40c16c4..7e2f54c17a5d5c70740bbfa92ba4d4f1aca2cf22 100644
> --- a/security/smack/smack_lsm.c
> +++ b/security/smack/smack_lsm.c
> @@ -182,7 +182,7 @@ static int smk_bu_inode(struct inode *inode, int mode, int rc)
> char acc[SMK_NUM_ACCESS_TYPE + 1];
>
> if (isp->smk_flags & SMK_INODE_IMPURE)
> - pr_info("Smack Unconfined Corruption: inode=(%s %ld) %s\n",
> + pr_info("Smack Unconfined Corruption: inode=(%s %lld) %s\n",
> inode->i_sb->s_id, inode->i_ino, current->comm);
>
> if (rc <= 0)
> @@ -195,7 +195,7 @@ static int smk_bu_inode(struct inode *inode, int mode, int rc)
>
> smk_bu_mode(mode, acc);
>
> - pr_info("Smack %s: (%s %s %s) inode=(%s %ld) %s\n", smk_bu_mess[rc],
> + pr_info("Smack %s: (%s %s %s) inode=(%s %lld) %s\n", smk_bu_mess[rc],
> tsp->smk_task->smk_known, isp->smk_inode->smk_known, acc,
> inode->i_sb->s_id, inode->i_ino, current->comm);
> return 0;
> @@ -214,7 +214,7 @@ static int smk_bu_file(struct file *file, int mode, int rc)
> char acc[SMK_NUM_ACCESS_TYPE + 1];
>
> if (isp->smk_flags & SMK_INODE_IMPURE)
> - pr_info("Smack Unconfined Corruption: inode=(%s %ld) %s\n",
> + pr_info("Smack Unconfined Corruption: inode=(%s %lld) %s\n",
> inode->i_sb->s_id, inode->i_ino, current->comm);
>
> if (rc <= 0)
> @@ -223,7 +223,7 @@ static int smk_bu_file(struct file *file, int mode, int rc)
> rc = 0;
>
> smk_bu_mode(mode, acc);
> - pr_info("Smack %s: (%s %s %s) file=(%s %ld %pD) %s\n", smk_bu_mess[rc],
> + pr_info("Smack %s: (%s %s %s) file=(%s %lld %pD) %s\n", smk_bu_mess[rc],
> sskp->smk_known, smk_of_inode(inode)->smk_known, acc,
> inode->i_sb->s_id, inode->i_ino, file,
> current->comm);
> @@ -244,7 +244,7 @@ static int smk_bu_credfile(const struct cred *cred, struct file *file,
> char acc[SMK_NUM_ACCESS_TYPE + 1];
>
> if (isp->smk_flags & SMK_INODE_IMPURE)
> - pr_info("Smack Unconfined Corruption: inode=(%s %ld) %s\n",
> + pr_info("Smack Unconfined Corruption: inode=(%s %lld) %s\n",
> inode->i_sb->s_id, inode->i_ino, current->comm);
>
> if (rc <= 0)
> @@ -253,7 +253,7 @@ static int smk_bu_credfile(const struct cred *cred, struct file *file,
> rc = 0;
>
> smk_bu_mode(mode, acc);
> - pr_info("Smack %s: (%s %s %s) file=(%s %ld %pD) %s\n", smk_bu_mess[rc],
> + pr_info("Smack %s: (%s %s %s) file=(%s %lld %pD) %s\n", smk_bu_mess[rc],
> sskp->smk_known, smk_of_inode(inode)->smk_known, acc,
> inode->i_sb->s_id, inode->i_ino, file,
> current->comm);
>
> --
> 2.53.0
>
>
^ permalink raw reply
* [PATCH v2] ima: Define and use a digest_size field in the ima_algo_desc structure
From: Roberto Sassu @ 2026-02-27 12:06 UTC (permalink / raw)
To: zohar, dmitry.kasatkin, eric.snowberg, paul, jmorris, serge
Cc: linux-integrity, linux-security-module, linux-kernel,
devnull+dima.arista.com, Roberto Sassu
From: Roberto Sassu <roberto.sassu@huawei.com>
Add the digest_size field to the ima_algo_desc structure to determine the
digest size from the correct source.
If the hash algorithm is among allocated PCR banks, take the value from the
TPM bank info (equal to the value from the crypto subsystem if the TPM
algorithm is supported by it; otherwise, not exceding the size of the
digest buffer in the tpm_digest structure, used by IMA).
If the hash algorithm is SHA1, use the predefined value. Lastly, if the
hash algorithm is the default one but not among the PCR banks, take the
digest size from the crypto subsystem (the default hash algorithm is
checked when parsing the ima_hash= command line option).
Finally, use the new information to correctly show the template digest in
ima_measurements_show() and ima_ascii_measurements_show().
Link: https://github.com/linux-integrity/linux/issues/14
Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
---
security/integrity/ima/ima.h | 1 +
security/integrity/ima/ima_crypto.c | 6 ++++++
security/integrity/ima/ima_fs.c | 18 ++++++------------
3 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 89ebe98ffc5e..c38a9eb945b6 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -53,6 +53,7 @@ extern atomic_t ima_setxattr_allowed_hash_algorithms;
struct ima_algo_desc {
struct crypto_shash *tfm;
enum hash_algo algo;
+ unsigned int digest_size;
};
/* set during initialization */
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
index 8ae7821a65c2..c2a859710d20 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -109,6 +109,7 @@ static struct crypto_shash *ima_alloc_tfm(enum hash_algo algo)
int __init ima_init_crypto(void)
{
+ unsigned int digest_size;
enum hash_algo algo;
long rc;
int i;
@@ -147,7 +148,9 @@ int __init ima_init_crypto(void)
for (i = 0; i < NR_BANKS(ima_tpm_chip); i++) {
algo = ima_tpm_chip->allocated_banks[i].crypto_id;
+ digest_size = ima_tpm_chip->allocated_banks[i].digest_size;
ima_algo_array[i].algo = algo;
+ ima_algo_array[i].digest_size = digest_size;
/* unknown TPM algorithm */
if (algo == HASH_ALGO__LAST)
@@ -183,12 +186,15 @@ int __init ima_init_crypto(void)
}
ima_algo_array[ima_sha1_idx].algo = HASH_ALGO_SHA1;
+ ima_algo_array[ima_sha1_idx].digest_size = SHA1_DIGEST_SIZE;
}
if (ima_hash_algo_idx >= NR_BANKS(ima_tpm_chip) &&
ima_hash_algo_idx != ima_sha1_idx) {
+ digest_size = hash_digest_size[ima_hash_algo];
ima_algo_array[ima_hash_algo_idx].tfm = ima_shash_tfm;
ima_algo_array[ima_hash_algo_idx].algo = ima_hash_algo;
+ ima_algo_array[ima_hash_algo_idx].digest_size = digest_size;
}
return 0;
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index 012a58959ff0..23d3a14b8ce3 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -132,16 +132,12 @@ int ima_measurements_show(struct seq_file *m, void *v)
char *template_name;
u32 pcr, namelen, template_data_len; /* temporary fields */
bool is_ima_template = false;
- enum hash_algo algo;
int i, algo_idx;
algo_idx = ima_sha1_idx;
- algo = HASH_ALGO_SHA1;
- if (m->file != NULL) {
+ if (m->file != NULL)
algo_idx = (unsigned long)file_inode(m->file)->i_private;
- algo = ima_algo_array[algo_idx].algo;
- }
/* get entry */
e = qe->entry;
@@ -160,7 +156,8 @@ int ima_measurements_show(struct seq_file *m, void *v)
ima_putc(m, &pcr, sizeof(e->pcr));
/* 2nd: template digest */
- ima_putc(m, e->digests[algo_idx].digest, hash_digest_size[algo]);
+ ima_putc(m, e->digests[algo_idx].digest,
+ ima_algo_array[algo_idx].digest_size);
/* 3rd: template name size */
namelen = !ima_canonical_fmt ? strlen(template_name) :
@@ -229,16 +226,12 @@ static int ima_ascii_measurements_show(struct seq_file *m, void *v)
struct ima_queue_entry *qe = v;
struct ima_template_entry *e;
char *template_name;
- enum hash_algo algo;
int i, algo_idx;
algo_idx = ima_sha1_idx;
- algo = HASH_ALGO_SHA1;
- if (m->file != NULL) {
+ if (m->file != NULL)
algo_idx = (unsigned long)file_inode(m->file)->i_private;
- algo = ima_algo_array[algo_idx].algo;
- }
/* get entry */
e = qe->entry;
@@ -252,7 +245,8 @@ static int ima_ascii_measurements_show(struct seq_file *m, void *v)
seq_printf(m, "%2d ", e->pcr);
/* 2nd: template hash */
- ima_print_digest(m, e->digests[algo_idx].digest, hash_digest_size[algo]);
+ ima_print_digest(m, e->digests[algo_idx].digest,
+ ima_algo_array[algo_idx].digest_size);
/* 3th: template name */
seq_printf(m, " %s", template_name);
--
2.43.0
^ permalink raw reply related
* Re: [PATCH 50/61] zonefs: update format strings for u64 i_ino
From: Johannes Thumshirn @ 2026-02-27 11:55 UTC (permalink / raw)
To: Jeff Layton, Alexander Viro, Christian Brauner, Jan Kara,
Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers, Dan Williams,
Matthew Wilcox, Eric Biggers, Theodore Y. Ts'o, Muchun Song,
Oscar Salvador, David Hildenbrand, David Howells, Paulo Alcantara,
Andreas Dilger, Jan Kara, Jaegeuk Kim, Chao Yu, Trond Myklebust,
Anna Schumaker, Chuck Lever, NeilBrown, Olga Kornievskaia,
Dai Ngo, Tom Talpey, Steve French, Ronnie Sahlberg,
Shyam Prasad N, Bharath SM, Alexander Aring, Ryusuke Konishi,
Viacheslav Dubeyko, Eric Van Hensbergen, Latchesar Ionkov,
Dominique Martinet, Christian Schoenebeck, David Sterba,
Marc Dionne, Ian Kent, Luis de Bethencourt, Salah Triki,
Tigran A. Aivazian, Ilya Dryomov, Alex Markuze, Jan Harkes,
coda@cs.cmu.edu, Nicolas Pitre, Tyler Hicks, Amir Goldstein,
hch@infradead.org, John Paul Adrian Glaubitz, Yangtao Li,
Mikulas Patocka, David Woodhouse, Richard Weinberger,
Dave Kleikamp, Konstantin Komarov, Mark Fasheh, Joel Becker,
Joseph Qi, Mike Marshall, Martin Brandenburg, Miklos Szeredi,
Anders Larsen, Zhihao Cheng, Damien Le Moal, Naohiro Aota,
Johannes Thumshirn, John Johansen, Paul Moore, James Morris,
Serge E. Hallyn, Mimi Zohar, Roberto Sassu, Dmitry Kasatkin,
Eric Snowberg, Fan Wu, Stephen Smalley, Ondrej Mosnacek,
Casey Schaufler, Alex Deucher, Christian König, David Airlie,
Simona Vetter, Sumit Semwal, Eric Dumazet, Kuniyuki Iwashima,
Paolo Abeni, Willem de Bruijn, David S. Miller, Jakub Kicinski,
Simon Horman, Oleg Nesterov, Peter Zijlstra, Ingo Molnar,
Arnaldo Carvalho de Melo, Namhyung Kim, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
James Clark, Darrick J. Wong, Martin Schiller
Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-trace-kernel@vger.kernel.org, nvdimm@lists.linux.dev,
fsverity@lists.linux.dev, linux-mm@kvack.org,
netfs@lists.linux.dev, linux-ext4@vger.kernel.org,
linux-f2fs-devel@lists.sourceforge.net, linux-nfs@vger.kernel.org,
linux-cifs@vger.kernel.org, samba-technical@lists.samba.org,
linux-nilfs@vger.kernel.org, v9fs@lists.linux.dev,
linux-afs@lists.infradead.org, autofs@vger.kernel.org,
ceph-devel@vger.kernel.org, codalist@coda.cs.cmu.edu,
ecryptfs@vger.kernel.org, linux-mtd@lists.infradead.org,
jfs-discussion@lists.sourceforge.net, ntfs3@lists.linux.dev,
ocfs2-devel@lists.linux.dev, devel@lists.orangefs.org,
linux-unionfs@vger.kernel.org, apparmor@lists.ubuntu.com,
linux-security-module@vger.kernel.org,
linux-integrity@vger.kernel.org, selinux@vger.kernel.org,
amd-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org,
linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org,
netdev@vger.kernel.org, linux-perf-users@vger.kernel.org,
linux-fscrypt@vger.kernel.org, linux-xfs@vger.kernel.org,
linux-hams@vger.kernel.org, linux-x25@vger.kernel.org
In-Reply-To: <20260226-iino-u64-v1-50-ccceff366db9@kernel.org>
Looks good,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
^ permalink raw reply
* Re: [PATCH 00/61] vfs: change inode->i_ino from unsigned long to u64
From: Jeff Layton @ 2026-02-27 11:52 UTC (permalink / raw)
To: Christian König, Alexander Viro, Christian Brauner, Jan Kara,
Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers, Dan Williams,
Matthew Wilcox, Eric Biggers, Theodore Y. Ts'o, Muchun Song,
Oscar Salvador, David Hildenbrand, David Howells, Paulo Alcantara,
Andreas Dilger, Jan Kara, Jaegeuk Kim, Chao Yu, Trond Myklebust,
Anna Schumaker, Chuck Lever, NeilBrown, Olga Kornievskaia,
Dai Ngo, Tom Talpey, Steve French, Ronnie Sahlberg,
Shyam Prasad N, Bharath SM, Alexander Aring, Ryusuke Konishi,
Viacheslav Dubeyko, Eric Van Hensbergen, Latchesar Ionkov,
Dominique Martinet, Christian Schoenebeck, David Sterba,
Marc Dionne, Ian Kent, Luis de Bethencourt, Salah Triki,
Tigran A. Aivazian, Ilya Dryomov, Alex Markuze, Jan Harkes, coda,
Nicolas Pitre, Tyler Hicks, Amir Goldstein, Christoph Hellwig,
John Paul Adrian Glaubitz, Yangtao Li, Mikulas Patocka,
David Woodhouse, Richard Weinberger, Dave Kleikamp,
Konstantin Komarov, Mark Fasheh, Joel Becker, Joseph Qi,
Mike Marshall, Martin Brandenburg, Miklos Szeredi, Anders Larsen,
Zhihao Cheng, Damien Le Moal, Naohiro Aota, Johannes Thumshirn,
John Johansen, Paul Moore, James Morris, Serge E. Hallyn,
Mimi Zohar, Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Fan Wu,
Stephen Smalley, Ondrej Mosnacek, Casey Schaufler, Alex Deucher,
David Airlie, Simona Vetter, Sumit Semwal, Eric Dumazet,
Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn, David S. Miller,
Jakub Kicinski, Simon Horman, Oleg Nesterov, Peter Zijlstra,
Ingo Molnar, Arnaldo Carvalho de Melo, Namhyung Kim, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
James Clark, Darrick J. Wong, Martin Schiller
Cc: linux-fsdevel, linux-kernel, linux-trace-kernel, nvdimm, fsverity,
linux-mm, netfs, linux-ext4, linux-f2fs-devel, linux-nfs,
linux-cifs, samba-technical, linux-nilfs, v9fs, linux-afs, autofs,
ceph-devel, codalist, ecryptfs, linux-mtd, jfs-discussion, ntfs3,
ocfs2-devel, devel, linux-unionfs, apparmor,
linux-security-module, linux-integrity, selinux, amd-gfx,
dri-devel, linux-media, linaro-mm-sig, netdev, linux-perf-users,
linux-fscrypt, linux-xfs, linux-hams, linux-x25
In-Reply-To: <b4f32cab-2b34-4002-83d1-3ae038a4bb38@amd.com>
On Fri, 2026-02-27 at 10:30 +0100, Christian König wrote:
> On 2/26/26 16:55, Jeff Layton wrote:
> > Christian said [1] to "just do it" when I proposed this, so here we are!
> >
> > For historical reasons, the inode->i_ino field is an unsigned long,
> > which means that it's 32 bits on 32 bit architectures. This has caused a
> > number of filesystems to implement hacks to hash a 64-bit identifier
> > into a 32-bit field, and deprives us of a universal identifier field for
> > an inode.
> >
> > This patchset changes the inode->i_ino field from an unsigned long to a
> > u64. This shouldn't make any material difference on 64-bit hosts, but
> > 32-bit hosts will see struct inode grow by at least 4 bytes. This could
> > have effects on slabcache sizes and field alignment.
> >
> > The bulk of the changes are to format strings and tracepoints, since the
> > kernel itself doesn't care that much about the i_ino field. The first
> > patch changes some vfs function arguments, so check that one out
> > carefully.
> >
> > With this change, we may be able to shrink some inode structures. For
> > instance, struct nfs_inode has a fileid field that holds the 64-bit
> > inode number. With this set of changes, that field could be eliminated.
> > I'd rather leave that sort of cleanups for later just to keep this
> > simple.
> >
> > Much of this set was generated by LLM, but I attributed it to myself
> > since I consider this to be in the "menial tasks" category of LLM usage.
>
> Sounds reasonable to me, should get_next_ino() also be changed to return an 64bit ino?
>
I'm not opposed to doing that, but I'd probably leave that for a
follow-on cleanup. Just doing the i_ino conversion is already making
for a huge patchset.
--
Jeff Layton <jlayton@kernel.org>
^ permalink raw reply
* [PATCH v2] cred: delete task_euid()
From: Alice Ryhl @ 2026-02-27 10:33 UTC (permalink / raw)
To: Paul Moore, Serge Hallyn, Jonathan Corbet, Greg Kroah-Hartman,
Shuah Khan, Alex Shi, Yanteng Si, Dongliang Mu
Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Trevor Gross, Danilo Krummrich,
linux-security-module, linux-doc, linux-kernel, rust-for-linux,
Jann Horn, Alice Ryhl
task_euid() is a very weird operation. You can see how weird it is by
grepping for task_euid() - binder is its only user. task_euid() obtains
the objective effective UID - it looks at the credentials of the task
for purposes of acting on it as an object, but then accesses the
effective UID (which the credentials.7 man page describes as "[...] used
by the kernel to determine the permissions that the process will have
when accessing shared resources [...]").
Since usage in Binder has now been removed, get rid of the resulting
dead code.
Changes to the zh_CN translation was carried out with the help of
Gemini and Google Translate.
Suggested-by: Jann Horn <jannh@google.com>
Reviewed-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
---
Depends on these two changes:
https://lore.kernel.org/all/20260212-rust-uid-v1-1-deff4214c766@google.com/ (not picked up)
https://lore.kernel.org/all/20260213-binder-uid-v1-0-7b795ae05523@google.com/ (in char-misc-testing)
---
Changes in v2:
- Update translation as per Alex Shi.
- Pick up Reviewed-by Gary.
- Update commit title to use cred: prefix.
- Link to v1: https://lore.kernel.org/r/20260219-remove-task-euid-v1-1-904060826e07@google.com
---
Documentation/security/credentials.rst | 6 ++----
Documentation/translations/zh_CN/security/credentials.rst | 4 +---
include/linux/cred.h | 1 -
rust/helpers/task.c | 5 -----
rust/kernel/task.rs | 10 ----------
5 files changed, 3 insertions(+), 23 deletions(-)
diff --git a/Documentation/security/credentials.rst b/Documentation/security/credentials.rst
index d0191c8b8060..81d3b5737d85 100644
--- a/Documentation/security/credentials.rst
+++ b/Documentation/security/credentials.rst
@@ -393,16 +393,14 @@ the credentials so obtained when they're finished with.
The result of ``__task_cred()`` should not be passed directly to
``get_cred()`` as this may race with ``commit_cred()``.
-There are a couple of convenience functions to access bits of another task's
-credentials, hiding the RCU magic from the caller::
+There is a convenience function to access bits of another task's credentials,
+hiding the RCU magic from the caller::
uid_t task_uid(task) Task's real UID
- uid_t task_euid(task) Task's effective UID
If the caller is holding the RCU read lock at the time anyway, then::
__task_cred(task)->uid
- __task_cred(task)->euid
should be used instead. Similarly, if multiple aspects of a task's credentials
need to be accessed, RCU read lock should be used, ``__task_cred()`` called,
diff --git a/Documentation/translations/zh_CN/security/credentials.rst b/Documentation/translations/zh_CN/security/credentials.rst
index 88fcd9152ffe..20c8696f8198 100644
--- a/Documentation/translations/zh_CN/security/credentials.rst
+++ b/Documentation/translations/zh_CN/security/credentials.rst
@@ -337,15 +337,13 @@ const指针上操作,因此不需要进行类型转换,但需要临时放弃
``__task_cred()`` 的结果不应直接传递给 ``get_cred()`` ,
因为这可能与 ``commit_cred()`` 发生竞争条件。
-还有一些方便的函数可以访问另一个任务凭据的特定部分,将RCU操作对调用方隐藏起来::
+有一个方便的函数可用于访问另一个任务凭据的特定部分,从而对调用方隐藏RCU机制::
uid_t task_uid(task) Task's real UID
- uid_t task_euid(task) Task's effective UID
如果调用方在此时已经持有RCU读锁,则应使用::
__task_cred(task)->uid
- __task_cred(task)->euid
类似地,如果需要访问任务凭据的多个方面,应使用RCU读锁,调用 ``__task_cred()``
函数,将结果存储在临时指针中,然后从临时指针中调用凭据的各个方面,最后释放锁。
diff --git a/include/linux/cred.h b/include/linux/cred.h
index ed1609d78cd7..b40ec3c72ee6 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -367,7 +367,6 @@ DEFINE_FREE(put_cred, struct cred *, if (!IS_ERR_OR_NULL(_T)) put_cred(_T))
})
#define task_uid(task) (task_cred_xxx((task), uid))
-#define task_euid(task) (task_cred_xxx((task), euid))
#define task_ucounts(task) (task_cred_xxx((task), ucounts))
#define current_cred_xxx(xxx) \
diff --git a/rust/helpers/task.c b/rust/helpers/task.c
index c0e1a06ede78..b46b1433a67e 100644
--- a/rust/helpers/task.c
+++ b/rust/helpers/task.c
@@ -28,11 +28,6 @@ __rust_helper kuid_t rust_helper_task_uid(struct task_struct *task)
return task_uid(task);
}
-__rust_helper kuid_t rust_helper_task_euid(struct task_struct *task)
-{
- return task_euid(task);
-}
-
#ifndef CONFIG_USER_NS
__rust_helper uid_t rust_helper_from_kuid(struct user_namespace *to, kuid_t uid)
{
diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs
index e07d0ddd76f6..169ff1dde936 100644
--- a/rust/kernel/task.rs
+++ b/rust/kernel/task.rs
@@ -218,16 +218,6 @@ pub fn uid(&self) -> Kuid {
Kuid::from_raw(unsafe { bindings::task_uid(self.as_ptr()) })
}
- /// Returns the objective effective UID of the given task.
- ///
- /// You should probably not be using this; the effective UID is normally
- /// only relevant in subjective credentials.
- #[inline]
- pub fn euid(&self) -> Kuid {
- // SAFETY: It's always safe to call `task_euid` on a valid task.
- Kuid::from_raw(unsafe { bindings::task_euid(self.as_ptr()) })
- }
-
/// Determines whether the given task has pending signals.
#[inline]
pub fn signal_pending(&self) -> bool {
---
base-commit: 7dff99b354601dd01829e1511711846e04340a69
change-id: 20260219-remove-task-euid-19e4b00beebe
prerequisite-change-id: 20260212-rust-uid-f1b3a45c8084:v1
prerequisite-patch-id: 7ec4933af3a7f4c6bb0403c34a6dd41306836295
prerequisite-change-id: 20260213-binder-uid-a24ede5026a8:v1
prerequisite-patch-id: 7be0128bd8902879bb271d0587ac98bf242cf612
prerequisite-patch-id: 4a9d0f595d2084b3f8982a2d0d8b3df35b9fae0e
Best regards,
--
Alice Ryhl <aliceryhl@google.com>
^ permalink raw reply related
* Re: [PATCH 00/61] vfs: change inode->i_ino from unsigned long to u64
From: Christian Brauner @ 2026-02-27 10:06 UTC (permalink / raw)
To: Jeff Layton
Cc: Alexander Viro, Jan Kara, Steven Rostedt, Masami Hiramatsu,
Mathieu Desnoyers, Dan Williams, Matthew Wilcox, Eric Biggers,
Theodore Y. Ts'o, Muchun Song, Oscar Salvador,
David Hildenbrand, David Howells, Paulo Alcantara, Andreas Dilger,
Jan Kara, Jaegeuk Kim, Chao Yu, Trond Myklebust, Anna Schumaker,
Chuck Lever, NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
Steve French, Ronnie Sahlberg, Shyam Prasad N, Bharath SM,
Alexander Aring, Ryusuke Konishi, Viacheslav Dubeyko,
Eric Van Hensbergen, Latchesar Ionkov, Dominique Martinet,
Christian Schoenebeck, David Sterba, Marc Dionne, Ian Kent,
Luis de Bethencourt, Salah Triki, Tigran A. Aivazian,
Ilya Dryomov, Alex Markuze, Jan Harkes, coda, Nicolas Pitre,
Tyler Hicks, Amir Goldstein, Christoph Hellwig,
John Paul Adrian Glaubitz, Yangtao Li, Mikulas Patocka,
David Woodhouse, Richard Weinberger, Dave Kleikamp,
Konstantin Komarov, Mark Fasheh, Joel Becker, Joseph Qi,
Mike Marshall, Martin Brandenburg, Miklos Szeredi, Anders Larsen,
Zhihao Cheng, Damien Le Moal, Naohiro Aota, Johannes Thumshirn,
John Johansen, Paul Moore, James Morris, Serge E. Hallyn,
Mimi Zohar, Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Fan Wu,
Stephen Smalley, Ondrej Mosnacek, Casey Schaufler, Alex Deucher,
Christian König, David Airlie, Simona Vetter, Sumit Semwal,
Eric Dumazet, Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn,
David S. Miller, Jakub Kicinski, Simon Horman, Oleg Nesterov,
Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
Ian Rogers, Adrian Hunter, James Clark, Darrick J. Wong,
Martin Schiller, linux-fsdevel, linux-kernel, linux-trace-kernel,
nvdimm, fsverity, linux-mm, netfs, linux-ext4, linux-f2fs-devel,
linux-nfs, linux-cifs, samba-technical, linux-nilfs, v9fs,
linux-afs, autofs, ceph-devel, codalist, ecryptfs, linux-mtd,
jfs-discussion, ntfs3, ocfs2-devel, devel, linux-unionfs,
apparmor, linux-security-module, linux-integrity, selinux,
amd-gfx, dri-devel, linux-media, linaro-mm-sig, netdev,
linux-perf-users, linux-fscrypt, linux-xfs, linux-hams, linux-x25
In-Reply-To: <20260226-iino-u64-v1-0-ccceff366db9@kernel.org>
On Thu, Feb 26, 2026 at 10:55:02AM -0500, Jeff Layton wrote:
> Christian said [1] to "just do it" when I proposed this, so here we are!
>
> For historical reasons, the inode->i_ino field is an unsigned long,
> which means that it's 32 bits on 32 bit architectures. This has caused a
> number of filesystems to implement hacks to hash a 64-bit identifier
> into a 32-bit field, and deprives us of a universal identifier field for
> an inode.
>
> This patchset changes the inode->i_ino field from an unsigned long to a
> u64. This shouldn't make any material difference on 64-bit hosts, but
> 32-bit hosts will see struct inode grow by at least 4 bytes. This could
> have effects on slabcache sizes and field alignment.
>
> The bulk of the changes are to format strings and tracepoints, since the
> kernel itself doesn't care that much about the i_ino field. The first
> patch changes some vfs function arguments, so check that one out
> carefully.
>
> With this change, we may be able to shrink some inode structures. For
> instance, struct nfs_inode has a fileid field that holds the 64-bit
> inode number. With this set of changes, that field could be eliminated.
> I'd rather leave that sort of cleanups for later just to keep this
> simple.
>
> Much of this set was generated by LLM, but I attributed it to myself
> since I consider this to be in the "menial tasks" category of LLM usage.
>
> [1]: https://lore.kernel.org/linux-fsdevel/20260219-portrait-winkt-959070cee42f@brauner/
I'm working under the assumption that we have crossed the threshold and
people send patches they did completely themselves and also patches that
were done with the help of or almost completely by a tool. You have to
defend it one way or the other.
Frankly, as long as you understand what you're doing in general well and
I know that you are a trusted and thorough developer/maintainer I could
not care less if you tell me whether or not you did this all on your
own or with the help of some tool. In my experience, laziness grows with
experience but so does the amount of ideas.
So attribute it to yourself or attribute it partially to the tool. I
personally don't care.
^ permalink raw reply
* Re: [PATCH] cred: clarify usage of get_cred_rcu()
From: Alice Ryhl @ 2026-02-27 10:04 UTC (permalink / raw)
To: Paul Moore; +Cc: Serge Hallyn, linux-security-module, linux-kernel
In-Reply-To: <CAHC9VhTwJbuXrdUFxWLVWfgk45hLScPgaC9Xb+R2NH6NGdaMZQ@mail.gmail.com>
On Thu, Feb 26, 2026 at 09:18:29PM -0500, Paul Moore wrote:
> On Fri, Feb 20, 2026 at 4:19 AM Alice Ryhl <aliceryhl@google.com> wrote:
> >
> > After being confused by looking at get_cred() and get_cred_rcu(), I
> > figured out what's going on. Thus, add some comments to clarify how
> > get_cred_rcu() works for the benefit of others looking in the future.
> >
> > Note that in principle we could add an assertion that non_rcu is zero in
> > the failure path of atomic_long_inc_not_zero().
>
> That would be interesting to add a WARN_ON() there and see what
> happens. Hopefully nothing, but one never knows ;) Have you tried
> this?
I tried just now. I put it on an Android phone, and it did not seem to
be triggered after a few minute of usage.
I can send a patch adding it if you would like?
> > Signed-off-by: Alice Ryhl <aliceryhl@google.com>
> > ---
> > include/linux/cred.h | 18 ++++++++++++++++++
> > 1 file changed, 18 insertions(+)
>
> ...
>
> > +/*
> > + * get_cred_rcu - Get a reference on a set of credentials under rcu
>
> I agree this is a bit pedantic, but it looks like the bulk of the file
> capitalizes RCU and technically that is correct as it is an acronym.
Will do.
> > + * @cred: The credentials to reference
> > + *
> > + * Get a reference on the specified set of credentials, or %NULL if the last
> > + * refcount has already been put.
> > + *
> > + * This is used to obtain a reference under an rcu read lock.
>
> I would suggest a different description:
>
> "Get a reference to the specified set of credentials and return a
> pointer to the cred struct, or %NULL if it is not possible to obtain a
> new reference. After successfully taking a new reference to the
> specified credentials, the cred struct will be marked for free'ing via
> RCU."
I actually think it's confusing to include
After successfully taking a new reference to the specified
credentials, the cred struct will be marked for free'ing via
RCU.
in the documentation, because it makes it sounds like this method has
the _rcu() suffix because it marks the struct for free'ing via RCU. But
that is not the case. After all, get_cred() also marks it for free'ing
via RCU.
It has the _rcu() suffix because - if the cred struct is *already*
marked for free'ing via RCU, then you are allowed to do this:
rcu_read_lock();
cred = get_cred_rcu(&foo->my_cred);
rcu_read_unlock();
even if another thread might put foo->my_cred in parallel with the above
piece of code.
> > + */
> > static inline const struct cred *get_cred_rcu(const struct cred *cred)
> > {
> > struct cred *nonconst_cred = (struct cred *) cred;
> > if (!cred)
> > return NULL;
> > if (!atomic_long_inc_not_zero(&nonconst_cred->usage))
> > return NULL;
> > + /*
> > + * If non_rcu is not already zero, then this call to get_cred_rcu() is
> > + * probably wrong because if 'usage' goes to zero prior to this call,
> > + * then get_cred_rcu() assumes it is freed with rcu.
> > + *
> > + * However, an exception to this is using get_cred_rcu() in cases where
> > + * get_cred() would have been okay. To support that case, we do not
> > + * check non_rcu and set it to zero regardless.
> > + */
>
> This is surely a matter of perspective, but the above seems a bit
> wordy, and doesn't address what I believe is the important part:
> setting non_rcu to zero means this credential will be freed
> asynchronously via RCU. Both get_cred_rcu() and get_cred() set
> non_rcu to 0/false ... although get_cred() doesn't do the non-zero
> check before bumping the refcount.
I think that would be a good comment to add to get_cred(), but in the
case of get_cred_rcu(), it really should already be set to zero, because
otherwise
rcu_read_lock();
cred = get_cred_rcu(&foo->my_cred);
rcu_read_unlock();
is illegal.
> I suppose we could consider adding the zero check in the get_cred()
> case, but even if we ignore the KCSAN barrier, it looks like the arch
> support for the inc_not_zero() case isn't nearly as good, likely
> resulting in more code to execute.
I don't think that's necessary. If you use get_cred() in a scenario
where it might be zero, you have a bug.
Alice
^ permalink raw reply
* Re: [PATCH 00/61] vfs: change inode->i_ino from unsigned long to u64
From: Christian König @ 2026-02-27 9:30 UTC (permalink / raw)
To: Jeff Layton, Alexander Viro, Christian Brauner, Jan Kara,
Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers, Dan Williams,
Matthew Wilcox, Eric Biggers, Theodore Y. Ts'o, Muchun Song,
Oscar Salvador, David Hildenbrand, David Howells, Paulo Alcantara,
Andreas Dilger, Jan Kara, Jaegeuk Kim, Chao Yu, Trond Myklebust,
Anna Schumaker, Chuck Lever, NeilBrown, Olga Kornievskaia,
Dai Ngo, Tom Talpey, Steve French, Ronnie Sahlberg,
Shyam Prasad N, Bharath SM, Alexander Aring, Ryusuke Konishi,
Viacheslav Dubeyko, Eric Van Hensbergen, Latchesar Ionkov,
Dominique Martinet, Christian Schoenebeck, David Sterba,
Marc Dionne, Ian Kent, Luis de Bethencourt, Salah Triki,
Tigran A. Aivazian, Ilya Dryomov, Alex Markuze, Jan Harkes, coda,
Nicolas Pitre, Tyler Hicks, Amir Goldstein, Christoph Hellwig,
John Paul Adrian Glaubitz, Yangtao Li, Mikulas Patocka,
David Woodhouse, Richard Weinberger, Dave Kleikamp,
Konstantin Komarov, Mark Fasheh, Joel Becker, Joseph Qi,
Mike Marshall, Martin Brandenburg, Miklos Szeredi, Anders Larsen,
Zhihao Cheng, Damien Le Moal, Naohiro Aota, Johannes Thumshirn,
John Johansen, Paul Moore, James Morris, Serge E. Hallyn,
Mimi Zohar, Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Fan Wu,
Stephen Smalley, Ondrej Mosnacek, Casey Schaufler, Alex Deucher,
David Airlie, Simona Vetter, Sumit Semwal, Eric Dumazet,
Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn, David S. Miller,
Jakub Kicinski, Simon Horman, Oleg Nesterov, Peter Zijlstra,
Ingo Molnar, Arnaldo Carvalho de Melo, Namhyung Kim, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
James Clark, Darrick J. Wong, Martin Schiller
Cc: linux-fsdevel, linux-kernel, linux-trace-kernel, nvdimm, fsverity,
linux-mm, netfs, linux-ext4, linux-f2fs-devel, linux-nfs,
linux-cifs, samba-technical, linux-nilfs, v9fs, linux-afs, autofs,
ceph-devel, codalist, ecryptfs, linux-mtd, jfs-discussion, ntfs3,
ocfs2-devel, devel, linux-unionfs, apparmor,
linux-security-module, linux-integrity, selinux, amd-gfx,
dri-devel, linux-media, linaro-mm-sig, netdev, linux-perf-users,
linux-fscrypt, linux-xfs, linux-hams, linux-x25
In-Reply-To: <20260226-iino-u64-v1-0-ccceff366db9@kernel.org>
On 2/26/26 16:55, Jeff Layton wrote:
> Christian said [1] to "just do it" when I proposed this, so here we are!
>
> For historical reasons, the inode->i_ino field is an unsigned long,
> which means that it's 32 bits on 32 bit architectures. This has caused a
> number of filesystems to implement hacks to hash a 64-bit identifier
> into a 32-bit field, and deprives us of a universal identifier field for
> an inode.
>
> This patchset changes the inode->i_ino field from an unsigned long to a
> u64. This shouldn't make any material difference on 64-bit hosts, but
> 32-bit hosts will see struct inode grow by at least 4 bytes. This could
> have effects on slabcache sizes and field alignment.
>
> The bulk of the changes are to format strings and tracepoints, since the
> kernel itself doesn't care that much about the i_ino field. The first
> patch changes some vfs function arguments, so check that one out
> carefully.
>
> With this change, we may be able to shrink some inode structures. For
> instance, struct nfs_inode has a fileid field that holds the 64-bit
> inode number. With this set of changes, that field could be eliminated.
> I'd rather leave that sort of cleanups for later just to keep this
> simple.
>
> Much of this set was generated by LLM, but I attributed it to myself
> since I consider this to be in the "menial tasks" category of LLM usage.
Sounds reasonable to me, should get_next_ino() also be changed to return an 64bit ino?
Currently it is always only 32bit and we have workarounds for that in DMA-buf for example.
Thanks,
Christian.
>
> [1]: https://lore.kernel.org/linux-fsdevel/20260219-portrait-winkt-959070cee42f@brauner/
>
> Signed-off-by: Jeff Layton <jlayton@kernel.org>
> ---
> Jeff Layton (61):
> vfs: widen inode hash/lookup functions to u64
> vfs: change i_ino from unsigned long to u64
> trace: update VFS-layer trace events for u64 i_ino
> ext4: update for u64 i_ino
> jbd2: update format strings for u64 i_ino
> f2fs: update for u64 i_ino
> lockd: update format strings for u64 i_ino
> nfs: update for u64 i_ino
> nfs: remove nfs_fattr_to_ino_t() and nfs_fileid_to_ino_t()
> nfs: remove nfs_compat_user_ino64()
> nfs: remove enable_ino64 module parameter
> nfsd: update format strings for u64 i_ino
> smb: store full 64-bit uniqueid in i_ino
> smb: remove cifs_uniqueid_to_ino_t()
> locks: update /proc/locks format for u64 i_ino
> proc: update /proc/PID/maps for u64 i_ino
> nilfs2: update for u64 i_ino
> 9p: update format strings for u64 i_ino
> affs: update format strings for u64 i_ino
> afs: update format strings for u64 i_ino
> autofs: update format strings for u64 i_ino
> befs: update format strings for u64 i_ino
> bfs: update format strings for u64 i_ino
> cachefiles: update format strings for u64 i_ino
> ceph: update format strings for u64 i_ino
> coda: update format strings for u64 i_ino
> cramfs: update format strings for u64 i_ino
> ecryptfs: update format strings for u64 i_ino
> efs: update format strings for u64 i_ino
> exportfs: update format strings for u64 i_ino
> ext2: update format strings for u64 i_ino
> freevxfs: update format strings for u64 i_ino
> hfs: update format strings for u64 i_ino
> hfsplus: update format strings for u64 i_ino
> hpfs: update format strings for u64 i_ino
> isofs: update format strings for u64 i_ino
> jffs2: update format strings for u64 i_ino
> jfs: update format strings for u64 i_ino
> minix: update format strings for u64 i_ino
> nsfs: update format strings for u64 i_ino
> ntfs3: update format strings for u64 i_ino
> ocfs2: update format strings for u64 i_ino
> orangefs: update format strings for u64 i_ino
> overlayfs: update format strings for u64 i_ino
> qnx4: update format strings for u64 i_ino
> qnx6: update format strings for u64 i_ino
> ubifs: update format strings for u64 i_ino
> udf: update format strings for u64 i_ino
> ufs: update format strings for u64 i_ino
> zonefs: update format strings for u64 i_ino
> security: update audit format strings for u64 i_ino
> drm/amdgpu: update for u64 i_ino
> fsnotify: update fdinfo format strings for u64 i_ino
> net: update socket dname format for u64 i_ino
> uprobes: update format strings for u64 i_ino
> dma-buf: update format string for u64 i_ino
> fscrypt: update format strings for u64 i_ino
> fsverity: update format string for u64 i_ino
> iomap: update format string for u64 i_ino
> net: update legacy protocol format strings for u64 i_ino
> vfs: update core format strings for u64 i_ino
>
> drivers/dma-buf/dma-buf.c | 2 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 4 +-
> fs/9p/vfs_addr.c | 4 +-
> fs/9p/vfs_inode.c | 6 +-
> fs/9p/vfs_inode_dotl.c | 6 +-
> fs/affs/amigaffs.c | 8 +-
> fs/affs/bitmap.c | 2 +-
> fs/affs/dir.c | 2 +-
> fs/affs/file.c | 20 +-
> fs/affs/inode.c | 12 +-
> fs/affs/namei.c | 14 +-
> fs/affs/symlink.c | 2 +-
> fs/afs/dir.c | 10 +-
> fs/afs/dir_search.c | 2 +-
> fs/afs/dynroot.c | 2 +-
> fs/afs/inode.c | 2 +-
> fs/autofs/inode.c | 2 +-
> fs/befs/linuxvfs.c | 28 +-
> fs/bfs/dir.c | 4 +-
> fs/cachefiles/io.c | 6 +-
> fs/cachefiles/namei.c | 12 +-
> fs/cachefiles/xattr.c | 2 +-
> fs/ceph/crypto.c | 4 +-
> fs/coda/dir.c | 2 +-
> fs/coda/inode.c | 2 +-
> fs/cramfs/inode.c | 2 +-
> fs/crypto/crypto.c | 2 +-
> fs/crypto/hooks.c | 2 +-
> fs/crypto/keysetup.c | 2 +-
> fs/dcache.c | 4 +-
> fs/ecryptfs/crypto.c | 6 +-
> fs/ecryptfs/file.c | 2 +-
> fs/efs/inode.c | 6 +-
> fs/eventpoll.c | 2 +-
> fs/exportfs/expfs.c | 4 +-
> fs/ext2/dir.c | 10 +-
> fs/ext2/ialloc.c | 9 +-
> fs/ext2/inode.c | 2 +-
> fs/ext2/xattr.c | 14 +-
> fs/ext4/dir.c | 2 +-
> fs/ext4/ext4.h | 4 +-
> fs/ext4/extents.c | 8 +-
> fs/ext4/extents_status.c | 28 +-
> fs/ext4/fast_commit.c | 8 +-
> fs/ext4/ialloc.c | 10 +-
> fs/ext4/indirect.c | 2 +-
> fs/ext4/inline.c | 14 +-
> fs/ext4/inode.c | 22 +-
> fs/ext4/ioctl.c | 4 +-
> fs/ext4/mballoc.c | 6 +-
> fs/ext4/migrate.c | 2 +-
> fs/ext4/move_extent.c | 20 +-
> fs/ext4/namei.c | 10 +-
> fs/ext4/orphan.c | 16 +-
> fs/ext4/page-io.c | 10 +-
> fs/ext4/super.c | 22 +-
> fs/ext4/xattr.c | 10 +-
> fs/f2fs/compress.c | 4 +-
> fs/f2fs/dir.c | 2 +-
> fs/f2fs/extent_cache.c | 8 +-
> fs/f2fs/f2fs.h | 6 +-
> fs/f2fs/file.c | 12 +-
> fs/f2fs/gc.c | 2 +-
> fs/f2fs/inline.c | 4 +-
> fs/f2fs/inode.c | 48 ++--
> fs/f2fs/namei.c | 8 +-
> fs/f2fs/node.c | 12 +-
> fs/f2fs/recovery.c | 10 +-
> fs/f2fs/xattr.c | 10 +-
> fs/freevxfs/vxfs_bmap.c | 4 +-
> fs/fserror.c | 2 +-
> fs/hfs/catalog.c | 2 +-
> fs/hfs/extent.c | 4 +-
> fs/hfs/inode.c | 4 +-
> fs/hfsplus/attributes.c | 10 +-
> fs/hfsplus/catalog.c | 2 +-
> fs/hfsplus/dir.c | 6 +-
> fs/hfsplus/extents.c | 6 +-
> fs/hfsplus/inode.c | 8 +-
> fs/hfsplus/super.c | 6 +-
> fs/hfsplus/xattr.c | 10 +-
> fs/hpfs/dir.c | 4 +-
> fs/hpfs/dnode.c | 4 +-
> fs/hpfs/ea.c | 4 +-
> fs/hpfs/inode.c | 4 +-
> fs/inode.c | 46 ++--
> fs/iomap/ioend.c | 2 +-
> fs/isofs/compress.c | 2 +-
> fs/isofs/dir.c | 2 +-
> fs/isofs/inode.c | 6 +-
> fs/isofs/namei.c | 2 +-
> fs/jbd2/journal.c | 4 +-
> fs/jbd2/transaction.c | 2 +-
> fs/jffs2/dir.c | 4 +-
> fs/jffs2/file.c | 4 +-
> fs/jffs2/fs.c | 18 +-
> fs/jfs/inode.c | 2 +-
> fs/jfs/jfs_imap.c | 2 +-
> fs/jfs/jfs_metapage.c | 2 +-
> fs/lockd/svclock.c | 8 +-
> fs/lockd/svcsubs.c | 2 +-
> fs/locks.c | 6 +-
> fs/minix/inode.c | 10 +-
> fs/nfs/dir.c | 22 +-
> fs/nfs/file.c | 8 +-
> fs/nfs/filelayout/filelayout.c | 8 +-
> fs/nfs/flexfilelayout/flexfilelayout.c | 8 +-
> fs/nfs/inode.c | 54 +---
> fs/nfs/nfs4proc.c | 4 +-
> fs/nfs/pnfs.c | 12 +-
> fs/nfsd/export.c | 2 +-
> fs/nfsd/nfs4state.c | 4 +-
> fs/nfsd/nfsfh.c | 4 +-
> fs/nfsd/vfs.c | 2 +-
> fs/nilfs2/alloc.c | 10 +-
> fs/nilfs2/bmap.c | 2 +-
> fs/nilfs2/btnode.c | 2 +-
> fs/nilfs2/btree.c | 12 +-
> fs/nilfs2/dir.c | 12 +-
> fs/nilfs2/direct.c | 4 +-
> fs/nilfs2/gcinode.c | 2 +-
> fs/nilfs2/inode.c | 8 +-
> fs/nilfs2/mdt.c | 2 +-
> fs/nilfs2/namei.c | 2 +-
> fs/nilfs2/segment.c | 2 +-
> fs/notify/fdinfo.c | 4 +-
> fs/nsfs.c | 4 +-
> fs/ntfs3/super.c | 2 +-
> fs/ocfs2/alloc.c | 2 +-
> fs/ocfs2/aops.c | 4 +-
> fs/ocfs2/dir.c | 8 +-
> fs/ocfs2/dlmfs/dlmfs.c | 10 +-
> fs/ocfs2/extent_map.c | 12 +-
> fs/ocfs2/inode.c | 2 +-
> fs/ocfs2/quota_local.c | 2 +-
> fs/ocfs2/refcounttree.c | 10 +-
> fs/ocfs2/xattr.c | 4 +-
> fs/orangefs/inode.c | 2 +-
> fs/overlayfs/export.c | 2 +-
> fs/overlayfs/namei.c | 4 +-
> fs/overlayfs/util.c | 2 +-
> fs/pipe.c | 2 +-
> fs/proc/fd.c | 2 +-
> fs/proc/task_mmu.c | 4 +-
> fs/qnx4/inode.c | 4 +-
> fs/qnx6/inode.c | 2 +-
> fs/smb/client/cifsfs.h | 17 --
> fs/smb/client/inode.c | 6 +-
> fs/smb/client/readdir.c | 2 +-
> fs/ubifs/debug.c | 8 +-
> fs/ubifs/dir.c | 28 +-
> fs/ubifs/file.c | 28 +-
> fs/ubifs/journal.c | 6 +-
> fs/ubifs/super.c | 16 +-
> fs/ubifs/tnc.c | 4 +-
> fs/ubifs/xattr.c | 14 +-
> fs/udf/directory.c | 18 +-
> fs/udf/file.c | 2 +-
> fs/udf/inode.c | 12 +-
> fs/udf/namei.c | 8 +-
> fs/udf/super.c | 2 +-
> fs/ufs/balloc.c | 6 +-
> fs/ufs/dir.c | 10 +-
> fs/ufs/ialloc.c | 6 +-
> fs/ufs/inode.c | 18 +-
> fs/ufs/ufs_fs.h | 6 +-
> fs/ufs/util.c | 2 +-
> fs/verity/init.c | 2 +-
> fs/zonefs/super.c | 8 +-
> include/linux/fs.h | 28 +-
> include/linux/nfs_fs.h | 10 -
> include/trace/events/cachefiles.h | 18 +-
> include/trace/events/ext4.h | 427 +++++++++++++++--------------
> include/trace/events/f2fs.h | 172 ++++++------
> include/trace/events/filelock.h | 16 +-
> include/trace/events/filemap.h | 20 +-
> include/trace/events/fs_dax.h | 20 +-
> include/trace/events/fsverity.h | 30 +-
> include/trace/events/hugetlbfs.h | 28 +-
> include/trace/events/netfs.h | 4 +-
> include/trace/events/nilfs2.h | 12 +-
> include/trace/events/readahead.h | 12 +-
> include/trace/events/timestamp.h | 12 +-
> include/trace/events/writeback.h | 148 +++++-----
> kernel/events/uprobes.c | 4 +-
> net/netrom/af_netrom.c | 4 +-
> net/rose/af_rose.c | 4 +-
> net/socket.c | 2 +-
> net/x25/x25_proc.c | 4 +-
> security/apparmor/apparmorfs.c | 4 +-
> security/integrity/integrity_audit.c | 2 +-
> security/ipe/audit.c | 2 +-
> security/lsm_audit.c | 10 +-
> security/selinux/hooks.c | 4 +-
> security/smack/smack_lsm.c | 12 +-
> 195 files changed, 1101 insertions(+), 1166 deletions(-)
> ---
> base-commit: 2bf35e96cf6c6c3a290b69b777d34be15888e364
> change-id: 20260224-iino-u64-b44a3a72543c
>
> Best regards,
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox