public inbox for audit@vger.kernel.org
 help / color / mirror / Atom feed
From: Fan Wu <wufan@linux.microsoft.com>
To: Paul Moore <paul@paul-moore.com>,
	corbet@lwn.net, zohar@linux.ibm.com, jmorris@namei.org,
	serge@hallyn.com, tytso@mit.edu, ebiggers@kernel.org,
	axboe@kernel.dk, agk@redhat.com, snitzer@kernel.org,
	eparis@redhat.com
Cc: linux-doc@vger.kernel.org, linux-integrity@vger.kernel.org,
	linux-security-module@vger.kernel.org,
	linux-fscrypt@vger.kernel.org, linux-block@vger.kernel.org,
	dm-devel@lists.linux.dev, audit@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	Deven Bowers <deven.desai@linux.microsoft.com>
Subject: Re: [PATCH RFC v12 6/20] ipe: introduce 'boot_verified' as a trust provider
Date: Mon, 5 Feb 2024 14:39:39 -0800	[thread overview]
Message-ID: <ef167e7a-9943-4879-beb6-5e473f9f0f78@linux.microsoft.com> (raw)
In-Reply-To: <44f88fef412127a795f4219ad9f9c6b8@paul-moore.com>



On 2/3/2024 2:25 PM, Paul Moore wrote:
> On Jan 30, 2024 Fan Wu <wufan@linux.microsoft.com> wrote:
>>
>> IPE is designed to provide system level trust guarantees, this usually
>> implies that trust starts from bootup with a hardware root of trust,
>> which validates the bootloader. After this, the bootloader verifies
>> the kernel and the initramfs.
>>
>> As there's no currently supported integrity method for initramfs, and
>> it's typically already verified by the bootloader. This patch introduces
>> a new IPE property `boot_verified` which allows author of IPE policy to
>> indicate trust for files from initramfs.
>>
>> The implementation of this feature utilizes the newly added
>> `unpack_initramfs` hook. This hook marks the superblock of the rootfs
>> after the initramfs has been unpacked into it.
>>
>> Since the rootfs is never unmounted during system operation, it is
>> advised to switch to a different policy that doesn't rely on the
>> `boot_verified` property after the real rootfs is in charge.
>> This ensures that the trust policies remain relevant and effective
>> throughout the system's operation.
> 
> To be clear, most (all?) init systems cleanup the initial rootfs and
> mount another filesystem on top of it during the boot process, correct?
> That should probably be mentioned in the commit description, perhaps
> with references to the pivot_root(2) and switch_root(8) docs.
> 
> While I don't disagree with your recommendation above, I do believe
> it is unnecessarily scary sounding.
> 
I agree more details/references will be helpful. I will rewrite the 
commit message.

>> Signed-off-by: Deven Bowers <deven.desai@linux.microsoft.com>
>> Signed-off-by: Fan Wu <wufan@linux.microsoft.com>
>> ---
>> v2:
>>    +No Changes
>>
>> v3:
>>    + Remove useless caching system
>>    + Move ipe_load_properties to this match
>>    + Minor changes from checkpatch --strict warnings
>>
>> v4:
>>    + Remove comments from headers that was missed previously.
>>    + Grammatical corrections.
>>
>> v5:
>>    + No significant changes
>>
>> v6:
>>    + No changes
>>
>> v7:
>>    + Reword and refactor patch 04/12 to [09/16], based on changes in
>> the underlying system.
>>    + Add common audit function for boolean values
>>    + Use common audit function as implementation.
>>
>> v8:
>>    + No changes
>>
>> v9:
>>    + No changes
>>
>> v10:
>>    + Replace struct file with struct super_block
>>
>> v11:
>>    + Fix code style issues
>>
>> v12:
>>    + Switch to use unpack_initramfs hook and security blob
>> ---
>>   security/ipe/eval.c          | 68 +++++++++++++++++++++++++++++++++++-
>>   security/ipe/eval.h          |  9 +++++
>>   security/ipe/hooks.c         |  8 +++++
>>   security/ipe/hooks.h         |  4 +++
>>   security/ipe/ipe.c           | 14 ++++++++
>>   security/ipe/ipe.h           |  3 ++
>>   security/ipe/policy.h        |  2 ++
>>   security/ipe/policy_parser.c | 37 +++++++++++++++++++-
>>   8 files changed, 143 insertions(+), 2 deletions(-)
> 
> More comments below, but one thing I wanted to mention at the top is
> that I believe there is too much conditional compilation depending on
> the state of CONFIG_BLK_DEV_INITRD.  While there is noting wrong about
> this from a correctness perspective, I believe the reality is that
> the vast majority of systems these days are built with this enabled,
> and having all these pre-processor checks adds to the complexity of
> the code.  Additional comments about this below ...
> 
Yes, removing the dependency on the switch can significantly simplify 
the code. I will refactor the code accordingly.

