summaryrefslogtreecommitdiffstats
path: root/security/smack
diff options
context:
space:
mode:
authorCasey Schaufler <casey@schaufler-ca.com>2020-08-11 17:39:43 -0700
committerCasey Schaufler <cschaufler@localhost.localdomain>2020-09-11 15:31:31 -0700
commit322dd63c7f98315b5794653bc582d109841219ae (patch)
tree8e27960271441520510c2cde964a4106212a547d /security/smack
parenta2af031885071604452f03cd4e0eafdbd8014767 (diff)
downloadlinux-322dd63c7f98315b5794653bc582d109841219ae.tar.bz2
Smack: Use the netlabel cache
Utilize the Netlabel cache mechanism for incoming packet matching. Refactor the initialization of secattr structures, as it was being done in two places. Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
Diffstat (limited to 'security/smack')
-rw-r--r--security/smack/smack.h1
-rw-r--r--security/smack/smack_access.c55
-rw-r--r--security/smack/smack_lsm.c27
-rw-r--r--security/smack/smackfs.c23
4 files changed, 68 insertions, 38 deletions
diff --git a/security/smack/smack.h b/security/smack/smack.h
index c5d745a3ada8..a9768b12716b 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -297,6 +297,7 @@ struct smack_known *smk_find_entry(const char *);
bool smack_privileged(int cap);
bool smack_privileged_cred(int cap, const struct cred *cred);
void smk_destroy_label_list(struct list_head *list);
+int smack_populate_secattr(struct smack_known *skp);
/*
* Shared data.
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 38ac3da4e791..efe2406a3960 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -511,6 +511,42 @@ int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap,
}
/**
+ * smack_populate_secattr - fill in the smack_known netlabel information
+ * @skp: pointer to the structure to fill
+ *
+ * Populate the netlabel secattr structure for a Smack label.
+ *
+ * Returns 0 unless creating the category mapping fails
+ */
+int smack_populate_secattr(struct smack_known *skp)
+{
+ int slen;
+
+ skp->smk_netlabel.attr.secid = skp->smk_secid;
+ skp->smk_netlabel.domain = skp->smk_known;
+ skp->smk_netlabel.cache = netlbl_secattr_cache_alloc(GFP_ATOMIC);
+ if (skp->smk_netlabel.cache != NULL) {
+ skp->smk_netlabel.flags |= NETLBL_SECATTR_CACHE;
+ skp->smk_netlabel.cache->free = NULL;
+ skp->smk_netlabel.cache->data = skp;
+ }
+ skp->smk_netlabel.flags |= NETLBL_SECATTR_SECID |
+ NETLBL_SECATTR_MLS_LVL |
+ NETLBL_SECATTR_DOMAIN;
+ /*
+ * If direct labeling works use it.
+ * Otherwise use mapped labeling.
+ */
+ slen = strlen(skp->smk_known);
+ if (slen < SMK_CIPSOLEN)
+ return smk_netlbl_mls(smack_cipso_direct, skp->smk_known,
+ &skp->smk_netlabel, slen);
+
+ return smk_netlbl_mls(smack_cipso_mapped, (char *)&skp->smk_secid,
+ &skp->smk_netlabel, sizeof(skp->smk_secid));
+}
+
+/**
* smk_import_entry - import a label, return the list entry
* @string: a text string that might be a Smack label
* @len: the maximum size, or zero if it is NULL terminated.
@@ -523,7 +559,6 @@ struct smack_known *smk_import_entry(const char *string, int len)
{
struct smack_known *skp;
char *smack;
- int slen;
int rc;
smack = smk_parse_smack(string, len);
@@ -544,21 +579,8 @@ struct smack_known *smk_import_entry(const char *string, int len)
skp->smk_known = smack;
skp->smk_secid = smack_next_secid++;
- skp->smk_netlabel.domain = skp->smk_known;
- skp->smk_netlabel.flags =
- NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
- /*
- * If direct labeling works use it.
- * Otherwise use mapped labeling.
- */
- slen = strlen(smack);
- if (slen < SMK_CIPSOLEN)
- rc = smk_netlbl_mls(smack_cipso_direct, skp->smk_known,
- &skp->smk_netlabel, slen);
- else
- rc = smk_netlbl_mls(smack_cipso_mapped, (char *)&skp->smk_secid,
- &skp->smk_netlabel, sizeof(skp->smk_secid));
+ rc = smack_populate_secattr(skp);
if (rc >= 0) {
INIT_LIST_HEAD(&skp->smk_rules);
mutex_init(&skp->smk_rules_lock);
@@ -569,9 +591,6 @@ struct smack_known *smk_import_entry(const char *string, int len)
smk_insert_entry(skp);
goto unlockout;
}
- /*
- * smk_netlbl_mls failed.
- */
kfree(skp);
skp = ERR_PTR(rc);
freeout:
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 7a79ddb39e94..86db667ce319 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -3715,6 +3715,18 @@ static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap,
int acat;
int kcat;
+ /*
+ * Netlabel found it in the cache.
+ */
+ if ((sap->flags & NETLBL_SECATTR_CACHE) != 0)
+ return (struct smack_known *)sap->cache->data;
+
+ if ((sap->flags & NETLBL_SECATTR_SECID) != 0)
+ /*
+ * Looks like a fallback, which gives us a secid.
+ */
+ return smack_from_secid(sap->attr.secid);
+
if ((sap->flags & NETLBL_SECATTR_MLS_LVL) != 0) {
/*
* Looks like a CIPSO packet.
@@ -3762,11 +3774,6 @@ static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap,
return &smack_known_web;
return &smack_known_star;
}
- if ((sap->flags & NETLBL_SECATTR_SECID) != 0)
- /*
- * Looks like a fallback, which gives us a secid.
- */
- return smack_from_secid(sap->attr.secid);
/*
* Without guidance regarding the smack value
* for the packet fall back on the network
@@ -3845,6 +3852,9 @@ static struct smack_known *smack_from_skb(struct sk_buff *skb)
* @family: address family
* @skb: packet
*
+ * Find the Smack label in the IP options. If it hasn't been
+ * added to the netlabel cache, add it here.
+ *
* Returns smack_known of the IP options or NULL if that won't work.
*/
static struct smack_known *smack_from_netlbl(struct sock *sk, u16 family,
@@ -3853,13 +3863,18 @@ static struct smack_known *smack_from_netlbl(struct sock *sk, u16 family,
struct netlbl_lsm_secattr secattr;
struct socket_smack *ssp = NULL;
struct smack_known *skp = NULL;
+ int rc = 0;
netlbl_secattr_init(&secattr);
if (sk)
ssp = sk->sk_security;
- if (netlbl_skbuff_getattr(skb, family, &secattr) == 0)
+
+ if (netlbl_skbuff_getattr(skb, family, &secattr) == 0) {
skp = smack_from_secattr(&secattr, ssp);
+ if (secattr.flags & NETLBL_SECATTR_CACHEABLE)
+ rc = netlbl_cache_add(skb, family, &skp->smk_netlabel);
+ }
netlbl_secattr_destroy(&secattr);
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 9c4308077574..e567b4baf3a0 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -922,6 +922,10 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf,
skp->smk_netlabel.attr.mls.cat = ncats.attr.mls.cat;
skp->smk_netlabel.attr.mls.lvl = ncats.attr.mls.lvl;
rc = count;
+ /*
+ * This mapping may have been cached, so clear the cache.
+ */
+ netlbl_cache_invalidate();
}
out:
@@ -2950,15 +2954,6 @@ static struct file_system_type smk_fs_type = {
static struct vfsmount *smackfs_mount;
-static int __init smk_preset_netlabel(struct smack_known *skp)
-{
- skp->smk_netlabel.domain = skp->smk_known;
- skp->smk_netlabel.flags =
- NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
- return smk_netlbl_mls(smack_cipso_direct, skp->smk_known,
- &skp->smk_netlabel, strlen(skp->smk_known));
-}
-
/**
* init_smk_fs - get the smackfs superblock
*
@@ -2997,19 +2992,19 @@ static int __init init_smk_fs(void)
smk_cipso_doi();
smk_unlbl_ambient(NULL);
- rc = smk_preset_netlabel(&smack_known_floor);
+ rc = smack_populate_secattr(&smack_known_floor);
if (err == 0 && rc < 0)
err = rc;
- rc = smk_preset_netlabel(&smack_known_hat);
+ rc = smack_populate_secattr(&smack_known_hat);
if (err == 0 && rc < 0)
err = rc;
- rc = smk_preset_netlabel(&smack_known_huh);
+ rc = smack_populate_secattr(&smack_known_huh);
if (err == 0 && rc < 0)
err = rc;
- rc = smk_preset_netlabel(&smack_known_star);
+ rc = smack_populate_secattr(&smack_known_star);
if (err == 0 && rc < 0)
err = rc;
- rc = smk_preset_netlabel(&smack_known_web);
+ rc = smack_populate_secattr(&smack_known_web);
if (err == 0 && rc < 0)
err = rc;