Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 73203361 authored by James Morris's avatar James Morris
Browse files

Merge branch 'smack-for-3.12' of git://git.gitorious.org/smack-next/kernel into ra-next

parents f8eb8a13 10289b0f
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@
 */
struct smack_known {
	struct list_head		list;
	struct hlist_node		smk_hashed;
	char				*smk_known;
	u32				smk_secid;
	struct netlbl_lsm_secattr	smk_netlabel;	/* on wire labels */
@@ -167,9 +168,13 @@ struct smk_port_label {
#define SMACK_CIPSO_DOI_INVALID		-1	/* Not a DOI */
#define SMACK_CIPSO_DIRECT_DEFAULT	250	/* Arbitrary */
#define SMACK_CIPSO_MAPPED_DEFAULT	251	/* Also arbitrary */
#define SMACK_CIPSO_MAXCATVAL		63	/* Bigger gets harder */
#define SMACK_CIPSO_MAXLEVEL            255     /* CIPSO 2.2 standard */
#define SMACK_CIPSO_MAXCATNUM           239     /* CIPSO 2.2 standard */
/*
 * CIPSO 2.2 standard is 239, but Smack wants to use the
 * categories in a structured way that limits the value to
 * the bits in 23 bytes, hence the unusual number.
 */
#define SMACK_CIPSO_MAXCATNUM           184     /* 23 * 8 */

/*
 * Flag for transmute access
@@ -222,6 +227,7 @@ char *smk_parse_smack(const char *string, int len);
int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int);
char *smk_import(const char *, int);
struct smack_known *smk_import_entry(const char *, int);
void smk_insert_entry(struct smack_known *skp);
struct smack_known *smk_find_entry(const char *);
u32 smack_to_secid(const char *);

@@ -247,6 +253,9 @@ extern struct list_head smk_netlbladdr_list;

extern struct security_operations smack_ops;

#define SMACK_HASH_SLOTS 16
extern struct hlist_head smack_known_hash[SMACK_HASH_SLOTS];

/*
 * Is the directory transmuting?
 */
+26 −3
Original line number Diff line number Diff line
@@ -325,6 +325,25 @@ void smack_log(char *subject_label, char *object_label, int request,

DEFINE_MUTEX(smack_known_lock);

struct hlist_head smack_known_hash[SMACK_HASH_SLOTS];

/**
 * smk_insert_entry - insert a smack label into a hash map,
 *
 * this function must be called under smack_known_lock
 */
void smk_insert_entry(struct smack_known *skp)
{
	unsigned int hash;
	struct hlist_head *head;

	hash = full_name_hash(skp->smk_known, strlen(skp->smk_known));
	head = &smack_known_hash[hash & (SMACK_HASH_SLOTS - 1)];

	hlist_add_head_rcu(&skp->smk_hashed, head);
	list_add_rcu(&skp->list, &smack_known_list);
}

/**
 * smk_find_entry - find a label on the list, return the list entry
 * @string: a text string that might be a Smack label
@@ -334,12 +353,16 @@ DEFINE_MUTEX(smack_known_lock);
 */
struct smack_known *smk_find_entry(const char *string)
{
	unsigned int hash;
	struct hlist_head *head;
	struct smack_known *skp;

	list_for_each_entry_rcu(skp, &smack_known_list, list) {
	hash = full_name_hash(string, strlen(string));
	head = &smack_known_hash[hash & (SMACK_HASH_SLOTS - 1)];

	hlist_for_each_entry_rcu(skp, head, smk_hashed)
		if (strcmp(skp->smk_known, string) == 0)
			return skp;
	}

	return NULL;
}
@@ -475,7 +498,7 @@ struct smack_known *smk_import_entry(const char *string, int len)
		 * Make sure that the entry is actually
		 * filled before putting it on the list.
		 */
		list_add_rcu(&skp->list, &smack_known_list);
		smk_insert_entry(skp);
		goto unlockout;
	}
	/*
+30 −12
Original line number Diff line number Diff line
@@ -3063,6 +3063,8 @@ static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap,
{
	struct smack_known *skp;
	int found = 0;
	int acat;
	int kcat;

	if ((sap->flags & NETLBL_SECATTR_MLS_LVL) != 0) {
		/*
@@ -3079,13 +3081,29 @@ static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap,
		list_for_each_entry(skp, &smack_known_list, list) {
			if (sap->attr.mls.lvl != skp->smk_netlabel.attr.mls.lvl)
				continue;
			if (memcmp(sap->attr.mls.cat,
			/*
			 * Compare the catsets. Use the netlbl APIs.
			 */
			if ((sap->flags & NETLBL_SECATTR_MLS_CAT) == 0) {
				if ((skp->smk_netlabel.flags &
				     NETLBL_SECATTR_MLS_CAT) == 0)
					found = 1;
				break;
			}
			for (acat = -1, kcat = -1; acat == kcat; ) {
				acat = netlbl_secattr_catmap_walk(
					sap->attr.mls.cat, acat + 1);
				kcat = netlbl_secattr_catmap_walk(
					skp->smk_netlabel.attr.mls.cat,
				SMK_CIPSOLEN) != 0)
				continue;
					kcat + 1);
				if (acat < 0 || kcat < 0)
					break;
			}
			if (acat == kcat) {
				found = 1;
				break;
			}
		}
		rcu_read_unlock();

		if (found)