>> diff --git a/security/ipe/eval.c b/security/ipe/eval.c
>> index 4f425afffcad..546bbc52a071 100644
>> --- a/security/ipe/eval.c
>> +++ b/security/ipe/eval.c
>> @@ -16,6 +16,24 @@
>>   
>>   struct ipe_policy __rcu *ipe_active_policy;
>>   
>> +#define FILE_SUPERBLOCK(f) ((f)->f_path.mnt->mnt_sb)
>> +
>> +#ifdef CONFIG_BLK_DEV_INITRD
>> +/**
>> + * build_ipe_sb_ctx - Build from_initramfs field of an evaluation context.
>> + * @ctx: Supplies a pointer to the context to be populated.
>> + * @file: Supplies the file struct of the file triggered IPE event.
>> + */
>> +static void build_ipe_sb_ctx(struct ipe_eval_ctx *ctx, const struct file *const file)
>> +{
>> +	ctx->from_initramfs = ipe_sb(FILE_SUPERBLOCK(file))->is_initramfs;
>> +}
>> +#else
>> +static void build_ipe_sb_ctx(struct ipe_eval_ctx *ctx, const struct file *const file)
>> +{
>> +}
>> +#endif /* CONFIG_BLK_DEV_INITRD */
> 
> If you move the @file NULL check into build_ipe_sb_ctx() you can save
> a comparison in the !CONFIG_BLK_DEV_INITRD case:
> 
> #ifdef CONFIG_BLK_DEV_INITRD
> void build(...)
> {
>    if (file)
>      ctx->initramfs = ipe_sb(file);
>    else
>      ctx->initramfs = false;
> }
> #else
> void build(...)
> {
>    ctx->initramfs = false;
> }
> #endif
> 
I agree this can save a comparision if we only have sb_ctx. But there 
are bdev_ctx(for dm-verity) and inode_ctx(for fsverity) will be 
introduced later. So I still think the NULL check should be done at the 
current place. (also the save won't exist if we are always enabling the 
initramfs boolean)

