@@ -1852,6 +1852,7 @@ struct lsm_blob_sizes {
int lbs_file;
int lbs_inode;
int lbs_sock;
+ int lbs_superblock;
};
/*
@@ -89,6 +89,7 @@ int __init security_init(void)
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);
+ pr_info("LSM: superblock blob size = %d\n", blob_sizes.lbs_superblock);
#endif
return 0;
@@ -230,6 +231,7 @@ void __init security_add_blobs(struct lsm_blob_sizes *needed)
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);
+ lsm_set_size(&needed->lbs_superblock, &blob_sizes.lbs_superblock);
}
/**
@@ -307,6 +309,31 @@ int lsm_sock_alloc(struct sock *sock)
return 0;
}
+/**
+ * lsm_superblock_alloc - allocate a composite superblock blob
+ * @sb: the superblock that needs a blob
+ *
+ * Allocate the superblock blob for all the modules
+ *
+ * Returns 0, or -ENOMEM if memory can't be allocated.
+ */
+int lsm_superblock_alloc(struct super_block *sb)
+{
+#ifdef CONFIG_SECURITY_STACKING_DEBUG
+ if (sb->s_security) {
+ pr_info("%s: Inbound superblock blob is not NULL.\n", __func__);
+ return 0;
+ }
+#endif
+ if (blob_sizes.lbs_superblock == 0)
+ return 0;
+
+ sb->s_security = kzalloc(blob_sizes.lbs_superblock, GFP_KERNEL);
+ if (sb->s_security == NULL)
+ return -ENOMEM;
+ return 0;
+}
+
/*
* Hook list operation macros.
*
@@ -479,12 +506,18 @@ int security_bprm_secureexec(struct linux_binprm *bprm)
int security_sb_alloc(struct super_block *sb)
{
+ int rc = lsm_superblock_alloc(sb);
+
+ if (rc)
+ return rc;
return call_int_hook(sb_alloc_security, 0, sb);
}
void security_sb_free(struct super_block *sb)
{
call_void_hook(sb_free_security, sb);
+ kfree(sb->s_security);
+ sb->s_security = NULL;
}
int security_sb_copy_data(char *orig, char *copy)
@@ -340,11 +340,7 @@ static int file_alloc_security(struct file *file)
static int superblock_alloc_security(struct super_block *sb)
{
- struct superblock_security_struct *sbsec;
-
- sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
- if (!sbsec)
- return -ENOMEM;
+ struct superblock_security_struct *sbsec = selinux_superblock(sb);
mutex_init(&sbsec->lock);
INIT_LIST_HEAD(&sbsec->isec_head);
@@ -353,18 +349,10 @@ static int superblock_alloc_security(struct super_block *sb)
sbsec->sid = SECINITSID_UNLABELED;
sbsec->def_sid = SECINITSID_FILE;
sbsec->mntpoint_sid = SECINITSID_UNLABELED;
- sb->s_security = sbsec;
return 0;
}
-static void superblock_free_security(struct super_block *sb)
-{
- struct superblock_security_struct *sbsec = selinux_superblock(sb);
- sb->s_security = NULL;
- kfree(sbsec);
-}
-
/* The file system's label must be initialized prior to use. */
static const char *labeling_behaviors[7] = {
@@ -2553,11 +2541,6 @@ static int selinux_sb_alloc_security(struct super_block *sb)
return superblock_alloc_security(sb);
}
-static void selinux_sb_free_security(struct super_block *sb)
-{
- superblock_free_security(sb);
-}
-
static inline int match_prefix(char *prefix, int plen, char *option, int olen)
{
if (plen > olen)
@@ -5960,6 +5943,7 @@ struct lsm_blob_sizes selinux_blob_sizes = {
.lbs_file = sizeof(struct file_security_struct),
.lbs_inode = sizeof(struct inode_security_struct),
.lbs_sock = sizeof(struct sk_security_struct),
+ .lbs_superblock = sizeof(struct superblock_security_struct),
};
static struct security_hook_list selinux_hooks[] = {
@@ -5986,7 +5970,6 @@ static struct security_hook_list selinux_hooks[] = {
LSM_HOOK_INIT(bprm_secureexec, selinux_bprm_secureexec),
LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security),
- LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security),
LSM_HOOK_INIT(sb_copy_data, selinux_sb_copy_data),
LSM_HOOK_INIT(sb_remount, selinux_sb_remount),
LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount),
@@ -161,7 +161,11 @@ static inline struct inode_security_struct *selinux_inode(
static inline struct superblock_security_struct *selinux_superblock(
const struct super_block *superblock)
{
+#ifdef CONFIG_SECURITY_STACKING
+ return superblock->s_security + selinux_blob_sizes.lbs_superblock;
+#else
return superblock->s_security;
+#endif
}
static inline struct msg_security_struct *selinux_msg_msg(
@@ -380,7 +380,11 @@ static inline struct socket_smack *smack_sock(const struct sock *sock)
static inline struct superblock_smack *smack_superblock(
const struct super_block *superblock)
{
+#ifdef CONFIG_SECURITY_STACKING
+ return superblock->s_security + smack_blob_sizes.lbs_superblock;
+#else
return superblock->s_security;
+#endif
}
static inline struct smack_known *smack_msg_msg(const struct msg_msg *msg)
@@ -522,12 +522,7 @@ static int smack_syslog(int typefrom_file)
*/
static int smack_sb_alloc_security(struct super_block *sb)
{
- struct superblock_smack *sbsp;
-
- sbsp = kzalloc(sizeof(struct superblock_smack), GFP_KERNEL);
-
- if (sbsp == NULL)
- return -ENOMEM;
+ struct superblock_smack *sbsp = smack_superblock(sb);
sbsp->smk_root = &smack_known_floor;
sbsp->smk_default = &smack_known_floor;
@@ -536,25 +531,11 @@ static int smack_sb_alloc_security(struct super_block *sb)
/*
* SMK_SB_INITIALIZED will be zero from kzalloc.
*/
- sb->s_security = sbsp;
return 0;
}
/**
- * smack_sb_free_security - free a superblock blob
- * @sb: the superblock getting the blob
- *
- */
-static void smack_sb_free_security(struct super_block *sb)
-{
- struct superblock_smack *sbsp = smack_superblock(sb);
-
- kfree(sbsp);
- sb->s_security = NULL;
-}
-
-/**
* smack_sb_copy_data - copy mount options data for processing
* @orig: where to start
* @smackopts: mount options string
@@ -4551,6 +4532,7 @@ struct lsm_blob_sizes smack_blob_sizes = {
.lbs_file = sizeof(struct smack_known *),
.lbs_inode = sizeof(struct inode_smack),
.lbs_sock = sizeof(struct socket_smack),
+ .lbs_superblock = sizeof(struct superblock_smack),
};
static struct security_hook_list smack_hooks[] = {
@@ -4559,7 +4541,6 @@ static struct security_hook_list smack_hooks[] = {
LSM_HOOK_INIT(syslog, smack_syslog),
LSM_HOOK_INIT(sb_alloc_security, smack_sb_alloc_security),
- LSM_HOOK_INIT(sb_free_security, smack_sb_free_security),
LSM_HOOK_INIT(sb_copy_data, smack_sb_copy_data),
LSM_HOOK_INIT(sb_kern_mount, smack_sb_kern_mount),
LSM_HOOK_INIT(sb_statfs, smack_sb_statfs),
Subject: [PATCH 20/25] LSM: Infrastructure managed superblock security blob Move management of the superblock 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 | 33 +++++++++++++++++++++++++++++++++ security/selinux/hooks.c | 21 ++------------------- security/selinux/include/objsec.h | 4 ++++ security/smack/smack.h | 4 ++++ security/smack/smack_lsm.c | 23 ++--------------------- 6 files changed, 46 insertions(+), 40 deletions(-)