[RFC PATCH 06/15] LSM: Exclusive secmark usage
STALE334d
From: Casey Schaufler <casey@schaufler-ca.com>
Date: 2025-06-21 17:20:40
Also in:
lkml, selinux
Subsystem:
apparmor security module, security subsystem, selinux security module, smack security module, the rest · Maintainers:
John Johansen, John Johansen, Georgia Garcia, Paul Moore, James Morris, "Serge E. Hallyn", Stephen Smalley, Casey Schaufler, Linus Torvalds
The network secmark can only be used by one security module at a time. Establish mechanism to identify to security modules whether they have access to the secmark. SELinux already incorparates mechanism, but it has to be added to Smack and AppArmor. Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> --- include/linux/lsm_hooks.h | 1 + security/apparmor/include/net.h | 5 +++++ security/apparmor/lsm.c | 7 ++++--- security/lsm_init.c | 6 ++++++ security/selinux/hooks.c | 4 +++- security/smack/smack.h | 5 +++++ security/smack/smack_lsm.c | 3 ++- security/smack/smack_netfilter.c | 10 ++++++++-- 8 files changed, 34 insertions(+), 7 deletions(-)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 5bc144c5f685..1ad9f8a86b10 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; + bool lbs_secmark; /* expressed desire for secmark use */ }; /*
diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
index c42ed8a73f1c..2e43e1e8303c 100644
--- a/security/apparmor/include/net.h
+++ b/security/apparmor/include/net.h@@ -51,6 +51,11 @@ struct aa_sk_ctx { struct aa_label *peer; }; +static inline bool aa_secmark(void) +{ + return apparmor_blob_sizes.lbs_secmark; +} + static inline struct aa_sk_ctx *aa_sock(const struct sock *sk) { return sk->sk_security + apparmor_blob_sizes.lbs_sock;
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 4ba6db93e5b0..255d2e40386f 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c@@ -1291,7 +1291,7 @@ static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) { struct aa_sk_ctx *ctx = aa_sock(sk); - if (!skb->secmark) + if (!aa_secmark() || !skb->secmark) return 0; /*
@@ -1407,7 +1407,7 @@ static int apparmor_inet_conn_request(const struct sock *sk, struct sk_buff *skb { struct aa_sk_ctx *ctx = aa_sock(sk); - if (!skb->secmark) + if (!aa_secmark() || !skb->secmark) return 0; return apparmor_secmark_check(ctx->label, OP_CONNECT, AA_MAY_CONNECT,
@@ -1423,6 +1423,7 @@ struct lsm_blob_sizes apparmor_blob_sizes __ro_after_init = { .lbs_file = sizeof(struct aa_file_ctx), .lbs_task = sizeof(struct aa_task_ctx), .lbs_sock = sizeof(struct aa_sk_ctx), + .lbs_secmark = true, }; static const struct lsm_id apparmor_lsmid = {
@@ -2085,7 +2086,7 @@ static unsigned int apparmor_ip_postroute(void *priv, struct aa_sk_ctx *ctx; struct sock *sk; - if (!skb->secmark) + if (!aa_secmark() || !skb->secmark) return NF_ACCEPT; sk = skb_to_full_sk(skb);
diff --git a/security/lsm_init.c b/security/lsm_init.c
index 54166688efff..4e3944c68bc8 100644
--- a/security/lsm_init.c
+++ b/security/lsm_init.c@@ -313,6 +313,12 @@ 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); + if (blobs->lbs_secmark) { + if (blob_sizes.lbs_secmark) + blobs->lbs_secmark = false; + else + blob_sizes.lbs_secmark = true; + } } /**
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 9f816e25198a..18ab1f13f3f9 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c@@ -165,7 +165,8 @@ __setup("checkreqprot=", checkreqprot_setup); */ static int selinux_secmark_enabled(void) { - return (selinux_policycap_alwaysnetwork() || + return selinux_blob_sizes.lbs_secmark && + (selinux_policycap_alwaysnetwork() || atomic_read(&selinux_secmark_refcount)); }
@@ -7160,6 +7161,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_secmark = true, }; #ifdef CONFIG_PERF_EVENTS
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 709e0d6cd5e1..2f7b8d79b69f 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h@@ -389,6 +389,11 @@ static inline int smk_inode_transmutable(const struct inode *isp) return (sip->smk_flags & SMK_INODE_TRANSMUTE) != 0; } +static inline bool smack_secmark(void) +{ + return smack_blob_sizes.lbs_secmark; +} + /* * Present a pointer to the smack label entry in an inode blob. */
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index d363adead435..c8c173bb9cc3 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c@@ -4102,7 +4102,7 @@ static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip) #ifdef CONFIG_NETWORK_SECMARK static struct smack_known *smack_from_skb(struct sk_buff *skb) { - if (skb == NULL || skb->secmark == 0) + if (!smack_secmark() || skb == NULL || skb->secmark == 0) return NULL; return smack_from_secid(skb->secmark);
@@ -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_secmark = true, }; static const struct lsm_id smack_lsmid = {
diff --git a/security/smack/smack_netfilter.c b/security/smack/smack_netfilter.c
index 17ba578b1308..1dcaba0d224a 100644
--- a/security/smack/smack_netfilter.c
+++ b/security/smack/smack_netfilter.c@@ -26,7 +26,7 @@ static unsigned int smack_ip_output(void *priv, struct socket_smack *ssp; struct smack_known *skp; - if (sk) { + if (smack_secmark() && sk) { ssp = smack_sock(sk); skp = ssp->smk_out; skb->secmark = skp->smk_secid;
@@ -54,12 +54,18 @@ static const struct nf_hook_ops smack_nf_ops[] = { static int __net_init smack_nf_register(struct net *net) { + if (!smack_secmark()) + return 0; + return nf_register_net_hooks(net, smack_nf_ops, ARRAY_SIZE(smack_nf_ops)); } static void __net_exit smack_nf_unregister(struct net *net) { + if (!smack_secmark()) + return; + nf_unregister_net_hooks(net, smack_nf_ops, ARRAY_SIZE(smack_nf_ops)); }
@@ -70,7 +76,7 @@ static struct pernet_operations smack_net_ops = { int __init smack_nf_ip_init(void) { - if (smack_enabled == 0) + if (smack_enabled == 0 || !smack_secmark()) return 0; printk(KERN_DEBUG "Smack: Registering netfilter hooks\n");
--
2.47.0