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 @@ -510,6 +510,42 @@ int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap, return 0; } +/** + * 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 @@ -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;