mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-16 05:50:19 +00:00
Merge branch 'smack-for-3.12' of git://git.gitorious.org/smack-next/kernel into ra-next
This commit is contained in:
commit
7320336146
@ -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?
|
||||
*/
|
||||
|
@ -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;
|
||||
}
|
||||
/*
|
||||
|
@ -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,12 +3081,28 @@ 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,
|
||||
skp->smk_netlabel.attr.mls.cat,
|
||||
SMK_CIPSOLEN) != 0)
|
||||
continue;
|
||||
found = 1;
|
||||
break;
|
||||
/*
|
||||
* 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,
|
||||
kcat + 1);
|
||||
if (acat < 0 || kcat < 0)
|
||||
break;
|
||||
}
|
||||
if (acat == kcat) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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)
|
||||
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 (data[cnt] == '\0')
|
||||
/* Unexpected end of data */
|
||||
return -1;
|
||||
|
||||
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);
|
||||
tok[i] = data + cnt;
|
||||
|
||||
while (data[cnt] && !isspace(data[cnt]))
|
||||
++cnt;
|
||||
}
|
||||
while (isspace(data[cnt]))
|
||||
data[cnt++] = '\0';
|
||||
|
||||
kfree(access2);
|
||||
free_out_a:
|
||||
kfree(access1);
|
||||
free_out_o:
|
||||
kfree(object);
|
||||
free_out_s:
|
||||
kfree(subject);
|
||||
return rc;
|
||||
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;
|
||||
goto out;
|
||||
/*
|
||||
* 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;
|
||||
} 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;
|
||||
data[count] = '\0';
|
||||
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 {
|
||||
rc = smk_parse_long_rule(data + cnt, &rule, 1, tokens);
|
||||
if (rc <= 0) {
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
cnt += rc;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (rule_list == NULL) {
|
||||
load = 1;
|
||||
rule_list = &rule->smk_subject->smk_rules;
|
||||
rule_lock = &rule->smk_subject->smk_rules_lock;
|
||||
}
|
||||
|
||||
rc = smk_set_access(rule, rule_list, rule_lock, load);
|
||||
if (rc == 0) {
|
||||
rc = count;
|
||||
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,
|
||||
|
Loading…
Reference in New Issue
Block a user