* [PATCH 0/3] LSM: Multiple LSM mount options
[not found] <20250617210105.17479-1-casey.ref@schaufler-ca.com>
@ 2025-06-17 21:01 ` Casey Schaufler
2025-06-17 21:01 ` [PATCH 1/3] LSM: Add mount opts blob size tracking Casey Schaufler
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Casey Schaufler @ 2025-06-17 21:01 UTC (permalink / raw)
To: casey, paul, eparis, linux-security-module
Cc: jmorris, serge, keescook, john.johansen, penguin-kernel,
stephen.smalley.work, linux-kernel, selinux
Linux Security Module (LSM) that support mount options, currently SELinux
and Smack, allocate their own data for those options. This patch set
moves the handling of mount option data out of the individual LSMs and
into the LSM infrastructure. This allows for multiple LSMs to support
mount options at the same time.
https://github.com/cschaufler/lsm-stacking#mount-opts-6.16-rc1
Based on patches Paul Moore's LSM initialization patchset.
https://lore.kernel.org/all/20250409185019.238841-31-paul@paul-moore.com/v3
Casey Schaufler (3):
LSM: Add mount opts blob size tracking
LSM: allocate mnt_opts blobs instead of module specific data
LSM: Infrastructure management of the mnt_opts security blob
include/linux/lsm_hooks.h | 2 ++
security/lsm_init.c | 2 ++
security/security.c | 26 ++++++++++-----
security/selinux/hooks.c | 65 +++++++++++++++++++++++++-------------
security/smack/smack_lsm.c | 62 +++++++++++++++++++++++++-----------
5 files changed, 108 insertions(+), 49 deletions(-)
--
2.47.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/3] LSM: Add mount opts blob size tracking
2025-06-17 21:01 ` [PATCH 0/3] LSM: Multiple LSM mount options Casey Schaufler
@ 2025-06-17 21:01 ` Casey Schaufler
2025-08-06 22:06 ` Paul Moore
2025-06-17 21:01 ` [PATCH 2/3] LSM: allocate mnt_opts blobs instead of module specific data Casey Schaufler
2025-06-17 21:01 ` [PATCH 3/3] LSM: Infrastructure management of the mnt_opts security blob Casey Schaufler
2 siblings, 1 reply; 8+ messages in thread
From: Casey Schaufler @ 2025-06-17 21:01 UTC (permalink / raw)
To: casey, paul, eparis, linux-security-module
Cc: jmorris, serge, keescook, john.johansen, penguin-kernel,
stephen.smalley.work, linux-kernel, selinux
Add mount option data to the blob size accounting in anticipation
of using a shared mnt_opts blob.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
include/linux/lsm_hooks.h | 1 +
security/lsm_init.c | 2 ++
security/selinux/hooks.c | 1 +
security/smack/smack_lsm.c | 1 +
4 files changed, 5 insertions(+)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 5bc144c5f685..9741c76e4654 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -122,6 +122,7 @@ struct lsm_blob_sizes {
unsigned int lbs_xattr_count; /* num xattr slots in new_xattrs array */
unsigned int lbs_tun_dev;
unsigned int lbs_bdev;
+ unsigned int lbs_mnt_opts;
};
/*
diff --git a/security/lsm_init.c b/security/lsm_init.c
index c2ef4db055db..26c9bdd5f851 100644
--- a/security/lsm_init.c
+++ b/security/lsm_init.c
@@ -318,6 +318,7 @@ static void __init lsm_prep_single(struct lsm_info *lsm)
lsm_blob_size_update(&blobs->lbs_xattr_count,
&blob_sizes.lbs_xattr_count);
lsm_blob_size_update(&blobs->lbs_bdev, &blob_sizes.lbs_bdev);
+ lsm_blob_size_update(&blobs->lbs_mnt_opts, &blob_sizes.lbs_mnt_opts);
}
/**
@@ -459,6 +460,7 @@ int __init security_init(void)
lsm_pr("blob(tun_dev) size %d\n", blob_sizes.lbs_tun_dev);
lsm_pr("blob(xattr) count %d\n", blob_sizes.lbs_xattr_count);
lsm_pr("blob(bdev) size %d\n", blob_sizes.lbs_bdev);
+ lsm_pr("blob(mnt_opts) size %d\n", blob_sizes.lbs_mnt_opts);
}
if (blob_sizes.lbs_file)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index b00c2627286a..88cd1d56081a 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -7160,6 +7160,7 @@ struct lsm_blob_sizes selinux_blob_sizes __ro_after_init = {
.lbs_xattr_count = SELINUX_INODE_INIT_XATTRS,
.lbs_tun_dev = sizeof(struct tun_security_struct),
.lbs_ib = sizeof(struct ib_security_struct),
+ .lbs_mnt_opts = sizeof(struct selinux_mnt_opts),
};
#ifdef CONFIG_PERF_EVENTS
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 46ef5ece991c..44bd92410425 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -5030,6 +5030,7 @@ struct lsm_blob_sizes smack_blob_sizes __ro_after_init = {
.lbs_sock = sizeof(struct socket_smack),
.lbs_superblock = sizeof(struct superblock_smack),
.lbs_xattr_count = SMACK_INODE_INIT_XATTRS,
+ .lbs_mnt_opts = sizeof(struct smack_mnt_opts),
};
static const struct lsm_id smack_lsmid = {
--
2.47.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/3] LSM: allocate mnt_opts blobs instead of module specific data
2025-06-17 21:01 ` [PATCH 0/3] LSM: Multiple LSM mount options Casey Schaufler
2025-06-17 21:01 ` [PATCH 1/3] LSM: Add mount opts blob size tracking Casey Schaufler
@ 2025-06-17 21:01 ` Casey Schaufler
2025-08-06 22:06 ` Paul Moore
2025-06-17 21:01 ` [PATCH 3/3] LSM: Infrastructure management of the mnt_opts security blob Casey Schaufler
2 siblings, 1 reply; 8+ messages in thread
From: Casey Schaufler @ 2025-06-17 21:01 UTC (permalink / raw)
To: casey, paul, eparis, linux-security-module
Cc: jmorris, serge, keescook, john.johansen, penguin-kernel,
stephen.smalley.work, linux-kernel, selinux
Replace allocations of LSM specific mount data with the
shared mnt_opts blob.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
include/linux/lsm_hooks.h | 1 +
security/security.c | 12 ++++++++++++
security/selinux/hooks.c | 10 +++++++---
security/smack/smack_lsm.c | 4 ++--
4 files changed, 22 insertions(+), 5 deletions(-)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 9741c76e4654..1871ebc5833b 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -219,4 +219,5 @@ static inline struct xattr *lsm_get_xattr_slot(struct xattr *xattrs,
return &xattrs[(*xattr_count)++];
}
+extern void *lsm_mnt_opts_alloc(gfp_t priority);
#endif /* ! __LINUX_LSM_HOOKS_H */
diff --git a/security/security.c b/security/security.c
index 8a4e0f70e49d..ec61fb7e6492 100644
--- a/security/security.c
+++ b/security/security.c
@@ -904,6 +904,18 @@ void security_sb_free(struct super_block *sb)
sb->s_security = NULL;
}
+/**
+ * lsm_mnt_opts_alloc - allocate a mnt_opts blob
+ * @priority: memory allocation priority
+ *
+ * Returns a newly allocated mnt_opts blob or NULL if
+ * memory isn't available.
+ */
+void *lsm_mnt_opts_alloc(gfp_t priority)
+{
+ return kzalloc(blob_sizes.lbs_mnt_opts, priority);
+}
+
/**
* security_free_mnt_opts() - Free memory associated with mount options
* @mnt_opts: LSM processed mount options
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 88cd1d56081a..f7eda0cce68f 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2808,7 +2808,7 @@ static int selinux_fs_context_submount(struct fs_context *fc,
if (!(sbsec->flags & (FSCONTEXT_MNT|CONTEXT_MNT|DEFCONTEXT_MNT)))
return 0;
- opts = kzalloc(sizeof(*opts), GFP_KERNEL);
+ opts = lsm_mnt_opts_alloc(GFP_KERNEL);
if (!opts)
return -ENOMEM;
@@ -2830,8 +2830,12 @@ static int selinux_fs_context_dup(struct fs_context *fc,
if (!src)
return 0;
- fc->security = kmemdup(src, sizeof(*src), GFP_KERNEL);
- return fc->security ? 0 : -ENOMEM;
+ fc->security = lsm_mnt_opts_alloc(GFP_KERNEL);
+ if (!fc->security)
+ return -ENOMEM;
+
+ memcpy(fc->security, src, sizeof(*src));
+ return 0;
}
static const struct fs_parameter_spec selinux_fs_parameters[] = {
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 44bd92410425..1d456df40096 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -622,7 +622,7 @@ static int smack_fs_context_submount(struct fs_context *fc,
struct smack_mnt_opts *ctx;
struct inode_smack *isp;
- ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ ctx = lsm_mnt_opts_alloc(GFP_KERNEL);
if (!ctx)
return -ENOMEM;
fc->security = ctx;
@@ -673,7 +673,7 @@ static int smack_fs_context_dup(struct fs_context *fc,
if (!src)
return 0;
- fc->security = kzalloc(sizeof(struct smack_mnt_opts), GFP_KERNEL);
+ fc->security = lsm_mnt_opts_alloc(GFP_KERNEL);
if (!fc->security)
return -ENOMEM;
--
2.47.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/3] LSM: Infrastructure management of the mnt_opts security blob
2025-06-17 21:01 ` [PATCH 0/3] LSM: Multiple LSM mount options Casey Schaufler
2025-06-17 21:01 ` [PATCH 1/3] LSM: Add mount opts blob size tracking Casey Schaufler
2025-06-17 21:01 ` [PATCH 2/3] LSM: allocate mnt_opts blobs instead of module specific data Casey Schaufler
@ 2025-06-17 21:01 ` Casey Schaufler
2 siblings, 0 replies; 8+ messages in thread
From: Casey Schaufler @ 2025-06-17 21:01 UTC (permalink / raw)
To: casey, paul, eparis, linux-security-module
Cc: jmorris, serge, keescook, john.johansen, penguin-kernel,
stephen.smalley.work, linux-kernel, selinux
Move management of the mnt_opts->security blob out of the
individual security modules and into the security
infrastructure. Blobs are still allocated within the modules
as they are only required when mount options are present.
The modules tell the infrastructure how much space is required,
and the space is allocated if needed. Modules can no longer
count on the presence of a blob implying that mount options
specific to that module are present, so flags are added
to the module specific blobs to indicate that this module
has options.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
security/security.c | 14 ++++-----
security/selinux/hooks.c | 58 +++++++++++++++++++++++-------------
security/smack/smack_lsm.c | 61 ++++++++++++++++++++++++++------------
3 files changed, 85 insertions(+), 48 deletions(-)
diff --git a/security/security.c b/security/security.c
index ec61fb7e6492..01fa3b5336b0 100644
--- a/security/security.c
+++ b/security/security.c
@@ -843,17 +843,14 @@ int security_fs_context_parse_param(struct fs_context *fc,
struct fs_parameter *param)
{
struct lsm_static_call *scall;
- int trc;
- int rc = -ENOPARAM;
+ int rc;
lsm_for_each_hook(scall, fs_context_parse_param) {
- trc = scall->hl->hook.fs_context_parse_param(fc, param);
- if (trc == 0)
- rc = 0;
- else if (trc != -ENOPARAM)
- return trc;
+ rc = scall->hl->hook.fs_context_parse_param(fc, param);
+ if (rc != -ENOPARAM)
+ return rc;
}
- return rc;
+ return -ENOPARAM;
}
/**
@@ -927,6 +924,7 @@ void security_free_mnt_opts(void **mnt_opts)
if (!*mnt_opts)
return;
call_void_hook(sb_free_mnt_opts, *mnt_opts);
+ kfree(*mnt_opts);
*mnt_opts = NULL;
}
EXPORT_SYMBOL(security_free_mnt_opts);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index f7eda0cce68f..b00c78e0a650 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -378,15 +378,28 @@ static void inode_free_security(struct inode *inode)
}
struct selinux_mnt_opts {
+ bool initialized;
u32 fscontext_sid;
u32 context_sid;
u32 rootcontext_sid;
u32 defcontext_sid;
};
+static inline struct selinux_mnt_opts *selinux_mnt_opts(void *mnt_opts)
+{
+ if (mnt_opts)
+ return mnt_opts + selinux_blob_sizes.lbs_mnt_opts;
+ return NULL;
+}
+
static void selinux_free_mnt_opts(void *mnt_opts)
{
- kfree(mnt_opts);
+ struct selinux_mnt_opts *opts;
+
+ if (mnt_opts) {
+ opts = selinux_mnt_opts(mnt_opts);
+ opts->initialized = false;
+ }
}
enum {
@@ -641,7 +654,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
const struct cred *cred = current_cred();
struct superblock_security_struct *sbsec = selinux_superblock(sb);
struct dentry *root = sb->s_root;
- struct selinux_mnt_opts *opts = mnt_opts;
+ struct selinux_mnt_opts *opts = selinux_mnt_opts(mnt_opts);
struct inode_security_struct *root_isec;
u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
u32 defcontext_sid = 0;
@@ -657,7 +670,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
mutex_lock(&sbsec->lock);
if (!selinux_initialized()) {
- if (!opts) {
+ if (!opts || !opts->initialized) {
/* Defer initialization until selinux_complete_init,
after the initial policy is loaded and the security
server is ready to handle calls. */
@@ -695,7 +708,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
* also check if someone is trying to mount the same sb more
* than once with different security options.
*/
- if (opts) {
+ if (opts && opts->initialized) {
if (opts->fscontext_sid) {
fscontext_sid = opts->fscontext_sid;
if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
@@ -1004,7 +1017,7 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
*/
static int selinux_add_opt(int token, const char *s, void **mnt_opts)
{
- struct selinux_mnt_opts *opts = *mnt_opts;
+ struct selinux_mnt_opts *opts;
u32 *dst_sid;
int rc;
@@ -1019,12 +1032,12 @@ static int selinux_add_opt(int token, const char *s, void **mnt_opts)
return -EINVAL;
}
- if (!opts) {
- opts = kzalloc(sizeof(*opts), GFP_KERNEL);
- if (!opts)
+ if (!*mnt_opts) {
+ *mnt_opts = lsm_mnt_opts_alloc(GFP_KERNEL);
+ if (!*mnt_opts)
return -ENOMEM;
- *mnt_opts = opts;
}
+ opts = selinux_mnt_opts(*mnt_opts);
switch (token) {
case Opt_context:
@@ -1051,6 +1064,7 @@ static int selinux_add_opt(int token, const char *s, void **mnt_opts)
WARN_ON(1);
return -EINVAL;
}
+ opts->initialized = true;
rc = security_context_str_to_sid(s, dst_sid, GFP_KERNEL);
if (rc)
pr_warn("SELinux: security_context_str_to_sid (%s) failed with errno=%d\n",
@@ -2650,10 +2664,7 @@ static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts)
return 0;
free_opt:
- if (*mnt_opts) {
- selinux_free_mnt_opts(*mnt_opts);
- *mnt_opts = NULL;
- }
+ selinux_free_mnt_opts(*mnt_opts);
return rc;
}
@@ -2704,13 +2715,13 @@ static int selinux_sb_mnt_opts_compat(struct super_block *sb, void *mnt_opts)
static int selinux_sb_remount(struct super_block *sb, void *mnt_opts)
{
- struct selinux_mnt_opts *opts = mnt_opts;
+ struct selinux_mnt_opts *opts = selinux_mnt_opts(mnt_opts);
struct superblock_security_struct *sbsec = selinux_superblock(sb);
if (!(sbsec->flags & SE_SBINITIALIZED))
return 0;
- if (!opts)
+ if (!opts || !opts->initialized)
return 0;
if (opts->fscontext_sid) {
@@ -2808,9 +2819,13 @@ static int selinux_fs_context_submount(struct fs_context *fc,
if (!(sbsec->flags & (FSCONTEXT_MNT|CONTEXT_MNT|DEFCONTEXT_MNT)))
return 0;
- opts = lsm_mnt_opts_alloc(GFP_KERNEL);
- if (!opts)
- return -ENOMEM;
+ if (!fc->security) {
+ fc->security = lsm_mnt_opts_alloc(GFP_KERNEL);
+ if (!fc->security)
+ return -ENOMEM;
+ }
+ opts = selinux_mnt_opts(fc->security);
+ opts->initialized = true;
if (sbsec->flags & FSCONTEXT_MNT)
opts->fscontext_sid = sbsec->sid;
@@ -2818,14 +2833,14 @@ static int selinux_fs_context_submount(struct fs_context *fc,
opts->context_sid = sbsec->mntpoint_sid;
if (sbsec->flags & DEFCONTEXT_MNT)
opts->defcontext_sid = sbsec->def_sid;
- fc->security = opts;
return 0;
}
static int selinux_fs_context_dup(struct fs_context *fc,
struct fs_context *src_fc)
{
- const struct selinux_mnt_opts *src = src_fc->security;
+ const struct selinux_mnt_opts *src = selinux_mnt_opts(src_fc->security);
+ struct selinux_mnt_opts *dst;
if (!src)
return 0;
@@ -2834,7 +2849,8 @@ static int selinux_fs_context_dup(struct fs_context *fc,
if (!fc->security)
return -ENOMEM;
- memcpy(fc->security, src, sizeof(*src));
+ dst = selinux_mnt_opts(fc->security);
+ memcpy(dst, src, sizeof(*src));
return 0;
}
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 1d456df40096..e88de89a5bc1 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -544,6 +544,7 @@ static int smack_sb_alloc_security(struct super_block *sb)
}
struct smack_mnt_opts {
+ bool initialized;
const char *fsdefault;
const char *fsfloor;
const char *fshat;
@@ -551,24 +552,37 @@ struct smack_mnt_opts {
const char *fstransmute;
};
+static inline struct smack_mnt_opts *smack_mnt_opts(void *mnt_opts)
+{
+ if (mnt_opts)
+ return mnt_opts + smack_blob_sizes.lbs_mnt_opts;
+ return NULL;
+}
+
static void smack_free_mnt_opts(void *mnt_opts)
{
- kfree(mnt_opts);
+ struct smack_mnt_opts *opts;
+
+ if (mnt_opts) {
+ opts = smack_mnt_opts(mnt_opts);
+ opts->initialized = false;
+ }
}
static int smack_add_opt(int token, const char *s, void **mnt_opts)
{
- struct smack_mnt_opts *opts = *mnt_opts;
+ struct smack_mnt_opts *opts;
struct smack_known *skp;
- if (!opts) {
- opts = kzalloc(sizeof(struct smack_mnt_opts), GFP_KERNEL);
- if (!opts)
+ if (!s)
+ return -EINVAL;
+
+ if (!*mnt_opts) {
+ *mnt_opts = lsm_mnt_opts_alloc(GFP_KERNEL);
+ if (!*mnt_opts)
return -ENOMEM;
- *mnt_opts = opts;
}
- if (!s)
- return -ENOMEM;
+ opts = smack_mnt_opts(*mnt_opts);
skp = smk_import_entry(s, 0);
if (IS_ERR(skp))
@@ -601,6 +615,7 @@ static int smack_add_opt(int token, const char *s, void **mnt_opts)
opts->fstransmute = skp->smk_known;
break;
}
+ opts->initialized = true;
return 0;
out_opt_err:
@@ -622,10 +637,12 @@ static int smack_fs_context_submount(struct fs_context *fc,
struct smack_mnt_opts *ctx;
struct inode_smack *isp;
- ctx = lsm_mnt_opts_alloc(GFP_KERNEL);
- if (!ctx)
- return -ENOMEM;
- fc->security = ctx;
+ if (!fc->security) {
+ fc->security = lsm_mnt_opts_alloc(GFP_KERNEL);
+ if (!fc->security)
+ return -ENOMEM;
+ }
+ ctx = smack_mnt_opts(fc->security);
sbsp = smack_superblock(reference);
isp = smack_inode(reference->s_root->d_inode);
@@ -655,6 +672,7 @@ static int smack_fs_context_submount(struct fs_context *fc,
return -ENOMEM;
}
}
+ ctx->initialized = true;
return 0;
}
@@ -668,16 +686,21 @@ static int smack_fs_context_submount(struct fs_context *fc,
static int smack_fs_context_dup(struct fs_context *fc,
struct fs_context *src_fc)
{
- struct smack_mnt_opts *dst, *src = src_fc->security;
+ struct smack_mnt_opts *src;
+ struct smack_mnt_opts *dst;
+ src = smack_mnt_opts(src_fc->security);
if (!src)
return 0;
- fc->security = lsm_mnt_opts_alloc(GFP_KERNEL);
- if (!fc->security)
- return -ENOMEM;
+ if (!fc->security) {
+ fc->security = lsm_mnt_opts_alloc(GFP_KERNEL);
+ if (!fc->security)
+ return -ENOMEM;
+ }
- dst = fc->security;
+ dst = smack_mnt_opts(fc->security);
+ dst->initialized = src->initialized;
dst->fsdefault = src->fsdefault;
dst->fsfloor = src->fsfloor;
dst->fshat = src->fshat;
@@ -787,7 +810,7 @@ static int smack_set_mnt_opts(struct super_block *sb,
struct superblock_smack *sp = smack_superblock(sb);
struct inode_smack *isp;
struct smack_known *skp;
- struct smack_mnt_opts *opts = mnt_opts;
+ struct smack_mnt_opts *opts = smack_mnt_opts(mnt_opts);
bool transmute = false;
if (sp->smk_flags & SMK_SB_INITIALIZED)
@@ -820,7 +843,7 @@ static int smack_set_mnt_opts(struct super_block *sb,
sp->smk_flags |= SMK_SB_INITIALIZED;
- if (opts) {
+ if (opts && opts->initialized) {
if (opts->fsdefault) {
skp = smk_import_entry(opts->fsdefault, 0);
if (IS_ERR(skp))
--
2.47.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 1/3] LSM: Add mount opts blob size tracking
2025-06-17 21:01 ` [PATCH 1/3] LSM: Add mount opts blob size tracking Casey Schaufler
@ 2025-08-06 22:06 ` Paul Moore
0 siblings, 0 replies; 8+ messages in thread
From: Paul Moore @ 2025-08-06 22:06 UTC (permalink / raw)
To: Casey Schaufler, casey, eparis, linux-security-module
Cc: jmorris, serge, keescook, john.johansen, penguin-kernel,
stephen.smalley.work, linux-kernel, selinux
On Jun 17, 2025 Casey Schaufler <casey@schaufler-ca.com> wrote:
>
> Add mount option data to the blob size accounting in anticipation
> of using a shared mnt_opts blob.
>
> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
> ---
> include/linux/lsm_hooks.h | 1 +
> security/lsm_init.c | 2 ++
> security/selinux/hooks.c | 1 +
> security/smack/smack_lsm.c | 1 +
> 4 files changed, 5 insertions(+)
Since you're respinning this patchset for other reasons, just base it
on the existing LSM initialization code. If this patchset collides with
the init rework mid-flight I'll handle the merge fixup.
I appreciate the consideration, but in this case I think it's easier to
not have the dependency.
--
paul-moore.com
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/3] LSM: allocate mnt_opts blobs instead of module specific data
2025-06-17 21:01 ` [PATCH 2/3] LSM: allocate mnt_opts blobs instead of module specific data Casey Schaufler
@ 2025-08-06 22:06 ` Paul Moore
2025-08-06 23:16 ` Casey Schaufler
0 siblings, 1 reply; 8+ messages in thread
From: Paul Moore @ 2025-08-06 22:06 UTC (permalink / raw)
To: Casey Schaufler, casey, eparis, linux-security-module
Cc: jmorris, serge, keescook, john.johansen, penguin-kernel,
stephen.smalley.work, linux-kernel, selinux
On Jun 17, 2025 Casey Schaufler <casey@schaufler-ca.com> wrote:
>
> Replace allocations of LSM specific mount data with the
> shared mnt_opts blob.
>
> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
> ---
> include/linux/lsm_hooks.h | 1 +
> security/security.c | 12 ++++++++++++
> security/selinux/hooks.c | 10 +++++++---
> security/smack/smack_lsm.c | 4 ++--
> 4 files changed, 22 insertions(+), 5 deletions(-)
...
> diff --git a/security/security.c b/security/security.c
> index 8a4e0f70e49d..ec61fb7e6492 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -904,6 +904,18 @@ void security_sb_free(struct super_block *sb)
> sb->s_security = NULL;
> }
>
> +/**
> + * lsm_mnt_opts_alloc - allocate a mnt_opts blob
> + * @priority: memory allocation priority
> + *
> + * Returns a newly allocated mnt_opts blob or NULL if
> + * memory isn't available.
> + */
> +void *lsm_mnt_opts_alloc(gfp_t priority)
> +{
> + return kzalloc(blob_sizes.lbs_mnt_opts, priority);
> +}
It's probably better to use lsm_blob_alloc() here so we have some
allocator consistency.
Also, make this private/static as we should just handle the blob
allocation in the LSM framework (see below) just like everything else,
unless you can explain why the mount options need to be handled
differently?
> /**
> * security_free_mnt_opts() - Free memory associated with mount options
> * @mnt_opts: LSM processed mount options
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 88cd1d56081a..f7eda0cce68f 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -2808,7 +2808,7 @@ static int selinux_fs_context_submount(struct fs_context *fc,
> if (!(sbsec->flags & (FSCONTEXT_MNT|CONTEXT_MNT|DEFCONTEXT_MNT)))
> return 0;
>
> - opts = kzalloc(sizeof(*opts), GFP_KERNEL);
> + opts = lsm_mnt_opts_alloc(GFP_KERNEL);
See above.
> if (!opts)
> return -ENOMEM;
>
> @@ -2830,8 +2830,12 @@ static int selinux_fs_context_dup(struct fs_context *fc,
> if (!src)
> return 0;
>
> - fc->security = kmemdup(src, sizeof(*src), GFP_KERNEL);
> - return fc->security ? 0 : -ENOMEM;
> + fc->security = lsm_mnt_opts_alloc(GFP_KERNEL);
> + if (!fc->security)
> + return -ENOMEM;
Another case where we should do the allocation in the LSM framework.
> + memcpy(fc->security, src, sizeof(*src));
> + return 0;
> }
>
> static const struct fs_parameter_spec selinux_fs_parameters[] = {
> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> index 44bd92410425..1d456df40096 100644
> --- a/security/smack/smack_lsm.c
> +++ b/security/smack/smack_lsm.c
> @@ -622,7 +622,7 @@ static int smack_fs_context_submount(struct fs_context *fc,
> struct smack_mnt_opts *ctx;
> struct inode_smack *isp;
>
> - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
> + ctx = lsm_mnt_opts_alloc(GFP_KERNEL);
> if (!ctx)
> return -ENOMEM;
> fc->security = ctx;
> @@ -673,7 +673,7 @@ static int smack_fs_context_dup(struct fs_context *fc,
> if (!src)
> return 0;
>
> - fc->security = kzalloc(sizeof(struct smack_mnt_opts), GFP_KERNEL);
> + fc->security = lsm_mnt_opts_alloc(GFP_KERNEL);
> if (!fc->security)
> return -ENOMEM;
Same thing in Smack.
--
paul-moore.com
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/3] LSM: allocate mnt_opts blobs instead of module specific data
2025-08-06 22:06 ` Paul Moore
@ 2025-08-06 23:16 ` Casey Schaufler
2025-08-07 0:40 ` Paul Moore
0 siblings, 1 reply; 8+ messages in thread
From: Casey Schaufler @ 2025-08-06 23:16 UTC (permalink / raw)
To: Paul Moore, eparis, linux-security-module
Cc: jmorris, serge, keescook, john.johansen, penguin-kernel,
stephen.smalley.work, linux-kernel, selinux, Casey Schaufler
On 8/6/2025 3:06 PM, Paul Moore wrote:
> On Jun 17, 2025 Casey Schaufler <casey@schaufler-ca.com> wrote:
>> Replace allocations of LSM specific mount data with the
>> shared mnt_opts blob.
>>
>> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
>> ---
>> include/linux/lsm_hooks.h | 1 +
>> security/security.c | 12 ++++++++++++
>> security/selinux/hooks.c | 10 +++++++---
>> security/smack/smack_lsm.c | 4 ++--
>> 4 files changed, 22 insertions(+), 5 deletions(-)
> ..
>
>> diff --git a/security/security.c b/security/security.c
>> index 8a4e0f70e49d..ec61fb7e6492 100644
>> --- a/security/security.c
>> +++ b/security/security.c
>> @@ -904,6 +904,18 @@ void security_sb_free(struct super_block *sb)
>> sb->s_security = NULL;
>> }
>>
>> +/**
>> + * lsm_mnt_opts_alloc - allocate a mnt_opts blob
>> + * @priority: memory allocation priority
>> + *
>> + * Returns a newly allocated mnt_opts blob or NULL if
>> + * memory isn't available.
>> + */
>> +void *lsm_mnt_opts_alloc(gfp_t priority)
>> +{
>> + return kzalloc(blob_sizes.lbs_mnt_opts, priority);
>> +}
> It's probably better to use lsm_blob_alloc() here so we have some
> allocator consistency.
>
> Also, make this private/static as we should just handle the blob
> allocation in the LSM framework (see below) just like everything else,
> unless you can explain why the mount options need to be handled
> differently?
The mount blob is different from the other blobs in that it is
only used if there are LSM specific mount options. If there aren't
LSM specific mount options there is no reason to have a blob.
I know it's not a huge deal, but there is a performance cost in
allocating a blob that isn't used.
If you'd really rather accept the overhead, I can make the blob
always allocated. Let me know.
>
>> /**
>> * security_free_mnt_opts() - Free memory associated with mount options
>> * @mnt_opts: LSM processed mount options
>> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
>> index 88cd1d56081a..f7eda0cce68f 100644
>> --- a/security/selinux/hooks.c
>> +++ b/security/selinux/hooks.c
>> @@ -2808,7 +2808,7 @@ static int selinux_fs_context_submount(struct fs_context *fc,
>> if (!(sbsec->flags & (FSCONTEXT_MNT|CONTEXT_MNT|DEFCONTEXT_MNT)))
>> return 0;
>>
>> - opts = kzalloc(sizeof(*opts), GFP_KERNEL);
>> + opts = lsm_mnt_opts_alloc(GFP_KERNEL);
> See above.
>
>> if (!opts)
>> return -ENOMEM;
>>
>> @@ -2830,8 +2830,12 @@ static int selinux_fs_context_dup(struct fs_context *fc,
>> if (!src)
>> return 0;
>>
>> - fc->security = kmemdup(src, sizeof(*src), GFP_KERNEL);
>> - return fc->security ? 0 : -ENOMEM;
>> + fc->security = lsm_mnt_opts_alloc(GFP_KERNEL);
>> + if (!fc->security)
>> + return -ENOMEM;
> Another case where we should do the allocation in the LSM framework.
>
>> + memcpy(fc->security, src, sizeof(*src));
>> + return 0;
>> }
>>
>> static const struct fs_parameter_spec selinux_fs_parameters[] = {
>> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
>> index 44bd92410425..1d456df40096 100644
>> --- a/security/smack/smack_lsm.c
>> +++ b/security/smack/smack_lsm.c
>> @@ -622,7 +622,7 @@ static int smack_fs_context_submount(struct fs_context *fc,
>> struct smack_mnt_opts *ctx;
>> struct inode_smack *isp;
>>
>> - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
>> + ctx = lsm_mnt_opts_alloc(GFP_KERNEL);
>> if (!ctx)
>> return -ENOMEM;
>> fc->security = ctx;
>> @@ -673,7 +673,7 @@ static int smack_fs_context_dup(struct fs_context *fc,
>> if (!src)
>> return 0;
>>
>> - fc->security = kzalloc(sizeof(struct smack_mnt_opts), GFP_KERNEL);
>> + fc->security = lsm_mnt_opts_alloc(GFP_KERNEL);
>> if (!fc->security)
>> return -ENOMEM;
> Same thing in Smack.
>
> --
> paul-moore.com
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/3] LSM: allocate mnt_opts blobs instead of module specific data
2025-08-06 23:16 ` Casey Schaufler
@ 2025-08-07 0:40 ` Paul Moore
0 siblings, 0 replies; 8+ messages in thread
From: Paul Moore @ 2025-08-07 0:40 UTC (permalink / raw)
To: Casey Schaufler
Cc: eparis, linux-security-module, jmorris, serge, keescook,
john.johansen, penguin-kernel, stephen.smalley.work, linux-kernel,
selinux
On Wed, Aug 6, 2025 at 7:16 PM Casey Schaufler <casey@schaufler-ca.com> wrote:
> On 8/6/2025 3:06 PM, Paul Moore wrote:
> > On Jun 17, 2025 Casey Schaufler <casey@schaufler-ca.com> wrote:
> >> Replace allocations of LSM specific mount data with the
> >> shared mnt_opts blob.
> >>
> >> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
> >> ---
> >> include/linux/lsm_hooks.h | 1 +
> >> security/security.c | 12 ++++++++++++
> >> security/selinux/hooks.c | 10 +++++++---
> >> security/smack/smack_lsm.c | 4 ++--
> >> 4 files changed, 22 insertions(+), 5 deletions(-)
> > ..
> >
> >> diff --git a/security/security.c b/security/security.c
> >> index 8a4e0f70e49d..ec61fb7e6492 100644
> >> --- a/security/security.c
> >> +++ b/security/security.c
> >> @@ -904,6 +904,18 @@ void security_sb_free(struct super_block *sb)
> >> sb->s_security = NULL;
> >> }
> >>
> >> +/**
> >> + * lsm_mnt_opts_alloc - allocate a mnt_opts blob
> >> + * @priority: memory allocation priority
> >> + *
> >> + * Returns a newly allocated mnt_opts blob or NULL if
> >> + * memory isn't available.
> >> + */
> >> +void *lsm_mnt_opts_alloc(gfp_t priority)
> >> +{
> >> + return kzalloc(blob_sizes.lbs_mnt_opts, priority);
> >> +}
> > It's probably better to use lsm_blob_alloc() here so we have some
> > allocator consistency.
> >
> > Also, make this private/static as we should just handle the blob
> > allocation in the LSM framework (see below) just like everything else,
> > unless you can explain why the mount options need to be handled
> > differently?
>
> The mount blob is different from the other blobs in that it is
> only used if there are LSM specific mount options. If there aren't
> LSM specific mount options there is no reason to have a blob.
> I know it's not a huge deal, but there is a performance cost in
> allocating a blob that isn't used.
>
> If you'd really rather accept the overhead, I can make the blob
> always allocated. Let me know.
Well, this is happening at mount time, which should already have a
non-trivial amount of overhead (parsing options, doing the filesystem
setup, mount tree addition, etc.) so I'm not sure this will really be
noticeable in practice. I guess one could also make an argument about
additional memory pressure, but the mount options blob should have a
fairly short lifetime so I don't see that as a significant issue
either. If one, or both, of these becomes an issue we can look into
ways of mitigating them, but right now I'd just assume keep with the
existing LSM blob allocation pattern to simplify the code and make
life easier.
--
paul-moore.com
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2025-08-07 0:40 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20250617210105.17479-1-casey.ref@schaufler-ca.com>
2025-06-17 21:01 ` [PATCH 0/3] LSM: Multiple LSM mount options Casey Schaufler
2025-06-17 21:01 ` [PATCH 1/3] LSM: Add mount opts blob size tracking Casey Schaufler
2025-08-06 22:06 ` Paul Moore
2025-06-17 21:01 ` [PATCH 2/3] LSM: allocate mnt_opts blobs instead of module specific data Casey Schaufler
2025-08-06 22:06 ` Paul Moore
2025-08-06 23:16 ` Casey Schaufler
2025-08-07 0:40 ` Paul Moore
2025-06-17 21:01 ` [PATCH 3/3] LSM: Infrastructure management of the mnt_opts security blob Casey Schaufler
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).