* Re: [PATCH] ima: Add digest_size field to ima_algo_desc structure and use to show meas.
From: Mimi Zohar @ 2026-02-25 18:37 UTC (permalink / raw)
To: Roberto Sassu, dmitry.kasatkin, eric.snowberg, paul, jmorris,
serge
Cc: linux-integrity, linux-security-module, linux-kernel,
devnull+dima.arista.com, Roberto Sassu
In-Reply-To: <20260225125301.87996-1-roberto.sassu@huaweicloud.com>
On Wed, 2026-02-25 at 13:53 +0100, Roberto Sassu wrote:
> 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; if the hash algorithm is SHA1, use the predefined value; 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().
>
> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
Thanks, Roberto. The patch looks fine, other than the patch title. Could it be
renamed as "ima: define and use a digest_size field in the ima_algo_desc
structure"?
thanks,
Mimi
^ permalink raw reply
* Re: [PATCH v5] ima_fs: Avoid creating measurement lists for unsupported hash algos
From: Dmitry Safonov @ 2026-02-25 18:00 UTC (permalink / raw)
To: Roberto Sassu
Cc: Mimi Zohar, Roberto Sassu, Dmitry Kasatkin, Eric Snowberg,
Paul Moore, James Morris, Serge E. Hallyn, Silvia Sisinni,
Enrico Bravi, Jonathan McDowell, linux-integrity,
linux-security-module, linux-kernel, stable, Dmitry Safonov
In-Reply-To: <5579780966d26d2fd0e3756d404d2156bd55a06b.camel@huaweicloud.com>
On Wed, Feb 25, 2026 at 1:20 PM Roberto Sassu
<roberto.sassu@huaweicloud.com> wrote:
>
> On Mon, 2026-02-23 at 14:56 +0000, Dmitry Safonov via B4 Relay wrote:
[..]
> > @@ -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_tpm_chip->allocated_banks[algo_idx].digest_size);
>
> Sorry, I realized that this does not work if SHA1 or the default hash
> algorithm are not among allocated PCR banks.
>
> I just sent a patch to correctly determine the digest size:
>
> https://marc.info/?l=linux-integrity&m=177202677128752&w=2
>
> and applied yours on top of that (if it is fine for you):
>
> https://github.com/linux-integrity/linux/commit/6efbd2b38b102ecbadc350228cc30fd67666a089
>
Thanks!
Dmitry
^ permalink raw reply
* Re: IMA and PQC
From: Stefan Berger @ 2026-02-25 14:25 UTC (permalink / raw)
To: Coiby Xu, Johannes Wiesböck
Cc: dhowells, dmitry.kasatkin, ebiggers, eric.snowberg, keyrings,
linux-crypto, linux-integrity, linux-kernel, linux-modules,
roberto.sassu, simo, zohar, michael.weiss
In-Reply-To: <aYHznG6vbptVOjHQ@Rk>
On 2/3/26 8:32 AM, Coiby Xu wrote:
> On Fri, Jan 30, 2026 at 09:31:26PM +0100, Johannes Wiesböck wrote:
>> Hi all,
>
> Hi Johannes,
>
>>
>> we conducted an evaluation regarding PQC use in IMA last year (see [1]
>> for all
>> details) where we also considered the interplay of different PQC
>> signatures and
>> file systems (ext4, btrfs, XFS, f2fs).
>
> Thanks for sharing this comprehensive study! There are many nuances in
> this research paper!
>
>>
>> Coiby Xu <coxu@redhat.com> wrote:
>>
>>> According to my experiments done so far, for verification speed,
>>> ML-DSA-65 is consistently faster than ECDSA P-384 which is used by
>>> current CentOS/RHEL to sign files in a package.
>>
>> Regarding performance, similar to Coiby, we found that all variants of
>> ML-DSA
>> consistently outperformed ECDSA P-256.
>
> Glad to know ML-DSA is also faster than ECDSA P-256!
To avoid duplicate work: Is either one of you planning on writing
patches for IMA to use ML-DSA and convert the current ML-DSA to also
support HashML? I had done the work on this before and could dig out the
patches again...
Stefan
^ permalink raw reply
* Re: [PATCH v5] ima_fs: Avoid creating measurement lists for unsupported hash algos
From: Roberto Sassu @ 2026-02-25 13:19 UTC (permalink / raw)
To: dima, Mimi Zohar, 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: <20260223-ima-oob-v5-1-91cc1064e767@arista.com>
On Mon, 2026-02-23 at 14:56 +0000, Dmitry Safonov via B4 Relay wrote:
> From: Dmitry Safonov <dima@arista.com>
>
> ima_tpm_chip->allocated_banks[i].crypto_id is initialized to
> HASH_ALGO__LAST if the TPM algorithm is not supported. However there
> are places relying on the algorithm to be valid because it is accessed
> by hash_algo_name[].
>
> On 6.12.40 I observe the following read out-of-bounds in hash_algo_name:
> ==================================================================
> BUG: KASAN: global-out-of-bounds in create_securityfs_measurement_lists+0x396/0x440
> Read of size 8 at addr ffffffff83e18138 by task swapper/0/1
>
> CPU: 4 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.12.40 #3
> Call Trace:
> <TASK>
> dump_stack_lvl+0x61/0x90
> print_report+0xc4/0x580
> ? kasan_addr_to_slab+0x26/0x80
> ? create_securityfs_measurement_lists+0x396/0x440
> kasan_report+0xc2/0x100
> ? create_securityfs_measurement_lists+0x396/0x440
> create_securityfs_measurement_lists+0x396/0x440
> ima_fs_init+0xa3/0x300
> ima_init+0x7d/0xd0
> init_ima+0x28/0x100
> do_one_initcall+0xa6/0x3e0
> kernel_init_freeable+0x455/0x740
> kernel_init+0x24/0x1d0
> ret_from_fork+0x38/0x80
> ret_from_fork_asm+0x11/0x20
> </TASK>
>
> The buggy address belongs to the variable:
> hash_algo_name+0xb8/0x420
>
> Memory state around the buggy address:
> ffffffff83e18000: 00 01 f9 f9 f9 f9 f9 f9 00 01 f9 f9 f9 f9 f9 f9
> ffffffff83e18080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> >ffffffff83e18100: 00 00 00 00 00 00 00 f9 f9 f9 f9 f9 00 05 f9 f9
> ^
> ffffffff83e18180: f9 f9 f9 f9 00 00 00 00 00 00 00 04 f9 f9 f9 f9
> ffffffff83e18200: 00 00 00 00 00 00 00 00 04 f9 f9 f9 f9 f9 f9 f9
> ==================================================================
>
> Seems like the TPM chip supports sha3_256, which isn't yet in
> tpm_algorithms:
> tpm tpm0: TPM with unsupported bank algorithm 0x0027
>
> Thus solve the problem by creating a file name with "_tpm_alg_<ID>"
> postfix if the crypto algorithm isn't initialized.
>
> This is how it looks on the test machine (patch ported to v6.12 release):
> # ls -1 /sys/kernel/security/ima/
> ascii_runtime_measurements
> ascii_runtime_measurements_tpm_alg_27
> ascii_runtime_measurements_sha1
> ascii_runtime_measurements_sha256
> binary_runtime_measurements
> binary_runtime_measurements_tpm_alg_27
> binary_runtime_measurements_sha1
> binary_runtime_measurements_sha256
> policy
> runtime_measurements_count
> violations
>
> Fixes: 9fa8e7625008 ("ima: add crypto agility support for template-hash algorithm")
> Signed-off-by: Dmitry Safonov <dima@arista.com>
> Cc: Enrico Bravi <enrico.bravi@polito.it>
> Cc: Silvia Sisinni <silvia.sisinni@polito.it>
> Cc: Roberto Sassu <roberto.sassu@huawei.com>
> Cc: Mimi Zohar <zohar@linux.ibm.com>
> ---
> Changes in v5:
> - Use lower-case for sysfs file name (as suggested-by Jonathan and Roberto)
> - Don't use email quotes for patch description (Roberto)
> - Re-word the patch description (suggested-by Roberto)
> - Link to v4: https://lore.kernel.org/r/20260127-ima-oob-v4-1-bf0cd7f9b4d4@arista.com
>
> Changes in v4:
> - Use ima_tpm_chip->allocated_banks[algo_idx].digest_size instead of hash_digest_size[algo]
> (Roberto Sassu)
> - Link to v3: https://lore.kernel.org/r/20260127-ima-oob-v3-1-1dd09f4c2a6a@arista.com
> Testing note: I test it on v6.12.40 kernel backport, which slightly differs as
> lookup_template_data_hash_algo() was yet present.
>
> Changes in v3:
> - Now fix the spelling *for real* (sorry, messed it up in v2)
> - Link to v2: https://lore.kernel.org/r/20260127-ima-oob-v2-1-f38a18c850cf@arista.com
>
> Changes in v2:
> - Instead of skipping unknown algorithms, add files under their TPM_ALG_ID (Roberto Sassu)
> - Fix spelling (Roberto Sassu)
> - Copy @stable on the fix
> - Link to v1: https://lore.kernel.org/r/20260127-ima-oob-v1-1-2d42f3418e57@arista.com
> ---
> security/integrity/ima/ima_fs.c | 34 ++++++++++++++++++----------------
> 1 file changed, 18 insertions(+), 16 deletions(-)
>
> diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
> index 012a58959ff0..3d9996ed486d 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_tpm_chip->allocated_banks[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_tpm_chip->allocated_banks[algo_idx].digest_size);
Sorry, I realized that this does not work if SHA1 or the default hash
algorithm are not among allocated PCR banks.
I just sent a patch to correctly determine the digest size:
https://marc.info/?l=linux-integrity&m=177202677128752&w=2
and applied yours on top of that (if it is fine for you):
https://github.com/linux-integrity/linux/commit/6efbd2b38b102ecbadc350228cc30fd67666a089
Thanks
Roberto
>
> /* 3th: template name */
> seq_printf(m, " %s", template_name);
> @@ -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);
> + else
> + sprintf(file_name, "binary_runtime_measurements_%s",
> + hash_algo_name[algo]);
> dentry = securityfs_create_file(file_name, S_IRUSR | S_IRGRP,
> ima_dir, (void *)(uintptr_t)i,
> &ima_measurements_ops);
>
> ---
> base-commit: 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f
> change-id: 20260127-ima-oob-9fa83a634d7b
>
> Best regards,
^ permalink raw reply
* [PATCH] ima: Add digest_size field to ima_algo_desc structure and use to show meas.
From: Roberto Sassu @ 2026-02-25 12:53 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; if the hash algorithm is SHA1, use the predefined value; 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().
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 1/3] integrity: Make arch_ima_get_secureboot integrity-wide
From: Mimi Zohar @ 2026-02-25 0:03 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: Coiby Xu, Dave Hansen, linux-integrity, Heiko Carstens,
Roberto Sassu, Catalin Marinas, Will Deacon, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Christophe Leroy (CS GROUP),
Vasily Gorbik, Alexander Gordeev, Christian Borntraeger,
Sven Schnelle, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT),
H. Peter Anvin, Roberto Sassu, Dmitry Kasatkin, Eric Snowberg,
Paul Moore, James Morris, Serge E. Hallyn, Jarkko Sakkinen,
moderated list:ARM64 PORT (AARCH64 ARCHITECTURE), open list,
open list:LINUX FOR POWERPC (32-BIT AND 64-BIT),
open list:S390 ARCHITECTURE,
open list:EXTENSIBLE FIRMWARE INTERFACE (EFI),
open list:SECURITY SUBSYSTEM, open list:KEYS/KEYRINGS_INTEGRITY
In-Reply-To: <CAMj1kXFBMSEdRL8FotASbQO3dcfNG0bpp9Vnm5JPn-yjyDr=GA@mail.gmail.com>
On Wed, 2026-01-21 at 17:25 +0100, Ard Biesheuvel wrote:
> On Wed, 21 Jan 2026 at 16:41, Mimi Zohar <zohar@linux.ibm.com> wrote:
> >
> > On Mon, 2026-01-19 at 12:04 +0800, Coiby Xu wrote:
> >
> > > diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
> > > index 976e75f9b9ba..5dce572192d6 100644
> > > --- a/security/integrity/ima/Kconfig
> > > +++ b/security/integrity/ima/Kconfig
> > > @@ -311,6 +311,7 @@ config IMA_QUEUE_EARLY_BOOT_KEYS
> > > config IMA_SECURE_AND_OR_TRUSTED_BOOT
> > > bool
> > > depends on IMA_ARCH_POLICY
> > > + depends on INTEGRITY_SECURE_BOOT
> > >
> > >
> > > Another idea is make a tree-wide arch_get_secureboot i.e. to move
> > > current arch_ima_get_secureboot code to arch-specific secure boot
> > > implementation. By this way, there will no need for a new Kconfig option
> > > INTEGRITY_SECURE_BOOT. But I'm not sure if there is any unforeseen
> > > concern.
> >
> > Originally basing IMA policy on the secure boot mode was an exception. As long
> > as making it public isn't an issue any longer, this sounds to me. Ard, Dave, do
> > you have any issues with replacing arch_ima_get_secureboot() with
> > arch_get_secureboot()?
>
> I don't see an issue with that. If there is a legitimate need to
> determine this even if IMA is not enabled, then this makes sense.
Ard, Dave -
FYI, Coiby posted v3 of this patch set[1], which is queued in the next-
integrity-testing branch[2].
[1]
https://lore.kernel.org/linux-integrity/20260213012851.2532722-1-coxu@redhat.com/
[2] https://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity.git/
Mimi
^ permalink raw reply
* Re: [PATCH] lsm: move inode IS_PRIVATE checks to individual LSMs
From: Paul Moore @ 2026-02-24 19:12 UTC (permalink / raw)
To: Stephen Smalley
Cc: Casey Schaufler, danieldurning.work, linux-security-module,
selinux, linux-integrity, jmorris, serge, john.johansen, zohar,
roberto.sassu, dmitry.kasatkin, mic, takedakn, penguin-kernel
In-Reply-To: <CAEjxPJ79V7hM=VnbB1dVA96jjr1yeN9qsLjXb4ALv1VmcRfJ-A@mail.gmail.com>
On Tue, Feb 24, 2026 at 9:44 AM Stephen Smalley
<stephen.smalley.work@gmail.com> wrote:
> On Mon, Feb 23, 2026 at 5:21 PM Paul Moore <paul@paul-moore.com> wrote:
> > I'm not going to argue with that, and perhaps that is a good next
> > step: send a quick RFC patch to the VFS folks, with the LSM list CC'd,
> > that drops setting the S_PRIVATE flag to see if they complain too
> > loudly. Based on other threads, Christian is aware that we are
> > starting to look at better/proper handling of pidfds/pidfs so he may
> > be open to dropping S_PRIVATE since it doesn't really have much impact
> > outside of the LSM, but who knows; the VFS folks have been growing a
> > bit more anti-LSM as of late.
>
> Adding S_PRIVATE to pidfs inodes was originally motivated by this bug report:
> https://lore.kernel.org/linux-fsdevel/20240222190334.GA412503@dev-arch.thelio-3990X/
> when pidfs was first introduced as its own distinct filesystem type.
> Otherwise, Fedora (and likely any other system enforcing SELinux)
> stopped working.
> So we can't unconditionally remove S_PRIVATE from pidfs inodes without breaking
> existing userspace/policy. If we want to introduce controls over pidfs
> inodes and do so in a
> backward-compatible manner, we have to either move the S_PRIVATE
> handling into the
> individual LSMs ...
... just like was originally proposed. Just do that and be done with
it; back-n-forth like this just wastes time and energy.
--
paul-moore.com
^ permalink raw reply
* Re: [PATCH] lsm: move inode IS_PRIVATE checks to individual LSMs
From: Casey Schaufler @ 2026-02-24 18:21 UTC (permalink / raw)
To: Stephen Smalley, Paul Moore
Cc: danieldurning.work, linux-security-module, selinux,
linux-integrity, jmorris, serge, john.johansen, zohar,
roberto.sassu, dmitry.kasatkin, mic, takedakn, penguin-kernel,
Casey Schaufler
In-Reply-To: <CAEjxPJ79V7hM=VnbB1dVA96jjr1yeN9qsLjXb4ALv1VmcRfJ-A@mail.gmail.com>
On 2/24/2026 6:44 AM, Stephen Smalley wrote:
> On Mon, Feb 23, 2026 at 5:21 PM Paul Moore <paul@paul-moore.com> wrote:
>> I'm not going to argue with that, and perhaps that is a good next
>> step: send a quick RFC patch to the VFS folks, with the LSM list CC'd,
>> that drops setting the S_PRIVATE flag to see if they complain too
>> loudly. Based on other threads, Christian is aware that we are
>> starting to look at better/proper handling of pidfds/pidfs so he may
>> be open to dropping S_PRIVATE since it doesn't really have much impact
>> outside of the LSM, but who knows; the VFS folks have been growing a
>> bit more anti-LSM as of late.
> Adding S_PRIVATE to pidfs inodes was originally motivated by this bug report:
> https://lore.kernel.org/linux-fsdevel/20240222190334.GA412503@dev-arch.thelio-3990X/
> when pidfs was first introduced as its own distinct filesystem type.
> Otherwise, Fedora (and likely any other system enforcing SELinux)
> stopped working.
Woof. Not a hill I'm willing to receive even minor injuries on. Carry on.
^ permalink raw reply
* Re: [PATCH v4 15/17] module: Introduce hash-based integrity checking
From: Nicolas Schier @ 2026-02-24 16:14 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Nathan Chancellor, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Daniel Gomez,
Aaron Tomlin, Christophe Leroy (CS GROUP), Nicolas Bouchinet,
Xiu Jianfeng, Fabian Grünbichler, Arnout Engelen,
Mattia Rizzolo, kpcyrd, Christian Heusel, Câju Mihai-Drosi,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity
In-Reply-To: <06054e9a-2b7a-4063-98b8-7d6c539e543f@t-8ch.de>
On Mon, Feb 23, 2026 at 10:43:30PM +0100, Thomas Weißschuh wrote:
> On 2026-02-23 19:41:52+0100, Nicolas Schier wrote:
> > On Mon, Feb 23, 2026 at 08:53:29AM +0100, Thomas Weißschuh wrote:
> > > On 2026-02-21 22:38:29+0100, Nicolas Schier wrote:
> > > > On Tue, Jan 13, 2026 at 01:28:59PM +0100, Thomas Weißschuh wrote:
[...]
> > > > [...]
> > > > > diff --git a/scripts/modules-merkle-tree.c b/scripts/modules-merkle-tree.c
> > > > > new file mode 100644
> > > > > index 000000000000..a6ec0e21213b
> > > > > --- /dev/null
> > > > > +++ b/scripts/modules-merkle-tree.c
> > > > > @@ -0,0 +1,467 @@
> > > > > +// SPDX-License-Identifier: GPL-2.0-or-later
> > > > > +/*
> > > > > + * Compute hashes for modules files and build a merkle tree.
> > > > > + *
> > > > > + * Copyright (C) 2025 Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
> > > > > + * Copyright (C) 2025 Thomas Weißschuh <linux@weissschuh.net>
> > > > > + *
> > > > > + */
> > > > > +#define _GNU_SOURCE 1
> > > > > +#include <arpa/inet.h>
> > > > > +#include <err.h>
> > > > > +#include <unistd.h>
> > > > > +#include <fcntl.h>
> > > > > +#include <stdarg.h>
> > > > > +#include <stdio.h>
> > > > > +#include <string.h>
> > > > > +#include <stdbool.h>
> > > > > +#include <stdlib.h>
> > > > > +
> > > > > +#include <sys/stat.h>
> > > > > +#include <sys/mman.h>
> > > > > +
> > > > > +#include <openssl/evp.h>
> > > > > +#include <openssl/err.h>
> > > > > +
> > > > > +#include "ssl-common.h"
> > > > > +
> > > > > +static int hash_size;
> > > > > +static EVP_MD_CTX *ctx;
> > > > > +
> > > > > +struct module_signature {
> > > > > + uint8_t algo; /* Public-key crypto algorithm [0] */
> > > > > + uint8_t hash; /* Digest algorithm [0] */
> > > > > + uint8_t id_type; /* Key identifier type [PKEY_ID_PKCS7] */
> > > > > + uint8_t signer_len; /* Length of signer's name [0] */
> > > > > + uint8_t key_id_len; /* Length of key identifier [0] */
> > > > > + uint8_t __pad[3];
> > > > > + uint32_t sig_len; /* Length of signature data */
> > > > > +};
> > > > > +
> > > > > +#define PKEY_ID_MERKLE 3
> > > > > +
> > > > > +static const char magic_number[] = "~Module signature appended~\n";
> > > >
> > > > This here will be the forth definition of struct module_signature,
> > > > increasing the risk of unwanted diversion. I second Petr's suggestion
> > > > to reuse a _common_ definition instead.
> > >
> > > Ack.
> > >
> > > > (Here, even include/linux/module_signature.h could be included itself.)
> > >
> > > I'd like to avoid including internal headers from other components.
> > > We could move it to an UAPI header. Various other subsystems use those
> > > for not-really-UAPI but still ABI definitions.
> >
> > Yeah, ack.
>
> What exactly is the 'ack' for?
> * Avoiding to include internal headers?
> * Moving the definition to UAPI headers?
ah, sorry. I think reduction of duplicated definitions is good; moving
these definitions to UAPI headers sounds like a valid compromise to me.
> (...)
>
> > > > Can you verify if I get the mechanics roughly correct?
> > > >
> > > > * Modules are merkle tree leaves. Modules are built and logically
> > > > paired by the order from modules.order; a single left-over module is
> > > > paired with itself.
> > > >
> > > > * Hashes of paired modules are hashed again (branch node hash);
> > > > hashes of pairs of branch nodes' hashes are hashed again;
> > > > repeat until we reach the single merkle tree root hash
> > > >
> > > > * The final merkle tree root hash (and the count of tree levels) is
> > > > included in vmlinux
> > >
> > > The merkle tree code was written by Sebastian so he will have the best
> > > knowledge about it. But this is also my understanding.
> >
> > I'd like to see some (rough) description in Documentation or in a commit
> > message at least, otherwise future me will have to ask that again.
>
> Ack in general. I'd prefer to document it in a source code comment,
> though. That feels like the best fit to me.
Great, thanks.
--
Nicolas
^ permalink raw reply
* Re: [PATCH] lsm: move inode IS_PRIVATE checks to individual LSMs
From: Stephen Smalley @ 2026-02-24 14:44 UTC (permalink / raw)
To: Paul Moore
Cc: Casey Schaufler, danieldurning.work, linux-security-module,
selinux, linux-integrity, jmorris, serge, john.johansen, zohar,
roberto.sassu, dmitry.kasatkin, mic, takedakn, penguin-kernel
In-Reply-To: <CAHC9VhSp+X8YNocS7sDz+UyhdJh2yY8CRoi6dwV1eOGdCu9f9w@mail.gmail.com>
On Mon, Feb 23, 2026 at 5:21 PM Paul Moore <paul@paul-moore.com> wrote:
> I'm not going to argue with that, and perhaps that is a good next
> step: send a quick RFC patch to the VFS folks, with the LSM list CC'd,
> that drops setting the S_PRIVATE flag to see if they complain too
> loudly. Based on other threads, Christian is aware that we are
> starting to look at better/proper handling of pidfds/pidfs so he may
> be open to dropping S_PRIVATE since it doesn't really have much impact
> outside of the LSM, but who knows; the VFS folks have been growing a
> bit more anti-LSM as of late.
Adding S_PRIVATE to pidfs inodes was originally motivated by this bug report:
https://lore.kernel.org/linux-fsdevel/20240222190334.GA412503@dev-arch.thelio-3990X/
when pidfs was first introduced as its own distinct filesystem type.
Otherwise, Fedora (and likely any other system enforcing SELinux)
stopped working.
So we can't unconditionally remove S_PRIVATE from pidfs inodes without breaking
existing userspace/policy. If we want to introduce controls over pidfs
inodes and do so in a
backward-compatible manner, we have to either move the S_PRIVATE
handling into the
individual LSMs or introduce a new hook in pidfs_init_inode() to
determine whether or not to
set S_PRIVATE. Such a hook might also handle labeling the pidfs inode
although we'd have to
see if we have enough information there to do so fully. Note that such
an approach will still likely
end up leaving pidfs inodes created before initial policy load with
the S_PRIVATE flag and hence
uncontrolled; not sure if that is a problem in practice.
>
> diff --git a/fs/pidfs.c b/fs/pidfs.c
> index 318253344b5c..4cec73b4cbcf 100644
> --- a/fs/pidfs.c
> +++ b/fs/pidfs.c
> @@ -921,7 +921,7 @@ static int pidfs_init_inode(struct inode *inode, void *data)
> const struct pid *pid = data;
>
> inode->i_private = data;
> - inode->i_flags |= S_PRIVATE | S_ANON_INODE;
> + inode->i_flags |= S_ANON_INODE;
> /* We allow to set xattrs. */
> inode->i_flags &= ~S_IMMUTABLE;
> inode->i_mode |= S_IRWXU;
>
> --
> paul-moore.com
^ permalink raw reply
* Re: [PATCH v9 06/19] x86: Add early SHA-1 support for Secure Launch early measurements
From: Ard Biesheuvel @ 2026-02-24 8:25 UTC (permalink / raw)
To: Andrew Cooper, Daniel P. Smith, Thomas Gleixner,
Eric W. Biederman, Eric Biggers
Cc: Ross Philipson, linux-kernel, x86, linux-integrity, linux-doc,
linux-crypto, kexec, linux-efi, iommu, Ingo Molnar,
Borislav Petkov, H . Peter Anvin, dave.hansen, Matthew Garrett,
James Bottomley, peterhuewe, Jarkko Sakkinen, jgg,
Andy Lutomirski, nivedita, Herbert Xu, davem, corbet, dwmw2,
baolu.lu, kanth.ghatraju, trenchboot-devel
In-Reply-To: <02e6a889-ff72-4c18-b9ee-35fcef3570f6@citrix.com>
On Tue, 24 Feb 2026, at 00:08, Andrew Cooper wrote:
> On 20/02/2026 3:35 pm, Ard Biesheuvel wrote:
>> Coming back to this old thread after having spent some time playing with the code:
>>
>> On Thu, 22 Aug 2024, at 20:29, Daniel P. Smith wrote:
>>
>> <selective snip>
>>
>>> Another fact to consider is that the current Intel's TXT MLE
>>> specification dictates SHA1 as a valid configuration. Secure Launch's
>>> use of SHA1 is therefore to comply with Intel's specification for TXT.
>> As I understand the Intel TXT spec and the code:
>>
>> - TPM 1.2 is no longer supported by the TXT spec (since 2023)
>> - TPM 1.2 is not supported by your GRUB implementation
>> - in TPM 2.0 mode, SHA1 is only supported by the TXT spec if it is the /only/ algo supported by the TPM
>> - the proposed kernel implementation ignores any SHA-384 and SM3-256 PCR banks if they are active, and caps them using a { 1, 0, ... } fake digest.
>>
>> So apologies for being slow, but I still struggle to understand why it is so important to have a SHA-1 implementation to cap those PCRs. Is it just to support systems with a TPM 2.0 that only has SHA-1 banks enabled?
>>
>> Assuming that this code will get merged this year, it will be in a LTS branch by 2027, by which time distros like Debian will pick it up.
>>
>> I fully understand that this code has lived out-of-tree for more than a decade, and you likely prefer to get everything upstream that your current users may be relying on. But for Linux, this is a new feature, and merging code now that is basically obsolete on day 1 is not something we should entertain imo.
>>
>> (and apologies for re-opening yet another can of worms - I assure you I am trying to be constructive here)
>>
>
> I appreciate that you've got concerns, but I don't think these
> characterisations are fair. Ultimately yes, we do want to support TPM
> 1.2 systems because we have users wanting a way off the out-of-tree patches.
>
That was my question, yes. So supporting TPM 1.2 as well as TPM 2.0 with only SHA-1 banks enabled is needed not to comply with the spec, but to support existing out-of-tree users. That needs to be called out, because what I am quoting above is a claim that it is needed to comply with the TXT MLE spec.
So the debate is really about whether or not such systems should be considered obsolete at this point.
And why is it ok to just cap active SHA-384 banks rather than perform the proper measurements?
> 3-year-old hardware is new enough to still be in full support from OEMs,
> and totally fair game for distro LTS's even at this juncture.
>
3-year old hardware that shipped with a TPM 1.2?
> The TXT spec does not speak for what OEMs choose to support, nor for the
> TPM spec (where SHA1 is a mandatory algorithm for TPM 2.0), nor does it
> speak for other silicon vendors we're trying to support (there are AMD
> patches waiting for the interface to stop changing).
>
>
> But lets ask the question the other way around. What does refusing SHA1
> gain?
>
> AFAICT, there's no meaningful reduction in complexity in the early code;
> the TPM library speaks TPM 1.2 and 2.0. There is a small reduction in
> binary size for not including SHA-1, but including it is no extra C
> because we reuse the library that already exists.
>
The complexity of the code is not the problem. The problem is that we'll be stuck supporting it long past the point where anyone is making meaningful use of it. I'm not keen on being on the receiving end of a bug report from your last remaining TPM 1.2 user, with no means whatsoever to test or reproduce.
> The cost is a failure to operate in some TXT configurations that exist
> on in-support CPUs, as well as older systems.
>
Sure, some systems will be left behind. I just wonder how many of those would be upgrading to the v7.3 LTS kernel to begin with, 4 years after TPM 1.2 support was dropped from the TXT spec.
In any case, the code changes themselves look fine to me. I am more concerned about the long term maintenance: the x86 boot code is very complex, given how many boot methods it supports, and it is rather difficult to regression test all of those.
^ permalink raw reply
* Re: [PATCH v3 3/3] s390: Drop unnecessary CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT
From: Alexander Egorenkov @ 2026-02-24 5:52 UTC (permalink / raw)
To: Mimi Zohar, Coiby Xu, linux-integrity
Cc: Heiko Carstens, Ard Biesheuvel, Dave Hansen, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
open list:S390 ARCHITECTURE, open list
In-Reply-To: <82f97981195dd5e0c1c265c21d5dac3ab907ed4c.camel@linux.ibm.com>
Mimi Zohar <zohar@linux.ibm.com> writes:
> On Fri, 2026-02-13 at 09:28 +0800, Coiby Xu wrote:
>> Commit b5ca117365d9 ("ima: prevent kexec_load syscall based on runtime
>> secureboot flag") and commit 268a78404973 ("s390/kexec_file: Disable
>> kexec_load when IPLed secure") disabled the kexec_load syscall based
>> on the secureboot mode. Commit 9e2b4be377f0 ("ima: add a new CONFIG
>> for loading arch-specific policies") needed to detect the secure boot
>> mode, not to load an IMA architecture specific policy. Since there is
>> the new CONFIG_INTEGRITY_SECURE_BOOT, drop
>> CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT for s390.
>>
>> Signed-off-by: Coiby Xu <coxu@redhat.com>
>
> Alexander, you added your Tested-by for the original version of this patch set.
> Can I apply it for v3?
>
> thanks,
>
> Mimi
I have verified v3 on one of our secure boot machines, it looks good too.
Tested-by: Alexander Egorenkov <egorenar@linux.ibm.com>
^ permalink raw reply
* Re: [PATCH v9 06/19] x86: Add early SHA-1 support for Secure Launch early measurements
From: Andrew Cooper @ 2026-02-23 23:08 UTC (permalink / raw)
To: Ard Biesheuvel, Daniel P. Smith, Thomas Gleixner,
Eric W. Biederman, Eric Biggers
Cc: Andrew Cooper, Ross Philipson, linux-kernel, x86, linux-integrity,
linux-doc, linux-crypto, kexec, linux-efi, iommu, Ingo Molnar,
Borislav Petkov, H . Peter Anvin, dave.hansen, Matthew Garrett,
James Bottomley, peterhuewe, Jarkko Sakkinen, jgg,
Andy Lutomirski, nivedita, Herbert Xu, davem, corbet, dwmw2,
baolu.lu, kanth.ghatraju, trenchboot-devel
In-Reply-To: <c9a0cd9f-17cb-49e5-a411-b78ef9c7e35e@app.fastmail.com>
On 20/02/2026 3:35 pm, Ard Biesheuvel wrote:
> Coming back to this old thread after having spent some time playing with the code:
>
> On Thu, 22 Aug 2024, at 20:29, Daniel P. Smith wrote:
>
> <selective snip>
>
>> Another fact to consider is that the current Intel's TXT MLE
>> specification dictates SHA1 as a valid configuration. Secure Launch's
>> use of SHA1 is therefore to comply with Intel's specification for TXT.
> As I understand the Intel TXT spec and the code:
>
> - TPM 1.2 is no longer supported by the TXT spec (since 2023)
> - TPM 1.2 is not supported by your GRUB implementation
> - in TPM 2.0 mode, SHA1 is only supported by the TXT spec if it is the /only/ algo supported by the TPM
> - the proposed kernel implementation ignores any SHA-384 and SM3-256 PCR banks if they are active, and caps them using a { 1, 0, ... } fake digest.
>
> So apologies for being slow, but I still struggle to understand why it is so important to have a SHA-1 implementation to cap those PCRs. Is it just to support systems with a TPM 2.0 that only has SHA-1 banks enabled?
>
> Assuming that this code will get merged this year, it will be in a LTS branch by 2027, by which time distros like Debian will pick it up.
>
> I fully understand that this code has lived out-of-tree for more than a decade, and you likely prefer to get everything upstream that your current users may be relying on. But for Linux, this is a new feature, and merging code now that is basically obsolete on day 1 is not something we should entertain imo.
>
> (and apologies for re-opening yet another can of worms - I assure you I am trying to be constructive here)
>
I appreciate that you've got concerns, but I don't think these
characterisations are fair. Ultimately yes, we do want to support TPM
1.2 systems because we have users wanting a way off the out-of-tree patches.
3-year-old hardware is new enough to still be in full support from OEMs,
and totally fair game for distro LTS's even at this juncture.
The TXT spec does not speak for what OEMs choose to support, nor for the
TPM spec (where SHA1 is a mandatory algorithm for TPM 2.0), nor does it
speak for other silicon vendors we're trying to support (there are AMD
patches waiting for the interface to stop changing).
But lets ask the question the other way around. What does refusing SHA1
gain?
AFAICT, there's no meaningful reduction in complexity in the early code;
the TPM library speaks TPM 1.2 and 2.0. There is a small reduction in
binary size for not including SHA-1, but including it is no extra C
because we reuse the library that already exists.
The cost is a failure to operate in some TXT configurations that exist
on in-support CPUs, as well as older systems.
~Andrew
^ permalink raw reply
* Re: [PATCH] lsm: move inode IS_PRIVATE checks to individual LSMs
From: Paul Moore @ 2026-02-23 22:21 UTC (permalink / raw)
To: Casey Schaufler
Cc: danieldurning.work, linux-security-module, selinux,
linux-integrity, stephen.smalley.work, jmorris, serge,
john.johansen, zohar, roberto.sassu, dmitry.kasatkin, mic,
takedakn, penguin-kernel
In-Reply-To: <9229d70d-aa7a-459f-b005-695e99888783@schaufler-ca.com>
On Fri, Feb 20, 2026 at 4:13 PM Casey Schaufler <casey@schaufler-ca.com> wrote:
> On 2/20/2026 11:54 AM, danieldurning.work@gmail.com wrote:
> > From: Daniel Durning <danieldurning.work@gmail.com>
> >
> > Move responsibility of bypassing S_PRIVATE inodes to the
> > individual LSMs. Originally the LSM framework would skip calling
> > the hooks on any inode that was marked S_PRIVATE. This would
> > prevent the LSMs from controlling access to any inodes marked as
> > such (ie. pidfds). We now perform the same IS_PRIVATE checks
> > within the LSMs instead. This is consistent with the general goal
> > of deferring as much as possible to the individual LSMs.
>
> Um ... ick?
>
> Sure, we generally want the LSMs to be responsible for their own
> decisions, but that doesn't look like the point to me. What appears
> to be the issue is that pidfs isn't using S_PRIVATE in a way that
> conveys the necessary information to the LSMs.
First off, consider this the annual reminder for everyone to *please*
trim their replies when discussing things on-list. Everything is
archived on lore, we're not losing anything, and it makes things *so*
much easier to read if we don't have to skim over the entire email to
make sure we haven't missed any comments.
Now, back to the S_PRIVATE issue ...
I was the one who first suggested (it may have been on the SELinux
list, or in an off-list discussion, not sure?) that moving the
S_PRIVATE check into the individual LSMs was a way to work around the
issue with pidfd/pidfs, so please don't blame Daniel for this, he has
been doing good work trying to solve a rather ugly problem.
> > This reorganization enables the LSMs to eventually implement
> > checks or labeling for some specific S_PRIVATE inodes like pidfds.
>
> We could consider these or similar changes when that eventuality occurs.
To be clear, that time is now, that is just a dependency of that which
needs to be sorted out first.
> I would strongly suggest that this is a pidfs issue, not an LSM
> infrastructure issue.
I'm not going to argue with that, and perhaps that is a good next
step: send a quick RFC patch to the VFS folks, with the LSM list CC'd,
that drops setting the S_PRIVATE flag to see if they complain too
loudly. Based on other threads, Christian is aware that we are
starting to look at better/proper handling of pidfds/pidfs so he may
be open to dropping S_PRIVATE since it doesn't really have much impact
outside of the LSM, but who knows; the VFS folks have been growing a
bit more anti-LSM as of late.
diff --git a/fs/pidfs.c b/fs/pidfs.c
index 318253344b5c..4cec73b4cbcf 100644
--- a/fs/pidfs.c
+++ b/fs/pidfs.c
@@ -921,7 +921,7 @@ static int pidfs_init_inode(struct inode *inode, void *data)
const struct pid *pid = data;
inode->i_private = data;
- inode->i_flags |= S_PRIVATE | S_ANON_INODE;
+ inode->i_flags |= S_ANON_INODE;
/* We allow to set xattrs. */
inode->i_flags &= ~S_IMMUTABLE;
inode->i_mode |= S_IRWXU;
--
paul-moore.com
^ permalink raw reply related
* Re: [PATCH v4 15/17] module: Introduce hash-based integrity checking
From: Thomas Weißschuh @ 2026-02-23 21:43 UTC (permalink / raw)
To: Nicolas Schier, Nathan Chancellor, Arnd Bergmann,
Luis Chamberlain, Petr Pavlu, Sami Tolvanen, Daniel Gomez,
Paul Moore, James Morris, Serge E. Hallyn, Jonathan Corbet,
Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
Naveen N Rao, Mimi Zohar, Roberto Sassu, Dmitry Kasatkin,
Eric Snowberg, Daniel Gomez, Aaron Tomlin,
Christophe Leroy (CS GROUP), Nicolas Bouchinet, Xiu Jianfeng,
Fabian Grünbichler, Arnout Engelen, Mattia Rizzolo, kpcyrd,
Christian Heusel, Câju Mihai-Drosi,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity
In-Reply-To: <aZyfcDCWOBJJztQ2@levanger>
On 2026-02-23 19:41:52+0100, Nicolas Schier wrote:
> On Mon, Feb 23, 2026 at 08:53:29AM +0100, Thomas Weißschuh wrote:
> > On 2026-02-21 22:38:29+0100, Nicolas Schier wrote:
> > > On Tue, Jan 13, 2026 at 01:28:59PM +0100, Thomas Weißschuh wrote:
> > > > The current signature-based module integrity checking has some drawbacks
> > > > in combination with reproducible builds. Either the module signing key
> > > > is generated at build time, which makes the build unreproducible, or a
> > > > static signing key is used, which precludes rebuilds by third parties
> > > > and makes the whole build and packaging process much more complicated.
> > > >
> > > > The goal is to reach bit-for-bit reproducibility. Excluding certain
> > > > parts of the build output from the reproducibility analysis would be
> > > > error-prone and force each downstream consumer to introduce new tooling.
> > > >
> > > > Introduce a new mechanism to ensure only well-known modules are loaded
> > > > by embedding a merkle tree root of all modules built as part of the full
> > > > kernel build into vmlinux.
> > > >
> > > > Non-builtin modules can be validated as before through signatures.
> > > >
> > > > Normally the .ko module files depend on a fully built vmlinux to be
> > > > available for modpost validation and BTF generation. With
> > > > CONFIG_MODULE_HASHES, vmlinux now depends on the modules
> > > > to build a merkle tree. This introduces a dependency cycle which is
> > > > impossible to satisfy. Work around this by building the modules during
> > > > link-vmlinux.sh, after vmlinux is complete enough for modpost and BTF
> > > > but before the final module hashes are
> > > >
> > > > The PKCS7 format which is used for regular module signatures can not
> > > > represent Merkle proofs, so a new kind of module signature is
> > > > introduced. As this signature type is only ever used for builtin
> > > > modules, no compatibility issues can arise.
> > > >
> > > > Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> > > > ---
> > > > .gitignore | 1 +
> > > > Documentation/kbuild/reproducible-builds.rst | 5 +-
> > > > Makefile | 8 +-
> > > > include/asm-generic/vmlinux.lds.h | 11 +
> > > > include/linux/module_hashes.h | 25 ++
> > > > include/linux/module_signature.h | 1 +
> > > > kernel/module/Kconfig | 21 +-
> > > > kernel/module/Makefile | 1 +
> > > > kernel/module/hashes.c | 92 ++++++
> > > > kernel/module/hashes_root.c | 6 +
> > > > kernel/module/internal.h | 1 +
> > > > kernel/module/main.c | 4 +-
> > > > scripts/.gitignore | 1 +
> > > > scripts/Makefile | 3 +
> > > > scripts/Makefile.modfinal | 11 +
> > > > scripts/Makefile.modinst | 13 +
> > > > scripts/Makefile.vmlinux | 5 +
> > > > scripts/link-vmlinux.sh | 14 +-
> > > > scripts/modules-merkle-tree.c | 467 +++++++++++++++++++++++++++
> > > > security/lockdown/Kconfig | 2 +-
> > > > 20 files changed, 685 insertions(+), 7 deletions(-)
> > > >
> > > [...]
> > >
> > > > diff --git a/kernel/module/hashes_root.c b/kernel/module/hashes_root.c
> > > > new file mode 100644
> > > > index 000000000000..1abfcd3aa679
> > > > --- /dev/null
> > > > +++ b/kernel/module/hashes_root.c
> > > > @@ -0,0 +1,6 @@
> > > > +// SPDX-License-Identifier: GPL-2.0-or-later
> > > > +
> > > > +#include <linux/module_hashes.h>
> > > > +
> > > > +/* Blank dummy data. Will be overridden by link-vmlinux.sh */
> > > > +const struct module_hashes_root module_hashes_root __module_hashes_section = {};
> > > > diff --git a/kernel/module/internal.h b/kernel/module/internal.h
> > > > index e2d49122c2a1..e22837d3ac76 100644
> > > > --- a/kernel/module/internal.h
> > > > +++ b/kernel/module/internal.h
> > > > @@ -338,6 +338,7 @@ void module_mark_ro_after_init(const Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
> > > > const char *secstrings);
> > > >
> > > > int module_sig_check(struct load_info *info, const u8 *sig, size_t sig_len);
> > > > +int module_hash_check(struct load_info *info, const u8 *sig, size_t sig_len);
> > > >
> > > > #ifdef CONFIG_DEBUG_KMEMLEAK
> > > > void kmemleak_load_module(const struct module *mod, const struct load_info *info);
> > > > diff --git a/kernel/module/main.c b/kernel/module/main.c
> > > > index 2a28a0ece809..fa30b6387936 100644
> > > > --- a/kernel/module/main.c
> > > > +++ b/kernel/module/main.c
> > > > @@ -3362,8 +3362,10 @@ static int module_integrity_check(struct load_info *info, int flags)
> > > >
> > > > if (IS_ENABLED(CONFIG_MODULE_SIG) && sig_type == PKEY_ID_PKCS7) {
> > > > err = module_sig_check(info, sig, sig_len);
> > > > + } else if (IS_ENABLED(CONFIG_MODULE_HASHES) && sig_type == PKEY_ID_MERKLE) {
> > > > + err = module_hash_check(info, sig, sig_len);
> > > > } else {
> > > > - pr_err("module: not signed with expected PKCS#7 message\n");
> > > > + pr_err("module: not signed with signature mechanism\n");
> > > > err = -ENOPKG;
> > >
> > > To prevent others from running into the same issue:
> > >
> > > My first test got stuck here, as I tested with virtme-ng, which symlinks
> > > modules from build tree to /lib/modules/$(uname -r)/..., resulting in
> > >
> > > [ 15.956855] module: not signed with signature mechanism
> > > modprobe: ERROR: could not insert 'efivarfs': Package not installed
> > >
> > > As the modules_install step was missing, modules were not being signed.
> >
> > Currently the signing is deferred to installation time to keep in sync
> > with regular module signing and to keep the logic simpler by not having
> > to gracefully handle previously-signed files.
> > But this could be changed.
>
> I did not want to suggest changing the behaviour, that would make things
> more complicated to prevent needless rebuilds. I just wanted to mention
> it here to prevent others from burning time.
Understood.
> > > [...]
> > > > diff --git a/scripts/modules-merkle-tree.c b/scripts/modules-merkle-tree.c
> > > > new file mode 100644
> > > > index 000000000000..a6ec0e21213b
> > > > --- /dev/null
> > > > +++ b/scripts/modules-merkle-tree.c
> > > > @@ -0,0 +1,467 @@
> > > > +// SPDX-License-Identifier: GPL-2.0-or-later
> > > > +/*
> > > > + * Compute hashes for modules files and build a merkle tree.
> > > > + *
> > > > + * Copyright (C) 2025 Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
> > > > + * Copyright (C) 2025 Thomas Weißschuh <linux@weissschuh.net>
> > > > + *
> > > > + */
> > > > +#define _GNU_SOURCE 1
> > > > +#include <arpa/inet.h>
> > > > +#include <err.h>
> > > > +#include <unistd.h>
> > > > +#include <fcntl.h>
> > > > +#include <stdarg.h>
> > > > +#include <stdio.h>
> > > > +#include <string.h>
> > > > +#include <stdbool.h>
> > > > +#include <stdlib.h>
> > > > +
> > > > +#include <sys/stat.h>
> > > > +#include <sys/mman.h>
> > > > +
> > > > +#include <openssl/evp.h>
> > > > +#include <openssl/err.h>
> > > > +
> > > > +#include "ssl-common.h"
> > > > +
> > > > +static int hash_size;
> > > > +static EVP_MD_CTX *ctx;
> > > > +
> > > > +struct module_signature {
> > > > + uint8_t algo; /* Public-key crypto algorithm [0] */
> > > > + uint8_t hash; /* Digest algorithm [0] */
> > > > + uint8_t id_type; /* Key identifier type [PKEY_ID_PKCS7] */
> > > > + uint8_t signer_len; /* Length of signer's name [0] */
> > > > + uint8_t key_id_len; /* Length of key identifier [0] */
> > > > + uint8_t __pad[3];
> > > > + uint32_t sig_len; /* Length of signature data */
> > > > +};
> > > > +
> > > > +#define PKEY_ID_MERKLE 3
> > > > +
> > > > +static const char magic_number[] = "~Module signature appended~\n";
> > >
> > > This here will be the forth definition of struct module_signature,
> > > increasing the risk of unwanted diversion. I second Petr's suggestion
> > > to reuse a _common_ definition instead.
> >
> > Ack.
> >
> > > (Here, even include/linux/module_signature.h could be included itself.)
> >
> > I'd like to avoid including internal headers from other components.
> > We could move it to an UAPI header. Various other subsystems use those
> > for not-really-UAPI but still ABI definitions.
>
> Yeah, ack.
What exactly is the 'ack' for?
* Avoiding to include internal headers?
* Moving the definition to UAPI headers?
(...)
> > > Can you verify if I get the mechanics roughly correct?
> > >
> > > * Modules are merkle tree leaves. Modules are built and logically
> > > paired by the order from modules.order; a single left-over module is
> > > paired with itself.
> > >
> > > * Hashes of paired modules are hashed again (branch node hash);
> > > hashes of pairs of branch nodes' hashes are hashed again;
> > > repeat until we reach the single merkle tree root hash
> > >
> > > * The final merkle tree root hash (and the count of tree levels) is
> > > included in vmlinux
> >
> > The merkle tree code was written by Sebastian so he will have the best
> > knowledge about it. But this is also my understanding.
>
> I'd like to see some (rough) description in Documentation or in a commit
> message at least, otherwise future me will have to ask that again.
Ack in general. I'd prefer to document it in a source code comment,
though. That feels like the best fit to me.
Thomas
^ permalink raw reply
* Re: [PATCH v15 00/28] x86: Secure Launch support for Intel TXT
From: Daniel P. Smith @ 2026-02-23 21:37 UTC (permalink / raw)
To: Ard Biesheuvel, Andy Lutomirski
Cc: Simo Sorce, H . Peter Anvin, Ross Philipson, linux-kernel, x86,
linux-integrity, linux-doc, linux-crypto, kexec, linux-efi, iommu,
dave.hansen, Thomas Gleixner, Ingo Molnar, Borislav Petkov, mjg59,
James.Bottomley, peterhuewe, Jarkko Sakkinen, jgg, nivedita,
Herbert Xu, davem, corbet, ebiederm, dwmw2, baolu.lu,
kanth.ghatraju, andrew.cooper3, trenchboot-devel
In-Reply-To: <9034c6a1-ebce-40b6-9ac8-0b8cc5a50dd4@app.fastmail.com>
On 2/20/26 03:30, Ard Biesheuvel wrote:
>
>
> On Thu, 19 Feb 2026, at 18:34, Andy Lutomirski wrote:
>> On Wed, Feb 18, 2026 at 11:55 PM Ard Biesheuvel <ardb@kernel.org> wrote:
>>>
>>> On Wed, 18 Feb 2026, at 22:54, Andy Lutomirski wrote:
>>>> On Wed, Feb 18, 2026 at 1:04 PM Simo Sorce <simo@redhat.com> wrote:
>>>>>
>>>>> On Wed, 2026-02-18 at 12:34 -0800, Andy Lutomirski wrote:
>>>>>> On Wed, Feb 18, 2026 at 12:29 PM H. Peter Anvin <hpa@zytor.com> wrote:
>>>>>>>
>>>>>>> On February 18, 2026 12:03:27 PM PST, Andy Lutomirski <luto@amacapital.net> wrote:
>>>>>>>> On Thu, Feb 12, 2026 at 12:40 PM Ard Biesheuvel <ardb@kernel.org> wrote:
>>>>>>>>>
>>>>>>>>> On Thu, 12 Feb 2026, at 20:49, Daniel P. Smith wrote:
>>>>>>>>>> On 2/9/26 09:04, Ard Biesheuvel wrote:
>>>>>>>>> ...
>>>>>>>>> But would it be better to disable the runtime services by default when doing a secure launch? PREEMPT_RT already does the same.
>>>>>>>>
>>>>>>>> So I have a possible way to disable EFI runtime service without losing
>>>>>>>> the ability to write EFI vars. We come up with a simple file format
>>>>>>>> to store deferred EFI var updates and we come up with a place to put
>>>>>>>> it so that we find it early-ish in boot the next time around. (This
>>>>>>>> could be done via integration with systemd-boot or shim some other
>>>>>>>> boot loader or it could actually be part of the kernel.) And then,
>>>>>>>> instead of writing variables directly, we write them to the deferred
>>>>>>>> list and then update them on reboot (before TXT launch, etc). [0]
>>>>>>>> This would be a distincly nontrivial project and would not work for
>>>>>>>> all configurations.
>>>>>>>>
>>>>>>>> As a maybe less painful option, we could disable EFI runtime services
>>>>>>>> but have a root-writable thing in sysfs that (a) turns them back on
>>>>>>>> but (b) first extends a PCR to say that they're turned back on.
>>>>>>>>
>>>>>>>> (Or someone could try running runtime services at CPL3...)
>>>>>>>>
>>>>>>>> [0] I have thought for years that Intel and AMD should do this on
>>>>>>>> their end, too. Keep the sensitive part of SMI flash entirely locked
>>>>>>>> after boot and, instead of using magic SMM stuff to validate that
>>>>>>>> write attempts have the appropriate permissions and signatures, queue
>>>>>>>> them up as deferred upates and validate the signatures on the next
>>>>>>>> boot before locking flash.
>>>>>>>>
>>>>>>>
>>>>>>> *If* a physical EFI partition exists there is a lot to be said for this approach.
>>>>>>>
>>>>>>> The only issue with this that I can see is for things like network or CD/DVD booting where there isn't necessarily any EFI boot partition, it might not be writable, or it might not be persistent (e.g. http booting typically uses a ramdisk, like the old Linux initrd.)
>>>>>>
>>>>>> Hmm, I guess my approach is a 100% complete nonstarter for installing
>>>>>> Linux from a CD, and it's really not awesome for installing Linux from
>>>>>> a USB stick.
>>>>>
>>>>> Doing any of this on a removable device feels generally like a trap.
>>>>> You get your USB disk in, try to boot, and it saves vars, but reboot
>>>>> fails for whatever reason, you plug it in another machine ... and it
>>>>> tries to "continue" from there? The amount of validation needed and
>>>>> testing for failure modes across reboots sounds really painful.
>>>>
>>>> I kind of stand by my other previous suggestion, though:
>>>>
>>>> As a maybe less painful option, we could disable EFI runtime services
>>>> but have a root-writable thing in sysfs that (a) turns them back on
>>>> but (b) first extends a PCR to say that they're turned back on.
>>>>
>>>
>>> After setting the EFI boot path to GRUB (or systemd-boot or whatever) at installation time, what other meaningful interactions do we expect with the EFI runtime services?
>>>
>>> And given that the secure launch is orchestrated by the bootloader , with which the kernel has a backchannel via its configuration file, it should be rather straight-forward to implement the staging of variable updates there if we really need it.
>>>
>>> Doing any of this at the EFI/spec level might lead to a situation where the OS now has to guess which of the provided APIs to manipulate variables is the least broken.
>>>
>>> Of course, for readinf variables, dumping the RT variables into a memory buffer at boot time and exposing it via a EFI config table would be rather straight-forward, but it is also something I feel should be the job of the boot component that takes part in the decision to shield the runtime services from the OS.
>>
>> So there's sort of a usability issue here. On the one hand, this can
>> all be orchestrated to work. We build a kernel, and the kernel
>> supports secure launch. Someone makes an installer image, and that
>> image is configured to skip secure launch, then install to disk, then
>> program EFI vars, then reboot. And the installed image is configured
>> to do the secure launch, and EFI variable writes are turned off.
>>
>> On the other hand, this all sucks. I'm getting sick of having the
>> kernel tell me that I am not permitted to do things. I'm sick of
>> writing software that deals with unnecessary restrictions. If I were
>> writing an OS with a USB stick-based installer, I might want to be
>> able to boot the thing and decide later whether I'm installing an OS
>> to disk. (In fact, many USB installers work this way.) But, in the
>> model where EFI variable writes are hard-disabled on a secure launch,
>> the decision to do the secure launch happens before the decision to
>> install an OS, and we all lose.
>>
>> So I'm proposing that EFI variable writes be treated a bit like kexec
>> [0] -- root (which is already part of the TCB for any practical
>> purpose) is going to decide, like a grown up, to execute some code
>> that it doesn't fully trust -- in this case, the EFI variable writes.
>> And root will coordinate, correctly, with whomever it's busy using the
>> TPM to coordinate with, and tell it that it's going to do something
>> that will change its trustworthiness. So it works like this:
>>
>> 1. Secure launch the environment on the stick. (At this stage,
>> neither the boot loader nor the kernel has the faintest clue whether
>> anyone needs that secure launch, but this doesn't matter.)
>>
>> 2. The owner of the machine clicks "install".
>>
>> 3. The installer makes some partitions and writes some files.
>>
>> (Up until now, the security posture of the running environment has not changed.)
>>
>> 4. The installer decides that it's now time to do untrustworthy
>> things, namely writing EFI vars. So it unmounts anything it mounted
>> using TPM-sealed keys (or not -- this is between the distro and
>> whoever trusts the distro), and it does:
>>
>> # echo 1 >/sys/.../extend_pcr_and_unlock_efi
>>
>> which *first* extends a PCR because we are about to change our
>> security posture and *second* sets whatever flag permits use of EFI
>> runtime services.
>>
>> 5. The installer writes to EFI variables. And the installer can no
>> longer generate attestations to its previous security posture, which
>> is the correct behavior. And maybe the user can no longer unlock
>> their home directory or whatever until they reboot. Which is not
>> really a big deal.
>>
>> (This is *dynamic* root of trust. In theory the system could do a
>> DRTM re-launch and recover its security posture, but I don't think
>> this is implemented.)
>>
>>
>> One thing I like about this is that it involves very little code.
>>
>
> It does seem rather straight-forward, and it doesn't have to be specific to TXT either. I.e., we should probably always measure the runtime enabled/disabled state into the PCRs.
As you mentioned, this is not unique to the DRTM case, but allow me to
provide our perspective. We would enjoy a sysfs controlled lock that
results in a PCR Event. With that said, while it may be getting down
into the implementation details, I would like to suggest the PCR be
configurable. When under DRTM, it would be desirable to have the ability
for the measurement to be extended into a DRTM PCR.
v/r,
dps
> But given the actual problem at hand (untrustworthy glue code running in ring 3 that does little more than poke SMM, which itself fundamentally remains part of the TCB), it would be nice if we could just sandbox that code using virtualization.
>
> This came up in a separate discussion regarding ACPI PRM (the new dumping ground for evil vendor code now that SMM has gone out of fashion), although there it should be feasible to run it unprivileged, as the spec requires that capability for the PRM payloads.
^ permalink raw reply
* Re: [PATCH v4 15/17] module: Introduce hash-based integrity checking
From: Nicolas Schier @ 2026-02-23 18:41 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Nathan Chancellor, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Daniel Gomez,
Aaron Tomlin, Christophe Leroy (CS GROUP), Nicolas Bouchinet,
Xiu Jianfeng, Fabian Grünbichler, Arnout Engelen,
Mattia Rizzolo, kpcyrd, Christian Heusel, Câju Mihai-Drosi,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity
In-Reply-To: <0d70db8d-702b-46ec-a010-298fe6515aab@t-8ch.de>
On Mon, Feb 23, 2026 at 08:53:29AM +0100, Thomas Weißschuh wrote:
> On 2026-02-21 22:38:29+0100, Nicolas Schier wrote:
> > On Tue, Jan 13, 2026 at 01:28:59PM +0100, Thomas Weißschuh wrote:
> > > The current signature-based module integrity checking has some drawbacks
> > > in combination with reproducible builds. Either the module signing key
> > > is generated at build time, which makes the build unreproducible, or a
> > > static signing key is used, which precludes rebuilds by third parties
> > > and makes the whole build and packaging process much more complicated.
> > >
> > > The goal is to reach bit-for-bit reproducibility. Excluding certain
> > > parts of the build output from the reproducibility analysis would be
> > > error-prone and force each downstream consumer to introduce new tooling.
> > >
> > > Introduce a new mechanism to ensure only well-known modules are loaded
> > > by embedding a merkle tree root of all modules built as part of the full
> > > kernel build into vmlinux.
> > >
> > > Non-builtin modules can be validated as before through signatures.
> > >
> > > Normally the .ko module files depend on a fully built vmlinux to be
> > > available for modpost validation and BTF generation. With
> > > CONFIG_MODULE_HASHES, vmlinux now depends on the modules
> > > to build a merkle tree. This introduces a dependency cycle which is
> > > impossible to satisfy. Work around this by building the modules during
> > > link-vmlinux.sh, after vmlinux is complete enough for modpost and BTF
> > > but before the final module hashes are
> > >
> > > The PKCS7 format which is used for regular module signatures can not
> > > represent Merkle proofs, so a new kind of module signature is
> > > introduced. As this signature type is only ever used for builtin
> > > modules, no compatibility issues can arise.
> > >
> > > Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> > > ---
> > > .gitignore | 1 +
> > > Documentation/kbuild/reproducible-builds.rst | 5 +-
> > > Makefile | 8 +-
> > > include/asm-generic/vmlinux.lds.h | 11 +
> > > include/linux/module_hashes.h | 25 ++
> > > include/linux/module_signature.h | 1 +
> > > kernel/module/Kconfig | 21 +-
> > > kernel/module/Makefile | 1 +
> > > kernel/module/hashes.c | 92 ++++++
> > > kernel/module/hashes_root.c | 6 +
> > > kernel/module/internal.h | 1 +
> > > kernel/module/main.c | 4 +-
> > > scripts/.gitignore | 1 +
> > > scripts/Makefile | 3 +
> > > scripts/Makefile.modfinal | 11 +
> > > scripts/Makefile.modinst | 13 +
> > > scripts/Makefile.vmlinux | 5 +
> > > scripts/link-vmlinux.sh | 14 +-
> > > scripts/modules-merkle-tree.c | 467 +++++++++++++++++++++++++++
> > > security/lockdown/Kconfig | 2 +-
> > > 20 files changed, 685 insertions(+), 7 deletions(-)
> > >
> > [...]
> >
> > > diff --git a/kernel/module/hashes_root.c b/kernel/module/hashes_root.c
> > > new file mode 100644
> > > index 000000000000..1abfcd3aa679
> > > --- /dev/null
> > > +++ b/kernel/module/hashes_root.c
> > > @@ -0,0 +1,6 @@
> > > +// SPDX-License-Identifier: GPL-2.0-or-later
> > > +
> > > +#include <linux/module_hashes.h>
> > > +
> > > +/* Blank dummy data. Will be overridden by link-vmlinux.sh */
> > > +const struct module_hashes_root module_hashes_root __module_hashes_section = {};
> > > diff --git a/kernel/module/internal.h b/kernel/module/internal.h
> > > index e2d49122c2a1..e22837d3ac76 100644
> > > --- a/kernel/module/internal.h
> > > +++ b/kernel/module/internal.h
> > > @@ -338,6 +338,7 @@ void module_mark_ro_after_init(const Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
> > > const char *secstrings);
> > >
> > > int module_sig_check(struct load_info *info, const u8 *sig, size_t sig_len);
> > > +int module_hash_check(struct load_info *info, const u8 *sig, size_t sig_len);
> > >
> > > #ifdef CONFIG_DEBUG_KMEMLEAK
> > > void kmemleak_load_module(const struct module *mod, const struct load_info *info);
> > > diff --git a/kernel/module/main.c b/kernel/module/main.c
> > > index 2a28a0ece809..fa30b6387936 100644
> > > --- a/kernel/module/main.c
> > > +++ b/kernel/module/main.c
> > > @@ -3362,8 +3362,10 @@ static int module_integrity_check(struct load_info *info, int flags)
> > >
> > > if (IS_ENABLED(CONFIG_MODULE_SIG) && sig_type == PKEY_ID_PKCS7) {
> > > err = module_sig_check(info, sig, sig_len);
> > > + } else if (IS_ENABLED(CONFIG_MODULE_HASHES) && sig_type == PKEY_ID_MERKLE) {
> > > + err = module_hash_check(info, sig, sig_len);
> > > } else {
> > > - pr_err("module: not signed with expected PKCS#7 message\n");
> > > + pr_err("module: not signed with signature mechanism\n");
> > > err = -ENOPKG;
> >
> > To prevent others from running into the same issue:
> >
> > My first test got stuck here, as I tested with virtme-ng, which symlinks
> > modules from build tree to /lib/modules/$(uname -r)/..., resulting in
> >
> > [ 15.956855] module: not signed with signature mechanism
> > modprobe: ERROR: could not insert 'efivarfs': Package not installed
> >
> > As the modules_install step was missing, modules were not being signed.
>
> Currently the signing is deferred to installation time to keep in sync
> with regular module signing and to keep the logic simpler by not having
> to gracefully handle previously-signed files.
> But this could be changed.
I did not want to suggest changing the behaviour, that would make things
more complicated to prevent needless rebuilds. I just wanted to mention
it here to prevent others from burning time.
> > [...]
> > > diff --git a/scripts/modules-merkle-tree.c b/scripts/modules-merkle-tree.c
> > > new file mode 100644
> > > index 000000000000..a6ec0e21213b
> > > --- /dev/null
> > > +++ b/scripts/modules-merkle-tree.c
> > > @@ -0,0 +1,467 @@
> > > +// SPDX-License-Identifier: GPL-2.0-or-later
> > > +/*
> > > + * Compute hashes for modules files and build a merkle tree.
> > > + *
> > > + * Copyright (C) 2025 Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
> > > + * Copyright (C) 2025 Thomas Weißschuh <linux@weissschuh.net>
> > > + *
> > > + */
> > > +#define _GNU_SOURCE 1
> > > +#include <arpa/inet.h>
> > > +#include <err.h>
> > > +#include <unistd.h>
> > > +#include <fcntl.h>
> > > +#include <stdarg.h>
> > > +#include <stdio.h>
> > > +#include <string.h>
> > > +#include <stdbool.h>
> > > +#include <stdlib.h>
> > > +
> > > +#include <sys/stat.h>
> > > +#include <sys/mman.h>
> > > +
> > > +#include <openssl/evp.h>
> > > +#include <openssl/err.h>
> > > +
> > > +#include "ssl-common.h"
> > > +
> > > +static int hash_size;
> > > +static EVP_MD_CTX *ctx;
> > > +
> > > +struct module_signature {
> > > + uint8_t algo; /* Public-key crypto algorithm [0] */
> > > + uint8_t hash; /* Digest algorithm [0] */
> > > + uint8_t id_type; /* Key identifier type [PKEY_ID_PKCS7] */
> > > + uint8_t signer_len; /* Length of signer's name [0] */
> > > + uint8_t key_id_len; /* Length of key identifier [0] */
> > > + uint8_t __pad[3];
> > > + uint32_t sig_len; /* Length of signature data */
> > > +};
> > > +
> > > +#define PKEY_ID_MERKLE 3
> > > +
> > > +static const char magic_number[] = "~Module signature appended~\n";
> >
> > This here will be the forth definition of struct module_signature,
> > increasing the risk of unwanted diversion. I second Petr's suggestion
> > to reuse a _common_ definition instead.
>
> Ack.
>
> > (Here, even include/linux/module_signature.h could be included itself.)
>
> I'd like to avoid including internal headers from other components.
> We could move it to an UAPI header. Various other subsystems use those
> for not-really-UAPI but still ABI definitions.
Yeah, ack.
> (...)
>
> > > +static inline char *xasprintf(const char *fmt, ...)
> > > +{
> > > + va_list ap;
> > > + char *strp;
> > > + int ret;
> > > +
> > > + va_start(ap, fmt);
> > > + ret = vasprintf(&strp, fmt, ap);
> > > + va_end(ap);
> > > + if (ret == -1)
> > > + err(1, "Memory allocation failed");
> > > +
> > > + return strp;
> > > +}
> >
> > Please consider moving these x* functions into scripts/include/xalloc.h
> > for reuse. (I am sure someone else wrote this already, but I can't find
> > it...)
>
> Petr suggested it somewhere, it is done for the next revision.
>
> > thanks for all your efforts for reproducibility!
> >
> > As I have no clue about that: Is the patent for merkle trees [1] a
> > problem when integrating that here?
>
> That should have expired a long time ago [2].
> And fs-verity is also using merkle trees.
Great, thanks.
> > Can you verify if I get the mechanics roughly correct?
> >
> > * Modules are merkle tree leaves. Modules are built and logically
> > paired by the order from modules.order; a single left-over module is
> > paired with itself.
> >
> > * Hashes of paired modules are hashed again (branch node hash);
> > hashes of pairs of branch nodes' hashes are hashed again;
> > repeat until we reach the single merkle tree root hash
> >
> > * The final merkle tree root hash (and the count of tree levels) is
> > included in vmlinux
>
> The merkle tree code was written by Sebastian so he will have the best
> knowledge about it. But this is also my understanding.
I'd like to see some (rough) description in Documentation or in a commit
message at least, otherwise future me will have to ask that again.
> > 'make && find . -name '*.ko' -exec rm {} \; && make' does not rebuild
> > the in-tree modules. Shifting the module-hashes support from
> > scripts/link-vmlinux.sh to scripts/Makefile.vmlinux might (make it
> > easier) to fix this again.
>
> I'll take a look at it.
Thanks!
Kind regards,
Nicolas
> > [1]: https://worldwide.espacenet.com/patent/search/family/022107098/publication/US4309569A?q=pn%3DUS4309569
>
> [2] https://patents.stackexchange.com/questions/17901/validity-of-patent-on-merkle-trees
>
>
> Thomas
--
Nicolas
^ permalink raw reply
* Re: [PATCH v3 3/3] s390: Drop unnecessary CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT
From: Mimi Zohar @ 2026-02-23 18:38 UTC (permalink / raw)
To: Coiby Xu, linux-integrity
Cc: Heiko Carstens, Alexander Egorenkov, Ard Biesheuvel, Dave Hansen,
Vasily Gorbik, Alexander Gordeev, Christian Borntraeger,
Sven Schnelle, open list:S390 ARCHITECTURE, open list
In-Reply-To: <20260213012851.2532722-4-coxu@redhat.com>
On Fri, 2026-02-13 at 09:28 +0800, Coiby Xu wrote:
> Commit b5ca117365d9 ("ima: prevent kexec_load syscall based on runtime
> secureboot flag") and commit 268a78404973 ("s390/kexec_file: Disable
> kexec_load when IPLed secure") disabled the kexec_load syscall based
> on the secureboot mode. Commit 9e2b4be377f0 ("ima: add a new CONFIG
> for loading arch-specific policies") needed to detect the secure boot
> mode, not to load an IMA architecture specific policy. Since there is
> the new CONFIG_INTEGRITY_SECURE_BOOT, drop
> CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT for s390.
>
> Signed-off-by: Coiby Xu <coxu@redhat.com>
Alexander, you added your Tested-by for the original version of this patch set.
Can I apply it for v3?
thanks,
Mimi
^ permalink raw reply
* [PATCH v1] tpm_crb: Convert ACPI driver to a platform one
From: Rafael J. Wysocki @ 2026-02-23 15:55 UTC (permalink / raw)
To: Jarkko Sakkinen
Cc: Peter Huewe, Jason Gunthorpe, linux-integrity, LKML, Linux ACPI
From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
In all cases in which a struct acpi_driver is used for binding a driver
to an ACPI device object, a corresponding platform device is created by
the ACPI core and that device is regarded as a proper representation of
underlying hardware. Accordingly, a struct platform_driver should be
used by driver code to bind to that device. There are multiple reasons
why drivers should not bind directly to ACPI device objects [1].
Overall, it is better to bind drivers to platform devices than to their
ACPI companions, so convert the tpm_crb ACPI driver to a platform one.
While this is not expected to alter functionality, it changes sysfs
layout and so it will be visible to user space.
Link: https://lore.kernel.org/all/2396510.ElGaqSPkdT@rafael.j.wysocki/ [1]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
drivers/char/tpm/tpm_crb.c | 35 ++++++++++++++++-------------------
1 file changed, 16 insertions(+), 19 deletions(-)
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
index 6c25305c256e..7d1377e8e616 100644
--- a/drivers/char/tpm/tpm_crb.c
+++ b/drivers/char/tpm/tpm_crb.c
@@ -15,6 +15,7 @@
#include <linux/highmem.h>
#include <linux/rculist.h>
#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#ifdef CONFIG_ARM64
#include <linux/arm-smccc.h>
@@ -602,13 +603,13 @@ static u64 crb_fixup_cmd_size(struct device *dev, struct resource *io_res,
return io_res->end - start + 1;
}
-static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
+static int crb_map_io(struct device *dev, struct crb_priv *priv,
struct acpi_table_tpm2 *buf)
{
+ struct acpi_device *device = ACPI_COMPANION(dev);
struct list_head acpi_resource_list;
struct resource iores_array[TPM_CRB_MAX_RESOURCES + 1] = { {0} };
void __iomem *iobase_array[TPM_CRB_MAX_RESOURCES] = {NULL};
- struct device *dev = &device->dev;
struct resource *iores;
void __iomem **iobase_ptr;
int i;
@@ -782,12 +783,13 @@ static int crb_map_pluton(struct device *dev, struct crb_priv *priv,
return 0;
}
-static int crb_acpi_add(struct acpi_device *device)
+static int crb_acpi_probe(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
+ struct acpi_device *device = ACPI_COMPANION(dev);
struct acpi_table_tpm2 *buf;
struct crb_priv *priv;
struct tpm_chip *chip;
- struct device *dev = &device->dev;
struct tpm2_crb_smc *crb_smc;
struct tpm2_crb_ffa *crb_ffa;
struct tpm2_crb_pluton *crb_pluton;
@@ -867,7 +869,7 @@ static int crb_acpi_add(struct acpi_device *device)
priv->sm = sm;
priv->hid = acpi_device_hid(device);
- rc = crb_map_io(device, priv, buf);
+ rc = crb_map_io(dev, priv, buf);
if (rc)
goto out;
@@ -901,12 +903,9 @@ static int crb_acpi_add(struct acpi_device *device)
return rc;
}
-static void crb_acpi_remove(struct acpi_device *device)
+static void crb_acpi_remove(struct platform_device *pdev)
{
- struct device *dev = &device->dev;
- struct tpm_chip *chip = dev_get_drvdata(dev);
-
- tpm_chip_unregister(chip);
+ tpm_chip_unregister(platform_get_drvdata(pdev));
}
static const struct dev_pm_ops crb_pm = {
@@ -919,19 +918,17 @@ static const struct acpi_device_id crb_device_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, crb_device_ids);
-static struct acpi_driver crb_acpi_driver = {
- .name = "tpm_crb",
- .ids = crb_device_ids,
- .ops = {
- .add = crb_acpi_add,
- .remove = crb_acpi_remove,
- },
- .drv = {
+static struct platform_driver crb_acpi_driver = {
+ .probe = crb_acpi_probe,
+ .remove = crb_acpi_remove,
+ .driver = {
+ .name = "tpm_crb_acpi",
+ .acpi_match_table = crb_device_ids,
.pm = &crb_pm,
},
};
-module_acpi_driver(crb_acpi_driver);
+module_platform_driver(crb_acpi_driver);
MODULE_AUTHOR("Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>");
MODULE_DESCRIPTION("TPM2 Driver");
MODULE_VERSION("0.1");
--
2.51.0
^ permalink raw reply related
* Re: [PATCH v4] ima_fs: Avoid creating measurement lists for unsupported hash algos
From: Dmitry Safonov @ 2026-02-23 14:59 UTC (permalink / raw)
To: Roberto Sassu
Cc: Mimi Zohar, Roberto Sassu, Dmitry Kasatkin, Eric Snowberg,
Paul Moore, James Morris, Serge E. Hallyn, Silvia Sisinni,
Enrico Bravi, linux-integrity, linux-security-module,
linux-kernel, stable, Dmitry Safonov
In-Reply-To: <89f51356ba5e630a8c305e5f65abd2f3ace37a48.camel@huaweicloud.com>
Hi Roberto,
On Thu, Feb 19, 2026 at 8:55 AM Roberto Sassu
<roberto.sassu@huaweicloud.com> wrote:
>
> On Tue, 2026-01-27 at 16:20 +0100, Roberto Sassu wrote:
> > On Tue, 2026-01-27 at 15:03 +0000, Dmitry Safonov via B4 Relay wrote:
> > > From: Dmitry Safonov <dima@arista.com>
> > >
> > > ima_init_crypto() skips initializing ima_algo_array[i] if the algorithm
> > > from ima_tpm_chip->allocated_banks[i].crypto_id is not supported.
> > > It seems avoid adding the unsupported algorithm to ima_algo_array will
> > > break all the logic that relies on indexing by NR_BANKS(ima_tpm_chip).
> >
> > The patch looks good, although I didn't try yet myself.
> >
> > I would make the commit message slightly better, with a more fluid
> > explanation.
> >
> > ima_tpm_chip->allocated_banks[i].crypto_id is initialized to
> > HASH_ALGO__LAST if the TPM algorithm is not supported. However there
> > are places relying on the algorithm to be valid because it is accessed
> > by hash_algo_name[].
> >
> > Thus solve the problem by creating a file name that does not depend on
> > the crypto algorithm to be initialized, ...
> >
> > Also print the template entry digest as populated by IMA.
> >
> > Something along these lines.
> >
> > Also, I have a preference for lower case instead of capital case for
> > the file name, given the other names.
>
> Hi Dmitry
>
> do you have time to make these small changes, so that we queue the
> patch for the next kernel?
I've just sent v5. Sorry for the delay — I got busy with the local release bugs.
Thanks,
Dmitry
^ permalink raw reply
* [PATCH v5] ima_fs: Avoid creating measurement lists for unsupported hash algos
From: Dmitry Safonov via B4 Relay @ 2026-02-23 14:56 UTC (permalink / raw)
To: Mimi Zohar, 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, Dmitry Safonov
From: Dmitry Safonov <dima@arista.com>
ima_tpm_chip->allocated_banks[i].crypto_id is initialized to
HASH_ALGO__LAST if the TPM algorithm is not supported. However there
are places relying on the algorithm to be valid because it is accessed
by hash_algo_name[].
On 6.12.40 I observe the following read out-of-bounds in hash_algo_name:
==================================================================
BUG: KASAN: global-out-of-bounds in create_securityfs_measurement_lists+0x396/0x440
Read of size 8 at addr ffffffff83e18138 by task swapper/0/1
CPU: 4 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.12.40 #3
Call Trace:
<TASK>
dump_stack_lvl+0x61/0x90
print_report+0xc4/0x580
? kasan_addr_to_slab+0x26/0x80
? create_securityfs_measurement_lists+0x396/0x440
kasan_report+0xc2/0x100
? create_securityfs_measurement_lists+0x396/0x440
create_securityfs_measurement_lists+0x396/0x440
ima_fs_init+0xa3/0x300
ima_init+0x7d/0xd0
init_ima+0x28/0x100
do_one_initcall+0xa6/0x3e0
kernel_init_freeable+0x455/0x740
kernel_init+0x24/0x1d0
ret_from_fork+0x38/0x80
ret_from_fork_asm+0x11/0x20
</TASK>
The buggy address belongs to the variable:
hash_algo_name+0xb8/0x420
Memory state around the buggy address:
ffffffff83e18000: 00 01 f9 f9 f9 f9 f9 f9 00 01 f9 f9 f9 f9 f9 f9
ffffffff83e18080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>ffffffff83e18100: 00 00 00 00 00 00 00 f9 f9 f9 f9 f9 00 05 f9 f9
^
ffffffff83e18180: f9 f9 f9 f9 00 00 00 00 00 00 00 04 f9 f9 f9 f9
ffffffff83e18200: 00 00 00 00 00 00 00 00 04 f9 f9 f9 f9 f9 f9 f9
==================================================================
Seems like the TPM chip supports sha3_256, which isn't yet in
tpm_algorithms:
tpm tpm0: TPM with unsupported bank algorithm 0x0027
Thus solve the problem by creating a file name with "_tpm_alg_<ID>"
postfix if the crypto algorithm isn't initialized.
This is how it looks on the test machine (patch ported to v6.12 release):
# ls -1 /sys/kernel/security/ima/
ascii_runtime_measurements
ascii_runtime_measurements_tpm_alg_27
ascii_runtime_measurements_sha1
ascii_runtime_measurements_sha256
binary_runtime_measurements
binary_runtime_measurements_tpm_alg_27
binary_runtime_measurements_sha1
binary_runtime_measurements_sha256
policy
runtime_measurements_count
violations
Fixes: 9fa8e7625008 ("ima: add crypto agility support for template-hash algorithm")
Signed-off-by: Dmitry Safonov <dima@arista.com>
Cc: Enrico Bravi <enrico.bravi@polito.it>
Cc: Silvia Sisinni <silvia.sisinni@polito.it>
Cc: Roberto Sassu <roberto.sassu@huawei.com>
Cc: Mimi Zohar <zohar@linux.ibm.com>
---
Changes in v5:
- Use lower-case for sysfs file name (as suggested-by Jonathan and Roberto)
- Don't use email quotes for patch description (Roberto)
- Re-word the patch description (suggested-by Roberto)
- Link to v4: https://lore.kernel.org/r/20260127-ima-oob-v4-1-bf0cd7f9b4d4@arista.com
Changes in v4:
- Use ima_tpm_chip->allocated_banks[algo_idx].digest_size instead of hash_digest_size[algo]
(Roberto Sassu)
- Link to v3: https://lore.kernel.org/r/20260127-ima-oob-v3-1-1dd09f4c2a6a@arista.com
Testing note: I test it on v6.12.40 kernel backport, which slightly differs as
lookup_template_data_hash_algo() was yet present.
Changes in v3:
- Now fix the spelling *for real* (sorry, messed it up in v2)
- Link to v2: https://lore.kernel.org/r/20260127-ima-oob-v2-1-f38a18c850cf@arista.com
Changes in v2:
- Instead of skipping unknown algorithms, add files under their TPM_ALG_ID (Roberto Sassu)
- Fix spelling (Roberto Sassu)
- Copy @stable on the fix
- Link to v1: https://lore.kernel.org/r/20260127-ima-oob-v1-1-2d42f3418e57@arista.com
---
security/integrity/ima/ima_fs.c | 34 ++++++++++++++++++----------------
1 file changed, 18 insertions(+), 16 deletions(-)
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index 012a58959ff0..3d9996ed486d 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_tpm_chip->allocated_banks[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_tpm_chip->allocated_banks[algo_idx].digest_size);
/* 3th: template name */
seq_printf(m, " %s", template_name);
@@ -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);
+ else
+ sprintf(file_name, "binary_runtime_measurements_%s",
+ hash_algo_name[algo]);
dentry = securityfs_create_file(file_name, S_IRUSR | S_IRGRP,
ima_dir, (void *)(uintptr_t)i,
&ima_measurements_ops);
---
base-commit: 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f
change-id: 20260127-ima-oob-9fa83a634d7b
Best regards,
--
Dmitry Safonov <dima@arista.com>
^ permalink raw reply related
* Re: [PATCH v4 15/17] module: Introduce hash-based integrity checking
From: Thomas Weißschuh @ 2026-02-23 7:53 UTC (permalink / raw)
To: Nicolas Schier
Cc: Nathan Chancellor, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Daniel Gomez,
Aaron Tomlin, Christophe Leroy (CS GROUP), Nicolas Bouchinet,
Xiu Jianfeng, Fabian Grünbichler, Arnout Engelen,
Mattia Rizzolo, kpcyrd, Christian Heusel, Câju Mihai-Drosi,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity
In-Reply-To: <aZol1Rsa2tX-WNaZ@derry.ads.avm.de>
On 2026-02-21 22:38:29+0100, Nicolas Schier wrote:
> On Tue, Jan 13, 2026 at 01:28:59PM +0100, Thomas Weißschuh wrote:
> > The current signature-based module integrity checking has some drawbacks
> > in combination with reproducible builds. Either the module signing key
> > is generated at build time, which makes the build unreproducible, or a
> > static signing key is used, which precludes rebuilds by third parties
> > and makes the whole build and packaging process much more complicated.
> >
> > The goal is to reach bit-for-bit reproducibility. Excluding certain
> > parts of the build output from the reproducibility analysis would be
> > error-prone and force each downstream consumer to introduce new tooling.
> >
> > Introduce a new mechanism to ensure only well-known modules are loaded
> > by embedding a merkle tree root of all modules built as part of the full
> > kernel build into vmlinux.
> >
> > Non-builtin modules can be validated as before through signatures.
> >
> > Normally the .ko module files depend on a fully built vmlinux to be
> > available for modpost validation and BTF generation. With
> > CONFIG_MODULE_HASHES, vmlinux now depends on the modules
> > to build a merkle tree. This introduces a dependency cycle which is
> > impossible to satisfy. Work around this by building the modules during
> > link-vmlinux.sh, after vmlinux is complete enough for modpost and BTF
> > but before the final module hashes are
> >
> > The PKCS7 format which is used for regular module signatures can not
> > represent Merkle proofs, so a new kind of module signature is
> > introduced. As this signature type is only ever used for builtin
> > modules, no compatibility issues can arise.
> >
> > Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> > ---
> > .gitignore | 1 +
> > Documentation/kbuild/reproducible-builds.rst | 5 +-
> > Makefile | 8 +-
> > include/asm-generic/vmlinux.lds.h | 11 +
> > include/linux/module_hashes.h | 25 ++
> > include/linux/module_signature.h | 1 +
> > kernel/module/Kconfig | 21 +-
> > kernel/module/Makefile | 1 +
> > kernel/module/hashes.c | 92 ++++++
> > kernel/module/hashes_root.c | 6 +
> > kernel/module/internal.h | 1 +
> > kernel/module/main.c | 4 +-
> > scripts/.gitignore | 1 +
> > scripts/Makefile | 3 +
> > scripts/Makefile.modfinal | 11 +
> > scripts/Makefile.modinst | 13 +
> > scripts/Makefile.vmlinux | 5 +
> > scripts/link-vmlinux.sh | 14 +-
> > scripts/modules-merkle-tree.c | 467 +++++++++++++++++++++++++++
> > security/lockdown/Kconfig | 2 +-
> > 20 files changed, 685 insertions(+), 7 deletions(-)
> >
> [...]
>
> > diff --git a/kernel/module/hashes_root.c b/kernel/module/hashes_root.c
> > new file mode 100644
> > index 000000000000..1abfcd3aa679
> > --- /dev/null
> > +++ b/kernel/module/hashes_root.c
> > @@ -0,0 +1,6 @@
> > +// SPDX-License-Identifier: GPL-2.0-or-later
> > +
> > +#include <linux/module_hashes.h>
> > +
> > +/* Blank dummy data. Will be overridden by link-vmlinux.sh */
> > +const struct module_hashes_root module_hashes_root __module_hashes_section = {};
> > diff --git a/kernel/module/internal.h b/kernel/module/internal.h
> > index e2d49122c2a1..e22837d3ac76 100644
> > --- a/kernel/module/internal.h
> > +++ b/kernel/module/internal.h
> > @@ -338,6 +338,7 @@ void module_mark_ro_after_init(const Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
> > const char *secstrings);
> >
> > int module_sig_check(struct load_info *info, const u8 *sig, size_t sig_len);
> > +int module_hash_check(struct load_info *info, const u8 *sig, size_t sig_len);
> >
> > #ifdef CONFIG_DEBUG_KMEMLEAK
> > void kmemleak_load_module(const struct module *mod, const struct load_info *info);
> > diff --git a/kernel/module/main.c b/kernel/module/main.c
> > index 2a28a0ece809..fa30b6387936 100644
> > --- a/kernel/module/main.c
> > +++ b/kernel/module/main.c
> > @@ -3362,8 +3362,10 @@ static int module_integrity_check(struct load_info *info, int flags)
> >
> > if (IS_ENABLED(CONFIG_MODULE_SIG) && sig_type == PKEY_ID_PKCS7) {
> > err = module_sig_check(info, sig, sig_len);
> > + } else if (IS_ENABLED(CONFIG_MODULE_HASHES) && sig_type == PKEY_ID_MERKLE) {
> > + err = module_hash_check(info, sig, sig_len);
> > } else {
> > - pr_err("module: not signed with expected PKCS#7 message\n");
> > + pr_err("module: not signed with signature mechanism\n");
> > err = -ENOPKG;
>
> To prevent others from running into the same issue:
>
> My first test got stuck here, as I tested with virtme-ng, which symlinks
> modules from build tree to /lib/modules/$(uname -r)/..., resulting in
>
> [ 15.956855] module: not signed with signature mechanism
> modprobe: ERROR: could not insert 'efivarfs': Package not installed
>
> As the modules_install step was missing, modules were not being signed.
Currently the signing is deferred to installation time to keep in sync
with regular module signing and to keep the logic simpler by not having
to gracefully handle previously-signed files.
But this could be changed.
> [...]
> > diff --git a/scripts/modules-merkle-tree.c b/scripts/modules-merkle-tree.c
> > new file mode 100644
> > index 000000000000..a6ec0e21213b
> > --- /dev/null
> > +++ b/scripts/modules-merkle-tree.c
> > @@ -0,0 +1,467 @@
> > +// SPDX-License-Identifier: GPL-2.0-or-later
> > +/*
> > + * Compute hashes for modules files and build a merkle tree.
> > + *
> > + * Copyright (C) 2025 Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
> > + * Copyright (C) 2025 Thomas Weißschuh <linux@weissschuh.net>
> > + *
> > + */
> > +#define _GNU_SOURCE 1
> > +#include <arpa/inet.h>
> > +#include <err.h>
> > +#include <unistd.h>
> > +#include <fcntl.h>
> > +#include <stdarg.h>
> > +#include <stdio.h>
> > +#include <string.h>
> > +#include <stdbool.h>
> > +#include <stdlib.h>
> > +
> > +#include <sys/stat.h>
> > +#include <sys/mman.h>
> > +
> > +#include <openssl/evp.h>
> > +#include <openssl/err.h>
> > +
> > +#include "ssl-common.h"
> > +
> > +static int hash_size;
> > +static EVP_MD_CTX *ctx;
> > +
> > +struct module_signature {
> > + uint8_t algo; /* Public-key crypto algorithm [0] */
> > + uint8_t hash; /* Digest algorithm [0] */
> > + uint8_t id_type; /* Key identifier type [PKEY_ID_PKCS7] */
> > + uint8_t signer_len; /* Length of signer's name [0] */
> > + uint8_t key_id_len; /* Length of key identifier [0] */
> > + uint8_t __pad[3];
> > + uint32_t sig_len; /* Length of signature data */
> > +};
> > +
> > +#define PKEY_ID_MERKLE 3
> > +
> > +static const char magic_number[] = "~Module signature appended~\n";
>
> This here will be the forth definition of struct module_signature,
> increasing the risk of unwanted diversion. I second Petr's suggestion
> to reuse a _common_ definition instead.
Ack.
> (Here, even include/linux/module_signature.h could be included itself.)
I'd like to avoid including internal headers from other components.
We could move it to an UAPI header. Various other subsystems use those
for not-really-UAPI but still ABI definitions.
(...)
> > +static inline char *xasprintf(const char *fmt, ...)
> > +{
> > + va_list ap;
> > + char *strp;
> > + int ret;
> > +
> > + va_start(ap, fmt);
> > + ret = vasprintf(&strp, fmt, ap);
> > + va_end(ap);
> > + if (ret == -1)
> > + err(1, "Memory allocation failed");
> > +
> > + return strp;
> > +}
>
> Please consider moving these x* functions into scripts/include/xalloc.h
> for reuse. (I am sure someone else wrote this already, but I can't find
> it...)
Petr suggested it somewhere, it is done for the next revision.
> thanks for all your efforts for reproducibility!
>
> As I have no clue about that: Is the patent for merkle trees [1] a
> problem when integrating that here?
That should have expired a long time ago [2].
And fs-verity is also using merkle trees.
> Can you verify if I get the mechanics roughly correct?
>
> * Modules are merkle tree leaves. Modules are built and logically
> paired by the order from modules.order; a single left-over module is
> paired with itself.
>
> * Hashes of paired modules are hashed again (branch node hash);
> hashes of pairs of branch nodes' hashes are hashed again;
> repeat until we reach the single merkle tree root hash
>
> * The final merkle tree root hash (and the count of tree levels) is
> included in vmlinux
The merkle tree code was written by Sebastian so he will have the best
knowledge about it. But this is also my understanding.
> 'make && find . -name '*.ko' -exec rm {} \; && make' does not rebuild
> the in-tree modules. Shifting the module-hashes support from
> scripts/link-vmlinux.sh to scripts/Makefile.vmlinux might (make it
> easier) to fix this again.
I'll take a look at it.
> [1]: https://worldwide.espacenet.com/patent/search/family/022107098/publication/US4309569A?q=pn%3DUS4309569
[2] https://patents.stackexchange.com/questions/17901/validity-of-patent-on-merkle-trees
Thomas
^ permalink raw reply
* Re: [PATCH v4 15/17] module: Introduce hash-based integrity checking
From: Nicolas Schier @ 2026-02-21 21:38 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Nathan Chancellor, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Daniel Gomez,
Aaron Tomlin, Christophe Leroy (CS GROUP), Nicolas Bouchinet,
Xiu Jianfeng, Fabian Grünbichler, Arnout Engelen,
Mattia Rizzolo, kpcyrd, Christian Heusel, Câju Mihai-Drosi,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity
In-Reply-To: <20260113-module-hashes-v4-15-0b932db9b56b@weissschuh.net>
Hi Thomas,
On Tue, Jan 13, 2026 at 01:28:59PM +0100, Thomas Weißschuh wrote:
> The current signature-based module integrity checking has some drawbacks
> in combination with reproducible builds. Either the module signing key
> is generated at build time, which makes the build unreproducible, or a
> static signing key is used, which precludes rebuilds by third parties
> and makes the whole build and packaging process much more complicated.
>
> The goal is to reach bit-for-bit reproducibility. Excluding certain
> parts of the build output from the reproducibility analysis would be
> error-prone and force each downstream consumer to introduce new tooling.
>
> Introduce a new mechanism to ensure only well-known modules are loaded
> by embedding a merkle tree root of all modules built as part of the full
> kernel build into vmlinux.
>
> Non-builtin modules can be validated as before through signatures.
>
> Normally the .ko module files depend on a fully built vmlinux to be
> available for modpost validation and BTF generation. With
> CONFIG_MODULE_HASHES, vmlinux now depends on the modules
> to build a merkle tree. This introduces a dependency cycle which is
> impossible to satisfy. Work around this by building the modules during
> link-vmlinux.sh, after vmlinux is complete enough for modpost and BTF
> but before the final module hashes are
>
> The PKCS7 format which is used for regular module signatures can not
> represent Merkle proofs, so a new kind of module signature is
> introduced. As this signature type is only ever used for builtin
> modules, no compatibility issues can arise.
>
> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> ---
> .gitignore | 1 +
> Documentation/kbuild/reproducible-builds.rst | 5 +-
> Makefile | 8 +-
> include/asm-generic/vmlinux.lds.h | 11 +
> include/linux/module_hashes.h | 25 ++
> include/linux/module_signature.h | 1 +
> kernel/module/Kconfig | 21 +-
> kernel/module/Makefile | 1 +
> kernel/module/hashes.c | 92 ++++++
> kernel/module/hashes_root.c | 6 +
> kernel/module/internal.h | 1 +
> kernel/module/main.c | 4 +-
> scripts/.gitignore | 1 +
> scripts/Makefile | 3 +
> scripts/Makefile.modfinal | 11 +
> scripts/Makefile.modinst | 13 +
> scripts/Makefile.vmlinux | 5 +
> scripts/link-vmlinux.sh | 14 +-
> scripts/modules-merkle-tree.c | 467 +++++++++++++++++++++++++++
> security/lockdown/Kconfig | 2 +-
> 20 files changed, 685 insertions(+), 7 deletions(-)
>
[...]
> diff --git a/kernel/module/hashes_root.c b/kernel/module/hashes_root.c
> new file mode 100644
> index 000000000000..1abfcd3aa679
> --- /dev/null
> +++ b/kernel/module/hashes_root.c
> @@ -0,0 +1,6 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +
> +#include <linux/module_hashes.h>
> +
> +/* Blank dummy data. Will be overridden by link-vmlinux.sh */
> +const struct module_hashes_root module_hashes_root __module_hashes_section = {};
> diff --git a/kernel/module/internal.h b/kernel/module/internal.h
> index e2d49122c2a1..e22837d3ac76 100644
> --- a/kernel/module/internal.h
> +++ b/kernel/module/internal.h
> @@ -338,6 +338,7 @@ void module_mark_ro_after_init(const Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
> const char *secstrings);
>
> int module_sig_check(struct load_info *info, const u8 *sig, size_t sig_len);
> +int module_hash_check(struct load_info *info, const u8 *sig, size_t sig_len);
>
> #ifdef CONFIG_DEBUG_KMEMLEAK
> void kmemleak_load_module(const struct module *mod, const struct load_info *info);
> diff --git a/kernel/module/main.c b/kernel/module/main.c
> index 2a28a0ece809..fa30b6387936 100644
> --- a/kernel/module/main.c
> +++ b/kernel/module/main.c
> @@ -3362,8 +3362,10 @@ static int module_integrity_check(struct load_info *info, int flags)
>
> if (IS_ENABLED(CONFIG_MODULE_SIG) && sig_type == PKEY_ID_PKCS7) {
> err = module_sig_check(info, sig, sig_len);
> + } else if (IS_ENABLED(CONFIG_MODULE_HASHES) && sig_type == PKEY_ID_MERKLE) {
> + err = module_hash_check(info, sig, sig_len);
> } else {
> - pr_err("module: not signed with expected PKCS#7 message\n");
> + pr_err("module: not signed with signature mechanism\n");
> err = -ENOPKG;
To prevent others from running into the same issue:
My first test got stuck here, as I tested with virtme-ng, which symlinks
modules from build tree to /lib/modules/$(uname -r)/..., resulting in
[ 15.956855] module: not signed with signature mechanism
modprobe: ERROR: could not insert 'efivarfs': Package not installed
As the modules_install step was missing, modules were not being signed.
[...]
> diff --git a/scripts/modules-merkle-tree.c b/scripts/modules-merkle-tree.c
> new file mode 100644
> index 000000000000..a6ec0e21213b
> --- /dev/null
> +++ b/scripts/modules-merkle-tree.c
> @@ -0,0 +1,467 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Compute hashes for modules files and build a merkle tree.
> + *
> + * Copyright (C) 2025 Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
> + * Copyright (C) 2025 Thomas Weißschuh <linux@weissschuh.net>
> + *
> + */
> +#define _GNU_SOURCE 1
> +#include <arpa/inet.h>
> +#include <err.h>
> +#include <unistd.h>
> +#include <fcntl.h>
> +#include <stdarg.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <stdbool.h>
> +#include <stdlib.h>
> +
> +#include <sys/stat.h>
> +#include <sys/mman.h>
> +
> +#include <openssl/evp.h>
> +#include <openssl/err.h>
> +
> +#include "ssl-common.h"
> +
> +static int hash_size;
> +static EVP_MD_CTX *ctx;
> +
> +struct module_signature {
> + uint8_t algo; /* Public-key crypto algorithm [0] */
> + uint8_t hash; /* Digest algorithm [0] */
> + uint8_t id_type; /* Key identifier type [PKEY_ID_PKCS7] */
> + uint8_t signer_len; /* Length of signer's name [0] */
> + uint8_t key_id_len; /* Length of key identifier [0] */
> + uint8_t __pad[3];
> + uint32_t sig_len; /* Length of signature data */
> +};
> +
> +#define PKEY_ID_MERKLE 3
> +
> +static const char magic_number[] = "~Module signature appended~\n";
This here will be the forth definition of struct module_signature,
increasing the risk of unwanted diversion. I second Petr's suggestion
to reuse a _common_ definition instead.
(Here, even include/linux/module_signature.h could be included itself.)
> +
> +struct file_entry {
> + char *name;
> + unsigned int pos;
> + unsigned char hash[EVP_MAX_MD_SIZE];
> +};
> +
> +static struct file_entry *fh_list;
> +static size_t num_files;
> +
> +struct leaf_hash {
> + unsigned char hash[EVP_MAX_MD_SIZE];
> +};
> +
> +struct mtree {
> + struct leaf_hash **l;
> + unsigned int *entries;
> + unsigned int levels;
> +};
> +
> +static inline void *xcalloc(size_t n, size_t size)
> +{
> + void *p;
> +
> + p = calloc(n, size);
> + if (!p)
> + errx(1, "Memory allocation failed");
> +
> + return p;
> +}
> +
> +static void *xmalloc(size_t size)
> +{
> + void *p;
> +
> + p = malloc(size);
> + if (!p)
> + errx(1, "Memory allocation failed");
> +
> + return p;
> +}
> +
> +static inline void *xreallocarray(void *oldp, size_t n, size_t size)
> +{
> + void *p;
> +
> + p = reallocarray(oldp, n, size);
> + if (!p)
> + errx(1, "Memory allocation failed");
> +
> + return p;
> +}
> +
> +static inline char *xasprintf(const char *fmt, ...)
> +{
> + va_list ap;
> + char *strp;
> + int ret;
> +
> + va_start(ap, fmt);
> + ret = vasprintf(&strp, fmt, ap);
> + va_end(ap);
> + if (ret == -1)
> + err(1, "Memory allocation failed");
> +
> + return strp;
> +}
Please consider moving these x* functions into scripts/include/xalloc.h
for reuse. (I am sure someone else wrote this already, but I can't find
it...)
>
>
thanks for all your efforts for reproducibility!
As I have no clue about that: Is the patent for merkle trees [1] a
problem when integrating that here?
Can you verify if I get the mechanics roughly correct?
* Modules are merkle tree leaves. Modules are built and logically
paired by the order from modules.order; a single left-over module is
paired with itself.
* Hashes of paired modules are hashed again (branch node hash);
hashes of pairs of branch nodes' hashes are hashed again;
repeat until we reach the single merkle tree root hash
* The final merkle tree root hash (and the count of tree levels) is
included in vmlinux
'make && find . -name '*.ko' -exec rm {} \; && make' does not rebuild
the in-tree modules. Shifting the module-hashes support from
scripts/link-vmlinux.sh to scripts/Makefile.vmlinux might (make it
easier) to fix this again.
Kind regards,
Nicolas
[1]: https://worldwide.espacenet.com/patent/search/family/022107098/publication/US4309569A?q=pn%3DUS4309569
--
Nicolas
^ permalink raw reply
* Re: [PATCH] lsm: move inode IS_PRIVATE checks to individual LSMs
From: Casey Schaufler @ 2026-02-20 21:13 UTC (permalink / raw)
To: danieldurning.work, linux-security-module, selinux,
linux-integrity
Cc: stephen.smalley.work, paul, jmorris, serge, john.johansen, zohar,
roberto.sassu, dmitry.kasatkin, mic, takedakn, penguin-kernel,
Casey Schaufler
In-Reply-To: <20260220195405.30612-1-danieldurning.work@gmail.com>
On 2/20/2026 11:54 AM, danieldurning.work@gmail.com wrote:
> From: Daniel Durning <danieldurning.work@gmail.com>
>
> Move responsibility of bypassing S_PRIVATE inodes to the
> individual LSMs. Originally the LSM framework would skip calling
> the hooks on any inode that was marked S_PRIVATE. This would
> prevent the LSMs from controlling access to any inodes marked as
> such (ie. pidfds). We now perform the same IS_PRIVATE checks
> within the LSMs instead. This is consistent with the general goal
> of deferring as much as possible to the individual LSMs.
Um ... ick?
Sure, we generally want the LSMs to be responsible for their own
decisions, but that doesn't look like the point to me. What appears
to be the issue is that pidfs isn't using S_PRIVATE in a way that
conveys the necessary information to the LSMs.
>
> This reorganization enables the LSMs to eventually implement
> checks or labeling for some specific S_PRIVATE inodes like pidfds.
We could consider these or similar changes when that eventuality occurs.
I would strongly suggest that this is a pidfs issue, not an LSM
infrastructure issue.
>
> Signed-off-by: Daniel Durning <danieldurning.work@gmail.com>
> ---
> security/apparmor/lsm.c | 32 ++++++++
> security/commoncap.c | 11 ++-
> security/integrity/evm/evm_main.c | 33 +++++++++
> security/integrity/ima/ima_appraise.c | 12 +++
> security/integrity/ima/ima_main.c | 6 ++
> security/landlock/fs.c | 23 ++++++
> security/security.c | 101 ++------------------------
> security/selinux/hooks.c | 77 ++++++++++++++++++++
> security/smack/smack_lsm.c | 56 ++++++++++++++
> security/tomoyo/tomoyo.c | 35 +++++++++
> 10 files changed, 290 insertions(+), 96 deletions(-)
>
> diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
> index a87cd60ed206..5b3ced11bdbc 100644
> --- a/security/apparmor/lsm.c
> +++ b/security/apparmor/lsm.c
> @@ -323,18 +323,27 @@ static int common_perm_create(const char *op, const struct path *dir,
>
> static int apparmor_path_unlink(const struct path *dir, struct dentry *dentry)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
> + return 0;
> +
> return common_perm_rm(OP_UNLINK, dir, dentry, AA_MAY_DELETE);
> }
>
> static int apparmor_path_mkdir(const struct path *dir, struct dentry *dentry,
> umode_t mode)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
> + return 0;
> +
> return common_perm_create(OP_MKDIR, dir, dentry, AA_MAY_CREATE,
> S_IFDIR);
> }
>
> static int apparmor_path_rmdir(const struct path *dir, struct dentry *dentry)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
> + return 0;
> +
> return common_perm_rm(OP_RMDIR, dir, dentry, AA_MAY_DELETE);
> }
>
> @@ -346,6 +355,9 @@ static int apparmor_path_mknod(const struct path *dir, struct dentry *dentry,
>
> static int apparmor_path_truncate(const struct path *path)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
> + return 0;
> +
> return common_perm_cond(OP_TRUNC, path, MAY_WRITE | AA_MAY_SETATTR);
> }
>
> @@ -357,6 +369,9 @@ static int apparmor_file_truncate(struct file *file)
> static int apparmor_path_symlink(const struct path *dir, struct dentry *dentry,
> const char *old_name)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
> + return 0;
> +
> return common_perm_create(OP_SYMLINK, dir, dentry, AA_MAY_CREATE,
> S_IFLNK);
> }
> @@ -367,6 +382,9 @@ static int apparmor_path_link(struct dentry *old_dentry, const struct path *new_
> struct aa_label *label;
> int error = 0;
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
> + return 0;
> +
> if (!path_mediated_fs(old_dentry))
> return 0;
>
> @@ -386,6 +404,11 @@ static int apparmor_path_rename(const struct path *old_dir, struct dentry *old_d
> struct aa_label *label;
> int error = 0;
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)) ||
> + (d_is_positive(new_dentry) &&
> + IS_PRIVATE(d_backing_inode(new_dentry)))))
> + return 0;
> +
> if (!path_mediated_fs(old_dentry))
> return 0;
> if ((flags & RENAME_EXCHANGE) && !path_mediated_fs(new_dentry))
> @@ -444,16 +467,25 @@ static int apparmor_path_rename(const struct path *old_dir, struct dentry *old_d
>
> static int apparmor_path_chmod(const struct path *path, umode_t mode)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
> + return 0;
> +
> return common_perm_cond(OP_CHMOD, path, AA_MAY_CHMOD);
> }
>
> static int apparmor_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
> + return 0;
> +
> return common_perm_cond(OP_CHOWN, path, AA_MAY_CHOWN);
> }
>
> static int apparmor_inode_getattr(const struct path *path)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
> + return 0;
> +
> return common_perm_cond(OP_GETATTR, path, AA_MAY_GETATTR);
> }
>
> diff --git a/security/commoncap.c b/security/commoncap.c
> index 8a23dfab7fac..1b61d43529c2 100644
> --- a/security/commoncap.c
> +++ b/security/commoncap.c
> @@ -88,7 +88,7 @@ static inline int cap_capable_helper(const struct cred *cred,
> if (ns->level <= cred_ns->level)
> return -EPERM;
>
> - /*
> + /*
> * The owner of the user namespace in the parent of the
> * user namespace has all caps.
> */
> @@ -432,6 +432,9 @@ int cap_inode_getsecurity(struct mnt_idmap *idmap,
> struct dentry *dentry;
> struct user_namespace *fs_ns;
>
> + if (unlikely(IS_PRIVATE(inode)))
> + return -EOPNOTSUPP;
> +
> if (strcmp(name, "capability") != 0)
> return -EOPNOTSUPP;
>
> @@ -1027,6 +1030,9 @@ int cap_inode_setxattr(struct dentry *dentry, const char *name,
> {
> struct user_namespace *user_ns = dentry->d_sb->s_user_ns;
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return 0;
> +
> /* Ignore non-security xattrs */
> if (strncmp(name, XATTR_SECURITY_PREFIX,
> XATTR_SECURITY_PREFIX_LEN) != 0)
> @@ -1068,6 +1074,9 @@ int cap_inode_removexattr(struct mnt_idmap *idmap,
> {
> struct user_namespace *user_ns = dentry->d_sb->s_user_ns;
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return 0;
> +
> /* Ignore non-security xattrs */
> if (strncmp(name, XATTR_SECURITY_PREFIX,
> XATTR_SECURITY_PREFIX_LEN) != 0)
> diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
> index 73d500a375cb..0095712b8d75 100644
> --- a/security/integrity/evm/evm_main.c
> +++ b/security/integrity/evm/evm_main.c
> @@ -590,6 +590,9 @@ static int evm_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry,
> {
> const struct evm_ima_xattr_data *xattr_data = xattr_value;
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return 0;
> +
> /* Policy permits modification of the protected xattrs even though
> * there's no HMAC key loaded
> */
> @@ -675,6 +678,9 @@ static int evm_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
> {
> enum integrity_status evm_status;
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return 0;
> +
> /* Policy permits modification of the protected xattrs even though
> * there's no HMAC key loaded
> */
> @@ -725,6 +731,9 @@ static int evm_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
> static int evm_inode_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry,
> const char *acl_name)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return 0;
> +
> return evm_inode_set_acl(idmap, dentry, acl_name, NULL);
> }
>
> @@ -807,6 +816,9 @@ static void evm_inode_post_setxattr(struct dentry *dentry,
> size_t xattr_value_len,
> int flags)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return;
> +
> if (!evm_revalidate_status(xattr_name))
> return;
>
> @@ -836,6 +848,9 @@ static void evm_inode_post_setxattr(struct dentry *dentry,
> static void evm_inode_post_set_acl(struct dentry *dentry, const char *acl_name,
> struct posix_acl *kacl)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return;
> +
> return evm_inode_post_setxattr(dentry, acl_name, NULL, 0, 0);
> }
>
> @@ -852,6 +867,9 @@ static void evm_inode_post_set_acl(struct dentry *dentry, const char *acl_name,
> static void evm_inode_post_removexattr(struct dentry *dentry,
> const char *xattr_name)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return;
> +
> if (!evm_revalidate_status(xattr_name))
> return;
>
> @@ -879,6 +897,9 @@ static inline void evm_inode_post_remove_acl(struct mnt_idmap *idmap,
> struct dentry *dentry,
> const char *acl_name)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return;
> +
> evm_inode_post_removexattr(dentry, acl_name);
> }
>
> @@ -911,6 +932,9 @@ static int evm_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
> unsigned int ia_valid = attr->ia_valid;
> enum integrity_status evm_status;
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return 0;
> +
> /* Policy permits modification of the protected attrs even though
> * there's no HMAC key loaded
> */
> @@ -960,6 +984,9 @@ static int evm_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
> static void evm_inode_post_setattr(struct mnt_idmap *idmap,
> struct dentry *dentry, int ia_valid)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return;
> +
> if (!evm_revalidate_status(NULL))
> return;
>
> @@ -1019,6 +1046,9 @@ int evm_inode_init_security(struct inode *inode, struct inode *dir,
> bool evm_protected_xattrs = false;
> int rc;
>
> + if (unlikely(IS_PRIVATE(inode)))
> + return 0;
> +
> if (!(evm_initialized & EVM_INIT_HMAC) || !xattrs)
> return 0;
>
> @@ -1094,6 +1124,9 @@ static void evm_post_path_mknod(struct mnt_idmap *idmap, struct dentry *dentry)
> struct inode *inode = d_backing_inode(dentry);
> struct evm_iint_cache *iint = evm_iint_inode(inode);
>
> + if (unlikely(IS_PRIVATE(inode)))
> + return;
> +
> if (!S_ISREG(inode->i_mode))
> return;
>
> diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
> index 5149ff4fd50d..d705c908132f 100644
> --- a/security/integrity/ima/ima_appraise.c
> +++ b/security/integrity/ima/ima_appraise.c
> @@ -665,6 +665,9 @@ static void ima_inode_post_setattr(struct mnt_idmap *idmap,
> struct ima_iint_cache *iint;
> int action;
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return;
> +
> if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)
> || !(inode->i_opflags & IOP_XATTR))
> return;
> @@ -790,6 +793,9 @@ static int ima_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry,
> int result;
> int err;
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return 0;
> +
> result = ima_protect_xattr(dentry, xattr_name, xattr_value,
> xattr_value_len);
> if (result == 1) {
> @@ -817,6 +823,9 @@ static int ima_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry,
> static int ima_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
> const char *acl_name, struct posix_acl *kacl)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return 0;
> +
> if (evm_revalidate_status(acl_name))
> ima_reset_appraise_flags(d_backing_inode(dentry), -1);
>
> @@ -842,6 +851,9 @@ static int ima_inode_removexattr(struct mnt_idmap *idmap, struct dentry *dentry,
> static int ima_inode_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry,
> const char *acl_name)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return 0;
> +
> return ima_inode_set_acl(idmap, dentry, acl_name, NULL);
> }
>
> diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
> index 5770cf691912..5ddac6c15c7f 100644
> --- a/security/integrity/ima/ima_main.c
> +++ b/security/integrity/ima/ima_main.c
> @@ -794,6 +794,9 @@ static void ima_post_create_tmpfile(struct mnt_idmap *idmap,
> struct ima_iint_cache *iint;
> int must_appraise;
>
> + if (unlikely(IS_PRIVATE(inode)))
> + return;
> +
> if (!ima_policy_flag || !S_ISREG(inode->i_mode))
> return;
>
> @@ -826,6 +829,9 @@ static void ima_post_path_mknod(struct mnt_idmap *idmap, struct dentry *dentry)
> struct inode *inode = dentry->d_inode;
> int must_appraise;
>
> + if (unlikely(IS_PRIVATE(inode)))
> + return;
> +
> if (!ima_policy_flag || !S_ISREG(inode->i_mode))
> return;
>
> diff --git a/security/landlock/fs.c b/security/landlock/fs.c
> index fe794875ad46..5fe15313a3f5 100644
> --- a/security/landlock/fs.c
> +++ b/security/landlock/fs.c
> @@ -1528,6 +1528,9 @@ static int hook_path_link(struct dentry *const old_dentry,
> const struct path *const new_dir,
> struct dentry *const new_dentry)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
> + return 0;
> +
> return current_check_refer_path(old_dentry, new_dir, new_dentry, false,
> false);
> }
> @@ -1538,6 +1541,11 @@ static int hook_path_rename(const struct path *const old_dir,
> struct dentry *const new_dentry,
> const unsigned int flags)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)) ||
> + (d_is_positive(new_dentry) &&
> + IS_PRIVATE(d_backing_inode(new_dentry)))))
> + return 0;
> +
> /* old_dir refers to old_dentry->d_parent and new_dir->mnt */
> return current_check_refer_path(old_dentry, new_dir, new_dentry, true,
> !!(flags & RENAME_EXCHANGE));
> @@ -1546,6 +1554,9 @@ static int hook_path_rename(const struct path *const old_dir,
> static int hook_path_mkdir(const struct path *const dir,
> struct dentry *const dentry, const umode_t mode)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
> + return 0;
> +
> return current_check_access_path(dir, LANDLOCK_ACCESS_FS_MAKE_DIR);
> }
>
> @@ -1560,23 +1571,35 @@ static int hook_path_symlink(const struct path *const dir,
> struct dentry *const dentry,
> const char *const old_name)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
> + return 0;
> +
> return current_check_access_path(dir, LANDLOCK_ACCESS_FS_MAKE_SYM);
> }
>
> static int hook_path_unlink(const struct path *const dir,
> struct dentry *const dentry)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
> + return 0;
> +
> return current_check_access_path(dir, LANDLOCK_ACCESS_FS_REMOVE_FILE);
> }
>
> static int hook_path_rmdir(const struct path *const dir,
> struct dentry *const dentry)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
> + return 0;
> +
> return current_check_access_path(dir, LANDLOCK_ACCESS_FS_REMOVE_DIR);
> }
>
> static int hook_path_truncate(const struct path *const path)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
> + return 0;
> +
> return current_check_access_path(path, LANDLOCK_ACCESS_FS_TRUNCATE);
> }
>
> diff --git a/security/security.c b/security/security.c
> index 31a688650601..658dbb10ea40 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -1310,9 +1310,6 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
> struct xattr *new_xattrs = NULL;
> int ret = -EOPNOTSUPP, xattr_count = 0;
>
> - if (unlikely(IS_PRIVATE(inode)))
> - return 0;
> -
> if (!blob_sizes.lbs_xattr_count)
> return 0;
>
> @@ -1386,8 +1383,6 @@ int security_inode_init_security_anon(struct inode *inode,
> int security_path_mknod(const struct path *dir, struct dentry *dentry,
> umode_t mode, unsigned int dev)
> {
> - if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
> - return 0;
> return call_int_hook(path_mknod, dir, dentry, mode, dev);
> }
> EXPORT_SYMBOL(security_path_mknod);
> @@ -1401,8 +1396,6 @@ EXPORT_SYMBOL(security_path_mknod);
> */
> void security_path_post_mknod(struct mnt_idmap *idmap, struct dentry *dentry)
> {
> - if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> - return;
> call_void_hook(path_post_mknod, idmap, dentry);
> }
>
> @@ -1419,8 +1412,6 @@ void security_path_post_mknod(struct mnt_idmap *idmap, struct dentry *dentry)
> int security_path_mkdir(const struct path *dir, struct dentry *dentry,
> umode_t mode)
> {
> - if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
> - return 0;
> return call_int_hook(path_mkdir, dir, dentry, mode);
> }
> EXPORT_SYMBOL(security_path_mkdir);
> @@ -1436,8 +1427,6 @@ EXPORT_SYMBOL(security_path_mkdir);
> */
> int security_path_rmdir(const struct path *dir, struct dentry *dentry)
> {
> - if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
> - return 0;
> return call_int_hook(path_rmdir, dir, dentry);
> }
>
> @@ -1452,8 +1441,6 @@ int security_path_rmdir(const struct path *dir, struct dentry *dentry)
> */
> int security_path_unlink(const struct path *dir, struct dentry *dentry)
> {
> - if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
> - return 0;
> return call_int_hook(path_unlink, dir, dentry);
> }
> EXPORT_SYMBOL(security_path_unlink);
> @@ -1471,8 +1458,6 @@ EXPORT_SYMBOL(security_path_unlink);
> int security_path_symlink(const struct path *dir, struct dentry *dentry,
> const char *old_name)
> {
> - if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
> - return 0;
> return call_int_hook(path_symlink, dir, dentry, old_name);
> }
>
> @@ -1489,8 +1474,6 @@ int security_path_symlink(const struct path *dir, struct dentry *dentry,
> int security_path_link(struct dentry *old_dentry, const struct path *new_dir,
> struct dentry *new_dentry)
> {
> - if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
> - return 0;
> return call_int_hook(path_link, old_dentry, new_dir, new_dentry);
> }
>
> @@ -1510,11 +1493,6 @@ int security_path_rename(const struct path *old_dir, struct dentry *old_dentry,
> const struct path *new_dir, struct dentry *new_dentry,
> unsigned int flags)
> {
> - if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)) ||
> - (d_is_positive(new_dentry) &&
> - IS_PRIVATE(d_backing_inode(new_dentry)))))
> - return 0;
> -
> return call_int_hook(path_rename, old_dir, old_dentry, new_dir,
> new_dentry, flags);
> }
> @@ -1532,8 +1510,6 @@ EXPORT_SYMBOL(security_path_rename);
> */
> int security_path_truncate(const struct path *path)
> {
> - if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
> - return 0;
> return call_int_hook(path_truncate, path);
> }
>
> @@ -1550,8 +1526,6 @@ int security_path_truncate(const struct path *path)
> */
> int security_path_chmod(const struct path *path, umode_t mode)
> {
> - if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
> - return 0;
> return call_int_hook(path_chmod, path, mode);
> }
>
> @@ -1567,8 +1541,6 @@ int security_path_chmod(const struct path *path, umode_t mode)
> */
> int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
> {
> - if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
> - return 0;
> return call_int_hook(path_chown, path, uid, gid);
> }
>
> @@ -1599,8 +1571,6 @@ int security_path_chroot(const struct path *path)
> int security_inode_create(struct inode *dir, struct dentry *dentry,
> umode_t mode)
> {
> - if (unlikely(IS_PRIVATE(dir)))
> - return 0;
> return call_int_hook(inode_create, dir, dentry, mode);
> }
> EXPORT_SYMBOL_GPL(security_inode_create);
> @@ -1615,8 +1585,6 @@ EXPORT_SYMBOL_GPL(security_inode_create);
> void security_inode_post_create_tmpfile(struct mnt_idmap *idmap,
> struct inode *inode)
> {
> - if (unlikely(IS_PRIVATE(inode)))
> - return;
> call_void_hook(inode_post_create_tmpfile, idmap, inode);
> }
>
> @@ -1633,8 +1601,6 @@ void security_inode_post_create_tmpfile(struct mnt_idmap *idmap,
> int security_inode_link(struct dentry *old_dentry, struct inode *dir,
> struct dentry *new_dentry)
> {
> - if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
> - return 0;
> return call_int_hook(inode_link, old_dentry, dir, new_dentry);
> }
>
> @@ -1649,8 +1615,6 @@ int security_inode_link(struct dentry *old_dentry, struct inode *dir,
> */
> int security_inode_unlink(struct inode *dir, struct dentry *dentry)
> {
> - if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> - return 0;
> return call_int_hook(inode_unlink, dir, dentry);
> }
>
> @@ -1667,8 +1631,6 @@ int security_inode_unlink(struct inode *dir, struct dentry *dentry)
> int security_inode_symlink(struct inode *dir, struct dentry *dentry,
> const char *old_name)
> {
> - if (unlikely(IS_PRIVATE(dir)))
> - return 0;
> return call_int_hook(inode_symlink, dir, dentry, old_name);
> }
>
> @@ -1685,8 +1647,6 @@ int security_inode_symlink(struct inode *dir, struct dentry *dentry,
> */
> int security_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
> {
> - if (unlikely(IS_PRIVATE(dir)))
> - return 0;
> return call_int_hook(inode_mkdir, dir, dentry, mode);
> }
> EXPORT_SYMBOL_GPL(security_inode_mkdir);
> @@ -1702,8 +1662,6 @@ EXPORT_SYMBOL_GPL(security_inode_mkdir);
> */
> int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
> {
> - if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> - return 0;
> return call_int_hook(inode_rmdir, dir, dentry);
> }
>
> @@ -1724,8 +1682,6 @@ int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
> int security_inode_mknod(struct inode *dir, struct dentry *dentry,
> umode_t mode, dev_t dev)
> {
> - if (unlikely(IS_PRIVATE(dir)))
> - return 0;
> return call_int_hook(inode_mknod, dir, dentry, mode, dev);
> }
>
> @@ -1745,11 +1701,6 @@ int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
> struct inode *new_dir, struct dentry *new_dentry,
> unsigned int flags)
> {
> - if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)) ||
> - (d_is_positive(new_dentry) &&
> - IS_PRIVATE(d_backing_inode(new_dentry)))))
> - return 0;
> -
> if (flags & RENAME_EXCHANGE) {
> int err = call_int_hook(inode_rename, new_dir, new_dentry,
> old_dir, old_dentry);
> @@ -1771,8 +1722,6 @@ int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
> */
> int security_inode_readlink(struct dentry *dentry)
> {
> - if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> - return 0;
> return call_int_hook(inode_readlink, dentry);
> }
>
> @@ -1790,8 +1739,6 @@ int security_inode_readlink(struct dentry *dentry)
> int security_inode_follow_link(struct dentry *dentry, struct inode *inode,
> bool rcu)
> {
> - if (unlikely(IS_PRIVATE(inode)))
> - return 0;
> return call_int_hook(inode_follow_link, dentry, inode, rcu);
> }
>
> @@ -1811,8 +1758,6 @@ int security_inode_follow_link(struct dentry *dentry, struct inode *inode,
> */
> int security_inode_permission(struct inode *inode, int mask)
> {
> - if (unlikely(IS_PRIVATE(inode)))
> - return 0;
> return call_int_hook(inode_permission, inode, mask);
> }
>
> @@ -1832,8 +1777,6 @@ int security_inode_permission(struct inode *inode, int mask)
> int security_inode_setattr(struct mnt_idmap *idmap,
> struct dentry *dentry, struct iattr *attr)
> {
> - if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> - return 0;
> return call_int_hook(inode_setattr, idmap, dentry, attr);
> }
> EXPORT_SYMBOL_GPL(security_inode_setattr);
> @@ -1849,8 +1792,6 @@ EXPORT_SYMBOL_GPL(security_inode_setattr);
> void security_inode_post_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
> int ia_valid)
> {
> - if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> - return;
> call_void_hook(inode_post_setattr, idmap, dentry, ia_valid);
> }
>
> @@ -1864,8 +1805,6 @@ void security_inode_post_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
> */
> int security_inode_getattr(const struct path *path)
> {
> - if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
> - return 0;
> return call_int_hook(inode_getattr, path);
> }
>
> @@ -1901,11 +1840,11 @@ int security_inode_setxattr(struct mnt_idmap *idmap,
> {
> int rc;
>
> - if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> - return 0;
> -
> /* enforce the capability checks at the lsm layer, if needed */
> if (!call_int_hook(inode_xattr_skipcap, name)) {
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return 0;
> +
> rc = cap_inode_setxattr(dentry, name, value, size, flags);
> if (rc)
> return rc;
> @@ -1931,8 +1870,6 @@ int security_inode_set_acl(struct mnt_idmap *idmap,
> struct dentry *dentry, const char *acl_name,
> struct posix_acl *kacl)
> {
> - if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> - return 0;
> return call_int_hook(inode_set_acl, idmap, dentry, acl_name, kacl);
> }
>
> @@ -1948,8 +1885,6 @@ int security_inode_set_acl(struct mnt_idmap *idmap,
> void security_inode_post_set_acl(struct dentry *dentry, const char *acl_name,
> struct posix_acl *kacl)
> {
> - if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> - return;
> call_void_hook(inode_post_set_acl, dentry, acl_name, kacl);
> }
>
> @@ -1967,8 +1902,6 @@ void security_inode_post_set_acl(struct dentry *dentry, const char *acl_name,
> int security_inode_get_acl(struct mnt_idmap *idmap,
> struct dentry *dentry, const char *acl_name)
> {
> - if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> - return 0;
> return call_int_hook(inode_get_acl, idmap, dentry, acl_name);
> }
>
> @@ -1986,8 +1919,6 @@ int security_inode_get_acl(struct mnt_idmap *idmap,
> int security_inode_remove_acl(struct mnt_idmap *idmap,
> struct dentry *dentry, const char *acl_name)
> {
> - if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> - return 0;
> return call_int_hook(inode_remove_acl, idmap, dentry, acl_name);
> }
>
> @@ -2003,8 +1934,6 @@ int security_inode_remove_acl(struct mnt_idmap *idmap,
> void security_inode_post_remove_acl(struct mnt_idmap *idmap,
> struct dentry *dentry, const char *acl_name)
> {
> - if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> - return;
> call_void_hook(inode_post_remove_acl, idmap, dentry, acl_name);
> }
>
> @@ -2021,8 +1950,6 @@ void security_inode_post_remove_acl(struct mnt_idmap *idmap,
> void security_inode_post_setxattr(struct dentry *dentry, const char *name,
> const void *value, size_t size, int flags)
> {
> - if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> - return;
> call_void_hook(inode_post_setxattr, dentry, name, value, size, flags);
> }
>
> @@ -2038,8 +1965,6 @@ void security_inode_post_setxattr(struct dentry *dentry, const char *name,
> */
> int security_inode_getxattr(struct dentry *dentry, const char *name)
> {
> - if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> - return 0;
> return call_int_hook(inode_getxattr, dentry, name);
> }
>
> @@ -2054,8 +1979,6 @@ int security_inode_getxattr(struct dentry *dentry, const char *name)
> */
> int security_inode_listxattr(struct dentry *dentry)
> {
> - if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> - return 0;
> return call_int_hook(inode_listxattr, dentry);
> }
>
> @@ -2087,11 +2010,11 @@ int security_inode_removexattr(struct mnt_idmap *idmap,
> {
> int rc;
>
> - if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> - return 0;
> -
> /* enforce the capability checks at the lsm layer, if needed */
> if (!call_int_hook(inode_xattr_skipcap, name)) {
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return 0;
> +
> rc = cap_inode_removexattr(idmap, dentry, name);
> if (rc)
> return rc;
> @@ -2109,8 +2032,6 @@ int security_inode_removexattr(struct mnt_idmap *idmap,
> */
> void security_inode_post_removexattr(struct dentry *dentry, const char *name)
> {
> - if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> - return;
> call_void_hook(inode_post_removexattr, dentry, name);
> }
>
> @@ -2197,9 +2118,6 @@ int security_inode_getsecurity(struct mnt_idmap *idmap,
> struct inode *inode, const char *name,
> void **buffer, bool alloc)
> {
> - if (unlikely(IS_PRIVATE(inode)))
> - return LSM_RET_DEFAULT(inode_getsecurity);
> -
> return call_int_hook(inode_getsecurity, idmap, inode, name, buffer,
> alloc);
> }
> @@ -2222,9 +2140,6 @@ int security_inode_getsecurity(struct mnt_idmap *idmap,
> int security_inode_setsecurity(struct inode *inode, const char *name,
> const void *value, size_t size, int flags)
> {
> - if (unlikely(IS_PRIVATE(inode)))
> - return LSM_RET_DEFAULT(inode_setsecurity);
> -
> return call_int_hook(inode_setsecurity, inode, name, value, size,
> flags);
> }
> @@ -2245,8 +2160,6 @@ int security_inode_setsecurity(struct inode *inode, const char *name,
> int security_inode_listsecurity(struct inode *inode,
> char *buffer, size_t buffer_size)
> {
> - if (unlikely(IS_PRIVATE(inode)))
> - return 0;
> return call_int_hook(inode_listsecurity, inode, buffer, buffer_size);
> }
> EXPORT_SYMBOL(security_inode_listsecurity);
> @@ -3596,8 +3509,6 @@ int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops,
> */
> void security_d_instantiate(struct dentry *dentry, struct inode *inode)
> {
> - if (unlikely(inode && IS_PRIVATE(inode)))
> - return;
> call_void_hook(d_instantiate, dentry, inode);
> }
> EXPORT_SYMBOL(security_d_instantiate);
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index feda34b18d83..e17d776fb159 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -2948,6 +2948,9 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
> int rc;
> char *context;
>
> + if (unlikely(IS_PRIVATE(inode)))
> + return 0;
> +
> sbsec = selinux_superblock(dir->i_sb);
>
> newsid = crsec->create_sid;
> @@ -3049,42 +3052,68 @@ static int selinux_inode_init_security_anon(struct inode *inode,
>
> static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
> {
> + if (unlikely(IS_PRIVATE(dir)))
> + return 0;
> +
> return may_create(dir, dentry, SECCLASS_FILE);
> }
>
> static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
> + return 0;
> +
> return may_link(dir, old_dentry, MAY_LINK);
> }
>
> static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return 0;
> +
> return may_link(dir, dentry, MAY_UNLINK);
> }
>
> static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
> {
> + if (unlikely(IS_PRIVATE(dir)))
> + return 0;
> +
> return may_create(dir, dentry, SECCLASS_LNK_FILE);
> }
>
> static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
> {
> + if (unlikely(IS_PRIVATE(dir)))
> + return 0;
> +
> return may_create(dir, dentry, SECCLASS_DIR);
> }
>
> static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return 0;
> +
> return may_link(dir, dentry, MAY_RMDIR);
> }
>
> static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
> {
> + if (unlikely(IS_PRIVATE(dir)))
> + return 0;
> +
> return may_create(dir, dentry, inode_mode_to_security_class(mode));
> }
>
> static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
> struct inode *new_inode, struct dentry *new_dentry)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)) ||
> + (d_is_positive(new_dentry) &&
> + IS_PRIVATE(d_backing_inode(new_dentry)))))
> + return 0;
> +
> return may_rename(old_inode, old_dentry, new_inode, new_dentry);
> }
>
> @@ -3092,6 +3121,9 @@ static int selinux_inode_readlink(struct dentry *dentry)
> {
> const struct cred *cred = current_cred();
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return 0;
> +
> return dentry_has_perm(cred, dentry, FILE__READ);
> }
>
> @@ -3102,6 +3134,9 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode,
> struct inode_security_struct *isec;
> u32 sid = current_sid();
>
> + if (unlikely(IS_PRIVATE(inode)))
> + return 0;
> +
> ad.type = LSM_AUDIT_DATA_DENTRY;
> ad.u.dentry = dentry;
> isec = inode_security_rcu(inode, rcu);
> @@ -3230,6 +3265,9 @@ static int selinux_inode_permission(struct inode *inode, int requested)
> int rc, rc2;
> u32 audited, denied;
>
> + if (unlikely(IS_PRIVATE(inode)))
> + return 0;
> +
> mask = requested & (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
>
> /* No permission to check. Existence test. */
> @@ -3283,6 +3321,9 @@ static int selinux_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
> unsigned int ia_valid = iattr->ia_valid;
> u32 av = FILE__WRITE;
>
> + if (unlikely(IS_PRIVATE(inode)))
> + return 0;
> +
> /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
> if (ia_valid & ATTR_FORCE) {
> ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
> @@ -3308,6 +3349,9 @@ static int selinux_inode_getattr(const struct path *path)
> {
> struct task_security_struct *tsec;
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
> + return 0;
> +
> tsec = selinux_task(current);
>
> if (task_avdcache_permnoaudit(tsec, current_sid()))
> @@ -3356,6 +3400,9 @@ static int selinux_inode_setxattr(struct mnt_idmap *idmap,
> u32 newsid, sid = current_sid();
> int rc = 0;
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return 0;
> +
> /* if not a selinux xattr, only check the ordinary setattr perm */
> if (strcmp(name, XATTR_NAME_SELINUX))
> return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
> @@ -3435,18 +3482,27 @@ static int selinux_inode_set_acl(struct mnt_idmap *idmap,
> struct dentry *dentry, const char *acl_name,
> struct posix_acl *kacl)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return 0;
> +
> return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
> }
>
> static int selinux_inode_get_acl(struct mnt_idmap *idmap,
> struct dentry *dentry, const char *acl_name)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return 0;
> +
> return dentry_has_perm(current_cred(), dentry, FILE__GETATTR);
> }
>
> static int selinux_inode_remove_acl(struct mnt_idmap *idmap,
> struct dentry *dentry, const char *acl_name)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return 0;
> +
> return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
> }
>
> @@ -3459,6 +3515,9 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
> u32 newsid;
> int rc;
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return;
> +
> if (strcmp(name, XATTR_NAME_SELINUX)) {
> /* Not an attribute we recognize, so nothing to do. */
> return;
> @@ -3494,6 +3553,9 @@ static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
> {
> const struct cred *cred = current_cred();
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return 0;
> +
> return dentry_has_perm(cred, dentry, FILE__GETATTR);
> }
>
> @@ -3501,6 +3563,9 @@ static int selinux_inode_listxattr(struct dentry *dentry)
> {
> const struct cred *cred = current_cred();
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return 0;
> +
> return dentry_has_perm(cred, dentry, FILE__GETATTR);
> }
>
> @@ -3593,6 +3658,9 @@ static int selinux_inode_getsecurity(struct mnt_idmap *idmap,
> char *context = NULL;
> struct inode_security_struct *isec;
>
> + if (unlikely(IS_PRIVATE(inode)))
> + return -EOPNOTSUPP;
> +
> /*
> * If we're not initialized yet, then we can't validate contexts, so
> * just let vfs_getxattr fall back to using the on-disk xattr.
> @@ -3637,6 +3705,9 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name,
> u32 newsid;
> int rc;
>
> + if (unlikely(IS_PRIVATE(inode)))
> + return -EOPNOTSUPP;
> +
> if (strcmp(name, XATTR_SELINUX_SUFFIX))
> return -EOPNOTSUPP;
>
> @@ -3664,6 +3735,9 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t
> {
> const int len = sizeof(XATTR_NAME_SELINUX);
>
> + if (unlikely(IS_PRIVATE(inode)))
> + return 0;
> +
> if (!selinux_initialized())
> return 0;
>
> @@ -6546,6 +6620,9 @@ static void selinux_ipc_getlsmprop(struct kern_ipc_perm *ipcp,
>
> static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
> {
> + if (unlikely(inode && IS_PRIVATE(inode)))
> + return;
> +
> if (inode)
> inode_doinit_with_dentry(inode, dentry);
> }
> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> index a0bd4919a9d9..8f432348dfbd 100644
> --- a/security/smack/smack_lsm.c
> +++ b/security/smack/smack_lsm.c
> @@ -1020,6 +1020,9 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
> bool trans_cred;
> bool trans_rule;
>
> + if (unlikely(IS_PRIVATE(inode)))
> + return 0;
> +
> /*
> * UNIX domain sockets use lower level socket data. Let
> * UDS inode have fixed * label to keep smack_inode_permission() calm
> @@ -1093,6 +1096,9 @@ static int smack_inode_link(struct dentry *old_dentry, struct inode *dir,
> struct smk_audit_info ad;
> int rc;
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
> + return 0;
> +
> smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
> smk_ad_setfield_u_fs_path_dentry(&ad, old_dentry);
>
> @@ -1124,6 +1130,9 @@ static int smack_inode_unlink(struct inode *dir, struct dentry *dentry)
> struct smk_audit_info ad;
> int rc;
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return 0;
> +
> smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
> smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
>
> @@ -1157,6 +1166,9 @@ static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry)
> struct smk_audit_info ad;
> int rc;
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return 0;
> +
> smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
> smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
>
> @@ -1199,6 +1211,11 @@ static int smack_inode_rename(struct inode *old_inode,
> struct smack_known *isp;
> struct smk_audit_info ad;
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)) ||
> + (d_is_positive(new_dentry) &&
> + IS_PRIVATE(d_backing_inode(new_dentry)))))
> + return 0;
> +
> smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
> smk_ad_setfield_u_fs_path_dentry(&ad, old_dentry);
>
> @@ -1231,6 +1248,9 @@ static int smack_inode_permission(struct inode *inode, int mask)
> int no_block = mask & MAY_NOT_BLOCK;
> int rc;
>
> + if (unlikely(IS_PRIVATE(inode)))
> + return 0;
> +
> mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
> /*
> * No permission to check. Existence test. Yup, it's there.
> @@ -1267,6 +1287,9 @@ static int smack_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
> struct smk_audit_info ad;
> int rc;
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return 0;
> +
> /*
> * Need to allow for clearing the setuid bit.
> */
> @@ -1292,6 +1315,9 @@ static int smack_inode_getattr(const struct path *path)
> struct inode *inode = d_backing_inode(path->dentry);
> int rc;
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
> + return 0;
> +
> smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
> smk_ad_setfield_u_fs_path(&ad, *path);
> rc = smk_curacc(smk_of_inode(inode), MAY_READ, &ad);
> @@ -1351,6 +1377,9 @@ static int smack_inode_setxattr(struct mnt_idmap *idmap,
> int rc = 0;
> umode_t const i_mode = d_backing_inode(dentry)->i_mode;
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return 0;
> +
> /*
> * Check label validity here so import won't fail in post_setxattr
> */
> @@ -1421,6 +1450,9 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
> struct smack_known *skp;
> struct inode_smack *isp = smack_inode(d_backing_inode(dentry));
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return;
> +
> if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) {
> isp->smk_flags |= SMK_INODE_TRANSMUTE;
> return;
> @@ -1455,6 +1487,9 @@ static int smack_inode_getxattr(struct dentry *dentry, const char *name)
> struct smk_audit_info ad;
> int rc;
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return 0;
> +
> smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
> smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
>
> @@ -1541,6 +1576,9 @@ static int smack_inode_set_acl(struct mnt_idmap *idmap,
> struct smk_audit_info ad;
> int rc;
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return 0;
> +
> smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
> smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
>
> @@ -1563,6 +1601,9 @@ static int smack_inode_get_acl(struct mnt_idmap *idmap,
> struct smk_audit_info ad;
> int rc;
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return 0;
> +
> smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
> smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
>
> @@ -1585,6 +1626,9 @@ static int smack_inode_remove_acl(struct mnt_idmap *idmap,
> struct smk_audit_info ad;
> int rc;
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> + return 0;
> +
> smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
> smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
>
> @@ -1616,6 +1660,9 @@ static int smack_inode_getsecurity(struct mnt_idmap *idmap,
> size_t label_len;
> char *label = NULL;
>
> + if (unlikely(IS_PRIVATE(inode)))
> + return -EOPNOTSUPP;
> +
> if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) {
> isp = smk_of_inode(inode);
> } else if (strcmp(name, XATTR_SMACK_TRANSMUTE) == 0) {
> @@ -1672,6 +1719,9 @@ static int smack_inode_listsecurity(struct inode *inode, char *buffer,
> {
> int len = sizeof(XATTR_NAME_SMACK);
>
> + if (unlikely(IS_PRIVATE(inode)))
> + return 0;
> +
> if (buffer != NULL && len <= buffer_size)
> memcpy(buffer, XATTR_NAME_SMACK, len);
>
> @@ -2918,6 +2968,9 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
> struct socket *sock;
> int rc = 0;
>
> + if (unlikely(IS_PRIVATE(inode)))
> + return -EOPNOTSUPP;
> +
> if (value == NULL || size > SMK_LONGLABEL || size == 0)
> return -EINVAL;
>
> @@ -3517,6 +3570,9 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
> if (inode == NULL)
> return;
>
> + if (unlikely(IS_PRIVATE(inode)))
> + return;
> +
> isp = smack_inode(inode);
>
> /*
> diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
> index c66e02ed8ee3..98eb8cd67f78 100644
> --- a/security/tomoyo/tomoyo.c
> +++ b/security/tomoyo/tomoyo.c
> @@ -120,6 +120,9 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm)
> */
> static int tomoyo_inode_getattr(const struct path *path)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
> + return 0;
> +
> return tomoyo_path_perm(TOMOYO_TYPE_GETATTR, path, NULL);
> }
>
> @@ -132,6 +135,9 @@ static int tomoyo_inode_getattr(const struct path *path)
> */
> static int tomoyo_path_truncate(const struct path *path)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
> + return 0;
> +
> return tomoyo_path_perm(TOMOYO_TYPE_TRUNCATE, path, NULL);
> }
>
> @@ -159,6 +165,9 @@ static int tomoyo_path_unlink(const struct path *parent, struct dentry *dentry)
> {
> struct path path = { .mnt = parent->mnt, .dentry = dentry };
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(parent->dentry))))
> + return 0;
> +
> return tomoyo_path_perm(TOMOYO_TYPE_UNLINK, &path, NULL);
> }
>
> @@ -176,6 +185,9 @@ static int tomoyo_path_mkdir(const struct path *parent, struct dentry *dentry,
> {
> struct path path = { .mnt = parent->mnt, .dentry = dentry };
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(parent->dentry))))
> + return 0;
> +
> return tomoyo_path_number_perm(TOMOYO_TYPE_MKDIR, &path,
> mode & S_IALLUGO);
> }
> @@ -192,6 +204,9 @@ static int tomoyo_path_rmdir(const struct path *parent, struct dentry *dentry)
> {
> struct path path = { .mnt = parent->mnt, .dentry = dentry };
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(parent->dentry))))
> + return 0;
> +
> return tomoyo_path_perm(TOMOYO_TYPE_RMDIR, &path, NULL);
> }
>
> @@ -209,6 +224,9 @@ static int tomoyo_path_symlink(const struct path *parent, struct dentry *dentry,
> {
> struct path path = { .mnt = parent->mnt, .dentry = dentry };
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(parent->dentry))))
> + return 0;
> +
> return tomoyo_path_perm(TOMOYO_TYPE_SYMLINK, &path, old_name);
> }
>
> @@ -229,6 +247,9 @@ static int tomoyo_path_mknod(const struct path *parent, struct dentry *dentry,
> int type = TOMOYO_TYPE_CREATE;
> const unsigned int perm = mode & S_IALLUGO;
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(parent->dentry))))
> + return 0;
> +
> switch (mode & S_IFMT) {
> case S_IFCHR:
> type = TOMOYO_TYPE_MKCHAR;
> @@ -267,6 +288,9 @@ static int tomoyo_path_link(struct dentry *old_dentry, const struct path *new_di
> struct path path1 = { .mnt = new_dir->mnt, .dentry = old_dentry };
> struct path path2 = { .mnt = new_dir->mnt, .dentry = new_dentry };
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
> + return 0;
> +
> return tomoyo_path2_perm(TOMOYO_TYPE_LINK, &path1, &path2);
> }
>
> @@ -290,6 +314,11 @@ static int tomoyo_path_rename(const struct path *old_parent,
> struct path path1 = { .mnt = old_parent->mnt, .dentry = old_dentry };
> struct path path2 = { .mnt = new_parent->mnt, .dentry = new_dentry };
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)) ||
> + (d_is_positive(new_dentry) &&
> + IS_PRIVATE(d_backing_inode(new_dentry)))))
> + return 0;
> +
> if (flags & RENAME_EXCHANGE) {
> const int err = tomoyo_path2_perm(TOMOYO_TYPE_RENAME, &path2,
> &path1);
> @@ -360,6 +389,9 @@ static int tomoyo_file_ioctl(struct file *file, unsigned int cmd,
> */
> static int tomoyo_path_chmod(const struct path *path, umode_t mode)
> {
> + if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
> + return 0;
> +
> return tomoyo_path_number_perm(TOMOYO_TYPE_CHMOD, path,
> mode & S_IALLUGO);
> }
> @@ -377,6 +409,9 @@ static int tomoyo_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
> {
> int error = 0;
>
> + if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
> + return 0;
> +
> if (uid_valid(uid))
> error = tomoyo_path_number_perm(TOMOYO_TYPE_CHOWN, path,
> from_kuid(&init_user_ns, uid));
^ permalink raw reply
* [PATCH] lsm: move inode IS_PRIVATE checks to individual LSMs
From: danieldurning.work @ 2026-02-20 19:54 UTC (permalink / raw)
To: linux-security-module, selinux, linux-integrity
Cc: stephen.smalley.work, paul, jmorris, serge, john.johansen, zohar,
roberto.sassu, dmitry.kasatkin, mic, casey, takedakn,
penguin-kernel
From: Daniel Durning <danieldurning.work@gmail.com>
Move responsibility of bypassing S_PRIVATE inodes to the
individual LSMs. Originally the LSM framework would skip calling
the hooks on any inode that was marked S_PRIVATE. This would
prevent the LSMs from controlling access to any inodes marked as
such (ie. pidfds). We now perform the same IS_PRIVATE checks
within the LSMs instead. This is consistent with the general goal
of deferring as much as possible to the individual LSMs.
This reorganization enables the LSMs to eventually implement
checks or labeling for some specific S_PRIVATE inodes like pidfds.
Signed-off-by: Daniel Durning <danieldurning.work@gmail.com>
---
security/apparmor/lsm.c | 32 ++++++++
security/commoncap.c | 11 ++-
security/integrity/evm/evm_main.c | 33 +++++++++
security/integrity/ima/ima_appraise.c | 12 +++
security/integrity/ima/ima_main.c | 6 ++
security/landlock/fs.c | 23 ++++++
security/security.c | 101 ++------------------------
security/selinux/hooks.c | 77 ++++++++++++++++++++
security/smack/smack_lsm.c | 56 ++++++++++++++
security/tomoyo/tomoyo.c | 35 +++++++++
10 files changed, 290 insertions(+), 96 deletions(-)
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index a87cd60ed206..5b3ced11bdbc 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -323,18 +323,27 @@ static int common_perm_create(const char *op, const struct path *dir,
static int apparmor_path_unlink(const struct path *dir, struct dentry *dentry)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
+ return 0;
+
return common_perm_rm(OP_UNLINK, dir, dentry, AA_MAY_DELETE);
}
static int apparmor_path_mkdir(const struct path *dir, struct dentry *dentry,
umode_t mode)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
+ return 0;
+
return common_perm_create(OP_MKDIR, dir, dentry, AA_MAY_CREATE,
S_IFDIR);
}
static int apparmor_path_rmdir(const struct path *dir, struct dentry *dentry)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
+ return 0;
+
return common_perm_rm(OP_RMDIR, dir, dentry, AA_MAY_DELETE);
}
@@ -346,6 +355,9 @@ static int apparmor_path_mknod(const struct path *dir, struct dentry *dentry,
static int apparmor_path_truncate(const struct path *path)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
+ return 0;
+
return common_perm_cond(OP_TRUNC, path, MAY_WRITE | AA_MAY_SETATTR);
}
@@ -357,6 +369,9 @@ static int apparmor_file_truncate(struct file *file)
static int apparmor_path_symlink(const struct path *dir, struct dentry *dentry,
const char *old_name)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
+ return 0;
+
return common_perm_create(OP_SYMLINK, dir, dentry, AA_MAY_CREATE,
S_IFLNK);
}
@@ -367,6 +382,9 @@ static int apparmor_path_link(struct dentry *old_dentry, const struct path *new_
struct aa_label *label;
int error = 0;
+ if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
+ return 0;
+
if (!path_mediated_fs(old_dentry))
return 0;
@@ -386,6 +404,11 @@ static int apparmor_path_rename(const struct path *old_dir, struct dentry *old_d
struct aa_label *label;
int error = 0;
+ if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)) ||
+ (d_is_positive(new_dentry) &&
+ IS_PRIVATE(d_backing_inode(new_dentry)))))
+ return 0;
+
if (!path_mediated_fs(old_dentry))
return 0;
if ((flags & RENAME_EXCHANGE) && !path_mediated_fs(new_dentry))
@@ -444,16 +467,25 @@ static int apparmor_path_rename(const struct path *old_dir, struct dentry *old_d
static int apparmor_path_chmod(const struct path *path, umode_t mode)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
+ return 0;
+
return common_perm_cond(OP_CHMOD, path, AA_MAY_CHMOD);
}
static int apparmor_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
+ return 0;
+
return common_perm_cond(OP_CHOWN, path, AA_MAY_CHOWN);
}
static int apparmor_inode_getattr(const struct path *path)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
+ return 0;
+
return common_perm_cond(OP_GETATTR, path, AA_MAY_GETATTR);
}
diff --git a/security/commoncap.c b/security/commoncap.c
index 8a23dfab7fac..1b61d43529c2 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -88,7 +88,7 @@ static inline int cap_capable_helper(const struct cred *cred,
if (ns->level <= cred_ns->level)
return -EPERM;
- /*
+ /*
* The owner of the user namespace in the parent of the
* user namespace has all caps.
*/
@@ -432,6 +432,9 @@ int cap_inode_getsecurity(struct mnt_idmap *idmap,
struct dentry *dentry;
struct user_namespace *fs_ns;
+ if (unlikely(IS_PRIVATE(inode)))
+ return -EOPNOTSUPP;
+
if (strcmp(name, "capability") != 0)
return -EOPNOTSUPP;
@@ -1027,6 +1030,9 @@ int cap_inode_setxattr(struct dentry *dentry, const char *name,
{
struct user_namespace *user_ns = dentry->d_sb->s_user_ns;
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return 0;
+
/* Ignore non-security xattrs */
if (strncmp(name, XATTR_SECURITY_PREFIX,
XATTR_SECURITY_PREFIX_LEN) != 0)
@@ -1068,6 +1074,9 @@ int cap_inode_removexattr(struct mnt_idmap *idmap,
{
struct user_namespace *user_ns = dentry->d_sb->s_user_ns;
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return 0;
+
/* Ignore non-security xattrs */
if (strncmp(name, XATTR_SECURITY_PREFIX,
XATTR_SECURITY_PREFIX_LEN) != 0)
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index 73d500a375cb..0095712b8d75 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -590,6 +590,9 @@ static int evm_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry,
{
const struct evm_ima_xattr_data *xattr_data = xattr_value;
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return 0;
+
/* Policy permits modification of the protected xattrs even though
* there's no HMAC key loaded
*/
@@ -675,6 +678,9 @@ static int evm_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
{
enum integrity_status evm_status;
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return 0;
+
/* Policy permits modification of the protected xattrs even though
* there's no HMAC key loaded
*/
@@ -725,6 +731,9 @@ static int evm_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
static int evm_inode_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry,
const char *acl_name)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return 0;
+
return evm_inode_set_acl(idmap, dentry, acl_name, NULL);
}
@@ -807,6 +816,9 @@ static void evm_inode_post_setxattr(struct dentry *dentry,
size_t xattr_value_len,
int flags)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return;
+
if (!evm_revalidate_status(xattr_name))
return;
@@ -836,6 +848,9 @@ static void evm_inode_post_setxattr(struct dentry *dentry,
static void evm_inode_post_set_acl(struct dentry *dentry, const char *acl_name,
struct posix_acl *kacl)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return;
+
return evm_inode_post_setxattr(dentry, acl_name, NULL, 0, 0);
}
@@ -852,6 +867,9 @@ static void evm_inode_post_set_acl(struct dentry *dentry, const char *acl_name,
static void evm_inode_post_removexattr(struct dentry *dentry,
const char *xattr_name)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return;
+
if (!evm_revalidate_status(xattr_name))
return;
@@ -879,6 +897,9 @@ static inline void evm_inode_post_remove_acl(struct mnt_idmap *idmap,
struct dentry *dentry,
const char *acl_name)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return;
+
evm_inode_post_removexattr(dentry, acl_name);
}
@@ -911,6 +932,9 @@ static int evm_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
unsigned int ia_valid = attr->ia_valid;
enum integrity_status evm_status;
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return 0;
+
/* Policy permits modification of the protected attrs even though
* there's no HMAC key loaded
*/
@@ -960,6 +984,9 @@ static int evm_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
static void evm_inode_post_setattr(struct mnt_idmap *idmap,
struct dentry *dentry, int ia_valid)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return;
+
if (!evm_revalidate_status(NULL))
return;
@@ -1019,6 +1046,9 @@ int evm_inode_init_security(struct inode *inode, struct inode *dir,
bool evm_protected_xattrs = false;
int rc;
+ if (unlikely(IS_PRIVATE(inode)))
+ return 0;
+
if (!(evm_initialized & EVM_INIT_HMAC) || !xattrs)
return 0;
@@ -1094,6 +1124,9 @@ static void evm_post_path_mknod(struct mnt_idmap *idmap, struct dentry *dentry)
struct inode *inode = d_backing_inode(dentry);
struct evm_iint_cache *iint = evm_iint_inode(inode);
+ if (unlikely(IS_PRIVATE(inode)))
+ return;
+
if (!S_ISREG(inode->i_mode))
return;
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 5149ff4fd50d..d705c908132f 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -665,6 +665,9 @@ static void ima_inode_post_setattr(struct mnt_idmap *idmap,
struct ima_iint_cache *iint;
int action;
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return;
+
if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)
|| !(inode->i_opflags & IOP_XATTR))
return;
@@ -790,6 +793,9 @@ static int ima_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry,
int result;
int err;
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return 0;
+
result = ima_protect_xattr(dentry, xattr_name, xattr_value,
xattr_value_len);
if (result == 1) {
@@ -817,6 +823,9 @@ static int ima_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry,
static int ima_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
const char *acl_name, struct posix_acl *kacl)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return 0;
+
if (evm_revalidate_status(acl_name))
ima_reset_appraise_flags(d_backing_inode(dentry), -1);
@@ -842,6 +851,9 @@ static int ima_inode_removexattr(struct mnt_idmap *idmap, struct dentry *dentry,
static int ima_inode_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry,
const char *acl_name)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return 0;
+
return ima_inode_set_acl(idmap, dentry, acl_name, NULL);
}
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 5770cf691912..5ddac6c15c7f 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -794,6 +794,9 @@ static void ima_post_create_tmpfile(struct mnt_idmap *idmap,
struct ima_iint_cache *iint;
int must_appraise;
+ if (unlikely(IS_PRIVATE(inode)))
+ return;
+
if (!ima_policy_flag || !S_ISREG(inode->i_mode))
return;
@@ -826,6 +829,9 @@ static void ima_post_path_mknod(struct mnt_idmap *idmap, struct dentry *dentry)
struct inode *inode = dentry->d_inode;
int must_appraise;
+ if (unlikely(IS_PRIVATE(inode)))
+ return;
+
if (!ima_policy_flag || !S_ISREG(inode->i_mode))
return;
diff --git a/security/landlock/fs.c b/security/landlock/fs.c
index fe794875ad46..5fe15313a3f5 100644
--- a/security/landlock/fs.c
+++ b/security/landlock/fs.c
@@ -1528,6 +1528,9 @@ static int hook_path_link(struct dentry *const old_dentry,
const struct path *const new_dir,
struct dentry *const new_dentry)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
+ return 0;
+
return current_check_refer_path(old_dentry, new_dir, new_dentry, false,
false);
}
@@ -1538,6 +1541,11 @@ static int hook_path_rename(const struct path *const old_dir,
struct dentry *const new_dentry,
const unsigned int flags)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)) ||
+ (d_is_positive(new_dentry) &&
+ IS_PRIVATE(d_backing_inode(new_dentry)))))
+ return 0;
+
/* old_dir refers to old_dentry->d_parent and new_dir->mnt */
return current_check_refer_path(old_dentry, new_dir, new_dentry, true,
!!(flags & RENAME_EXCHANGE));
@@ -1546,6 +1554,9 @@ static int hook_path_rename(const struct path *const old_dir,
static int hook_path_mkdir(const struct path *const dir,
struct dentry *const dentry, const umode_t mode)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
+ return 0;
+
return current_check_access_path(dir, LANDLOCK_ACCESS_FS_MAKE_DIR);
}
@@ -1560,23 +1571,35 @@ static int hook_path_symlink(const struct path *const dir,
struct dentry *const dentry,
const char *const old_name)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
+ return 0;
+
return current_check_access_path(dir, LANDLOCK_ACCESS_FS_MAKE_SYM);
}
static int hook_path_unlink(const struct path *const dir,
struct dentry *const dentry)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
+ return 0;
+
return current_check_access_path(dir, LANDLOCK_ACCESS_FS_REMOVE_FILE);
}
static int hook_path_rmdir(const struct path *const dir,
struct dentry *const dentry)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
+ return 0;
+
return current_check_access_path(dir, LANDLOCK_ACCESS_FS_REMOVE_DIR);
}
static int hook_path_truncate(const struct path *const path)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
+ return 0;
+
return current_check_access_path(path, LANDLOCK_ACCESS_FS_TRUNCATE);
}
diff --git a/security/security.c b/security/security.c
index 31a688650601..658dbb10ea40 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1310,9 +1310,6 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
struct xattr *new_xattrs = NULL;
int ret = -EOPNOTSUPP, xattr_count = 0;
- if (unlikely(IS_PRIVATE(inode)))
- return 0;
-
if (!blob_sizes.lbs_xattr_count)
return 0;
@@ -1386,8 +1383,6 @@ int security_inode_init_security_anon(struct inode *inode,
int security_path_mknod(const struct path *dir, struct dentry *dentry,
umode_t mode, unsigned int dev)
{
- if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
- return 0;
return call_int_hook(path_mknod, dir, dentry, mode, dev);
}
EXPORT_SYMBOL(security_path_mknod);
@@ -1401,8 +1396,6 @@ EXPORT_SYMBOL(security_path_mknod);
*/
void security_path_post_mknod(struct mnt_idmap *idmap, struct dentry *dentry)
{
- if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
- return;
call_void_hook(path_post_mknod, idmap, dentry);
}
@@ -1419,8 +1412,6 @@ void security_path_post_mknod(struct mnt_idmap *idmap, struct dentry *dentry)
int security_path_mkdir(const struct path *dir, struct dentry *dentry,
umode_t mode)
{
- if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
- return 0;
return call_int_hook(path_mkdir, dir, dentry, mode);
}
EXPORT_SYMBOL(security_path_mkdir);
@@ -1436,8 +1427,6 @@ EXPORT_SYMBOL(security_path_mkdir);
*/
int security_path_rmdir(const struct path *dir, struct dentry *dentry)
{
- if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
- return 0;
return call_int_hook(path_rmdir, dir, dentry);
}
@@ -1452,8 +1441,6 @@ int security_path_rmdir(const struct path *dir, struct dentry *dentry)
*/
int security_path_unlink(const struct path *dir, struct dentry *dentry)
{
- if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
- return 0;
return call_int_hook(path_unlink, dir, dentry);
}
EXPORT_SYMBOL(security_path_unlink);
@@ -1471,8 +1458,6 @@ EXPORT_SYMBOL(security_path_unlink);
int security_path_symlink(const struct path *dir, struct dentry *dentry,
const char *old_name)
{
- if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
- return 0;
return call_int_hook(path_symlink, dir, dentry, old_name);
}
@@ -1489,8 +1474,6 @@ int security_path_symlink(const struct path *dir, struct dentry *dentry,
int security_path_link(struct dentry *old_dentry, const struct path *new_dir,
struct dentry *new_dentry)
{
- if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
- return 0;
return call_int_hook(path_link, old_dentry, new_dir, new_dentry);
}
@@ -1510,11 +1493,6 @@ int security_path_rename(const struct path *old_dir, struct dentry *old_dentry,
const struct path *new_dir, struct dentry *new_dentry,
unsigned int flags)
{
- if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)) ||
- (d_is_positive(new_dentry) &&
- IS_PRIVATE(d_backing_inode(new_dentry)))))
- return 0;
-
return call_int_hook(path_rename, old_dir, old_dentry, new_dir,
new_dentry, flags);
}
@@ -1532,8 +1510,6 @@ EXPORT_SYMBOL(security_path_rename);
*/
int security_path_truncate(const struct path *path)
{
- if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
- return 0;
return call_int_hook(path_truncate, path);
}
@@ -1550,8 +1526,6 @@ int security_path_truncate(const struct path *path)
*/
int security_path_chmod(const struct path *path, umode_t mode)
{
- if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
- return 0;
return call_int_hook(path_chmod, path, mode);
}
@@ -1567,8 +1541,6 @@ int security_path_chmod(const struct path *path, umode_t mode)
*/
int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
{
- if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
- return 0;
return call_int_hook(path_chown, path, uid, gid);
}
@@ -1599,8 +1571,6 @@ int security_path_chroot(const struct path *path)
int security_inode_create(struct inode *dir, struct dentry *dentry,
umode_t mode)
{
- if (unlikely(IS_PRIVATE(dir)))
- return 0;
return call_int_hook(inode_create, dir, dentry, mode);
}
EXPORT_SYMBOL_GPL(security_inode_create);
@@ -1615,8 +1585,6 @@ EXPORT_SYMBOL_GPL(security_inode_create);
void security_inode_post_create_tmpfile(struct mnt_idmap *idmap,
struct inode *inode)
{
- if (unlikely(IS_PRIVATE(inode)))
- return;
call_void_hook(inode_post_create_tmpfile, idmap, inode);
}
@@ -1633,8 +1601,6 @@ void security_inode_post_create_tmpfile(struct mnt_idmap *idmap,
int security_inode_link(struct dentry *old_dentry, struct inode *dir,
struct dentry *new_dentry)
{
- if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
- return 0;
return call_int_hook(inode_link, old_dentry, dir, new_dentry);
}
@@ -1649,8 +1615,6 @@ int security_inode_link(struct dentry *old_dentry, struct inode *dir,
*/
int security_inode_unlink(struct inode *dir, struct dentry *dentry)
{
- if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
- return 0;
return call_int_hook(inode_unlink, dir, dentry);
}
@@ -1667,8 +1631,6 @@ int security_inode_unlink(struct inode *dir, struct dentry *dentry)
int security_inode_symlink(struct inode *dir, struct dentry *dentry,
const char *old_name)
{
- if (unlikely(IS_PRIVATE(dir)))
- return 0;
return call_int_hook(inode_symlink, dir, dentry, old_name);
}
@@ -1685,8 +1647,6 @@ int security_inode_symlink(struct inode *dir, struct dentry *dentry,
*/
int security_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
{
- if (unlikely(IS_PRIVATE(dir)))
- return 0;
return call_int_hook(inode_mkdir, dir, dentry, mode);
}
EXPORT_SYMBOL_GPL(security_inode_mkdir);
@@ -1702,8 +1662,6 @@ EXPORT_SYMBOL_GPL(security_inode_mkdir);
*/
int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
{
- if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
- return 0;
return call_int_hook(inode_rmdir, dir, dentry);
}
@@ -1724,8 +1682,6 @@ int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
int security_inode_mknod(struct inode *dir, struct dentry *dentry,
umode_t mode, dev_t dev)
{
- if (unlikely(IS_PRIVATE(dir)))
- return 0;
return call_int_hook(inode_mknod, dir, dentry, mode, dev);
}
@@ -1745,11 +1701,6 @@ int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry,
unsigned int flags)
{
- if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)) ||
- (d_is_positive(new_dentry) &&
- IS_PRIVATE(d_backing_inode(new_dentry)))))
- return 0;
-
if (flags & RENAME_EXCHANGE) {
int err = call_int_hook(inode_rename, new_dir, new_dentry,
old_dir, old_dentry);
@@ -1771,8 +1722,6 @@ int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
*/
int security_inode_readlink(struct dentry *dentry)
{
- if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
- return 0;
return call_int_hook(inode_readlink, dentry);
}
@@ -1790,8 +1739,6 @@ int security_inode_readlink(struct dentry *dentry)
int security_inode_follow_link(struct dentry *dentry, struct inode *inode,
bool rcu)
{
- if (unlikely(IS_PRIVATE(inode)))
- return 0;
return call_int_hook(inode_follow_link, dentry, inode, rcu);
}
@@ -1811,8 +1758,6 @@ int security_inode_follow_link(struct dentry *dentry, struct inode *inode,
*/
int security_inode_permission(struct inode *inode, int mask)
{
- if (unlikely(IS_PRIVATE(inode)))
- return 0;
return call_int_hook(inode_permission, inode, mask);
}
@@ -1832,8 +1777,6 @@ int security_inode_permission(struct inode *inode, int mask)
int security_inode_setattr(struct mnt_idmap *idmap,
struct dentry *dentry, struct iattr *attr)
{
- if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
- return 0;
return call_int_hook(inode_setattr, idmap, dentry, attr);
}
EXPORT_SYMBOL_GPL(security_inode_setattr);
@@ -1849,8 +1792,6 @@ EXPORT_SYMBOL_GPL(security_inode_setattr);
void security_inode_post_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
int ia_valid)
{
- if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
- return;
call_void_hook(inode_post_setattr, idmap, dentry, ia_valid);
}
@@ -1864,8 +1805,6 @@ void security_inode_post_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
*/
int security_inode_getattr(const struct path *path)
{
- if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
- return 0;
return call_int_hook(inode_getattr, path);
}
@@ -1901,11 +1840,11 @@ int security_inode_setxattr(struct mnt_idmap *idmap,
{
int rc;
- if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
- return 0;
-
/* enforce the capability checks at the lsm layer, if needed */
if (!call_int_hook(inode_xattr_skipcap, name)) {
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return 0;
+
rc = cap_inode_setxattr(dentry, name, value, size, flags);
if (rc)
return rc;
@@ -1931,8 +1870,6 @@ int security_inode_set_acl(struct mnt_idmap *idmap,
struct dentry *dentry, const char *acl_name,
struct posix_acl *kacl)
{
- if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
- return 0;
return call_int_hook(inode_set_acl, idmap, dentry, acl_name, kacl);
}
@@ -1948,8 +1885,6 @@ int security_inode_set_acl(struct mnt_idmap *idmap,
void security_inode_post_set_acl(struct dentry *dentry, const char *acl_name,
struct posix_acl *kacl)
{
- if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
- return;
call_void_hook(inode_post_set_acl, dentry, acl_name, kacl);
}
@@ -1967,8 +1902,6 @@ void security_inode_post_set_acl(struct dentry *dentry, const char *acl_name,
int security_inode_get_acl(struct mnt_idmap *idmap,
struct dentry *dentry, const char *acl_name)
{
- if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
- return 0;
return call_int_hook(inode_get_acl, idmap, dentry, acl_name);
}
@@ -1986,8 +1919,6 @@ int security_inode_get_acl(struct mnt_idmap *idmap,
int security_inode_remove_acl(struct mnt_idmap *idmap,
struct dentry *dentry, const char *acl_name)
{
- if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
- return 0;
return call_int_hook(inode_remove_acl, idmap, dentry, acl_name);
}
@@ -2003,8 +1934,6 @@ int security_inode_remove_acl(struct mnt_idmap *idmap,
void security_inode_post_remove_acl(struct mnt_idmap *idmap,
struct dentry *dentry, const char *acl_name)
{
- if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
- return;
call_void_hook(inode_post_remove_acl, idmap, dentry, acl_name);
}
@@ -2021,8 +1950,6 @@ void security_inode_post_remove_acl(struct mnt_idmap *idmap,
void security_inode_post_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
- if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
- return;
call_void_hook(inode_post_setxattr, dentry, name, value, size, flags);
}
@@ -2038,8 +1965,6 @@ void security_inode_post_setxattr(struct dentry *dentry, const char *name,
*/
int security_inode_getxattr(struct dentry *dentry, const char *name)
{
- if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
- return 0;
return call_int_hook(inode_getxattr, dentry, name);
}
@@ -2054,8 +1979,6 @@ int security_inode_getxattr(struct dentry *dentry, const char *name)
*/
int security_inode_listxattr(struct dentry *dentry)
{
- if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
- return 0;
return call_int_hook(inode_listxattr, dentry);
}
@@ -2087,11 +2010,11 @@ int security_inode_removexattr(struct mnt_idmap *idmap,
{
int rc;
- if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
- return 0;
-
/* enforce the capability checks at the lsm layer, if needed */
if (!call_int_hook(inode_xattr_skipcap, name)) {
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return 0;
+
rc = cap_inode_removexattr(idmap, dentry, name);
if (rc)
return rc;
@@ -2109,8 +2032,6 @@ int security_inode_removexattr(struct mnt_idmap *idmap,
*/
void security_inode_post_removexattr(struct dentry *dentry, const char *name)
{
- if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
- return;
call_void_hook(inode_post_removexattr, dentry, name);
}
@@ -2197,9 +2118,6 @@ int security_inode_getsecurity(struct mnt_idmap *idmap,
struct inode *inode, const char *name,
void **buffer, bool alloc)
{
- if (unlikely(IS_PRIVATE(inode)))
- return LSM_RET_DEFAULT(inode_getsecurity);
-
return call_int_hook(inode_getsecurity, idmap, inode, name, buffer,
alloc);
}
@@ -2222,9 +2140,6 @@ int security_inode_getsecurity(struct mnt_idmap *idmap,
int security_inode_setsecurity(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
{
- if (unlikely(IS_PRIVATE(inode)))
- return LSM_RET_DEFAULT(inode_setsecurity);
-
return call_int_hook(inode_setsecurity, inode, name, value, size,
flags);
}
@@ -2245,8 +2160,6 @@ int security_inode_setsecurity(struct inode *inode, const char *name,
int security_inode_listsecurity(struct inode *inode,
char *buffer, size_t buffer_size)
{
- if (unlikely(IS_PRIVATE(inode)))
- return 0;
return call_int_hook(inode_listsecurity, inode, buffer, buffer_size);
}
EXPORT_SYMBOL(security_inode_listsecurity);
@@ -3596,8 +3509,6 @@ int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops,
*/
void security_d_instantiate(struct dentry *dentry, struct inode *inode)
{
- if (unlikely(inode && IS_PRIVATE(inode)))
- return;
call_void_hook(d_instantiate, dentry, inode);
}
EXPORT_SYMBOL(security_d_instantiate);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index feda34b18d83..e17d776fb159 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2948,6 +2948,9 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
int rc;
char *context;
+ if (unlikely(IS_PRIVATE(inode)))
+ return 0;
+
sbsec = selinux_superblock(dir->i_sb);
newsid = crsec->create_sid;
@@ -3049,42 +3052,68 @@ static int selinux_inode_init_security_anon(struct inode *inode,
static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
{
+ if (unlikely(IS_PRIVATE(dir)))
+ return 0;
+
return may_create(dir, dentry, SECCLASS_FILE);
}
static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
+ return 0;
+
return may_link(dir, old_dentry, MAY_LINK);
}
static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return 0;
+
return may_link(dir, dentry, MAY_UNLINK);
}
static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
{
+ if (unlikely(IS_PRIVATE(dir)))
+ return 0;
+
return may_create(dir, dentry, SECCLASS_LNK_FILE);
}
static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
{
+ if (unlikely(IS_PRIVATE(dir)))
+ return 0;
+
return may_create(dir, dentry, SECCLASS_DIR);
}
static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return 0;
+
return may_link(dir, dentry, MAY_RMDIR);
}
static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
{
+ if (unlikely(IS_PRIVATE(dir)))
+ return 0;
+
return may_create(dir, dentry, inode_mode_to_security_class(mode));
}
static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
struct inode *new_inode, struct dentry *new_dentry)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)) ||
+ (d_is_positive(new_dentry) &&
+ IS_PRIVATE(d_backing_inode(new_dentry)))))
+ return 0;
+
return may_rename(old_inode, old_dentry, new_inode, new_dentry);
}
@@ -3092,6 +3121,9 @@ static int selinux_inode_readlink(struct dentry *dentry)
{
const struct cred *cred = current_cred();
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return 0;
+
return dentry_has_perm(cred, dentry, FILE__READ);
}
@@ -3102,6 +3134,9 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode,
struct inode_security_struct *isec;
u32 sid = current_sid();
+ if (unlikely(IS_PRIVATE(inode)))
+ return 0;
+
ad.type = LSM_AUDIT_DATA_DENTRY;
ad.u.dentry = dentry;
isec = inode_security_rcu(inode, rcu);
@@ -3230,6 +3265,9 @@ static int selinux_inode_permission(struct inode *inode, int requested)
int rc, rc2;
u32 audited, denied;
+ if (unlikely(IS_PRIVATE(inode)))
+ return 0;
+
mask = requested & (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
/* No permission to check. Existence test. */
@@ -3283,6 +3321,9 @@ static int selinux_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
unsigned int ia_valid = iattr->ia_valid;
u32 av = FILE__WRITE;
+ if (unlikely(IS_PRIVATE(inode)))
+ return 0;
+
/* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
if (ia_valid & ATTR_FORCE) {
ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
@@ -3308,6 +3349,9 @@ static int selinux_inode_getattr(const struct path *path)
{
struct task_security_struct *tsec;
+ if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
+ return 0;
+
tsec = selinux_task(current);
if (task_avdcache_permnoaudit(tsec, current_sid()))
@@ -3356,6 +3400,9 @@ static int selinux_inode_setxattr(struct mnt_idmap *idmap,
u32 newsid, sid = current_sid();
int rc = 0;
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return 0;
+
/* if not a selinux xattr, only check the ordinary setattr perm */
if (strcmp(name, XATTR_NAME_SELINUX))
return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
@@ -3435,18 +3482,27 @@ static int selinux_inode_set_acl(struct mnt_idmap *idmap,
struct dentry *dentry, const char *acl_name,
struct posix_acl *kacl)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return 0;
+
return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
}
static int selinux_inode_get_acl(struct mnt_idmap *idmap,
struct dentry *dentry, const char *acl_name)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return 0;
+
return dentry_has_perm(current_cred(), dentry, FILE__GETATTR);
}
static int selinux_inode_remove_acl(struct mnt_idmap *idmap,
struct dentry *dentry, const char *acl_name)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return 0;
+
return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
}
@@ -3459,6 +3515,9 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
u32 newsid;
int rc;
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return;
+
if (strcmp(name, XATTR_NAME_SELINUX)) {
/* Not an attribute we recognize, so nothing to do. */
return;
@@ -3494,6 +3553,9 @@ static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
{
const struct cred *cred = current_cred();
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return 0;
+
return dentry_has_perm(cred, dentry, FILE__GETATTR);
}
@@ -3501,6 +3563,9 @@ static int selinux_inode_listxattr(struct dentry *dentry)
{
const struct cred *cred = current_cred();
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return 0;
+
return dentry_has_perm(cred, dentry, FILE__GETATTR);
}
@@ -3593,6 +3658,9 @@ static int selinux_inode_getsecurity(struct mnt_idmap *idmap,
char *context = NULL;
struct inode_security_struct *isec;
+ if (unlikely(IS_PRIVATE(inode)))
+ return -EOPNOTSUPP;
+
/*
* If we're not initialized yet, then we can't validate contexts, so
* just let vfs_getxattr fall back to using the on-disk xattr.
@@ -3637,6 +3705,9 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name,
u32 newsid;
int rc;
+ if (unlikely(IS_PRIVATE(inode)))
+ return -EOPNOTSUPP;
+
if (strcmp(name, XATTR_SELINUX_SUFFIX))
return -EOPNOTSUPP;
@@ -3664,6 +3735,9 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t
{
const int len = sizeof(XATTR_NAME_SELINUX);
+ if (unlikely(IS_PRIVATE(inode)))
+ return 0;
+
if (!selinux_initialized())
return 0;
@@ -6546,6 +6620,9 @@ static void selinux_ipc_getlsmprop(struct kern_ipc_perm *ipcp,
static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
{
+ if (unlikely(inode && IS_PRIVATE(inode)))
+ return;
+
if (inode)
inode_doinit_with_dentry(inode, dentry);
}
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index a0bd4919a9d9..8f432348dfbd 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -1020,6 +1020,9 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
bool trans_cred;
bool trans_rule;
+ if (unlikely(IS_PRIVATE(inode)))
+ return 0;
+
/*
* UNIX domain sockets use lower level socket data. Let
* UDS inode have fixed * label to keep smack_inode_permission() calm
@@ -1093,6 +1096,9 @@ static int smack_inode_link(struct dentry *old_dentry, struct inode *dir,
struct smk_audit_info ad;
int rc;
+ if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
+ return 0;
+
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
smk_ad_setfield_u_fs_path_dentry(&ad, old_dentry);
@@ -1124,6 +1130,9 @@ static int smack_inode_unlink(struct inode *dir, struct dentry *dentry)
struct smk_audit_info ad;
int rc;
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return 0;
+
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
@@ -1157,6 +1166,9 @@ static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry)
struct smk_audit_info ad;
int rc;
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return 0;
+
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
@@ -1199,6 +1211,11 @@ static int smack_inode_rename(struct inode *old_inode,
struct smack_known *isp;
struct smk_audit_info ad;
+ if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)) ||
+ (d_is_positive(new_dentry) &&
+ IS_PRIVATE(d_backing_inode(new_dentry)))))
+ return 0;
+
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
smk_ad_setfield_u_fs_path_dentry(&ad, old_dentry);
@@ -1231,6 +1248,9 @@ static int smack_inode_permission(struct inode *inode, int mask)
int no_block = mask & MAY_NOT_BLOCK;
int rc;
+ if (unlikely(IS_PRIVATE(inode)))
+ return 0;
+
mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
/*
* No permission to check. Existence test. Yup, it's there.
@@ -1267,6 +1287,9 @@ static int smack_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
struct smk_audit_info ad;
int rc;
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return 0;
+
/*
* Need to allow for clearing the setuid bit.
*/
@@ -1292,6 +1315,9 @@ static int smack_inode_getattr(const struct path *path)
struct inode *inode = d_backing_inode(path->dentry);
int rc;
+ if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
+ return 0;
+
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
smk_ad_setfield_u_fs_path(&ad, *path);
rc = smk_curacc(smk_of_inode(inode), MAY_READ, &ad);
@@ -1351,6 +1377,9 @@ static int smack_inode_setxattr(struct mnt_idmap *idmap,
int rc = 0;
umode_t const i_mode = d_backing_inode(dentry)->i_mode;
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return 0;
+
/*
* Check label validity here so import won't fail in post_setxattr
*/
@@ -1421,6 +1450,9 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
struct smack_known *skp;
struct inode_smack *isp = smack_inode(d_backing_inode(dentry));
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return;
+
if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) {
isp->smk_flags |= SMK_INODE_TRANSMUTE;
return;
@@ -1455,6 +1487,9 @@ static int smack_inode_getxattr(struct dentry *dentry, const char *name)
struct smk_audit_info ad;
int rc;
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return 0;
+
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
@@ -1541,6 +1576,9 @@ static int smack_inode_set_acl(struct mnt_idmap *idmap,
struct smk_audit_info ad;
int rc;
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return 0;
+
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
@@ -1563,6 +1601,9 @@ static int smack_inode_get_acl(struct mnt_idmap *idmap,
struct smk_audit_info ad;
int rc;
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return 0;
+
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
@@ -1585,6 +1626,9 @@ static int smack_inode_remove_acl(struct mnt_idmap *idmap,
struct smk_audit_info ad;
int rc;
+ if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+ return 0;
+
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
@@ -1616,6 +1660,9 @@ static int smack_inode_getsecurity(struct mnt_idmap *idmap,
size_t label_len;
char *label = NULL;
+ if (unlikely(IS_PRIVATE(inode)))
+ return -EOPNOTSUPP;
+
if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) {
isp = smk_of_inode(inode);
} else if (strcmp(name, XATTR_SMACK_TRANSMUTE) == 0) {
@@ -1672,6 +1719,9 @@ static int smack_inode_listsecurity(struct inode *inode, char *buffer,
{
int len = sizeof(XATTR_NAME_SMACK);
+ if (unlikely(IS_PRIVATE(inode)))
+ return 0;
+
if (buffer != NULL && len <= buffer_size)
memcpy(buffer, XATTR_NAME_SMACK, len);
@@ -2918,6 +2968,9 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
struct socket *sock;
int rc = 0;
+ if (unlikely(IS_PRIVATE(inode)))
+ return -EOPNOTSUPP;
+
if (value == NULL || size > SMK_LONGLABEL || size == 0)
return -EINVAL;
@@ -3517,6 +3570,9 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
if (inode == NULL)
return;
+ if (unlikely(IS_PRIVATE(inode)))
+ return;
+
isp = smack_inode(inode);
/*
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index c66e02ed8ee3..98eb8cd67f78 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -120,6 +120,9 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm)
*/
static int tomoyo_inode_getattr(const struct path *path)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
+ return 0;
+
return tomoyo_path_perm(TOMOYO_TYPE_GETATTR, path, NULL);
}
@@ -132,6 +135,9 @@ static int tomoyo_inode_getattr(const struct path *path)
*/
static int tomoyo_path_truncate(const struct path *path)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
+ return 0;
+
return tomoyo_path_perm(TOMOYO_TYPE_TRUNCATE, path, NULL);
}
@@ -159,6 +165,9 @@ static int tomoyo_path_unlink(const struct path *parent, struct dentry *dentry)
{
struct path path = { .mnt = parent->mnt, .dentry = dentry };
+ if (unlikely(IS_PRIVATE(d_backing_inode(parent->dentry))))
+ return 0;
+
return tomoyo_path_perm(TOMOYO_TYPE_UNLINK, &path, NULL);
}
@@ -176,6 +185,9 @@ static int tomoyo_path_mkdir(const struct path *parent, struct dentry *dentry,
{
struct path path = { .mnt = parent->mnt, .dentry = dentry };
+ if (unlikely(IS_PRIVATE(d_backing_inode(parent->dentry))))
+ return 0;
+
return tomoyo_path_number_perm(TOMOYO_TYPE_MKDIR, &path,
mode & S_IALLUGO);
}
@@ -192,6 +204,9 @@ static int tomoyo_path_rmdir(const struct path *parent, struct dentry *dentry)
{
struct path path = { .mnt = parent->mnt, .dentry = dentry };
+ if (unlikely(IS_PRIVATE(d_backing_inode(parent->dentry))))
+ return 0;
+
return tomoyo_path_perm(TOMOYO_TYPE_RMDIR, &path, NULL);
}
@@ -209,6 +224,9 @@ static int tomoyo_path_symlink(const struct path *parent, struct dentry *dentry,
{
struct path path = { .mnt = parent->mnt, .dentry = dentry };
+ if (unlikely(IS_PRIVATE(d_backing_inode(parent->dentry))))
+ return 0;
+
return tomoyo_path_perm(TOMOYO_TYPE_SYMLINK, &path, old_name);
}
@@ -229,6 +247,9 @@ static int tomoyo_path_mknod(const struct path *parent, struct dentry *dentry,
int type = TOMOYO_TYPE_CREATE;
const unsigned int perm = mode & S_IALLUGO;
+ if (unlikely(IS_PRIVATE(d_backing_inode(parent->dentry))))
+ return 0;
+
switch (mode & S_IFMT) {
case S_IFCHR:
type = TOMOYO_TYPE_MKCHAR;
@@ -267,6 +288,9 @@ static int tomoyo_path_link(struct dentry *old_dentry, const struct path *new_di
struct path path1 = { .mnt = new_dir->mnt, .dentry = old_dentry };
struct path path2 = { .mnt = new_dir->mnt, .dentry = new_dentry };
+ if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
+ return 0;
+
return tomoyo_path2_perm(TOMOYO_TYPE_LINK, &path1, &path2);
}
@@ -290,6 +314,11 @@ static int tomoyo_path_rename(const struct path *old_parent,
struct path path1 = { .mnt = old_parent->mnt, .dentry = old_dentry };
struct path path2 = { .mnt = new_parent->mnt, .dentry = new_dentry };
+ if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)) ||
+ (d_is_positive(new_dentry) &&
+ IS_PRIVATE(d_backing_inode(new_dentry)))))
+ return 0;
+
if (flags & RENAME_EXCHANGE) {
const int err = tomoyo_path2_perm(TOMOYO_TYPE_RENAME, &path2,
&path1);
@@ -360,6 +389,9 @@ static int tomoyo_file_ioctl(struct file *file, unsigned int cmd,
*/
static int tomoyo_path_chmod(const struct path *path, umode_t mode)
{
+ if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
+ return 0;
+
return tomoyo_path_number_perm(TOMOYO_TYPE_CHMOD, path,
mode & S_IALLUGO);
}
@@ -377,6 +409,9 @@ static int tomoyo_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
{
int error = 0;
+ if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
+ return 0;
+
if (uid_valid(uid))
error = tomoyo_path_number_perm(TOMOYO_TYPE_CHOWN, path,
from_kuid(&init_user_ns, uid));
--
2.52.0
^ permalink raw reply related
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