> NOTE: see my comment below about always enabling the initramfs boolean
> in @ipe_eval_ctx and other structs.
> 
>>   /**
>>    * build_eval_ctx - Build an evaluation context.
>>    * @ctx: Supplies a pointer to the context to be populated.
>> @@ -28,8 +46,49 @@ void build_eval_ctx(struct ipe_eval_ctx *ctx,
>>   {
>>   	ctx->file = file;
>>   	ctx->op = op;
>> +
>> +	if (file)
>> +		build_ipe_sb_ctx(ctx, file);
>> +}
> 
> See my comment above regarding the @file NULL check.
> 
>> +#ifdef CONFIG_BLK_DEV_INITRD
>> +/**
>> + * evaluate_boot_verified_true - Evaluate @ctx for the boot verified property.
>> + * @ctx: Supplies a pointer to the context being evaluated.
>> + *
>> + * Return:
>> + * * true	- The current @ctx match the @p
>> + * * false	- The current @ctx doesn't match the @p
>> + */
>> +static bool evaluate_boot_verified_true(const struct ipe_eval_ctx *const ctx)
>> +{
>> +	return ctx->from_initramfs;
>>   }
>>   
>> +/**
>> + * evaluate_boot_verified_false - Evaluate @ctx for the boot verified property.
>> + * @ctx: Supplies a pointer to the context being evaluated.
>> + *
>> + * Return:
>> + * * true	- The current @ctx match the @p
>> + * * false	- The current @ctx doesn't match the @p
>> + */
>> +static bool evaluate_boot_verified_false(const struct ipe_eval_ctx *const ctx)
>> +{
>> +	return !evaluate_boot_verified_true(ctx);
>> +}
>> +#else
>> +static bool evaluate_boot_verified_true(const struct ipe_eval_ctx *const ctx)
>> +{
>> +	return false;
>> +}
>> +
>> +static bool evaluate_boot_verified_false(const struct ipe_eval_ctx *const ctx)
>> +{
>> +	return false;
>> +}
>> +#endif /* CONFIG_BLK_DEV_INITRD */
> 
> That is a lot of lines of code just to check a single boolean value.
> I understand the layers of abstraction, but this looks a bit excessive
> to me.  Assuming you agree with the other comments in this email
> regarding always including an initramfs flag in @ipe_eval_ctx, I think
> you could reduce all of the above into one single line function as shown
> below, and just negate it as needed in evaluate_property().
> 
> static bool evaluate_boot_verified(ctx)
> {
>    return ctx->initramfs;
> }
> 
>>   /**
>>    * evaluate_property - Analyze @ctx against a property.
>>    * @ctx: Supplies a pointer to the context to be evaluated.
>> @@ -42,7 +101,14 @@ void build_eval_ctx(struct ipe_eval_ctx *ctx,
>>   static bool evaluate_property(const struct ipe_eval_ctx *const ctx,
>>   			      struct ipe_prop *p)
>>   {
>> -	return false;
>> +	switch (p->type) {
>> +	case IPE_PROP_BOOT_VERIFIED_FALSE:
>> +		return evaluate_boot_verified_false(ctx);
>> +	case IPE_PROP_BOOT_VERIFIED_TRUE:
>> +		return evaluate_boot_verified_true(ctx);
> 
> According to my comment above:
> 
>    case IPE_PROP_BOOT_VERIFIED_FALSE:
>      return !evaludate_boot_verified(ctx);
>    case IPE_PROP_BOOT_VERIFIED_TRUE:
>      return evaludate_boot_verified(ctx);
> 
This looks better, I will update this part accordingly.

>> +	default:
>> +		return false;
>> +	}
>>   }
>>   
>>   /**
>> diff --git a/security/ipe/eval.h b/security/ipe/eval.h
>> index cfdf3c8dfe8a..7d79fdb63bbf 100644
>> --- a/security/ipe/eval.h
>> +++ b/security/ipe/eval.h
>> @@ -15,10 +15,19 @@
>>   
>>   extern struct ipe_policy __rcu *ipe_active_policy;
>>   
>> +#ifdef CONFIG_BLK_DEV_INITRD
>> +struct ipe_sb {
>> +	bool is_initramfs;
>> +}
> 
> You've already got a function named "ipe_sb()", I would suggest saving
> us all some headaches by renaming the above to "ipe_superblock" or
> something similar.  The point is to not have a struct and a function
> with the same name.
> 
> I also think you can shorten the field name to "initramfs", it's
> defined as a boolean flag so I'm not sure the "is_" prefix lends any
> useful hints but does make for longer lines, more typing, etc.
>
>> +#endif /* CONFIG_BLK_DEV_INITRD */
>> +
>>   struct ipe_eval_ctx {
>>   	enum ipe_op_type op;
>>   
>>   	const struct file *file;
>> +#ifdef CONFIG_BLK_DEV_INITRD
>> +	bool from_initramfs;
>> +#endif /* CONFIG_BLK_DEV_INITRD */
>>   };
> 
> I suppose I understand the desire to make the @from_initramfs
> conditional to potentially reduce the size of @ipe_eval_ctx when it is
> not needed, however, I believe in the vast majority of systems we are
> going to see CONFIG_BLK_DEV_INITRD enabled so I believe this adds a lot
> extra code noise for little practical benefit.
> 
> Similarly to ipe_sb::is_initramfs, I think you can rename this field to
> "initramfs" and we would all be better for the change.
> 