@@ -3876,12 +3894,12 @@ static __init void init_smack_known_list(void)
	/*
	 * Create the known labels list
	 */
	list_add(&smack_known_huh.list, &smack_known_list);
	list_add(&smack_known_hat.list, &smack_known_list);
	list_add(&smack_known_star.list, &smack_known_list);
	list_add(&smack_known_floor.list, &smack_known_list);
	list_add(&smack_known_invalid.list, &smack_known_list);
	list_add(&smack_known_web.list, &smack_known_list);
	smk_insert_entry(&smack_known_huh);
	smk_insert_entry(&smack_known_hat);
	smk_insert_entry(&smack_known_star);
	smk_insert_entry(&smack_known_floor);
	smk_insert_entry(&smack_known_invalid);
	smk_insert_entry(&smack_known_web);
}

/**
+83 −97
Original line number Diff line number Diff line
@@ -368,56 +368,43 @@ static int smk_parse_rule(const char *data, struct smack_parsed_rule *rule,
 * @data: string to be parsed, null terminated
 * @rule: Will be filled with Smack parsed rule
 * @import: if non-zero, import labels
 * @change: if non-zero, data is from /smack/change-rule
 * @tokens: numer of substrings expected in data
 *
 * Returns 0 on success, -1 on failure
 * Returns number of processed bytes on success, -1 on failure.
 */
static int smk_parse_long_rule(const char *data, struct smack_parsed_rule *rule,
				int import, int change)
static ssize_t smk_parse_long_rule(char *data, struct smack_parsed_rule *rule,
				int import, int tokens)
{
	char *subject;
	char *object;
	char *access1;
	char *access2;
	int datalen;
	int rc = -1;
	ssize_t cnt = 0;
	char *tok[4];
	int i;

	/* This is inefficient */
	datalen = strlen(data);
	/*
	 * Parsing the rule in-place, filling all white-spaces with '\0'
	 */
	for (i = 0; i < tokens; ++i) {
		while (isspace(data[cnt]))
			data[cnt++] = '\0';

	/* Our first element can be 64 + \0 with no spaces */
	subject = kzalloc(datalen + 1, GFP_KERNEL);
	if (subject == NULL)
		if (data[cnt] == '\0')
			/* Unexpected end of data */
			return -1;
	object = kzalloc(datalen, GFP_KERNEL);
	if (object == NULL)
		goto free_out_s;
	access1 = kzalloc(datalen, GFP_KERNEL);
	if (access1 == NULL)
		goto free_out_o;
	access2 = kzalloc(datalen, GFP_KERNEL);
	if (access2 == NULL)
		goto free_out_a;

	if (change) {
		if (sscanf(data, "%s %s %s %s",
			subject, object, access1, access2) == 4)
			rc = smk_fill_rule(subject, object, access1, access2,
				rule, import, 0);
	} else {
		if (sscanf(data, "%s %s %s", subject, object, access1) == 3)
			rc = smk_fill_rule(subject, object, access1, NULL,
				rule, import, 0);
	}

	kfree(access2);
free_out_a:
	kfree(access1);
free_out_o:
	kfree(object);
free_out_s:
	kfree(subject);
	return rc;

		tok[i] = data + cnt;

		while (data[cnt] && !isspace(data[cnt]))
			++cnt;
	}
	while (isspace(data[cnt]))
		data[cnt++] = '\0';

	while (i < 4)
		tok[i++] = NULL;

	if (smk_fill_rule(tok[0], tok[1], tok[2], tok[3], rule, import, 0))
		return -1;

	return cnt;
}

#define SMK_FIXED24_FMT	0	/* Fixed 24byte label format */
@@ -447,11 +434,12 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
					struct list_head *rule_list,
					struct mutex *rule_lock, int format)
{
	struct smack_parsed_rule *rule;
	struct smack_parsed_rule rule;
	char *data;
	int datalen;
	int rc = -EINVAL;
	int load = 0;
	int rc;
	int trunc = 0;
	int tokens;
	ssize_t cnt = 0;

