@@ -1851,6 +1851,7 @@ struct lsm_blob_sizes {
int lbs_cred;
int lbs_file;
int lbs_inode;
+ int lbs_sock;
};
/*
@@ -26,6 +26,7 @@
#include <linux/personality.h>
#include <linux/backing-dev.h>
#include <net/flow.h>
+#include <net/sock.h>
#define MAX_LSM_EVM_XATTR 2
@@ -87,6 +88,7 @@ int __init security_init(void)
pr_info("LSM: cred blob size = %d\n", blob_sizes.lbs_cred);
pr_info("LSM: file blob size = %d\n", blob_sizes.lbs_file);
pr_info("LSM: inode blob size = %d\n", blob_sizes.lbs_inode);
+ pr_info("LSM: sock blob size = %d\n", blob_sizes.lbs_sock);
#endif
return 0;
@@ -227,6 +229,7 @@ void __init security_add_blobs(struct lsm_blob_sizes *needed)
lsm_set_size(&needed->lbs_cred, &blob_sizes.lbs_cred);
lsm_set_size(&needed->lbs_file, &blob_sizes.lbs_file);
lsm_set_size(&needed->lbs_inode, &blob_sizes.lbs_inode);
+ lsm_set_size(&needed->lbs_sock, &blob_sizes.lbs_sock);
}
/**
@@ -279,6 +282,31 @@ int lsm_inode_alloc(struct inode *inode)
return 0;
}
+/**
+ * lsm_sock_alloc - allocate a composite sock blob
+ * @sock: the sock that needs a blob
+ *
+ * Allocate the sock blob for all the modules
+ *
+ * Returns 0, or -ENOMEM if memory can't be allocated.
+ */
+int lsm_sock_alloc(struct sock *sock)
+{
+#ifdef CONFIG_SECURITY_STACKING_DEBUG
+ if (sock->sk_security) {
+ pr_info("%s: Inbound sock blob is not NULL.\n", __func__);
+ return 0;
+ }
+#endif
+ if (blob_sizes.lbs_sock == 0)
+ return 0;
+
+ sock->sk_security = kzalloc(blob_sizes.lbs_sock, GFP_KERNEL);
+ if (sock->sk_security == NULL)
+ return -ENOMEM;
+ return 0;
+}
+
/*
* Hook list operation macros.
*
@@ -1645,12 +1673,18 @@ EXPORT_SYMBOL(security_socket_getpeersec_dgram);
int security_sk_alloc(struct sock *sk, int family, gfp_t priority)
{
+ int rc = lsm_sock_alloc(sk);
+
+ if (rc)
+ return rc;
return call_int_hook(sk_alloc_security, 0, sk, family, priority);
}
void security_sk_free(struct sock *sk)
{
call_void_hook(sk_free_security, sk);
+ kfree(sk->sk_security);
+ sk->sk_security = NULL;
}
void security_sk_clone(const struct sock *sk, struct sock *newsk)
@@ -4639,17 +4639,12 @@ out:
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;
}
@@ -4658,9 +4653,7 @@ static void selinux_sk_free_security(struct sock *sk)
{
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)
@@ -5966,6 +5959,7 @@ struct lsm_blob_sizes selinux_blob_sizes = {
.lbs_cred = sizeof(struct task_security_struct),
.lbs_file = sizeof(struct file_security_struct),
.lbs_inode = sizeof(struct inode_security_struct),
+ .lbs_sock = sizeof(struct sk_security_struct),
};
static struct security_hook_list selinux_hooks[] = {
@@ -183,7 +183,11 @@ static inline struct key_security_struct *selinux_key(const struct key *key)
static inline struct sk_security_struct *selinux_sock(const struct sock *sock)
{
+#ifdef CONFIG_SECURITY_STACKING
+ return sock->sk_security + selinux_blob_sizes.lbs_sock;
+#else
return sock->sk_security;
+#endif
}
#endif /* _SELINUX_OBJSEC_H_ */
@@ -370,7 +370,11 @@ static inline struct inode_smack *smack_inode(const struct inode *inode)
static inline struct socket_smack *smack_sock(const struct sock *sock)
{
+#ifdef CONFIG_SECURITY_STACKING
+ return sock->sk_security + smack_blob_sizes.lbs_sock;
+#else
return sock->sk_security;
+#endif
}
static inline struct superblock_smack *smack_superblock(
@@ -1859,7 +1859,7 @@ static int smack_file_receive(struct file *file)
if (S_ISSOCK(inode->i_mode)) {
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
@@ -2279,35 +2279,16 @@ 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);
ssp->smk_in = skp;
ssp->smk_out = skp;
ssp->smk_packet = NULL;
- sk->sk_security = ssp;
-
return 0;
}
/**
- * smack_sk_free_security - Free a socket blob
- * @sk: the socket
- *
- * Clears the blob pointer
- */
-static void smack_sk_free_security(struct sock *sk)
-{
- struct socket_smack *ssp = smack_sock(sk);
-
- kfree(ssp);
-}
-
-/**
* smack_ipv4host_label - check host based restrictions
* @sip: the object end
*
@@ -4569,6 +4550,7 @@ struct lsm_blob_sizes smack_blob_sizes = {
.lbs_cred = sizeof(struct task_smack),
.lbs_file = sizeof(struct smack_known *),
.lbs_inode = sizeof(struct inode_smack),
+ .lbs_sock = sizeof(struct socket_smack),
};
static struct security_hook_list smack_hooks[] = {
@@ -4681,7 +4663,6 @@ static struct security_hook_list smack_hooks[] = {
LSM_HOOK_INIT(socket_getpeersec_stream, smack_socket_getpeersec_stream),
LSM_HOOK_INIT(socket_getpeersec_dgram, smack_socket_getpeersec_dgram),
LSM_HOOK_INIT(sk_alloc_security, smack_sk_alloc_security),
- LSM_HOOK_INIT(sk_free_security, smack_sk_free_security),
LSM_HOOK_INIT(sock_graft, smack_sock_graft),
LSM_HOOK_INIT(inet_conn_request, smack_inet_conn_request),
LSM_HOOK_INIT(inet_csk_clone, smack_inet_csk_clone),
Subject: [PATCH 19/25] LSM: Infrastructure managed socket security blob Move management of the sock security blob from the security modules to the LSM infrastructure. This requires that the modules declare the blob size they require, so the module registration process has to include that. Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> --- include/linux/lsm_hooks.h | 1 + security/security.c | 34 ++++++++++++++++++++++++++++++++++ security/selinux/hooks.c | 10 ++-------- security/selinux/include/objsec.h | 4 ++++ security/smack/smack.h | 4 ++++ security/smack/smack_lsm.c | 25 +++---------------------- 6 files changed, 48 insertions(+), 30 deletions(-)