Sure, I can change the name and remove the KCONFIG dependency.
>>   void build_eval_ctx(struct ipe_eval_ctx *ctx, const struct file *file, enum ipe_op_type op);
>> diff --git a/security/ipe/hooks.c b/security/ipe/hooks.c
>> index 3aec88c074e1..8ee105bf7bad 100644
>> --- a/security/ipe/hooks.c
>> +++ b/security/ipe/hooks.c
>> @@ -4,6 +4,7 @@
>>    */
>>   
>>   #include <linux/fs.h>
>> +#include <linux/fs_struct.h>
>>   #include <linux/types.h>
>>   #include <linux/binfmts.h>
>>   #include <linux/mman.h>
>> @@ -181,3 +182,10 @@ int ipe_kernel_load_data(enum kernel_load_data_id id, bool contents)
>>   	build_eval_ctx(&ctx, NULL, op);
>>   	return ipe_evaluate_event(&ctx);
>>   }
>> +
>> +#ifdef CONFIG_BLK_DEV_INITRD
>> +void ipe_unpack_initramfs(void)
>> +{
>> +	ipe_sb(current->fs->root.mnt->mnt_sb)->is_initramfs = true;
>> +}
>> +#endif /* CONFIG_BLK_DEV_INITRD */
>> diff --git a/security/ipe/hooks.h b/security/ipe/hooks.h
>> index 23205452f758..3b1bb0a6e89c 100644
>> --- a/security/ipe/hooks.h
>> +++ b/security/ipe/hooks.h
>> @@ -22,4 +22,8 @@ int ipe_kernel_read_file(struct file *file, enum kernel_read_file_id id,
>>   
>>   int ipe_kernel_load_data(enum kernel_load_data_id id, bool contents);
>>   
>> +#ifdef CONFIG_BLK_DEV_INITRD
>> +void ipe_unpack_initramfs(void);
>> +#endif /* CONFIG_BLK_DEV_INITRD */
>> +
>>   #endif /* _IPE_HOOKS_H */
>> diff --git a/security/ipe/ipe.c b/security/ipe/ipe.c
>> index 22bd95116087..ed3acf6174d8 100644
>> --- a/security/ipe/ipe.c
>> +++ b/security/ipe/ipe.c
>> @@ -5,9 +5,13 @@
>>   #include <uapi/linux/lsm.h>
>>   
>>   #include "ipe.h"
>> +#include "eval.h"
>>   #include "hooks.h"
>>   
>>   static struct lsm_blob_sizes ipe_blobs __ro_after_init = {
>> +#ifdef CONFIG_BLK_DEV_INITRD
>> +	.lbs_superblock = sizeof(struct ipe_sb),
>> +#endif /* CONFIG_BLK_DEV_INITRD */
>>   };
> 
> I would drop the CONFIG_BLK_DEV_INITRD conditional above for reasons
> already mentioned, it's also not like a running system has that many
> superblocks allocated.  The increase in memory usage should be
> trivial.
> 
>>   static const struct lsm_id ipe_lsmid = {
>> @@ -15,12 +19,22 @@ static const struct lsm_id ipe_lsmid = {
>>   	.id = LSM_ID_IPE,
>>   };
>>   
>> +#ifdef CONFIG_BLK_DEV_INITRD
>> +struct ipe_sb *ipe_sb(const struct super_block *sb)
>> +{
>> +	return sb->s_security + ipe_blobs.lbs_superblock;
>> +}
>> +#endif /* CONFIG_BLK_DEV_INITRD */
> 
> If we always have an IPE slot in the superblock's security blob, there
> is not need to make the above conditional.
> 
>>   static struct security_hook_list ipe_hooks[] __ro_after_init = {
>>   	LSM_HOOK_INIT(bprm_check_security, ipe_bprm_check_security),
>>   	LSM_HOOK_INIT(mmap_file, ipe_mmap_file),
>>   	LSM_HOOK_INIT(file_mprotect, ipe_file_mprotect),
>>   	LSM_HOOK_INIT(kernel_read_file, ipe_kernel_read_file),
>>   	LSM_HOOK_INIT(kernel_load_data, ipe_kernel_load_data),
>> +#ifdef CONFIG_BLK_DEV_INITRD
>> +	LSM_HOOK_INIT(unpack_initramfs_security, ipe_unpack_initramfs),
>> +#endif /* CONFIG_BLK_DEV_INITRD */
>>   };
>>   
>>   /**
>> diff --git a/security/ipe/ipe.h b/security/ipe/ipe.h
>> index a1c68d0fc2e0..f1e7c3222b6d 100644
>> --- a/security/ipe/ipe.h
>> +++ b/security/ipe/ipe.h
>> @@ -12,5 +12,8 @@
>>   #define pr_fmt(fmt) "IPE: " fmt
>>   
>>   #include <linux/lsm_hooks.h>
>> +#ifdef CONFIG_BLK_DEV_INITRD
>> +struct ipe_sb *ipe_sb(const struct super_block *sb);
>> +#endif /* CONFIG_BLK_DEV_INITRD */
>>   
>>   #endif /* _IPE_H */
>> diff --git a/security/ipe/policy.h b/security/ipe/policy.h
>> index fb906f41522b..fb48024bb63e 100644
>> --- a/security/ipe/policy.h
>> +++ b/security/ipe/policy.h
>> @@ -30,6 +30,8 @@ enum ipe_action_type {
>>   #define IPE_ACTION_INVALID __IPE_ACTION_MAX
>>   
>>   enum ipe_prop_type {
>> +	IPE_PROP_BOOT_VERIFIED_FALSE,
>> +	IPE_PROP_BOOT_VERIFIED_TRUE,
>>   	__IPE_PROP_MAX
>>   };
>>   
>> diff --git a/security/ipe/policy_parser.c b/security/ipe/policy_parser.c
>> index 612839b405f4..cce15f0eb645 100644
>> --- a/security/ipe/policy_parser.c
>> +++ b/security/ipe/policy_parser.c
>> @@ -265,6 +265,14 @@ static enum ipe_action_type parse_action(char *t)
>>   	return match_token(t, action_tokens, args);
>>   }
>>   
>> +static const match_table_t property_tokens = {
>> +#ifdef CONFIG_BLK_DEV_INITRD
>> +	{IPE_PROP_BOOT_VERIFIED_FALSE,	"boot_verified=FALSE"},
>> +	{IPE_PROP_BOOT_VERIFIED_TRUE,	"boot_verified=TRUE"},
>> +#endif /* CONFIG_BLK_DEV_INITRD */
> 
> You want the "boot_verified" field to be part of the IPE policy
> regardless of the state of CONFIG_BLK_DEV_INITRD, yes?  On a system
> without _INITRD the TRUE case would never trigger, only the FALSE
> case, which seems like the Right Thing.
> 
> It just seems wrong to me to have the policy grammar change depending
> on what the kernel supports, it seems like IPE should parse and enforce
> the policy regardless of the kernel's config, with the understanding
> that some rules might never be satisfied as it would be impossible
> for a given kernel config, e.g. "boot_verified=TRUE" on a non-initramfs
> system.
> 
> I probably should have thought of this sooner, but I believe the same
> applies to the dm-verity and fs-verity policy tokens.
> 
This sounds reasonable to me. I will change the parser to make the 
policy grammar not depending on any kernel config.

Thanks,
Fan

>> +	{IPE_PROP_INVALID,		NULL}
>> +};
>> +
>>   /**
>>    * parse_property - Parse the property type given a token string.
>>    * @t: Supplies the token string to be parsed.
>> @@ -277,7 +285,34 @@ static enum ipe_action_type parse_action(char *t)
>>    */
>>   static int parse_property(char *t, struct ipe_rule *r)
>>   {
>> -	return -EBADMSG;
>> +	substring_t args[MAX_OPT_ARGS];
>> +	struct ipe_prop *p = NULL;
>> +	int rc = 0;
>> +	int token;
>> +
>> +	p = kzalloc(sizeof(*p), GFP_KERNEL);
>> +	if (!p)
>> +		return -ENOMEM;
>> +
>> +	token = match_token(t, property_tokens, args);
>> +
>> +	switch (token) {
>> +	case IPE_PROP_BOOT_VERIFIED_FALSE:
>> +	case IPE_PROP_BOOT_VERIFIED_TRUE:
>> +		p->type = token;
>> +		break;
>> +	default:
>> +		rc = -EBADMSG;
>> +		break;
>> +	}
>> +	if (rc)
>> +		goto err;
>> +	list_add_tail(&p->next, &r->props);
>> +
>> +	return rc;
>> +err:
>> +	kfree(p);
>> +	return rc;
>>   }
>>   
>>   /**
>> -- 
>> 2.43.0
> 
> --
> paul-moore.com

  reply	other threads:[~2024-02-05 22:39 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-30 22:36 [RFC PATCH v12 00/20] Integrity Policy Enforcement LSM (IPE) Fan Wu
2024-01-30 22:36 ` [RFC PATCH v12 01/20] security: add ipe lsm Fan Wu
2024-01-30 22:36 ` [RFC PATCH v12 02/20] ipe: add policy parser Fan Wu
2024-01-30 22:36 ` [RFC PATCH v12 03/20] ipe: add evaluation loop Fan Wu
2024-01-30 22:36 ` [RFC PATCH v12 04/20] ipe: add LSM hooks on execution and kernel read Fan Wu
2024-01-30 22:36 ` [RFC PATCH v12 05/20] initramfs|security: Add security hook to initramfs unpack Fan Wu
2024-02-03 22:25   ` [PATCH RFC v12 5/20] " Paul Moore
2024-02-05 21:18     ` Fan Wu
2024-01-30 22:36 ` [RFC PATCH v12 06/20] ipe: introduce 'boot_verified' as a trust provider Fan Wu
2024-02-03 22:25   ` [PATCH RFC v12 6/20] " Paul Moore
2024-02-05 22:39     ` Fan Wu [this message]
2024-01-30 22:36 ` [RFC PATCH v12 07/20] security: add new securityfs delete function Fan Wu
2024-01-30 22:36 ` [RFC PATCH v12 08/20] ipe: add userspace interface Fan Wu
2024-02-03 22:25   ` [PATCH RFC v12 8/20] " Paul Moore
2024-02-05 23:01     ` Fan Wu
2024-02-05 23:10       ` Paul Moore
2024-02-05 23:21         ` Fan Wu
2024-01-30 22:36 ` [RFC PATCH v12 09/20] uapi|audit|ipe: add ipe auditing support Fan Wu
2024-02-03 22:25   ` [PATCH RFC v12 9/20] " Paul Moore
2024-01-30 22:36 ` [RFC PATCH v12 10/20] ipe: add permissive toggle Fan Wu
2024-02-03 22:25   ` [PATCH RFC " Paul Moore
2024-01-30 22:36 ` [RFC PATCH v12 11/20] block|security: add LSM blob to block_device Fan Wu
2024-01-30 22:37 ` [RFC PATCH v12 12/20] dm verity: set DM_TARGET_SINGLETON feature flag Fan Wu
2024-02-02 18:51   ` Mike Snitzer
2024-02-03  3:56     ` Fan Wu
2024-01-30 22:37 ` [RFC PATCH v12 13/20] dm: add finalize hook to target_type Fan Wu
2024-01-30 22:37 ` [RFC PATCH v12 14/20] dm verity: consume root hash digest and signature data via LSM hook Fan Wu
2024-01-30 22:37 ` [RFC PATCH v12 15/20] ipe: add support for dm-verity as a trust provider Fan Wu
2024-02-03 22:25   ` [PATCH RFC " Paul Moore
2024-02-05 23:11     ` Fan Wu
2024-02-06 21:53       ` Paul Moore
2024-01-30 22:37 ` [RFC PATCH v12 16/20] fsverity: consume builtin signature via LSM hook Fan Wu
2024-01-30 22:37 ` [RFC PATCH v12 17/20] ipe: enable support for fs-verity as a trust provider Fan Wu
2024-02-03 22:25   ` [PATCH RFC " Paul Moore
2024-01-30 22:37 ` [RFC PATCH v12 18/20] scripts: add boot policy generation program Fan Wu
2024-01-30 22:37 ` [RFC PATCH v12 19/20] ipe: kunit test for parser Fan Wu
2024-01-30 22:37 ` [RFC PATCH v12 20/20] documentation: add ipe documentation Fan Wu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ef167e7a-9943-4879-beb6-5e473f9f0f78@linux.microsoft.com \
    --to=wufan@linux.microsoft.com \
    --cc=agk@redhat.com \
    --cc=audit@vger.kernel.org \
    --cc=axboe@kernel.dk \
    --cc=corbet@lwn.net \
    --cc=deven.desai@linux.microsoft.com \
    --cc=dm-devel@lists.linux.dev \
    --cc=ebiggers@kernel.org \
    --cc=eparis@redhat.com \
    --cc=jmorris@namei.org \
    --cc=linux-block@vger.kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-fscrypt@vger.kernel.org \
    --cc=linux-integrity@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=paul@paul-moore.com \
    --cc=serge@hallyn.com \
    --cc=snitzer@kernel.org \
    --cc=tytso@mit.edu \
    --cc=zohar@linux.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox