From 1b0649d3955ec7decf4fe387bb9b1b50d866a796 Mon Sep 17 00:00:00 2001 From: Casey Schaufler Date: Mon, 11 Dec 2023 10:56:53 -0800 Subject: [PATCH] UBUNTU: SAUCE: apparmor4.0.0 [31/90]: LSM stacking v39: LSM: Exclusive secmark usage BugLink: http://bugs.launchpad.net/bugs/2028253 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 (cherry picked from commit c0c9497b3b4153c7cea3e7dec321996b24b96c04 https://git.launchpad.net/~apparmor-dev/ubuntu-kernel-next) Signed-off-by: Paolo Pisati --- include/linux/lsm_hooks.h | 1 + security/apparmor/include/net.h | 5 +++++ security/apparmor/lsm.c | 7 ++++--- security/security.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 605aaf38c3f5..4deb1a4d2d1a 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -81,6 +81,7 @@ struct lsm_blob_sizes { int lbs_msg_msg; int lbs_task; int lbs_xattr_count; /* number of xattr slots in new_xattrs array */ + 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 e62a00d198e0..748e8cca495f 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -1296,7 +1296,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; return apparmor_secmark_check(ctx->label, OP_RECVMSG, AA_MAY_RECEIVE, @@ -1405,7 +1405,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, @@ -1421,6 +1421,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 = { @@ -2084,7 +2085,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/security.c b/security/security.c index b0e08573257f..1d50b59ee656 100644 --- a/security/security.c +++ b/security/security.c @@ -233,6 +233,12 @@ static void __init lsm_set_blob_sizes(struct lsm_blob_sizes *needed) lsm_set_blob_size(&needed->lbs_task, &blob_sizes.lbs_task); lsm_set_blob_size(&needed->lbs_xattr_count, &blob_sizes.lbs_xattr_count); + if (needed->lbs_secmark) { + if (!blob_sizes.lbs_secmark) + blob_sizes.lbs_secmark = true; + else + needed->lbs_secmark = false; + } } /* Prepare LSM for initialization. */ diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index a7e2e9a9a744..334a6b79753a 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)); } @@ -7025,6 +7026,7 @@ struct lsm_blob_sizes selinux_blob_sizes __ro_after_init = { .lbs_sock = sizeof(struct sk_security_struct), .lbs_superblock = sizeof(struct superblock_security_struct), .lbs_xattr_count = SELINUX_INODE_INIT_XATTRS, + .lbs_secmark = true, }; #ifdef CONFIG_PERF_EVENTS diff --git a/security/smack/smack.h b/security/smack/smack.h index 297f21446f45..0f5bc5c03b9e 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h @@ -369,6 +369,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 220fda8ea101..51bfb3a656a0 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -4091,7 +4091,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); @@ -5065,6 +5065,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 bad71b7e648d..fd146e3a2286 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 = { static 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");