[PATCH] LSM: Infrastructure management of the sock

Casey Schaufler casey at schaufler-ca.com
Wed May 31 14:00:40 UTC 2023


On 5/31/2023 4:05 AM, GONG, Ruiqi wrote:
> As the security infrastructure has taken over the management of multiple
> *_security blobs that are accessed by multiple security modules, and
> sk->sk_security shares the same situation, move its management out of
> individual security modules and into the security infrastructure as
> well. The infrastructure does the memory allocation, and each relavant
> module uses its own share.

Do you have a reason to make this change? The LSM infrastructure
manages other security blobs to enable multiple concurrently active
LSMs to use the blob. If only one LSM on a system can use the
socket blob there's no reason to move the management.

>
> Signed-off-by: GONG, Ruiqi <gongruiqi at huaweicloud.com>
> ---
>  include/linux/lsm_hooks.h         |  1 +
>  security/apparmor/include/net.h   |  2 +-
>  security/apparmor/lsm.c           | 20 +-------
>  security/security.c               | 35 ++++++++++++-
>  security/selinux/hooks.c          | 81 ++++++++++++++-----------------
>  security/selinux/include/objsec.h |  4 ++
>  security/selinux/netlabel.c       | 22 ++++-----
>  security/smack/smack.h            |  5 ++
>  security/smack/smack_lsm.c        | 65 +++++++++++--------------
>  security/smack/smack_netfilter.c  |  4 +-
>  10 files changed, 125 insertions(+), 114 deletions(-)
>
> diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
> index ab2b2fafa4a4..67b6e87ca6ec 100644
> --- a/include/linux/lsm_hooks.h
> +++ b/include/linux/lsm_hooks.h
> @@ -62,6 +62,7 @@ struct lsm_blob_sizes {
>  	int	lbs_superblock;
>  	int	lbs_ipc;
>  	int	lbs_msg_msg;
> +	int	lbs_sock;
>  	int	lbs_task;
>  };
>  
> diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
> index 6fa440b5daed..9eb159c09578 100644
> --- a/security/apparmor/include/net.h
> +++ b/security/apparmor/include/net.h
> @@ -51,7 +51,7 @@ struct aa_sk_ctx {
>  	struct aa_label *peer;
>  };
>  
> -#define SK_CTX(X) ((X)->sk_security)
> +#define SK_CTX(X) ((X)->sk_security + apparmor_blob_sizes.lbs_sock)
>  #define SOCK_ctx(X) SOCK_INODE(X)->i_security
>  #define DEFINE_AUDIT_NET(NAME, OP, SK, F, T, P)				  \
>  	struct lsm_network_audit NAME ## _net = { .sk = (SK),		  \
> diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
> index f431251ffb91..3dd849a6d7a1 100644
> --- a/security/apparmor/lsm.c
> +++ b/security/apparmor/lsm.c
> @@ -818,22 +818,6 @@ static int apparmor_task_kill(struct task_struct *target, struct kernel_siginfo
>  	return error;
>  }
>  
> -/**
> - * apparmor_sk_alloc_security - allocate and attach the sk_security field
> - */
> -static int apparmor_sk_alloc_security(struct sock *sk, int family, gfp_t flags)
> -{
> -	struct aa_sk_ctx *ctx;
> -
> -	ctx = kzalloc(sizeof(*ctx), flags);
> -	if (!ctx)
> -		return -ENOMEM;
> -
> -	SK_CTX(sk) = ctx;
> -
> -	return 0;
> -}
> -
>  /**
>   * apparmor_sk_free_security - free the sk_security field
>   */
> @@ -841,10 +825,8 @@ static void apparmor_sk_free_security(struct sock *sk)
>  {
>  	struct aa_sk_ctx *ctx = SK_CTX(sk);
>  
> -	SK_CTX(sk) = NULL;
>  	aa_put_label(ctx->label);
>  	aa_put_label(ctx->peer);
> -	kfree(ctx);
>  }
>  
>  /**
> @@ -1212,6 +1194,7 @@ static int apparmor_inet_conn_request(const struct sock *sk, struct sk_buff *skb
>  struct lsm_blob_sizes apparmor_blob_sizes __ro_after_init = {
>  	.lbs_cred = sizeof(struct aa_label *),
>  	.lbs_file = sizeof(struct aa_file_ctx),
> +	.lbs_sock = sizeof(struct aa_sk_ctx),
>  	.lbs_task = sizeof(struct aa_task_ctx),
>  };
>  
> @@ -1250,7 +1233,6 @@ static struct security_hook_list apparmor_hooks[] __ro_after_init = {
>  	LSM_HOOK_INIT(getprocattr, apparmor_getprocattr),
>  	LSM_HOOK_INIT(setprocattr, apparmor_setprocattr),
>  
> -	LSM_HOOK_INIT(sk_alloc_security, apparmor_sk_alloc_security),
>  	LSM_HOOK_INIT(sk_free_security, apparmor_sk_free_security),
>  	LSM_HOOK_INIT(sk_clone_security, apparmor_sk_clone_security),
>  
> diff --git a/security/security.c b/security/security.c
> index b720424ca37d..e71f4717cde5 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -30,6 +30,7 @@
>  #include <linux/string.h>
>  #include <linux/msg.h>
>  #include <net/flow.h>
> +#include <net/sock.h>
>  
>  #define MAX_LSM_EVM_XATTR	2
>  
> @@ -210,6 +211,7 @@ static void __init lsm_set_blob_sizes(struct lsm_blob_sizes *needed)
>  	lsm_set_blob_size(&needed->lbs_inode, &blob_sizes.lbs_inode);
>  	lsm_set_blob_size(&needed->lbs_ipc, &blob_sizes.lbs_ipc);
>  	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);
>  	lsm_set_blob_size(&needed->lbs_task, &blob_sizes.lbs_task);
>  }
> @@ -376,6 +378,7 @@ static void __init ordered_lsm_init(void)
>  	init_debug("inode blob size      = %d\n", blob_sizes.lbs_inode);
>  	init_debug("ipc blob size        = %d\n", blob_sizes.lbs_ipc);
>  	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);
>  	init_debug("task blob size       = %d\n", blob_sizes.lbs_task);
>  
> @@ -733,6 +736,27 @@ static int lsm_superblock_alloc(struct super_block *sb)
>  	return 0;
>  }
>  
> +/**
> + * lsm_sock_alloc - allocate a composite socket blob
> + * @sk: the socket that needs a blob
> + *
> + * Allocate the socket blob for all the modules
> + *
> + * Returns 0, or -ENOMEM if memory can't be allocated.
> + */
> +static int lsm_sock_alloc(struct sock *sk)
> +{
> +	if (blob_sizes.lbs_sock == 0) {
> +		sk->sk_security = NULL;
> +		return 0;
> +	}
> +
> +	sk->sk_security = kzalloc(blob_sizes.lbs_sock, GFP_KERNEL);
> +	if (sk->sk_security == NULL)
> +		return -ENOMEM;
> +	return 0;
> +}
> +
>  /*
>   * The default value of the LSM hook is defined in linux/lsm_hook_defs.h and
>   * can be accessed with:
> @@ -4369,7 +4393,14 @@ EXPORT_SYMBOL(security_socket_getpeersec_dgram);
>   */
>  int security_sk_alloc(struct sock *sk, int family, gfp_t priority)
>  {
> -	return call_int_hook(sk_alloc_security, 0, sk, family, priority);
> +	int rc = lsm_sock_alloc(sk);
> +
> +	if (unlikely(rc))
> +		return rc;
> +	rc = call_int_hook(sk_alloc_security, 0, sk, family, priority);
> +	if (unlikely(rc))
> +		security_sk_free(sk);
> +	return rc;
>  }
>  
>  /**
> @@ -4381,6 +4412,8 @@ int security_sk_alloc(struct sock *sk, int family, gfp_t priority)
>  void security_sk_free(struct sock *sk)
>  {
>  	call_void_hook(sk_free_security, sk);
> +	kfree(sk->sk_security);
> +	sk->sk_security = NULL;
>  }
>  
>  /**
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index d06e350fedee..f8397f05dc90 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -4497,7 +4497,7 @@ static int socket_sockcreate_sid(const struct task_security_struct *tsec,
>  
>  static int sock_has_perm(struct sock *sk, u32 perms)
>  {
> -	struct sk_security_struct *sksec = sk->sk_security;
> +	struct sk_security_struct *sksec = selinux_sock(sk);
>  	struct common_audit_data ad;
>  	struct lsm_network_audit net = {0,};
>  
> @@ -4552,7 +4552,7 @@ static int selinux_socket_post_create(struct socket *sock, int family,
>  	isec->initialized = LABEL_INITIALIZED;
>  
>  	if (sock->sk) {
> -		sksec = sock->sk->sk_security;
> +		sksec = selinux_sock(sock->sk);
>  		sksec->sclass = sclass;
>  		sksec->sid = sid;
>  		/* Allows detection of the first association on this socket */
> @@ -4568,8 +4568,8 @@ static int selinux_socket_post_create(struct socket *sock, int family,
>  static int selinux_socket_socketpair(struct socket *socka,
>  				     struct socket *sockb)
>  {
> -	struct sk_security_struct *sksec_a = socka->sk->sk_security;
> -	struct sk_security_struct *sksec_b = sockb->sk->sk_security;
> +	struct sk_security_struct *sksec_a = selinux_sock(socka->sk);
> +	struct sk_security_struct *sksec_b = selinux_sock(sockb->sk);
>  
>  	sksec_a->peer_sid = sksec_b->sid;
>  	sksec_b->peer_sid = sksec_a->sid;
> @@ -4584,7 +4584,7 @@ static int selinux_socket_socketpair(struct socket *socka,
>  static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
>  {
>  	struct sock *sk = sock->sk;
> -	struct sk_security_struct *sksec = sk->sk_security;
> +	struct sk_security_struct *sksec = selinux_sock(sk);
>  	u16 family;
>  	int err;
>  
> @@ -4717,7 +4717,7 @@ static int selinux_socket_connect_helper(struct socket *sock,
>  					 struct sockaddr *address, int addrlen)
>  {
>  	struct sock *sk = sock->sk;
> -	struct sk_security_struct *sksec = sk->sk_security;
> +	struct sk_security_struct *sksec = selinux_sock(sk);
>  	int err;
>  
>  	err = sock_has_perm(sk, SOCKET__CONNECT);
> @@ -4895,9 +4895,9 @@ static int selinux_socket_unix_stream_connect(struct sock *sock,
>  					      struct sock *other,
>  					      struct sock *newsk)
>  {
> -	struct sk_security_struct *sksec_sock = sock->sk_security;
> -	struct sk_security_struct *sksec_other = other->sk_security;
> -	struct sk_security_struct *sksec_new = newsk->sk_security;
> +	struct sk_security_struct *sksec_sock = selinux_sock(sock);
> +	struct sk_security_struct *sksec_other = selinux_sock(other);
> +	struct sk_security_struct *sksec_new = selinux_sock(newsk);
>  	struct common_audit_data ad;
>  	struct lsm_network_audit net = {0,};
>  	int err;
> @@ -4928,8 +4928,8 @@ static int selinux_socket_unix_stream_connect(struct sock *sock,
>  static int selinux_socket_unix_may_send(struct socket *sock,
>  					struct socket *other)
>  {
> -	struct sk_security_struct *ssec = sock->sk->sk_security;
> -	struct sk_security_struct *osec = other->sk->sk_security;
> +	struct sk_security_struct *ssec = selinux_sock(sock->sk);
> +	struct sk_security_struct *osec = selinux_sock(other->sk);
>  	struct common_audit_data ad;
>  	struct lsm_network_audit net = {0,};
>  
> @@ -4968,7 +4968,7 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
>  				       u16 family)
>  {
>  	int err = 0;
> -	struct sk_security_struct *sksec = sk->sk_security;
> +	struct sk_security_struct *sksec = selinux_sock(sk);
>  	u32 sk_sid = sksec->sid;
>  	struct common_audit_data ad;
>  	struct lsm_network_audit net = {0,};
> @@ -5000,7 +5000,7 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
>  static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
>  {
>  	int err;
> -	struct sk_security_struct *sksec = sk->sk_security;
> +	struct sk_security_struct *sksec = selinux_sock(sk);
>  	u16 family = sk->sk_family;
>  	u32 sk_sid = sksec->sid;
>  	struct common_audit_data ad;
> @@ -5073,7 +5073,7 @@ static int selinux_socket_getpeersec_stream(struct socket *sock,
>  	int err = 0;
>  	char *scontext = NULL;
>  	u32 scontext_len;
> -	struct sk_security_struct *sksec = sock->sk->sk_security;
> +	struct sk_security_struct *sksec = selinux_sock(sock->sk);
>  	u32 peer_sid = SECSID_NULL;
>  
>  	if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
> @@ -5131,34 +5131,27 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
>  
>  static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
>  {
> -	struct sk_security_struct *sksec;
> -
> -	sksec = kzalloc(sizeof(*sksec), priority);
> -	if (!sksec)
> -		return -ENOMEM;
> +	struct sk_security_struct *sksec = selinux_sock(sk);
>  
>  	sksec->peer_sid = SECINITSID_UNLABELED;
>  	sksec->sid = SECINITSID_UNLABELED;
>  	sksec->sclass = SECCLASS_SOCKET;
>  	selinux_netlbl_sk_security_reset(sksec);
> -	sk->sk_security = sksec;
>  
>  	return 0;
>  }
>  
>  static void selinux_sk_free_security(struct sock *sk)
>  {
> -	struct sk_security_struct *sksec = sk->sk_security;
> +	struct sk_security_struct *sksec = selinux_sock(sk);
>  
> -	sk->sk_security = NULL;
>  	selinux_netlbl_sk_security_free(sksec);
> -	kfree(sksec);
>  }
>  
>  static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
>  {
> -	struct sk_security_struct *sksec = sk->sk_security;
> -	struct sk_security_struct *newsksec = newsk->sk_security;
> +	struct sk_security_struct *sksec = selinux_sock(sk);
> +	struct sk_security_struct *newsksec = selinux_sock(newsk);
>  
>  	newsksec->sid = sksec->sid;
>  	newsksec->peer_sid = sksec->peer_sid;
> @@ -5172,7 +5165,7 @@ static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
>  	if (!sk)
>  		*secid = SECINITSID_ANY_SOCKET;
>  	else {
> -		struct sk_security_struct *sksec = sk->sk_security;
> +		struct sk_security_struct *sksec = selinux_sock(sk);
>  
>  		*secid = sksec->sid;
>  	}
> @@ -5182,7 +5175,7 @@ static void selinux_sock_graft(struct sock *sk, struct socket *parent)
>  {
>  	struct inode_security_struct *isec =
>  		inode_security_novalidate(SOCK_INODE(parent));
> -	struct sk_security_struct *sksec = sk->sk_security;
> +	struct sk_security_struct *sksec = selinux_sock(sk);
>  
>  	if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
>  	    sk->sk_family == PF_UNIX)
> @@ -5199,7 +5192,7 @@ static int selinux_sctp_process_new_assoc(struct sctp_association *asoc,
>  {
>  	struct sock *sk = asoc->base.sk;
>  	u16 family = sk->sk_family;
> -	struct sk_security_struct *sksec = sk->sk_security;
> +	struct sk_security_struct *sksec = selinux_sock(sk);
>  	struct common_audit_data ad;
>  	struct lsm_network_audit net = {0,};
>  	int err;
> @@ -5256,7 +5249,7 @@ static int selinux_sctp_process_new_assoc(struct sctp_association *asoc,
>  static int selinux_sctp_assoc_request(struct sctp_association *asoc,
>  				      struct sk_buff *skb)
>  {
> -	struct sk_security_struct *sksec = asoc->base.sk->sk_security;
> +	struct sk_security_struct *sksec = selinux_sock(asoc->base.sk);
>  	u32 conn_sid;
>  	int err;
>  
> @@ -5289,7 +5282,7 @@ static int selinux_sctp_assoc_request(struct sctp_association *asoc,
>  static int selinux_sctp_assoc_established(struct sctp_association *asoc,
>  					  struct sk_buff *skb)
>  {
> -	struct sk_security_struct *sksec = asoc->base.sk->sk_security;
> +	struct sk_security_struct *sksec = selinux_sock(asoc->base.sk);
>  
>  	if (!selinux_policycap_extsockclass())
>  		return 0;
> @@ -5388,8 +5381,8 @@ static int selinux_sctp_bind_connect(struct sock *sk, int optname,
>  static void selinux_sctp_sk_clone(struct sctp_association *asoc, struct sock *sk,
>  				  struct sock *newsk)
>  {
> -	struct sk_security_struct *sksec = sk->sk_security;
> -	struct sk_security_struct *newsksec = newsk->sk_security;
> +	struct sk_security_struct *sksec = selinux_sock(sk);
> +	struct sk_security_struct *newsksec = selinux_sock(newsk);
>  
>  	/* If policy does not support SECCLASS_SCTP_SOCKET then call
>  	 * the non-sctp clone version.
> @@ -5405,8 +5398,8 @@ static void selinux_sctp_sk_clone(struct sctp_association *asoc, struct sock *sk
>  
>  static int selinux_mptcp_add_subflow(struct sock *sk, struct sock *ssk)
>  {
> -	struct sk_security_struct *ssksec = ssk->sk_security;
> -	struct sk_security_struct *sksec = sk->sk_security;
> +	struct sk_security_struct *ssksec = selinux_sock(ssk);
> +	struct sk_security_struct *sksec = selinux_sock(sk);
>  
>  	ssksec->sclass = sksec->sclass;
>  	ssksec->sid = sksec->sid;
> @@ -5421,7 +5414,7 @@ static int selinux_mptcp_add_subflow(struct sock *sk, struct sock *ssk)
>  static int selinux_inet_conn_request(const struct sock *sk, struct sk_buff *skb,
>  				     struct request_sock *req)
>  {
> -	struct sk_security_struct *sksec = sk->sk_security;
> +	struct sk_security_struct *sksec = selinux_sock(sk);
>  	int err;
>  	u16 family = req->rsk_ops->family;
>  	u32 connsid;
> @@ -5442,7 +5435,7 @@ static int selinux_inet_conn_request(const struct sock *sk, struct sk_buff *skb,
>  static void selinux_inet_csk_clone(struct sock *newsk,
>  				   const struct request_sock *req)
>  {
> -	struct sk_security_struct *newsksec = newsk->sk_security;
> +	struct sk_security_struct *newsksec = selinux_sock(newsk);
>  
>  	newsksec->sid = req->secid;
>  	newsksec->peer_sid = req->peer_secid;
> @@ -5459,7 +5452,7 @@ static void selinux_inet_csk_clone(struct sock *newsk,
>  static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
>  {
>  	u16 family = sk->sk_family;
> -	struct sk_security_struct *sksec = sk->sk_security;
> +	struct sk_security_struct *sksec = selinux_sock(sk);
>  
>  	/* handle mapped IPv4 packets arriving via IPv6 sockets */
>  	if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
> @@ -5540,7 +5533,7 @@ static int selinux_tun_dev_attach_queue(void *security)
>  static int selinux_tun_dev_attach(struct sock *sk, void *security)
>  {
>  	struct tun_security_struct *tunsec = security;
> -	struct sk_security_struct *sksec = sk->sk_security;
> +	struct sk_security_struct *sksec = selinux_sock(sk);
>  
>  	/* we don't currently perform any NetLabel based labeling here and it
>  	 * isn't clear that we would want to do so anyway; while we could apply
> @@ -5666,7 +5659,7 @@ static unsigned int selinux_ip_output(void *priv, struct sk_buff *skb,
>  			return NF_ACCEPT;
>  
>  		/* standard practice, label using the parent socket */
> -		sksec = sk->sk_security;
> +		sksec = selinux_sock(sk);
>  		sid = sksec->sid;
>  	} else
>  		sid = SECINITSID_KERNEL;
> @@ -5689,7 +5682,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
>  	sk = skb_to_full_sk(skb);
>  	if (sk == NULL)
>  		return NF_ACCEPT;
> -	sksec = sk->sk_security;
> +	sksec = selinux_sock(sk);
>  
>  	ad.type = LSM_AUDIT_DATA_NET;
>  	ad.u.net = &net;
> @@ -5779,9 +5772,8 @@ static unsigned int selinux_ip_postroute(void *priv,
>  		 * selinux_inet_conn_request().  See also selinux_ip_output()
>  		 * for similar problems. */
>  		u32 skb_sid;
> -		struct sk_security_struct *sksec;
> +		struct sk_security_struct *sksec = selinux_sock(sk);
>  
> -		sksec = sk->sk_security;
>  		if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
>  			return NF_DROP;
>  		/* At this point, if the returned skb peerlbl is SECSID_NULL
> @@ -5810,7 +5802,7 @@ static unsigned int selinux_ip_postroute(void *priv,
>  	} else {
>  		/* Locally generated packet, fetch the security label from the
>  		 * associated socket. */
> -		struct sk_security_struct *sksec = sk->sk_security;
> +		struct sk_security_struct *sksec = selinux_sock(sk);
>  		peer_sid = sksec->sid;
>  		secmark_perm = PACKET__SEND;
>  	}
> @@ -5856,7 +5848,7 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
>  	unsigned int data_len = skb->len;
>  	unsigned char *data = skb->data;
>  	struct nlmsghdr *nlh;
> -	struct sk_security_struct *sksec = sk->sk_security;
> +	struct sk_security_struct *sksec = selinux_sock(sk);
>  	u16 sclass = sksec->sclass;
>  	u32 perm;
>  
> @@ -6814,6 +6806,7 @@ struct lsm_blob_sizes selinux_blob_sizes __ro_after_init = {
>  	.lbs_inode = sizeof(struct inode_security_struct),
>  	.lbs_ipc = sizeof(struct ipc_security_struct),
>  	.lbs_msg_msg = sizeof(struct msg_security_struct),
> +	.lbs_sock = sizeof(struct sk_security_struct),
>  	.lbs_superblock = sizeof(struct superblock_security_struct),
>  };
>  
> diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
> index 2953132408bf..49221f441c68 100644
> --- a/security/selinux/include/objsec.h
> +++ b/security/selinux/include/objsec.h
> @@ -194,4 +194,8 @@ static inline struct superblock_security_struct *selinux_superblock(
>  	return superblock->s_security + selinux_blob_sizes.lbs_superblock;
>  }
>  
> +static inline struct sk_security_struct *selinux_sock(const struct sock *sk)
> +{
> +	return sk->sk_security + selinux_blob_sizes.lbs_sock;
> +}
>  #endif /* _SELINUX_OBJSEC_H_ */
> diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
> index 528f5186e912..9755561aa466 100644
> --- a/security/selinux/netlabel.c
> +++ b/security/selinux/netlabel.c
> @@ -68,7 +68,7 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
>  static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk)
>  {
>  	int rc;
> -	struct sk_security_struct *sksec = sk->sk_security;
> +	struct sk_security_struct *sksec = selinux_sock(sk);
>  	struct netlbl_lsm_secattr *secattr;
>  
>  	if (sksec->nlbl_secattr != NULL)
> @@ -100,7 +100,7 @@ static struct netlbl_lsm_secattr *selinux_netlbl_sock_getattr(
>  							const struct sock *sk,
>  							u32 sid)
>  {
> -	struct sk_security_struct *sksec = sk->sk_security;
> +	struct sk_security_struct *sksec = selinux_sock(sk);
>  	struct netlbl_lsm_secattr *secattr = sksec->nlbl_secattr;
>  
>  	if (secattr == NULL)
> @@ -239,7 +239,7 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
>  	 * being labeled by it's parent socket, if it is just exit */
>  	sk = skb_to_full_sk(skb);
>  	if (sk != NULL) {
> -		struct sk_security_struct *sksec = sk->sk_security;
> +		struct sk_security_struct *sksec = selinux_sock(sk);
>  
>  		if (sksec->nlbl_state != NLBL_REQSKB)
>  			return 0;
> @@ -276,7 +276,7 @@ int selinux_netlbl_sctp_assoc_request(struct sctp_association *asoc,
>  {
>  	int rc;
>  	struct netlbl_lsm_secattr secattr;
> -	struct sk_security_struct *sksec = asoc->base.sk->sk_security;
> +	struct sk_security_struct *sksec = selinux_sock(asoc->base.sk);
>  	struct sockaddr_in addr4;
>  	struct sockaddr_in6 addr6;
>  
> @@ -355,7 +355,7 @@ int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family)
>   */
>  void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family)
>  {
> -	struct sk_security_struct *sksec = sk->sk_security;
> +	struct sk_security_struct *sksec = selinux_sock(sk);
>  
>  	if (family == PF_INET)
>  		sksec->nlbl_state = NLBL_LABELED;
> @@ -373,8 +373,8 @@ void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family)
>   */
>  void selinux_netlbl_sctp_sk_clone(struct sock *sk, struct sock *newsk)
>  {
> -	struct sk_security_struct *sksec = sk->sk_security;
> -	struct sk_security_struct *newsksec = newsk->sk_security;
> +	struct sk_security_struct *sksec = selinux_sock(sk);
> +	struct sk_security_struct *newsksec = selinux_sock(newsk);
>  
>  	newsksec->nlbl_state = sksec->nlbl_state;
>  }
> @@ -392,7 +392,7 @@ void selinux_netlbl_sctp_sk_clone(struct sock *sk, struct sock *newsk)
>  int selinux_netlbl_socket_post_create(struct sock *sk, u16 family)
>  {
>  	int rc;
> -	struct sk_security_struct *sksec = sk->sk_security;
> +	struct sk_security_struct *sksec = selinux_sock(sk);
>  	struct netlbl_lsm_secattr *secattr;
>  
>  	if (family != PF_INET && family != PF_INET6)
> @@ -506,7 +506,7 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
>  {
>  	int rc = 0;
>  	struct sock *sk = sock->sk;
> -	struct sk_security_struct *sksec = sk->sk_security;
> +	struct sk_security_struct *sksec = selinux_sock(sk);
>  	struct netlbl_lsm_secattr secattr;
>  
>  	if (selinux_netlbl_option(level, optname) &&
> @@ -544,7 +544,7 @@ static int selinux_netlbl_socket_connect_helper(struct sock *sk,
>  						struct sockaddr *addr)
>  {
>  	int rc;
> -	struct sk_security_struct *sksec = sk->sk_security;
> +	struct sk_security_struct *sksec = selinux_sock(sk);
>  	struct netlbl_lsm_secattr *secattr;
>  
>  	/* connected sockets are allowed to disconnect when the address family
> @@ -583,7 +583,7 @@ static int selinux_netlbl_socket_connect_helper(struct sock *sk,
>  int selinux_netlbl_socket_connect_locked(struct sock *sk,
>  					 struct sockaddr *addr)
>  {
> -	struct sk_security_struct *sksec = sk->sk_security;
> +	struct sk_security_struct *sksec = selinux_sock(sk);
>  
>  	if (sksec->nlbl_state != NLBL_REQSKB &&
>  	    sksec->nlbl_state != NLBL_CONNLABELED)
> diff --git a/security/smack/smack.h b/security/smack/smack.h
> index aa15ff56ed6e..2d0163076eca 100644
> --- a/security/smack/smack.h
> +++ b/security/smack/smack.h
> @@ -355,6 +355,11 @@ static inline struct superblock_smack *smack_superblock(
>  	return superblock->s_security + smack_blob_sizes.lbs_superblock;
>  }
>  
> +static inline struct socket_smack *smack_sock(const struct sock *sk)
> +{
> +	return sk->sk_security + smack_blob_sizes.lbs_sock;
> +}
> +
>  /*
>   * Is the directory transmuting?
>   */
> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> index 6e270cf3fd30..ab026ff79504 100644
> --- a/security/smack/smack_lsm.c
> +++ b/security/smack/smack_lsm.c
> @@ -1502,7 +1502,7 @@ static int smack_inode_getsecurity(struct mnt_idmap *idmap,
>  		if (sock == NULL || sock->sk == NULL)
>  			return -EOPNOTSUPP;
>  
> -		ssp = sock->sk->sk_security;
> +		ssp = smack_sock(sock->sk);
>  
>  		if (strcmp(name, XATTR_SMACK_IPIN) == 0)
>  			isp = ssp->smk_in;
> @@ -1890,7 +1890,7 @@ static int smack_file_receive(struct file *file)
>  
>  	if (inode->i_sb->s_magic == SOCKFS_MAGIC) {
>  		sock = SOCKET_I(inode);
> -		ssp = sock->sk->sk_security;
> +		ssp = smack_sock(sock->sk);
>  		tsp = smack_cred(current_cred());
>  		/*
>  		 * If the receiving process can't write to the
> @@ -2310,11 +2310,7 @@ static void smack_task_to_inode(struct task_struct *p, struct inode *inode)
>  static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags)
>  {
>  	struct smack_known *skp = smk_of_current();
> -	struct socket_smack *ssp;
> -
> -	ssp = kzalloc(sizeof(struct socket_smack), gfp_flags);
> -	if (ssp == NULL)
> -		return -ENOMEM;
> +	struct socket_smack *ssp = smack_sock(sk);
>  
>  	/*
>  	 * Sockets created by kernel threads receive web label.
> @@ -2328,8 +2324,6 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags)
>  	}
>  	ssp->smk_packet = NULL;
>  
> -	sk->sk_security = ssp;
> -
>  	return 0;
>  }
>  
> @@ -2355,7 +2349,6 @@ static void smack_sk_free_security(struct sock *sk)
>  		rcu_read_unlock();
>  	}
>  #endif
> -	kfree(sk->sk_security);
>  }
>  
>  /**
> @@ -2367,8 +2360,8 @@ static void smack_sk_free_security(struct sock *sk)
>   */
>  static void smack_sk_clone_security(const struct sock *sk, struct sock *newsk)
>  {
> -	struct socket_smack *ssp_old = sk->sk_security;
> -	struct socket_smack *ssp_new = newsk->sk_security;
> +	struct socket_smack *ssp_old = smack_sock(sk);
> +	struct socket_smack *ssp_new = smack_sock(newsk);
>  
>  	*ssp_new = *ssp_old;
>  }
> @@ -2484,7 +2477,7 @@ static struct smack_known *smack_ipv6host_label(struct sockaddr_in6 *sip)
>   */
>  static int smack_netlbl_add(struct sock *sk)
>  {
> -	struct socket_smack *ssp = sk->sk_security;
> +	struct socket_smack *ssp = smack_sock(sk);
>  	struct smack_known *skp = ssp->smk_out;
>  	int rc;
>  
> @@ -2516,7 +2509,7 @@ static int smack_netlbl_add(struct sock *sk)
>   */
>  static void smack_netlbl_delete(struct sock *sk)
>  {
> -	struct socket_smack *ssp = sk->sk_security;
> +	struct socket_smack *ssp = smack_sock(sk);
>  
>  	/*
>  	 * Take the label off the socket if one is set.
> @@ -2548,7 +2541,7 @@ static int smk_ipv4_check(struct sock *sk, struct sockaddr_in *sap)
>  	struct smack_known *skp;
>  	int rc = 0;
>  	struct smack_known *hkp;
> -	struct socket_smack *ssp = sk->sk_security;
> +	struct socket_smack *ssp = smack_sock(sk);
>  	struct smk_audit_info ad;
>  
>  	rcu_read_lock();
> @@ -2621,7 +2614,7 @@ static void smk_ipv6_port_label(struct socket *sock, struct sockaddr *address)
>  {
>  	struct sock *sk = sock->sk;
>  	struct sockaddr_in6 *addr6;
> -	struct socket_smack *ssp = sock->sk->sk_security;
> +	struct socket_smack *ssp = smack_sock(sock->sk);
>  	struct smk_port_label *spp;
>  	unsigned short port = 0;
>  
> @@ -2709,7 +2702,7 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address,
>  				int act)
>  {
>  	struct smk_port_label *spp;
> -	struct socket_smack *ssp = sk->sk_security;
> +	struct socket_smack *ssp = smack_sock(sk);
>  	struct smack_known *skp = NULL;
>  	unsigned short port;
>  	struct smack_known *object;
> @@ -2803,7 +2796,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
>  	if (sock == NULL || sock->sk == NULL)
>  		return -EOPNOTSUPP;
>  
> -	ssp = sock->sk->sk_security;
> +	ssp = smack_sock(sock->sk);
>  
>  	if (strcmp(name, XATTR_SMACK_IPIN) == 0)
>  		ssp->smk_in = skp;
> @@ -2851,7 +2844,7 @@ static int smack_socket_post_create(struct socket *sock, int family,
>  	 * Sockets created by kernel threads receive web label.
>  	 */
>  	if (unlikely(current->flags & PF_KTHREAD)) {
> -		ssp = sock->sk->sk_security;
> +		ssp = smack_sock(sock->sk);
>  		ssp->smk_in = &smack_known_web;
>  		ssp->smk_out = &smack_known_web;
>  	}
> @@ -2876,8 +2869,8 @@ static int smack_socket_post_create(struct socket *sock, int family,
>  static int smack_socket_socketpair(struct socket *socka,
>  		                   struct socket *sockb)
>  {
> -	struct socket_smack *asp = socka->sk->sk_security;
> -	struct socket_smack *bsp = sockb->sk->sk_security;
> +	struct socket_smack *asp = smack_sock(socka->sk);
> +	struct socket_smack *bsp = smack_sock(sockb->sk);
>  
>  	asp->smk_packet = bsp->smk_out;
>  	bsp->smk_packet = asp->smk_out;
> @@ -2940,7 +2933,7 @@ static int smack_socket_connect(struct socket *sock, struct sockaddr *sap,
>  		if (__is_defined(SMACK_IPV6_SECMARK_LABELING))
>  			rsp = smack_ipv6host_label(sip);
>  		if (rsp != NULL) {
> -			struct socket_smack *ssp = sock->sk->sk_security;
> +			struct socket_smack *ssp = smack_sock(sock->sk);
>  
>  			rc = smk_ipv6_check(ssp->smk_out, rsp, sip,
>  					    SMK_CONNECTING);
> @@ -3671,9 +3664,9 @@ static int smack_unix_stream_connect(struct sock *sock,
>  {
>  	struct smack_known *skp;
>  	struct smack_known *okp;
> -	struct socket_smack *ssp = sock->sk_security;
> -	struct socket_smack *osp = other->sk_security;
> -	struct socket_smack *nsp = newsk->sk_security;
> +	struct socket_smack *ssp = smack_sock(sock);
> +	struct socket_smack *osp = smack_sock(other);
> +	struct socket_smack *nsp = smack_sock(newsk);
>  	struct smk_audit_info ad;
>  	int rc = 0;
>  #ifdef CONFIG_AUDIT
> @@ -3719,8 +3712,8 @@ static int smack_unix_stream_connect(struct sock *sock,
>   */
>  static int smack_unix_may_send(struct socket *sock, struct socket *other)
>  {
> -	struct socket_smack *ssp = sock->sk->sk_security;
> -	struct socket_smack *osp = other->sk->sk_security;
> +	struct socket_smack *ssp = smack_sock(sock->sk);
> +	struct socket_smack *osp = smack_sock(other->sk);
>  	struct smk_audit_info ad;
>  	int rc;
>  
> @@ -3757,7 +3750,7 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
>  	struct sockaddr_in6 *sap = (struct sockaddr_in6 *) msg->msg_name;
>  #endif
>  #ifdef SMACK_IPV6_SECMARK_LABELING
> -	struct socket_smack *ssp = sock->sk->sk_security;
> +	struct socket_smack *ssp = smack_sock(sock->sk);
>  	struct smack_known *rsp;
>  #endif
>  	int rc = 0;
> @@ -3969,7 +3962,7 @@ static struct smack_known *smack_from_netlbl(const struct sock *sk, u16 family,
>  	netlbl_secattr_init(&secattr);
>  
>  	if (sk)
> -		ssp = sk->sk_security;
> +		ssp = smack_sock(sk);
>  
>  	if (netlbl_skbuff_getattr(skb, family, &secattr) == 0) {
>  		skp = smack_from_secattr(&secattr, ssp);
> @@ -3991,7 +3984,7 @@ static struct smack_known *smack_from_netlbl(const struct sock *sk, u16 family,
>   */
>  static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
>  {
> -	struct socket_smack *ssp = sk->sk_security;
> +	struct socket_smack *ssp = smack_sock(sk);
>  	struct smack_known *skp = NULL;
>  	int rc = 0;
>  	struct smk_audit_info ad;
> @@ -4090,12 +4083,11 @@ static int smack_socket_getpeersec_stream(struct socket *sock,
>  					  sockptr_t optval, sockptr_t optlen,
>  					  unsigned int len)
>  {
> -	struct socket_smack *ssp;
> +	struct socket_smack *ssp = smack_sock(sock->sk);
>  	char *rcp = "";
>  	u32 slen = 1;
>  	int rc = 0;
>  
> -	ssp = sock->sk->sk_security;
>  	if (ssp->smk_packet != NULL) {
>  		rcp = ssp->smk_packet->smk_known;
>  		slen = strlen(rcp) + 1;
> @@ -4145,7 +4137,7 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
>  
>  	switch (family) {
>  	case PF_UNIX:
> -		ssp = sock->sk->sk_security;
> +		ssp = smack_sock(sock->sk);
>  		s = ssp->smk_out->smk_secid;
>  		break;
>  	case PF_INET:
> @@ -4194,7 +4186,7 @@ static void smack_sock_graft(struct sock *sk, struct socket *parent)
>  	    (sk->sk_family != PF_INET && sk->sk_family != PF_INET6))
>  		return;
>  
> -	ssp = sk->sk_security;
> +	ssp = smack_sock(sk);
>  	ssp->smk_in = skp;
>  	ssp->smk_out = skp;
>  	/* cssp->smk_packet is already set in smack_inet_csk_clone() */
> @@ -4214,7 +4206,7 @@ static int smack_inet_conn_request(const struct sock *sk, struct sk_buff *skb,
>  {
>  	u16 family = sk->sk_family;
>  	struct smack_known *skp;
> -	struct socket_smack *ssp = sk->sk_security;
> +	struct socket_smack *ssp = smack_sock(sk);
>  	struct sockaddr_in addr;
>  	struct iphdr *hdr;
>  	struct smack_known *hskp;
> @@ -4300,7 +4292,7 @@ static int smack_inet_conn_request(const struct sock *sk, struct sk_buff *skb,
>  static void smack_inet_csk_clone(struct sock *sk,
>  				 const struct request_sock *req)
>  {
> -	struct socket_smack *ssp = sk->sk_security;
> +	struct socket_smack *ssp = smack_sock(sk);
>  	struct smack_known *skp;
>  
>  	if (req->peer_secid != 0) {
> @@ -4868,6 +4860,7 @@ struct lsm_blob_sizes smack_blob_sizes __ro_after_init = {
>  	.lbs_inode = sizeof(struct inode_smack),
>  	.lbs_ipc = sizeof(struct smack_known *),
>  	.lbs_msg_msg = sizeof(struct smack_known *),
> +	.lbs_sock = sizeof(struct socket_smack),
>  	.lbs_superblock = sizeof(struct superblock_smack),
>  };
>  
> diff --git a/security/smack/smack_netfilter.c b/security/smack/smack_netfilter.c
> index b945c1d3a743..bad71b7e648d 100644
> --- a/security/smack/smack_netfilter.c
> +++ b/security/smack/smack_netfilter.c
> @@ -26,8 +26,8 @@ static unsigned int smack_ip_output(void *priv,
>  	struct socket_smack *ssp;
>  	struct smack_known *skp;
>  
> -	if (sk && sk->sk_security) {
> -		ssp = sk->sk_security;
> +	if (sk) {
> +		ssp = smack_sock(sk);
>  		skp = ssp->smk_out;
>  		skb->secmark = skp->smk_secid;
>  	}



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