Commit 322dd63c authored by Casey Schaufler's avatar Casey Schaufler Committed by Casey Schaufler
Browse files

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: default avatarCasey Schaufler <casey@schaufler-ca.com>
parent a2af0318
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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.
+37 −18
Original line number Diff line number Diff line
@@ -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:
+21 −6
Original line number Diff line number Diff line
@@ -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);

+9 −14
Original line number Diff line number Diff line
@@ -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;