	/*
	 * No partial writes.
@@ -466,11 +454,14 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
		 */
		if (count != SMK_OLOADLEN && count != SMK_LOADLEN)
			return -EINVAL;
		datalen = SMK_LOADLEN;
	} else
		datalen = count + 1;
	} else {
		if (count >= PAGE_SIZE) {
			count = PAGE_SIZE - 1;
			trunc = 1;
		}
	}

	data = kzalloc(datalen, GFP_KERNEL);
	data = kmalloc(count + 1, GFP_KERNEL);
	if (data == NULL)
		return -ENOMEM;

@@ -479,47 +470,49 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
		goto out;
	}

	rule = kzalloc(sizeof(*rule), GFP_KERNEL);
	if (rule == NULL) {
		rc = -ENOMEM;
	/*
	 * In case of parsing only part of user buf,
	 * avoid having partial rule at the data buffer
	 */
	if (trunc) {
		while (count > 0 && (data[count - 1] != '\n'))
			--count;
		if (count == 0) {
			rc = -EINVAL;
			goto out;
		}
	}

	if (format == SMK_LONG_FMT) {
		/*
		 * Be sure the data string is terminated.
		 */
	data[count] = '\0';
		if (smk_parse_long_rule(data, rule, 1, 0))
			goto out_free_rule;
	} else if (format == SMK_CHANGE_FMT) {
		data[count] = '\0';
		if (smk_parse_long_rule(data, rule, 1, 1))
			goto out_free_rule;
	tokens = (format == SMK_CHANGE_FMT ? 4 : 3);
	while (cnt < count) {
		if (format == SMK_FIXED24_FMT) {
			rc = smk_parse_rule(data, &rule, 1);
			if (rc != 0) {
				rc = -EINVAL;
				goto out;
			}
			cnt = count;
		} else {
		/*
		 * More on the minor hack for backward compatibility
		 */
		if (count == (SMK_OLOADLEN))
			data[SMK_OLOADLEN] = '-';
		if (smk_parse_rule(data, rule, 1))
			goto out_free_rule;
			rc = smk_parse_long_rule(data + cnt, &rule, 1, tokens);
			if (rc <= 0) {
				rc = -EINVAL;
				goto out;
			}

	if (rule_list == NULL) {
		load = 1;
		rule_list = &rule->smk_subject->smk_rules;
		rule_lock = &rule->smk_subject->smk_rules_lock;
			cnt += rc;
		}

	rc = smk_set_access(rule, rule_list, rule_lock, load);
	if (rc == 0) {
		rc = count;
		if (rule_list == NULL)
			rc = smk_set_access(&rule, &rule.smk_subject->smk_rules,
				&rule.smk_subject->smk_rules_lock, 1);
		else
			rc = smk_set_access(&rule, rule_list, rule_lock, 0);

		if (rc)
			goto out;
	}

out_free_rule:
	kfree(rule);
	rc = cnt;
out:
	kfree(data);
	return rc;
@@ -901,7 +894,7 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf,
	for (i = 0; i < catlen; i++) {
		rule += SMK_DIGITLEN;
		ret = sscanf(rule, "%u", &cat);
		if (ret != 1 || cat > SMACK_CIPSO_MAXCATVAL)
		if (ret != 1 || cat > SMACK_CIPSO_MAXCATNUM)
			goto out;

		smack_catset_bit(cat, mapcatset);
@@ -1840,7 +1833,6 @@ static ssize_t smk_user_access(struct file *file, const char __user *buf,
{
	struct smack_parsed_rule rule;
	char *data;
	char *cod;
	int res;

	data = simple_transaction_get(file, buf, count);
@@ -1853,18 +1845,12 @@ static ssize_t smk_user_access(struct file *file, const char __user *buf,
		res = smk_parse_rule(data, &rule, 0);
	} else {
		/*
		 * Copy the data to make sure the string is terminated.
		 * simple_transaction_get() returns null-terminated data
		 */
		cod = kzalloc(count + 1, GFP_KERNEL);
		if (cod == NULL)
			return -ENOMEM;
		memcpy(cod, data, count);
		cod[count] = '\0';
		res = smk_parse_long_rule(cod, &rule, 0, 0);
		kfree(cod);
		res = smk_parse_long_rule(data, &rule, 0, 3);
	}

	if (res)
	if (res < 0)
		return -EINVAL;

	res = smk_access(rule.smk_subject, rule.smk_object,