[PATCH v8 03/28] LSM: Infrastructure management of the key blob

Stephen Smalley sds at tycho.nsa.gov
Mon Sep 16 18:47:28 UTC 2019


On 8/29/19 7:29 PM, Casey Schaufler wrote:
> From: Casey Schaufler <cschaufler at schaufler-ca.com>
> 
> Move management of the key->security blob out of the
> individual security modules and into the security
> infrastructure. Instead of allocating the blobs from within
> the modules the modules tell the infrastructure how much
> space is required, and the space is allocated there.

As with the superblock blob, I don't see that this is needed for 
stacking AA but I don't object to moving all the security blobs to 
infrastructure management for consistency.

Reviewed-by: Stephen Smalley <sds at tycho.nsa.gov>

> 
> Reviewed-by: Kees Cook <keescook at chromium.org>
> Reviewed-by: John Johansen <jojn.johansen at canonical.com>
> Signed-off-by: Casey Schaufler <casey at schaufler-ca.com>
> ---
>   include/linux/lsm_hooks.h         |  1 +
>   security/security.c               | 40 ++++++++++++++++++++++++++++++-
>   security/selinux/hooks.c          | 23 +++++-------------
>   security/selinux/include/objsec.h |  7 ++++++
>   security/smack/smack.h            |  7 ++++++
>   security/smack/smack_lsm.c        | 33 ++++++++++++-------------
>   6 files changed, 75 insertions(+), 36 deletions(-)
> 
> diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
> index b353482ea348..3fe39abccc8f 100644
> --- a/include/linux/lsm_hooks.h
> +++ b/include/linux/lsm_hooks.h
> @@ -2050,6 +2050,7 @@ struct lsm_blob_sizes {
>   	int	lbs_sock;
>   	int	lbs_superblock;
>   	int	lbs_ipc;
> +	int	lbs_key;
>   	int	lbs_msg_msg;
>   	int	lbs_task;
>   };
> diff --git a/security/security.c b/security/security.c
> index 2c0834db7976..7cfedb90210a 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -172,6 +172,9 @@ static void __init lsm_set_blob_sizes(struct lsm_blob_sizes *needed)
>   		blob_sizes.lbs_inode = sizeof(struct rcu_head);
>   	lsm_set_blob_size(&needed->lbs_inode, &blob_sizes.lbs_inode);
>   	lsm_set_blob_size(&needed->lbs_ipc, &blob_sizes.lbs_ipc);
> +#ifdef CONFIG_KEYS
> +	lsm_set_blob_size(&needed->lbs_key, &blob_sizes.lbs_key);
> +#endif
>   	lsm_set_blob_size(&needed->lbs_msg_msg, &blob_sizes.lbs_msg_msg);
>   	lsm_set_blob_size(&needed->lbs_sock, &blob_sizes.lbs_sock);
>   	lsm_set_blob_size(&needed->lbs_superblock, &blob_sizes.lbs_superblock);
> @@ -307,6 +310,9 @@ static void __init ordered_lsm_init(void)
>   	init_debug("file blob size       = %d\n", blob_sizes.lbs_file);
>   	init_debug("inode blob size      = %d\n", blob_sizes.lbs_inode);
>   	init_debug("ipc blob size        = %d\n", blob_sizes.lbs_ipc);
> +#ifdef CONFIG_KEYS
> +	init_debug("key blob size        = %d\n", blob_sizes.lbs_key);
> +#endif /* CONFIG_KEYS */
>   	init_debug("msg_msg blob size    = %d\n", blob_sizes.lbs_msg_msg);
>   	init_debug("sock blob size       = %d\n", blob_sizes.lbs_sock);
>   	init_debug("superblock blob size = %d\n", blob_sizes.lbs_superblock);
> @@ -573,6 +579,29 @@ static int lsm_ipc_alloc(struct kern_ipc_perm *kip)
>   	return 0;
>   }
>   
> +#ifdef CONFIG_KEYS
> +/**
> + * lsm_key_alloc - allocate a composite key blob
> + * @key: the key that needs a blob
> + *
> + * Allocate the key blob for all the modules
> + *
> + * Returns 0, or -ENOMEM if memory can't be allocated.
> + */
> +static int lsm_key_alloc(struct key *key)
> +{
> +	if (blob_sizes.lbs_key == 0) {
> +		key->security = NULL;
> +		return 0;
> +	}
> +
> +	key->security = kzalloc(blob_sizes.lbs_key, GFP_KERNEL);
> +	if (key->security == NULL)
> +		return -ENOMEM;
> +	return 0;
> +}
> +#endif /* CONFIG_KEYS */
> +
>   /**
>    * lsm_msg_msg_alloc - allocate a composite msg_msg blob
>    * @mp: the msg_msg that needs a blob
> @@ -2339,12 +2368,21 @@ EXPORT_SYMBOL(security_skb_classify_flow);
>   int security_key_alloc(struct key *key, const struct cred *cred,
>   		       unsigned long flags)
>   {
> -	return call_int_hook(key_alloc, 0, key, cred, flags);
> +	int rc = lsm_key_alloc(key);
> +
> +	if (unlikely(rc))
> +		return rc;
> +	rc = call_int_hook(key_alloc, 0, key, cred, flags);
> +	if (unlikely(rc))
> +		security_key_free(key);
> +	return rc;
>   }
>   
>   void security_key_free(struct key *key)
>   {
>   	call_void_hook(key_free, key);
> +	kfree(key->security);
> +	key->security = NULL;
>   }
>   
>   int security_key_permission(key_ref_t key_ref,
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 5d74ed35b728..c83ec2652eda 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -6353,11 +6353,7 @@ static int selinux_key_alloc(struct key *k, const struct cred *cred,
>   			     unsigned long flags)
>   {
>   	const struct task_security_struct *tsec;
> -	struct key_security_struct *ksec;
> -
> -	ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
> -	if (!ksec)
> -		return -ENOMEM;
> +	struct key_security_struct *ksec = selinux_key(k);
>   
>   	tsec = selinux_cred(cred);
>   	if (tsec->keycreate_sid)
> @@ -6365,18 +6361,9 @@ static int selinux_key_alloc(struct key *k, const struct cred *cred,
>   	else
>   		ksec->sid = tsec->sid;
>   
> -	k->security = ksec;
>   	return 0;
>   }
>   
> -static void selinux_key_free(struct key *k)
> -{
> -	struct key_security_struct *ksec = k->security;
> -
> -	k->security = NULL;
> -	kfree(ksec);
> -}
> -
>   static int selinux_key_permission(key_ref_t key_ref,
>   				  const struct cred *cred,
>   				  unsigned perm)
> @@ -6394,7 +6381,7 @@ static int selinux_key_permission(key_ref_t key_ref,
>   	sid = cred_sid(cred);
>   
>   	key = key_ref_to_ptr(key_ref);
> -	ksec = key->security;
> +	ksec = selinux_key(key);
>   
>   	return avc_has_perm(&selinux_state,
>   			    sid, ksec->sid, SECCLASS_KEY, perm, NULL);
> @@ -6402,7 +6389,7 @@ static int selinux_key_permission(key_ref_t key_ref,
>   
>   static int selinux_key_getsecurity(struct key *key, char **_buffer)
>   {
> -	struct key_security_struct *ksec = key->security;
> +	struct key_security_struct *ksec = selinux_key(key);
>   	char *context = NULL;
>   	unsigned len;
>   	int rc;
> @@ -6627,6 +6614,9 @@ struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = {
>   	.lbs_file = sizeof(struct file_security_struct),
>   	.lbs_inode = sizeof(struct inode_security_struct),
>   	.lbs_ipc = sizeof(struct ipc_security_struct),
> +#ifdef CONFIG_KEYS
> +	.lbs_key = sizeof(struct key_security_struct),
> +#endif /* CONFIG_KEYS */
>   	.lbs_msg_msg = sizeof(struct msg_security_struct),
>   	.lbs_sock = sizeof(struct sk_security_struct),
>   	.lbs_superblock = sizeof(struct superblock_security_struct),
> @@ -6842,7 +6832,6 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
>   
>   #ifdef CONFIG_KEYS
>   	LSM_HOOK_INIT(key_alloc, selinux_key_alloc),
> -	LSM_HOOK_INIT(key_free, selinux_key_free),
>   	LSM_HOOK_INIT(key_permission, selinux_key_permission),
>   	LSM_HOOK_INIT(key_getsecurity, selinux_key_getsecurity),
>   #endif
> diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
> index 29f02b8f8f31..3b78aa4ee98f 100644
> --- a/security/selinux/include/objsec.h
> +++ b/security/selinux/include/objsec.h
> @@ -194,6 +194,13 @@ static inline struct superblock_security_struct *selinux_superblock(
>   	return superblock->s_security + selinux_blob_sizes.lbs_superblock;
>   }
>   
> +#ifdef CONFIG_KEYS
> +static inline struct key_security_struct *selinux_key(const struct key *key)
> +{
> +	return key->security + selinux_blob_sizes.lbs_key;
> +}
> +#endif /* CONFIG_KEYS */
> +
>   static inline struct sk_security_struct *selinux_sock(const struct sock *sock)
>   {
>   	return sock->sk_security + selinux_blob_sizes.lbs_sock;
> diff --git a/security/smack/smack.h b/security/smack/smack.h
> index 4ac4bf3310d7..7cc3a3382fee 100644
> --- a/security/smack/smack.h
> +++ b/security/smack/smack.h
> @@ -386,6 +386,13 @@ static inline struct superblock_smack *smack_superblock(
>   	return superblock->s_security + smack_blob_sizes.lbs_superblock;
>   }
>   
> +#ifdef CONFIG_KEYS
> +static inline struct smack_known **smack_key(const struct key *key)
> +{
> +	return key->security + smack_blob_sizes.lbs_key;
> +}
> +#endif /* CONFIG_KEYS */
> +
>   /*
>    * Is the directory transmuting?
>    */
> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> index fd69e1bd841b..e9560b078efe 100644
> --- a/security/smack/smack_lsm.c
> +++ b/security/smack/smack_lsm.c
> @@ -4179,23 +4179,13 @@ static void smack_inet_csk_clone(struct sock *sk,
>   static int smack_key_alloc(struct key *key, const struct cred *cred,
>   			   unsigned long flags)
>   {
> +	struct smack_known **blob = smack_key(key);
>   	struct smack_known *skp = smk_of_task(smack_cred(cred));
>   
> -	key->security = skp;
> +	*blob = skp;
>   	return 0;
>   }
>   
> -/**
> - * smack_key_free - Clear the key security blob
> - * @key: the object
> - *
> - * Clear the blob pointer
> - */
> -static void smack_key_free(struct key *key)
> -{
> -	key->security = NULL;
> -}
> -
>   /**
>    * smack_key_permission - Smack access on a key
>    * @key_ref: gets to the object
> @@ -4208,6 +4198,8 @@ static void smack_key_free(struct key *key)
>   static int smack_key_permission(key_ref_t key_ref,
>   				const struct cred *cred, unsigned perm)
>   {
> +	struct smack_known **blob;
> +	struct smack_known *skp;
>   	struct key *keyp;
>   	struct smk_audit_info ad;
>   	struct smack_known *tkp = smk_of_task(smack_cred(cred));
> @@ -4227,7 +4219,9 @@ static int smack_key_permission(key_ref_t key_ref,
>   	 * If the key hasn't been initialized give it access so that
>   	 * it may do so.
>   	 */
> -	if (keyp->security == NULL)
> +	blob = smack_key(keyp);
> +	skp = *blob;
> +	if (skp == NULL)
>   		return 0;
>   	/*
>   	 * This should not occur
> @@ -4247,8 +4241,8 @@ static int smack_key_permission(key_ref_t key_ref,
>   		request |= MAY_READ;
>   	if (perm & (KEY_NEED_WRITE | KEY_NEED_LINK | KEY_NEED_SETATTR))
>   		request |= MAY_WRITE;
> -	rc = smk_access(tkp, keyp->security, request, &ad);
> -	rc = smk_bu_note("key access", tkp, keyp->security, request, rc);
> +	rc = smk_access(tkp, skp, request, &ad);
> +	rc = smk_bu_note("key access", tkp, skp, request, rc);
>   	return rc;
>   }
>   
> @@ -4263,11 +4257,12 @@ static int smack_key_permission(key_ref_t key_ref,
>    */
>   static int smack_key_getsecurity(struct key *key, char **_buffer)
>   {
> -	struct smack_known *skp = key->security;
> +	struct smack_known **blob = smack_key(key);
> +	struct smack_known *skp = *blob;
>   	size_t length;
>   	char *copy;
>   
> -	if (key->security == NULL) {
> +	if (skp == NULL) {
>   		*_buffer = NULL;
>   		return 0;
>   	}
> @@ -4550,6 +4545,9 @@ struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
>   	.lbs_file = sizeof(struct smack_known *),
>   	.lbs_inode = sizeof(struct inode_smack),
>   	.lbs_ipc = sizeof(struct smack_known *),
> +#ifdef CONFIG_KEYS
> +	.lbs_key = sizeof(struct smack_known *),
> +#endif /* CONFIG_KEYS */
>   	.lbs_msg_msg = sizeof(struct smack_known *),
>   	.lbs_sock = sizeof(struct socket_smack),
>   	.lbs_superblock = sizeof(struct superblock_smack),
> @@ -4671,7 +4669,6 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
>    /* key management security hooks */
>   #ifdef CONFIG_KEYS
>   	LSM_HOOK_INIT(key_alloc, smack_key_alloc),
> -	LSM_HOOK_INIT(key_free, smack_key_free),
>   	LSM_HOOK_INIT(key_permission, smack_key_permission),
>   	LSM_HOOK_INIT(key_getsecurity, smack_key_getsecurity),
>   #endif /* CONFIG_KEYS */
> 



More information about the Linux-security-module-archive mailing list